Loader 和 Plugin

Loader

Loader 是一个打包方案,本身是一个函数,接受源文件作为参数,返回转换的结果。

loaders 需要安装:npm install [loader名称] -D

Loader 的使用方式

  • 配置方式(Configuration)
    Loader 是有执行顺序的,从下到上,从右到左 ,因为 Webpack 使用的是 compose 函数式编程方式,这种表达式的执行是从右到左。

    js 复制代码
    module.exports = {
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader", "postcss-loader"],
          },
        ]
      }
    }
  • 内联方式(Inline)
    可以在 import 语句或任何与 import 方法同等的引用方式中指定 loader。
    使用 ! 将资源中的 loader 分开。

    js 复制代码
    import Styles from 'style-loader!css-loader?modules!./styles.css';

常用的 Loader

babel-loader

转换 ES6+ 新语法为 ES5。

js 复制代码
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: ['babel-loader'],
        include: srcPath,
        exclude: /node_modules/
      }
    ]
  }
}

style-loader

把 CSS 插入到 DOM 中。

推荐将 style-loadercss-loader 一起使用。

css-loader

@importurl() 进行处理,分析 CSS 模块之间的关系,并合并成一个 CSS。

js 复制代码
module.exports = {
  module: {
    rules: [
      {
        test: /.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
};

postcss-loader

  • CSS 预处理器 :可以使用像 Sass、Less 或 Stylus 这样的预处理器编写 CSS 代码,然后通过 postcss-loader 将其转换为标准的 CSS。
  • 自动添加前缀 :通过 Autoprefixer 等插件,postcss-loader 可以自动为 CSS 属性添加浏览器前缀,以确保在不同浏览器中具有一致的表现。
js 复制代码
module.exports = {
  module: {
    rules: [
      {
        test: /.css$/i,
        use: ['style-loader', 'css-loader', 'postcss-loader'],
      },
    ],
  },
};

手写一个 loader

  • loader 是一个函数,不能使用箭头函数,因为要用到上下文中的 this
  • 接收一个源文件参数
  • 返回处理后的文件结果
js 复制代码
// customLoader.js
// 转化文件大小写
module.exports = function (source) {
  const transform = source.replace(/[A-Z]/g, function (match) {
    return match.toLowerCase();
  });

  return transform;
};

使用:

js 复制代码
module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.js$/, // 匹配需要使用 loader 的文件
        use: path.resolve(__dirname, "./customBabel.js"),
      },
    ],
  },
};

测试文件:

js 复制代码
// index.js
const a = "A";
const B = "B";
console.log("a", a);
console.log("B", B);

打包后结果:

js 复制代码
// dist/bundle.js
console.log("a","a"),console.log("b","b");

Plugin

插件的目的是为了解决 Loader 无法实现的其他事。

Webpack 插件是一个具有 apply 方法的 js 对象。

用法: new xxxPlugin(参数)

常用的 plugin

CommonsChunkPlugin

提取 chunk 之间的公共模块用来共享,是一个 Webpack 的内置插件,不需要安装。

js 复制代码
new webpack.optimize.CommonsChunkPlugin({
  name: 'commons',
  filename: 'commons.js',
});

CleanWebpackPlugin

删除/清理构建目录。

shell 复制代码
$ yarn add clean-webpack-plugin -D
js 复制代码
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  plugins: [
    // 打包之前清除 dist 文件
    new CleanWebpackPlugin(['dist'], { root: process.cwd(), verbose: true })
  ]
}

HtmlWebpackPlugin

在打包结束后,自动生成一个 html 文件,并把打包生成的 js 模块引入到该 html 中。

shell 复制代码
$ npm install --save-dev html-webpack-plugin
js 复制代码
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  plugins: [
     new HtmlWebpackPlugin({
      template: path.join(__dirname, "../../src/template.html.ejs"),
      filename: "index.html",
      chunks: ["vendor", "runtime"],
      inject: "body",
    }),
  ]
};
html 复制代码
<!-- src/template.html.ejs -->
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>
    <%= htmlWebpackPlugin.options.title || '标题' %>
  </title>
