【问题标题】:Can I use a webpack hook to modify file output just before it gets saved?我可以在保存之前使用 webpack 挂钩来修改文件输出吗?
【发布时间】:2020-12-31 00:43:35
【问题描述】:

我想在 webpack 和 babel 处理完文件后对其进行操作。在保存新文件之前触发了一个emit 钩子,但我看不到操作文件内容的方法。所以我决定使用afterEmit钩子来读入刚刚写好的文件,修改它,然后写回:

    plugins: [
      new class OutputMonitor {
        apply(compiler) {
          compiler.hooks.afterEmit.tap('OutputMonitor', compilation => {
            if (compilation.emittedAssets.has('index.js')) {
              let contents = fs.readFileSync('./dist/web/index.js', 'utf-8');
              // Strip out dynamic import() so it doesn't generate warnings.
              contents = contents.replace(/import(?=\("tseuqer-yb")/, 'console.log');
              // Strip out large and large-alt timezone definitions from this build.
              contents = contents.replace(large, 'null');
              contents = contents.replace(largeAlt, 'null');
              fs.writeFileSync('./dist/web/index.js', contents);
            }
          });
        }
      }()
    ],

这样就完成了工作,但有更好的方法吗?

【问题讨论】:

  • 我不想让它看起来像是我实际上在提供问题的答案,我想展示 chenxsan 解决方案的样子,因为我对其进行了调整,而不是看起来像我在获得荣誉为它。
  • 如果您认为您的改编会帮助其他人,那么您应该将其发布为替代答案。如果它不会给主题增加太多内容,那就保持现状。

标签: javascript webpack babel-loader


【解决方案1】:

据我所知,您基本上是在用另一个字符串替换一些字符串。

如果你正在运行 webpack 5,我相信你可以使用 processAssets 钩子。

这是一个您可以根据自己的情况进行调整的示例:

const { Compilation, sources } = require('webpack');

class Replace {
  apply(compiler) {
    compiler.hooks.thisCompilation.tap('Replace', (compilation) => {
      compilation.hooks.processAssets.tap(
        {
          name: 'Replace',
          stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,
        },
        () => {
          // get the file main.js
          const file = compilation.getAsset('main.js');
          // update main.js with new content
          compilation.updateAsset(
            'main.js',
            new sources.RawSource(file.source.source().replace('a', 'b'))
          );
        }
      );
    });
  }
}
module.exports = {
  entry: './wp.js',
  plugins: [new Replace()],
};

【讨论】:

  • 这个几乎看起来对我有用,而且它绝对是有用的信息,因为我不知道在编译过程中像这样的钩子中有钩子。问题是我的编辑是基于修改缩小的代码,但上面的插件在输出被缩小之前拦截了它。我想我需要某种挂钩到 TerserPlugin 中?
  • 我一直在想你的这个解决方案有多好,并意识到我可以使用不同的(更好的)方法来查找我想要删除的代码——标记 cmets。这实际上比我使用的大数据块的精确字符匹配要好得多。我会将我的解决方案附加到我的问题中。
  • 由于有人编辑掉了我更新的代码,这里的关键点是:contents.replace(/\/\* trim-file-start \*\/.*?\/\* trim-file-end \*\//sg, 'null');,一个在要替换的代码周围寻找特殊开始和结束 cmets 的正则表达式。
  • processAssets 钩子有很多阶段可以使用。例如,TerserPlugin 使用PROCESS_ASSETS_STAGE_OPTIMIZE_SIZEgithub.com/webpack-contrib/terser-webpack-plugin/blob/master/…,这意味着如果你想修改压缩代码,你可以在该阶段之后使用钩子。但我没有测试过。
  • 对我来说效果很好。只是想在我的styles.css中添加一行CSS,这成功了!
猜你喜欢
  • 2020-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多