我希望我的webpack构建的输出在编译我的服务工作者时被定义为变量.
我想使用子编译功能来编译放在不同路径中的服务工作者.我需要从webpack编译发出的输出来正确编译服务工作者.
我最初的尝试是使用与创建子编译器的offline-plugin相同的策略,但我需要能够更改服务工作者的输出路径.服务工作者路径很重要,因为它定义了范围.
我想知道如何使用子编译器API来完成下面的工作,以防止我的构建产生这种副作用(希望它会给我webpack-dev-server支持.
var webpack = require('webpack');
function ServiceWorkerPlugin(options) {
this.options = options;
}
ServiceWorkerPlugin.prototype.apply = function(compiler) {
compiler.plugin('emit', (compilation, callback) => {
const stats = compilation.getStats().toJson();
const child = webpack(this.options);
child.apply(
new webpack.DefinePlugin({
assets: stats.assets
})
);
child.run((err, swStats) => {
if (err) {
callback(err);
}
const swStatsJson = swStats.toJson();
if(swStatsJson.errors.length > 0) {
console.log(swStatsJson.errors);
}
if(swStatsJson.warnings.length > 0) {
console.log(swStatsJson.warnings);
}
callback();
});
module.exports = ServiceWorkerPlugin;
Run Code Online (Sandbox Code Playgroud)
Nek*_*ekR 12
首先,你所描述的一切都在offline-plugin实施中,所以现在我将向你展示我是如何做到的.
当你需要使用一切成为的WebPack有点棘手孩子编译并compilation.assets在里面.问题是必须在事件上创建子编译complier.plugin('make'),但compilation.assets仅在compiler.plugin('emit')几乎在编译结束时触发的事件上可用.
(注意:代码在ES2015版本中)
import SingleEntryPlugin from 'webpack/lib/SingleEntryPlugin';
export default class AwesomePlugin {
constructor() {
// Define compilation name and output name
this.childCompilerName = 'awesome-plugin-compilation';
this.outputFileName = 'custom-file.js';
// To make child compiler work, you have to have a entry in the file system
this.compilationEntry = 'entry-file.js';
}
apply(compiler) {
// Listen to `make` event
compiler.plugin('make', (compilation, callback) => {
// Creating child compiler with params
const childCompiler = compilation.createChildCompiler(this.childCompilerName, {
filename: this.outputFileName
});
// Everyone plugin does this, I don't know why
childCompiler.context = compiler.context;
// Add SingleEntryPlugin to make all this work
childCompiler.apply(new SingleEntryPlugin(compiler.context, this.compilationEntry, this.outputFileName));
// Needed for HMR. Even if your plugin don't support HMR,
// this code seems to be always needed just in case to prevent possible errors
childCompiler.plugin('compilation', (compilation) => {
if (compilation.cache) {
if (!compilation.cache[name]) {
compilation.cache[name] = {};
}
compilation.cache = compilation.cache[name];
}
});
// Run child compilation
childCompiler.runAsChild((err, entries, childCompilation) => {
callback(err);
});
});
}
}
Run Code Online (Sandbox Code Playgroud)
这将使您的条目编译成单独的文件,您可以根据需要命名.接下来,你需要对compilation.assetson 'emit'事件进行一些hacky操作:
compiler.plugin('emit', function(compilation, callback) {
// Get our output asset
const asset = compilation.assets[this.outputFileName];
// Delete delete our asset from output
delete compilation.assets[this.outputFileName];
// Collect all output assets
const assets = Object.keys(compilation.assets);
// Combine collected assets and child compilation output into new source.
// Note: `globalAssets` is global variable
let source = `
var globalAssets = ${ JSON.stringify(assets) }
${ asset.source() }
`;
// Add out asset back to the output
compilation.assets[this.outputFileName] = {
source() {
return source;
},
size() {
return Buffer.byteLength(source, 'utf8');
}
};
});
Run Code Online (Sandbox Code Playgroud)
编辑:您可能在要插入资产列表的条目中有一些特殊的位置.但要小心,如果您将使用常规模板语法,那么JS加载器将无法解析您的文件.所以你可以放置这样的东西__INSERT_WEBPACK_ASSETS_DATA__,然后用String#replace它来替换实际的数据.
基本上就是这样.现在,您应该能够将变量注入compilation.assets到子编译输出中.请注意,在我创建它时offline-plugin使用伪编译名称,然后在'emit'事件上将其重命名为真实文件名.我不记得确切的原因,但我记得我有它们.所以,你可能需要自己试验一下.
以下是此样板的完整代码(包含'make'和'emit'事件):https://gist.github.com/NekR/f85d297fe4f1ea3c168827b305c13844
| 归档时间: |
|
| 查看次数: |
1727 次 |
| 最近记录: |