</head>
<body></body>
</html>

EJS 是一套简单的模版语法,帮你利用普通的 JavaScript 代码生成 HTML 文件。

MiniCssExtractPlugin

提取 CSS 到一个单独的文件中。

shell 复制代码
$ npm install --save-dev mini-css-extract-plugin
js 复制代码
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
 ...,
  module: {
   rules: [
    {
       test: /\.s[ac]ss$/,
       use: [
         {
           loader: MiniCssExtractPlugin.loader
         },
         'css-loader',
         'sass-loader'
        ]
     }
   ]
 },
  plugins: [
    ...,
    new MiniCssExtractPlugin({
     filename: '[name].css'
    }),
    ...
  ]
}

DefinePlugin

允许在编译时创建配置的全局对象,是一个 webpack 内置的插件,不需要安装。

js 复制代码
module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': '"production"',
      PRODUCTION: true
    })
  ]
}

CopyWebpackPlugin

复制文件或目录到执行区域。

shell 复制代码
$ yarn add copy-webpack-plugin -D
js 复制代码
const pathUtil = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const appRoot = pathUtil.join(__dirname, '../..');
module.exports = {
  plugins: [
    new CopyWebpackPlugin([
      {
        from: './static',  // 设置从哪一个源开始复制
        to: pathUtil.join(appRoot, 'priv/static'),  // 复制到的位置,可以省略,默认复制到打包的目录中
        globOptions: {}  // 设置一些额外的选项,其中可以编写需要忽略的文件
      }
    ])
  ]
}

__dirname :返回当前模块文件解析后,所在的文件夹(目录)的绝对路径。
__filename:返回当前模块文件被解析后的绝对路径。

手写一个 Plugin

  • plugin 是一个构造函数,能够通过 new 来实例化对象;
  • PluginName 可以写成普通函数,apply 方法必须挂载到原型对象(PluginName.prototype)上;
  • 有一个 apply 方法,作为插件的入口点,Webpack 会调用此方法并传入 compiler对象参数。
js 复制代码
// customPlugin.js
// 该定义插件会在打包完成后会输出每个模块的打包时间
class CustomPlugin {
  // 构造函数接收一个 options 参数,用来配置插件的行为
  constructor(options) {}
  // apply 方法是插件的入口点,webpack 会调用此方法并传入 compiler 对象
  apply(compiler) {
    // 注册一个钩子函数,监听 webpack 打包完成的事件
    compiler.hooks.compilation.tap("CustomPlugin", (compilation) => {
      compilation.hooks.buildModule.tap("CustomPlugin", (module) => {
        module.startTime = Date.now();
      });
    });
    compiler.hooks.thisCompilation.tap("CustomPlugin", (compilation) => {
      compilation.hooks.finishModules.tap("CustomPlugin", (modules) => {
        modules.forEach((module) => {
          if (module.resource) {
            const buildTime = module.startTime ? Date.now() - module.startTime : "N/A";
            console.log(`${module.resource} - Build Time: ${buildTime}ms`);
          }
        });
      });
    });
  }
}

module.exports = CustomPlugin;

执行结果:

loader 🆚 plugin

功能不同

  • Loader:加载器,Webpack 将一切文件视为模块,但 Webpack 原生只能解析 JS 文件,所以 Loader 的作用是让 Webpack 拥有了加载和解析非 JS 文件的能力。
  • Plugin:插件,Plugin 是用于拓展 Webpack 的功能,在 Webpack 构建过程中执行一些额外的任务,如优化资源、打包输出结果、注入环境变量等。

用法不同

  • Loader :在 module.rules 中配置,类型是数组,每一项都是 Object,里面描述了对于什么类型的文件(test),使用什么加载(use),使用的参数(options)等。
  • Plugin :在 plugins 中单独配置,类型是数组,每一项为一个 pluin 的实例,参数通过构造函数传入。

运行时机不同

  • Loader:打包之前。
  • Plugin:整个构建过程都起作用。

参考:官方文档 Loaders
参考:官方文档 Plugins

欢迎纠错~

相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax