Javascript 如何使用webpack构建JSON文件?

Javascript 如何使用webpack构建JSON文件?,javascript,npm,webpack,Javascript,Npm,Webpack,我想以一种“更智能”的编程方式组装一个Chrome扩展使用的manifest.json文件。我正在使用npm进行依赖项解析,它的包.json包含一些与manifest.json文件共享的字段,包括“name”、“description”和“version” 有没有一种方法可以定义一个部分manifest.json文件,其中包含所有特定于Chrome的内容,但在适当的地方填充共享值?我发现这一点非常简单: var gulp = require('gulp'); var fs = require('

我想以一种“更智能”的编程方式组装一个Chrome扩展使用的
manifest.json
文件。我正在使用npm进行依赖项解析,它的
包.json
包含一些与
manifest.json
文件共享的字段,包括“name”、“description”和“version”

有没有一种方法可以定义一个部分
manifest.json
文件,其中包含所有特定于Chrome的内容,但在适当的地方填充共享值?我发现这一点非常简单:

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加载器,但我不清楚在这种情况下如何使用它。

感谢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;
};
然后将webpack配置为使用我的自定义
清单加载程序

// 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时,结果是一个
dist/
目录,其中包含
manifest.js
manifest.json
,其中
manifest.json
包含原始顶级
manifest.json
以及
package.json
中的附加信息。额外的
manifest.js
脚本将
manifest.json
的内容公开给项目中需要它的任何其他JavaScript。这可能不太有用,但是Chrome扩展可能希望
在某个地方的脚本中要求
以友好的方式公开这些信息。

我使用了您的脚本,所以我在NPM上发布了一个稍微修改过的版本:

希望它像添加-D清单包加载器和更新webpack.config.js一样简单


巧合的是,就在今天早上,我遇到了chem loader,它可能也能工作:

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

webpack.config.js app/main.js app/manifest.js package.json依赖项
实际上有一个比@user108471的解决方案更优雅的解决方案(尽管它是受其启发的),那就是使用。通过它的功能,您可以在将所需的值动态添加到
manifest.json
中,然后将其复制到目标

它有两个优点:

  • 它不会生成额外的不必要的
    manifest.js
    -bundle(也解决了这个问题)
  • 您不需要
    在其他一些
    .js
    -文件中要求
    manifest.json
    (在我看来,这在语义上是向后的)
最低限度的设置可以是:

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)
            }
         }])
   ]

}

如果您使用的是Webpack4,它非常简单。我们不需要指定任何显式json加载程序

注意:这里我只是将所有内容捆绑到一个html文件中,但您会发现webpack.config.js文件中没有json加载程序

webpack.config.js

const HtmlWebPackPlugin = require("html-webpack-plugin");
 const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');

module.exports = {
 module: {
rules: [
  {
    test: /\.js$/,
    exclude: [/node_modules/],
    use: [{
      loader: 'babel-loader'
    }],
  },
  {
    test: /\.css$/,
    use: ["style-loader", "css-loader"]
  },
  {
      test: /\.ico$/,
      use: ["file-loader"]
  },
  {
    test: /\.html$/,
    use: [
      {
        loader: "html-loader",
        options: { minimize: true }
      }
    ]
  }
],
},
 plugins: [
new HtmlWebPackPlugin({
  template: "./src/index.html",
  filename: "./index.html",
  inlineSource: '.(js|css)$'
}),
new HtmlWebpackInlineSourcePlugin(),
],
devServer: {
  compress: true,
  disableHostCheck: true,
  }
}
在我的app.js中,我只使用

import data from './data/data.json'

