浅谈Webpack的loader和plugin

关于 loader

loader 用于对模块的源代码进行转换。loader 可以让我们在 import 或“加载”模块时预处理文件。因此,loader 类似于 gulp 中的“任务”(task)。loader 可以将文件从不同的语言(TS或者ES6)转换为 JS,或者将内联图像转换为data URL。loader甚至允许你直接在JS模块中 import CSS文件! ——引自webpack.docschina.org

loader 的使用方式

  1. 配置(推荐):在 webpack.config.js 文件中指定 loader。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
webpack.config.js

module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
};
module.rules 允许你在 webpack 配置中指定多个 loader。建议在这里指明 loader,简洁明了,并且可以全局概览。减少源码中的代码量,并且可以在出错的时候,更快的调试和定位 loader 中的问题。
  1. 内联:在每个 import 语句中显式指定 loader。
1
import Styles from 'style-loader!css-loader?modules!./styles.css';
可以在 import 语句或者任何等效于“import”的方式中指定loader。使用 ! 将资源中的 loader分开。分开的每个部分都相对于当前目录解析。
  1. CLI:在 shell 命令中指定它们。

loader 特性

1. loader 支持链式传递。loader 链中的每个 loader 对前一个 loader 处理后的资源进行转换。当前 loader 的处理结果会传递给下一个 loader ,依次执行下去。在链中的最后一个 loader 返回webpack 所预期的 JS。

2. loader 运行在 Node.js 中,并且能够执行任何操作。

3. loader 可同步可异步。

4. loader 能够产生额外的任意文件。

loader 通过预处理函数,为JS生态系统提供了更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如压缩、打包、语言翻译和其他更多。

解析 loader

loader 遵循标准的模块解析。多数情况下,loader 将从模块路径(通常将模块路径认为是 npm install,node_modules)解析。

loader 是导出为一个函数的 node 模块。该函数在 loader 转换资源的时候调用。给定的函数将调用 loader API,并通过 this 上下文访问。

关于 plugin

plugin 是 webpack 的支柱功能。webpack 自身也是构建于在 webpack 配置中用到的相同的插件系统之上的!plugin 的目的在于解决 loader 无法实现的其他功能。

剖析 plugin

webpack 插件是一个具有 apply 方法的 JS 对象。apply 属性会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。

plugin 用法

由于 plugin 可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例,根据 webpack 的用法,可以有很多种方式使用插件。

  1. 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); //通过 npm 安装
const webpack = require('webpack'); //访问内置的插件
const path = require('path');

module.exports = {
entry: './path/to/my/entry/file.js',
output: {
filename: 'my-first-webpack.bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: 'babel-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
  1. Node API
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const webpack = require('webpack'); //访问 webpack 运行时(runtime)
    const configuration = require('./webpack.config.js');

    let compiler = webpack(configuration);
    compiler.apply(new webpack.ProgressPlugin());

    compiler.run(function(err, stats) {
    // ...
    });