如何使用webpack构建JSON文件?

use*_*471 13 javascript npm webpack

我想以manifest.json"更智能"的程序化方式汇编Chrome扩展程序使用的文件.我正在使用npm进行依赖项解析,它package.json包含一些与manifest.json文件共享的字段,包括"name","description"和"version".

有没有办法定义类似于部分manifest.json文件的内容,其中包含所有特定于Chrome的内容,但是在适当的地方填写共享值?我发现这在Gulp中非常简单:

var gulp = require('gulp');
var fs = require('fs');
var jeditor = require('gulp-json-editor');

gulp.task('manifest', function() {
    var pkg = JSON.parse(fs.readFileSync('./package.json'));
    gulp.src('./manifest.json')
      .pipe(jeditor({
        'name': pkg.name,
        'description': pkg.description,
        'version': pkg.version,
        'author': pkg.author,
        'homepage_url': pkg.homepage,
      }))
      .pipe(gulp.dest("./dist"));
});
Run Code Online (Sandbox Code Playgroud)

即使有一些为此目的而设计的npm包,有人可以向我解释一般这样的事情是怎么做的吗?我知道Webpack 2有一个内置的json加载器,但我不清楚如何在这样的情况下使用它.

Ren*_*man 12

实际上,有一个比@ user108471提供的解决方案更优雅的解决方案(尽管它受其启发),那就是使用copy-webpack-plugin。借助其transform功能,您可以manifest.json在将其复制到目标位置之前即时添加所需的值。

它有两个优点:

  • 它不会产生额外的不必要的manifest.js-bundle(@bronson的解决方案也可以解决此问题)
  • 你不需要requiremanifest.json其他一些.js-file(这似乎语义向后我)

最小的设置可能是这样的:

webpack.config.js

// you can just require .json, saves the 'fs'-hassle
let package = require('./package.json');

function modify(buffer) {
   // copy-webpack-plugin passes a buffer
   var manifest = JSON.parse(buffer.toString());

   // make any modifications you like, such as
   manifest.version = package.version;

   // pretty print to JSON with two spaces
   manifest_JSON = JSON.stringify(manifest, null, 2);
   return manifest_JSON;
}


module.exports = {

   // ...

   plugins: [
      new CopyWebpackPlugin([
         {
            from: "./src/manifest.json",
            to:   "./dist/manifest.json",
            transform (content, path) {
                return modify(content)
            }
         }])
   ]

}
Run Code Online (Sandbox Code Playgroud)


use*_*471 7

感谢Webpack项目中的Sean Larkin与我联系并帮助我弄清楚如何完成此工作。我需要创建一个自定义加载器来处理现有内容的读取manifest.json并将我感兴趣的字段添加到其中。

// File: src/manifest-loader.js

const fs = require('fs');

// A loader to transform a partial manifest.json file into a complete
// manifest.json file by adding entries from an NPM package.json.
module.exports = function(source) {
  const pkg = JSON.parse(fs.readFileSync('./package.json'));
  const merged = Object.assign({}, JSON.parse(source), {
    'name': pkg.name,
    'description': pkg.description,
    'version': pkg.version,
    'author': pkg.author,
    'homepage_url': pkg.homepage,
  });
  const mergedJson = JSON.stringify(merged);
  // In Webpack, loaders ultimately produce JavaScript. In order to produce
  // another file type (like JSON), it needs to be emitted separately.
  this.emitFile('manifest.json', mergedJson);
  // Return the processed JSON to be used by the next item in the loader chain.
  return mergedJson;
};
Run Code Online (Sandbox Code Playgroud)

然后将webpack配置为使用我的custom manifest-loader

// File: webpack.config.js

const path = require('path');

module.exports = {
  // Tell Webpack where to find our custom loader (in the "src" directory).
  resolveLoader: {
    modules: [path.resolve(__dirname, "src"), "node_modules"]
  },

  // The path to the incomplete manifest.json file.
  entry: "./manifest.json",
  output: {
    // Where the newly built manifest.json will go.
    path: path.resolve(__dirname, 'dist'),
    // This file probably won't actually be used by anything.
    filename: "manifest.js",
  },

  module: {
    rules: [
      {
        // Only apply these loaders to manifest.json.
        test: /manifest.json$/,
        // Loaders are applied in reverse order.
        use: [
          // Second: JSON -> JS
          "json-loader",
          // First: partial manifest.json -> complete manifest.json
          "manifest-loader",
        ]
      }
    ]
  }
};
Run Code Online (Sandbox Code Playgroud)

运行Webpack时,结果是一个dist/包含manifest.js和的目录manifest.json,其中manifest.json包含原始顶级目录中的所有内容manifest.json以及的其他信息package.json。额外的manifest.js是一个脚本,该脚本将其内容公开manifest.json给需要它的项目中的任何其他JavaScript。这可能不太有用,但是可以想象,Chrome扩展程序可能希望require在脚本中的某个地方对此进行显示,以友好的方式公开其中的某些信息。

  • 是的,将 'manifest.json' 作为入口点会创建 manifest.json 文件,但它也会创建 manifest.bundle.js。(找不到任何解决方法)我认为在我的最顶层 js 文件中放置一个导入并没有一个未使用的文件最终出现在我的构建中那么奇怪。我想这是一个品味问题。:) (2认同)