Webpack子编译器更改配置

Mer*_*sen 5 webpack

我希望我的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