关于javascript:如何使用webpack构建JSON文件?

How do I build a JSON file with webpack?

我想以一种"更智能"的程序化方式来组装Chrome扩展程序使用的manifest.json文件。 我使用npm进行依赖项解析,它的package.json包含与manifest.json文件共享的一些字段,包括"名称","描述"和"版本"。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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"));
});

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


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

它有两个优点:

  • 它不会生成多余的manifest.js -bundle(@bronson的解决方案也可以解决此问题)
  • 您不需要在其他.js文件中require manifest.json(在我看来在语义上是倒退的)

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

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 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)
            }
         }])
   ]

}


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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;
};

然后将webpack配置为使用我的自定义manifest-loader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 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",
        ]
      }
    ]
  }
};

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


我在下面的Webpack 4中的解决方案。这是使用Webpack加载程序生成json文件的通用解决方案,但它也适用于manifest.json文件。

webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const resolve = require("path").resolve;

module.exports = {
    entry: {
        entry: resolve(__dirname,"app/main.js"),
    },
    module: {
        rules: [
            {
                test: /manifest\.js$/,
                use: ExtractTextPlugin.extract({
                    use: []  // Empty array on purpose.
                })
            }
        ],
        {
            test: /\.png$/,
            use: [{
                loader:"file-loader",
                options: {
                    context: resolve(__dirname,"app"),
                    name:"[path][name].[ext]",
                    publicPath:"/",
                }
            }]
        }
    },
    output: {
        filename:"[name].js",
        path: resolve(__dirname, 'dist'),
    },
    plugins: [
        new webpack.EnvironmentPlugin(["npm_package_version"]),  // automagically populated by webpack, available as process.env.npm_package_version in loaded files.
        new ExtractTextPlugin("manifest.json"),
    ]
};

app / main.js

1
2
3
const manifest = require('./manifest.js');

// Other parts of app …

app / manifest.js

1
2
3
4
5
6
7
8
9
10
const icon = require('./icon.png');  

const manifestData = {  
    icon: {"128": icon},  // icon.png will be in the emitted files, yay!
    version: process.env.npm_package_version,  // See webpack.config.js plugins
    // other manifest data …
};

// Whatever string you output here will be emitted as manifest.json:
module.exports = JSON.stringify(manifestData, null, 2);

package.json依赖项

1
2
3
4
5
{
   "extract-text-webpack-plugin":"4.0.0-beta.0",
   "file-loader":"1.1.11",
   "webpack":"4.12.0",
}

我使用了足够多的脚本,因此在NPM上发布了该脚本的某种修改版本:https://github.com/bronson/manifest-package-loader

希望它像yarn add -D manifest-package-loader一样简单,并更新您的webpack.config.js。

巧合的是,就在今天早上,我遇到了chem-loader,它也可能起作用:https://github.com/mrmisterman/chem-loader


试试这个包,您可以读取您的json文件,然后在自定义它之后构建新的json。
https://github.com/webpack-contrib/json-loader