Skip to main content

Loaders

webpack 开箱即用只支持 JSJSON 两种文件类型,通过 Loaders 去支持其它文件类型并且把它们转化成有效的模块,并且可以添加到依赖图中。本身是一个函数,接受源文件作为参数,返回转换的结果。

常用的 loaders

名称描述
babel-loader转换ES6以上新版本的JS代码
css-loader支持.css文件的加载和解析
less-loader.less文件转换成.css
postcss-loader为 CSS 属性补齐前缀
file-loader进行图片、字体等打包
url-loader将体积小于设定值的图片、字体等转化为 base64
ts-loader.ts转换成.js
thread-loader多进程打包jscss

Loaders 的用法

module.exports = {
output: {
filename: 'bundle.js'
},
module: {
rules: [
{test: /\.txt$/, use: 'raw-loader'} // test指的是匹配规则,use指定使用loader的名称。
]
}
};

其中use 字段有以下三种写法:

  • 可以是一个字符串,例如上例中的 use: 'raw-loader''。
  • use 字段可以是一个数组,例如打包.css文件use: ['style-loader', 'css-loader']
  • use 数组的每一项既可以是字符串也可以是对象,当我们需要在webpack 的配置文件中对 loader 进行配置,就需要将其编写为一个对象,并且在此对象的 options 字段中进行配置,如:
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash:8].[ext]'
}
}
];
tip

useloader 的调用顺序从右向左。

概要

webpack 默认只支持打包 JSJSON 两种文件类型,为了支持其它文件类型的打包,需要使用对应的LoadersLoaders本身是一个函数,接受源文件作为参数,返回转换的结果。常用的Loaders如下所示:

名称描述
babel-loader转换ES6以上新版本的JS代码
css-loader支持.css文件的加载和解析
less-loader.less文件转换成.css
postcss-loader为 CSS 属性补齐前缀
file-loader进行图片、字体等打包
url-loader将体积小于设定值的图片、字体等转化为 base64
ts-loader.ts转换成.js
thread-loader多进程打包jscss

下面我们将分别讲述这些Loaders

babel-loader

babel-loader 的作用主要是配合babel解析和打包 ES6 语法文件。在配置 babel-loader 前我们需要安装和配置babel

  • 安装babelbabel-loader
npm install -D @babel/core @babel/preset-env babel-loader

@babel/core:该模块中包含了babel的核心功能,是使用babel必装的模块。

@babel/preset-env:该模块包含了一组可以将ES6语法转换为ES5语法的插件,并能够根据browserslist配置的目标环境加载不同的插件来编译ES6语法。

关于babel的更多内容推荐学习这篇博客--《不容错过的 Babel7 知识》

  • .babelrc 文件的配置如下:
{
"presets": [
"@babel/preset-env"
]
}
  • webpak.config.js 配置
webpak.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
}
]
}
};

为了更好的理解babel-loader,可以下载我所编写的小demo执行一下。demo 打包的结果如下所示:

通过打包结果可以看出,ES6 语法的babel.js可以通过babel转换成 ES5 语法,同时代码还会被自动压缩在一起。

css-loader

css-loader用于加载解析.css文件。

css-loader经常一起使用的还有style-loaderless-loaderpostcss-loader,其中style-loader可以将样式通过<style>标签插入到<head>标签中,less-loader用来转换lesscsspostcss-loader结合autoprefixer插件可以为 CSS3 属性自动补齐前缀。

使用style-loader后样式会插入到html文件中:

  • loader安装:
npm install -D css-loader style-loader less-loader postcss-loader
  • 使用css-loader时,webpak.config.js 配置:
webpak.config.js
const path = require('path');

module.exports = {
entry: {
split: './src/search/index'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name]_bundle.js',
chunkFilename: '[name].chunk.js'
},
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [autoprefixer({})]
}
}
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [autoprefixer({})]
}
}
]
}
]
}
};

如果项目中还存在less文件,还可以在css-loader后面加上less-loader;

caution

需要注意的是,因为 webpack 中 loader 的解析采用了函数式编程中的compose,所以 loader 的加载顺序是从右向左。当 loader 的位置放反时,构建会报错。

通过上例可以看出,先postcss-loader为匹配的.less文件中的 CSS3 属性添加前缀,再用less-loader将 Less 代码编译为 CSS 代码,然后再使用 css-loader 加载和解析 CSS 代码,最后将其交给 style-loader 插入到网页中去。

为了更好的理解与样式相关的loader,可以下载我所编写的小demo执行一下。demo 打包后的结果如下图所示:

通过打包结果可以看出,使用了style-loader后,demo 中的.less.css文件都会被打包到.js文件中,并通过 DOM 操作将它们插入到.html<head>标签中。

tip

我们知道CSS样式分为内联、外联和行内样式,使用style-loader打包后样式文件将会内联到html文件中,如果想要样式文件外联,可以使用插件mini-css-extract-plugin

file-loader

file-loader可以帮助webpack打包和解析图片、字体等文件。

  • loader安装
npm install -D file-loader
  • webpack.config.json配置
webpak.config.js
const path = require('path');

