loader和plugin区别

149 阅读1分钟

一、基础定义与定位

概念本质作用阶段核心职责
loader模块转换器(函数)编译阶段将源文件转换为可打包的模块
plugin事件监听与处理器(对象)整个构建周期扩展 webpack 功能,执行特定任务

二、核心区别对比

1. 功能维度
  • loader

    • 专注于文件内容的转换,例如:
      • .jsx 转为 JS(Babel-loader)
      • 将 Sass 转为 CSS(sass-loader)
      • 将图片转为 Base64(url-loader)
    • 单文件处理,输入源文件,输出转换后的代码。
  • plugin

    • 监听 webpack 构建过程中的生命周期事件,执行对应操作:
      • 打包后生成 HTML 文件(HtmlWebpackPlugin)
      • 压缩 JS/CSS(UglifyJSPlugin)
      • 热更新(HotModuleReplacementPlugin)
    • 全局影响,可操作构建后的资源、修改打包配置等。
2. 用法与形态
  • loader 用法

    // webpack.config.js
    module.exports = {
      module: {
        rules: [
          {
            test: /\.js$/,
            use: 'babel-loader', // 字符串形式
            // 或对象形式配置参数
            use: {
              loader: 'babel-loader',
              options: { presets: ['@babel/preset-env'] }
            }
          }
        ]
      }
    };
    
  • plugin 用法

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    module.exports = {
      plugins: [
        new HtmlWebpackPlugin({ template: './index.html' }), // 实例化插件
        new webpack.DefinePlugin({ NODE_ENV: JSON.stringify('production') })
      ]
    };
    
3. 执行时机与流程
  • loader 执行流程

    1. 从右到左、从下到上调用(如 style-loader!css-loader!less-loader)。
    2. 每个 loader 处理前一个 loader 的输出,最终转为 JS 模块。
  • plugin 事件机制

    1. 通过 compiler.hooks 监听事件(如 beforeCompileafterEmit)。
    2. 例如:HtmlWebpackPlugincompilation.finish 阶段生成 HTML 文件。

三、问题

1. 问:为什么 loader 是函数,plugin 是对象?
    • loader 需直接处理文件内容,函数形态更适合输入输出转换;
    • plugin 需注册事件钩子,对象形态可通过 apply 方法绑定到 webpack 实例,符合发布-订阅模式。
2. 问:如何实现一个简单的 loader?
  • // 示例:将文本转为大写的 loader
    module.exports = function(source) {
      // this.cacheable() // 开启缓存
      return source.toUpperCase();
    };
    
    • 核心:导出函数,接收源文件内容,返回转换后的代码。
3. 问:plugin 如何监听打包事件?
  • // 示例:打包完成后打印日志的 plugin
    class LogPlugin {
      apply(compiler) {
        compiler.hooks.afterEmit.tap('LogPlugin', (compilation) => {
          console.log('打包完成!文件数量:', Object.keys(compilation.assets).length);
        });
      }
    }
    
    • 关键:实现 apply 方法,通过 compiler.hooks 注册事件处理器。
4. 问:生产环境中常见的 plugin 有哪些?
    • 优化类TerserPlugin(JS 压缩)、MiniCssExtractPlugin(CSS 抽离);
    • 资源类HtmlWebpackPlugin(生成 HTML)、ImageMinimizerPlugin(图片压缩);
    • 环境类DefinePlugin(注入环境变量)、ProvidePlugin(自动加载模块)。

四、实战场景与选型

  • 当需要处理文件内容时:用 loader(如 .vue 文件 → vue-loader)。
  • 当需要控制构建流程时:用 plugin(如打包后自动清理旧文件)。
  • 组合使用案例
    // 场景:将 ES6 转为 ES5 并压缩 JS
    module.exports = {
      module: {
        rules: [{ test: /\.js$/, use: 'babel-loader' }] // loader 转换代码
      },
      plugins: [
        new TerserPlugin() // plugin 压缩代码
      ]
    };