webpack Plugin

129 阅读3分钟

一、Plugin与Loader的区别

loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。

二、plugins

HtmlWebpackPlugin 简化了 HTML 文件的创建,以便为你的 webpack 包提供服务。这对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包特别有用。你可以让该插件为你生成一个 HTML 文件,使用 lodash 模板提供模板,或者使用你自己的 loader。
AutomaticPrefetchPlugin 会观察之前编译的 所有模块 的变化,以改进增量构建的时间。对比PrefetchPlugin 而言,PrefetchPlugin 是预先发现 单个模块。
BannerPlugin 为每个 chunk 文件头部添加 banner。
CopyWebpackPlugin 将单个文件或整个目录复制到构建目录。
DefinePlugin 允许创建一个在编译时可以配置的全局常量。这可能会对开发模式和发布模式的构建允许不同的行为非常有用。如果在开发构建中,而不在发布构建中执行日志记录,则可以使用全局常量来决定是否记录日志。这就是 DefinePlugin 的用处,设置它,就可以忘记开发和发布构建的规则。
DLLPlugin 和 DLLReferencePlugin 用某种方法实现了拆分 bundles,同时还大大提升了构建的速度。
EnvironmentPlugin 是使用DefinePluginon process.env键的简写。
HashedModuleIdsPlugin 该插件会根据模块的相对路径生成一个四位数的hash作为模块id, 建议用于生产环境。
HotModuleReplacementPlugin 启用热模块更换,也称为HMR。
LimitChunkCountPlugin 当你在编写代码时,可能已经添加了许多代码分离点( code split point )来实现按需加载( load stuff on demand )。在编译完之后,你可能会注意到有一些很小的 chunk - 这产生了大量 HTTP 请求开销。幸运的是,此插件可以通过合并的方式,后处理你的 chunk,以减少请求数。
MinChunkSizePlugin 通过合并小于 minChunkSize 大小的 chunk,将 chunk 体积保持在指定大小限制以上。
NamedModulesPlugin 当开启 HMR 的时候使用该插件会显示模块的相对路径,建议用于开发环境。
UglifyjsWebpackPlugin 这个插件使用UglifyJS v3 (uglify-es)来缩小你的JavaScript。

三、开发plugin

一个简单的示例插件,生成一个叫做 assets.md 的新文件;文件内容是所有构建生成的文件的列表。

class FileListPlugin {
    static defaultOptions = {
      outputFile: 'assets.md',
    };
  
    // 需要传入自定义插件构造函数的任意选项
    //(这是自定义插件的公开API)
    constructor(options = {}) {
      // 在应用默认选项前,先应用用户指定选项
      // 合并后的选项暴露给插件方法
      // 记得在这里校验所有选项
      this.options = { ...FileListPlugin.defaultOptions, ...options };
    }
  
    apply(compiler) {
      const pluginName = FileListPlugin.name;
  
      // webpack 模块实例,可以通过 compiler 对象访问,
      // 这样确保使用的是模块的正确版本
      // (不要直接 require/import webpack)
      const { webpack } = compiler;
  
      // Compilation 对象提供了对一些有用常量的访问。
      const { Compilation } = webpack;
  
      // RawSource 是其中一种 “源码”("sources") 类型,
      // 用来在 compilation 中表示资源的源码
      const { RawSource } = webpack.sources;
  
      // 绑定到 “thisCompilation” 钩子,
      // 以便进一步绑定到 compilation 过程更早期的阶段
      compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
        // 绑定到资源处理流水线(assets processing pipeline)
        compilation.hooks.processAssets.tap(
          {
            name: pluginName,
  
            // 用某个靠后的资源处理阶段,
            // 确保所有资源已被插件添加到 compilation
            stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE,
          },
          (assets) => {
            // "assets" 是一个包含 compilation 中所有资源(assets)的对象。
            // 该对象的键是资源的路径,
            // 值是文件的源码
  
            // 遍历所有资源,
            // 生成 Markdown 文件的内容
            const content =
              '# In this build:\n\n' +
              Object.keys(assets)
                .map((filename) => `- ${filename}`)
                .join('\n');
  
            // 向 compilation 添加新的资源,
            // 这样 webpack 就会自动生成并输出到 output 目录
            compilation.emitAsset(
              this.options.outputFile,
              new RawSource(content)
            );
          }
        );
      });
    }
  }
  
  module.exports = { FileListPlugin };