module.exports = {
entry: {
index: './src/index.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name]_[chunkhash:8].js'
},
mode: 'production',
module: {
rules: [
{
test: /.(png|jpe?g|gif|svg)$/i, // 匹配常用图片文件类型
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash:8].[ext]' // 打包后文件名,‘hash:8’为添加8位哈希值,ext代表文件扩展名
}
}
]
},
{
test: /.(woff|woff2|eot|ttf|otf|svg)$/, // svg代表svg fonts
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash:8].[ext]'
}
}
]
}
]
}
};

为了更好的理解file-loader,可以下载我所编写的小demo执行一下。该 demo 的打包结果如下图所示:

在该 demo 中,我们在src/images目录下创建了logo.png文件,在src/font文件下导入了字体库LiuJianMaoCao-Regular。需要注意的是在样式文件中使用外部字体库时,需要用@font-face对其进行配置:

@font-face {
font-family: 'LiuJianMaoCao-Regular';
src: url('./font/LiuJianMaoCao-Regular.ttf') format('truetype');
}

.search-text {
font-size: 20px;
color: #f00;
font-family: 'LiuJianMaoCao-Regular';
}

url-loader

url-loader 功能类似于 file-loader,但是在文件大小低于指定的限制时会将资源自动转为base64

  • 安装url-loader
npm install -D url-loader file-loader
  • webpack.config.js配置
webpak.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
entry: {
index: './src/index.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name]_[chunkhash:8].js'
},
mode: 'production',
module: {
rules: [
{
test: /.(png|jpe?g|gif|svg)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 10240
}
}
]
},
{
test: /.(woff|woff2|eot|ttf|otf|svg)$/,
use: [
{
loader: 'url-loader',
options: {
name: '[name]_[hash:8].[ext]',
limit: 10240
}
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, `src/index.html`),
filename: 'index.html',
chunks: ['index']
})
]
};

为了更好的理解url-loader,可以下载我所编写的小demo执行一下。

在该 demo 中,src/images目录下创建的图片logo.png的体积小于10kb,在src/font文件下导入的字体库LiuJianMaoCao-Regular的体积大于10kb

执行 demo 的打包过程如下图所示:

通过打包过程可以看出,图片文件没有以boundle的形式输出,查看打包后的js文件,可以看到图片被转成了base64,如下图所示:

url-loader内部的实现也使用了file-loader。在 demo 中由于字体库LiuJianMaoCao-Regular的体积有4.7mb,远远超过了设置 limit 的值,所以打包的时候会使用file-loader将文件以boundle的形式输出。

caution

安装url-loader时也必须同时安装file-loader模块,但不需要在webpack.config.js添加file-loader。否则当文件超过设定的limit的值时,会提示'Cannot find module 'file-loader'

我们使用npm uninstall file-loader卸载file-loader模块,然后重新打包后的结果如下所示:

ts-loader

当项目中使用ts开发时,webpack 打包时需要使用ts-loader

  • 安装 TypeScript 编译器和ts-loader
npm install -D typescript ts-loader
  • webpack.config.js配置
webpak.config.js
const path = require('path');

module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/ // 减少被处理的文件
}
]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};

为了更好的理解ts-loader,可以下载我编写的小demo执行一下。打包后的结果如下图所示

thread-loader

因为基于 Node.jswebpack 是单线程模型,所以 webpack 处理任务时只能一件一件的做。当项目中存在大量文件时,打包时间就会比较漫长。使用thread-loader可以让 webpack 在同一时刻处理多个任务发挥多核 CPU 电脑的功能,提升构建速度。

thread-loader使用起来很简单,只需要将其放置到其它的loader之前,放置其后的 loader 就会在一个单独 worker pool 中运行。对于一个前端项目来说,项目中最多的文件一般为JSCSS文件,所以thread-loader经常被用在babel-loadercss-loader前。

  • thread-loader的安装
npm install -D thread-loader
  • webpack.config.js 配置
webpack.config.js
module: {
rules: [
{
test: /\.js$/,
use: ['thread-loader', 'babel-loader']
}
];
}
caution

当项目较小时,使用thread-loader打包可能会对打包速度没有影响,甚至导致打包速度变慢,这是因为它本身的额外开销导致,建议只在极高性能消耗的场景下使用。

Used in TypeScript:

webpack.config.dev.js
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'thread-loader'
},
{
loader: 'ts-loader',
options: {
transpileOnly: true,
happyPackMode: true // IMPORTANT! use happyPackMode mode to speed-up compilation and reduce errors reported to webpack
}
}
]
}
];
}
webpack.config.prod.js
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: 'thread-loader',
options: {
// there should be 1 cpu for the fork-ts-checker-webpack-plugin
workers: require('os').cpus().length - 1
}
},
{
loader: 'ts-loader',
options: {
happyPackMode: true // IMPORTANT! use happyPackMode mode to speed-up compilation and reduce errors reported to webpack
}
}
]
}
]
},
plugins: [
new ForkTsCheckerWebpackPlugin({
typescript: {
diagnosticOptions: {
semantic: true,
syntactic: true
}
}
})
]

参考资料