系统更换中,可能存在不可预料的 BUG

May 13, 2019

Webpack Loader 和 Plugin

想写个插件解析 JS 生成 JSON 的配置文件,其实就是 JSON.stringify(require('./manifest.js'))。这个简单的操作。

找了个 SO 上面的回答,How do I build a JSON file with webpack?

里面大概有 3 种看起来可行的方法,但是 CopyWebpackPlugin 这种太丑了,其实是没怎么用到 webpack 的东西(到最后就发现这才是最好用的方法

那就看第一个 manifest-loader.js,相比他的 JSON to JSON,我们的 JS to JSON 是不是更复杂一点。

{
	test: /manifest\.js$/,
	use: 'js2json-loader'
}

但是这个 JS 可能存在 ES6 甚至更高的语法,所以不能直接 JSON.stringify,那如何套一个 babel,之前的知识告诉我们,它的 Loader 会组合成一个洋葱模型,先 pitchloader ,那等 babel 完成获取结果,并导出不就好了。

{
    test: /manifest\.js$/,
    use: [
        './src/js2json-loader',
        'babel-loader',
    ]
}

很不幸输出的内容,还是没法直接运行,因为 js2json-loader 得到的内容虽然经过 babel 处理但是,依然无法执行。即使执行成功了,生成文件之后会发现完全不符合预期。

/***/ "./src/manifest.js":
/*!*************************!*\
  !*** ./src/manifest.js ***!
  \*************************/
/*! no static exports found */
/***/ (function(module, exports) {
  ...
/***/ })

或许会想到有个分离 CSS 的 Loader,为什么它可以那么操作?

因为它有 Loader 和 Plugin 2 个部分,Loader 抽取 require(xxx.css) 这样的内容,通过 Plugin 合并导出为独立的样式表文件,因为流程挂在 main.js 生成过程中,只是用 emitFile 把文件丢出来;所以实现起来并不优雅。

简而言之就是之前对 Loader 和 Plugin 里理解有问题,Loader 是加载文件,转化成 JS 可以操作的内容(对象,字符串或者流);而 Plugin 是提供了一个对流程的控制,甚至产生一个新的流程。

所以这里还是简单的用 CopyWebpackPlugin 这种操作,因为这和 Webpack 正常的打包流程没啥关系。

但是直接用实在不优雅,而且没法用上 webpack 的 Loader,尤其是 babel 转化。

所以只能用 babel-node 替换 node,然后通过 require 引入模块,来解决这个问题。

{
  "scripts": {
    "build": "npx babel-node ./node_modules/webpack/bin/webpack",
    "watch": "npx babel-node ./node_modules/webpack/bin/webpack --watch"
  }
}

然后用 CopyWebpackPlugin 这个插件。

new CopyWebpackPlugin ([{
    from: 'src/manifest.js', to: './manifest.json',
    transform: function (_, path) {
        return JSON.stringify(require (path), null, 2)
    }
}])

勉强算是解决了,虽然好丑啊

© Gitai 2011

Powered by Hugo & Kiss.