它是固定的吗?或者,如果愿意,您可以尝试使用gulp的webpack,这样您就可以使用这个包
gulp json编辑器
。@RahmatAligos谢谢,但我的目标是简化构建过程,这样我就不必同时使用gulp和webpack了。这是少数几个阻止我切换的问题之一,这里的自定义加载程序解决方案解决了我的问题。这是一个伟大的解决方案!我使用了文件加载器而不是json加载器,所以我没有得到manifest.js,并做了一些其他调整:非常感谢您回答自己的问题。@bronson我很高兴它帮助了其他人。我注意到一条关于需要导入manifest.json以使您的解决方案工作的要点的评论,我想我知道修复:名称“manifest.json”是您的Web包配置中的一个入口点。是的,将“manifest.json”作为入口点创建manifest.json文件,但它也创建manifest.bundle.js。(找不到任何方法解决这个问题)我觉得在我最顶层的js文件中放置一个导入比在我的构建中放置一个未使用的文件要简单得多。我想这是品味的问题。:)嘿,谢谢你。实际上,我很喜欢manifest.js用于一些方便的应用程序内报告,但这绝对是更直接的解决方案。实际上,我很想深入研究这个插件并了解它是如何工作的,因为有足够多的人有相同的特定manifest.json需求,这可能会证明一个插件可以处理这个特定的情况。这正是我需要的解决方案+1这很酷,只是想注意,当我通过
webpack.config.babel.js
使用babel配置时,我在toString()行上收到了一个明显的模糊错误。错误是“找不到模块'core js/modules/es.object.to string'”,我的解决方案是从配置文件名=)中删除
.babel
),我不知道这是什么数据聚合网站,但我在找到它之前找到了这个答案SO@Luminous谢谢我给他们发了一条信息,要求他们根据CC BY-SA许可证添加正确的属性。真有趣——我也有同样的问题,我在谷歌上搜索了“webpack write json file”,这篇帖子出现了!谢谢:)我也是,在这个页面上寻找“webpack convert js to json”,而实际上我在检查同样的问题)
{
    "extract-text-webpack-plugin": "4.0.0-beta.0",
    "file-loader": "1.1.11",
    "webpack": "4.12.0",
}
// 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)
            }
         }])
   ]

}
const HtmlWebPackPlugin = require("html-webpack-plugin");
 const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');

module.exports = {
 module: {
rules: [
  {
    test: /\.js$/,
    exclude: [/node_modules/],
    use: [{
      loader: 'babel-loader'
    }],
  },
  {
    test: /\.css$/,
    use: ["style-loader", "css-loader"]
  },
  {
      test: /\.ico$/,
      use: ["file-loader"]
  },
  {
    test: /\.html$/,
    use: [
      {
        loader: "html-loader",
        options: { minimize: true }
      }
    ]
  }
],
},
 plugins: [
new HtmlWebPackPlugin({
  template: "./src/index.html",
  filename: "./index.html",
  inlineSource: '.(js|css)$'
}),
new HtmlWebpackInlineSourcePlugin(),
],
devServer: {
  compress: true,
  disableHostCheck: true,
  }
}
import data from './data/data.json'
const manifest = {
  entry: './src/chrome_extension/dummy_index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'DELETED.js',
  },
  plugins: [
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [
        {from: 'LICENSE.md'},
        {from: 'assets/img/icon.png', to: `${ASSETS_PATH}/icon.png`},
        {from: 'src/chrome_extension/manifest.json',
          transform: function(manifestBuffer, path) {
            const manifestString = manifestBuffer.toString()
                .replace(/\$\{OPTIONS_PAGE_PATH\}/g, OPTIONS_PAGE_PATH)
                .replace(/\$\{CONTENT_SCRIPT_PATH\}/g, CONTENT_SCRIPT_PATH)
                .replace(/\$\{ASSETS_PATH\}/g, ASSETS_PATH);
            return Buffer.from(manifestString);
          },
        },
      ],
    }),
    new RemoveFilesWebpackPlugin({
      after: {
        log: false,
        include: [
          'dist/DELETED.js',
        ],
      },
    }),
  ],
  stats: 'none',
  mode: 'none',
};