Loaders
webpack
开箱即用只支持 JS
和 JSON
两种文件类型,通过 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 | 多进程打包js 和css |
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]'
}
}
];
use
中 loader
的调用顺序从右向左。
概要
webpack
默认只支持打包 JS
和 JSON
两种文件类型,为了支持其它文件类型的打包,需要使用对应的Loaders
。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 | 多进程打包js 和css |
下面我们将分别讲述这些Loaders
。
babel-loader
babel-loader 的作用主要是配合babel
解析和打包 ES6 语法文件。在配置 babel-loader 前我们需要安装和配置babel
。
- 安装
babel
和babel-loader
- npm
- Yarn
- pnpm
npm install -D @babel/core @babel/preset-env babel-loader
yarn add --dev @babel/core @babel/preset-env babel-loader
pnpm add -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 配置
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-loader
、less-loader
和postcss-loader
,其中style-loader
可以将样式通过<style>
标签插入到<head>
标签中,less-loader
用来转换less
为css
,postcss-loader
结合autoprefixer
插件可以为 CSS3 属性自动补齐前缀。
使用style-loader
后样式会插入到html
文件中:
loader
安装:
- npm
- Yarn
- pnpm
npm install -D css-loader style-loader less-loader postcss-loader
yarn add --dev css-loader style-loader less-loader postcss-loader
pnpm add -D css-loader style-loader less-loader postcss-loader
- 使用
css-loader
时,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
;
需要注意的是,因为 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>
标签中。
我们知道CSS
样式分为内联、外联和行内样式,使用style-loader
打包后样式文件将会内联到html
文件中,如果想要样式文件外联,可以使用插件mini-css-extract-plugin
file-loader
file-loader
可以帮助webpack
打包和解析图片、字体等文件。
loader
安装
- npm
- Yarn
- pnpm
npm install -D file-loader
yarn add --dev file-loader
pnpm add -D file-loader
webpack.config.json
配置
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
- Yarn
- pnpm
npm install -D url-loader file-loader
yarn add --dev url-loader file-loader
pnpm add -D url-loader file-loader
webpack.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
的形式输出。
安装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
- Yarn
- pnpm
npm install -D typescript ts-loader
yarn add --dev typescript ts-loader
pnpm add -D typescript ts-loader
webpack.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.js
的 webpack
是单线程模型,所以 webpack
处理任务时只能一件一件的做。当项目中存在大量文件时,打包时间就会比较漫长。使用thread-loader
可以让 webpack
在同一时刻处理多个任务发挥多核 CPU 电脑的功能,提升构建速度。
thread-loader
使用起来很简单,只需要将其放置到其它的loader
之前,放置其后的 loader
就会在一个单独 worker pool 中运行。对于一个前端项目来说,项目中最多的文件一般为JS
和CSS
文件,所以thread-loader
经常被用在babel-loader
和css-loader
前。
thread-loader
的安装
- npm
- Yarn
- pnpm
npm install -D thread-loader
yarn add --dev thread-loader
pnpm add -D thread-loader
- webpack.config.js 配置
module: {
rules: [
{
test: /\.js$/,
use: ['thread-loader', 'babel-loader']
}
];
}
当项目较小时,使用thread-loader
打包可能会对打包速度没有影响,甚至导致打包速度变慢,这是因为它本身的额外开销导致,建议只在极高性能消耗的场景下使用。
Used in TypeScript:
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
}
}
]
}
];
}
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
}
}
})
]