目录
1. 处理资源 - loader
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
在更高层面,在 webpack 的配置中,loader 有两个属性:
test
属性,识别出哪些文件会被转换。use
属性,定义出在进行转换时,应该使用哪个 loader。
webpack.config.js
const path = require('path');
module.exports = {
output: {
filename: 'my-first-webpack.bundle.js',
},
module: {
rules: [{
test: /\.txt$/, use: 'raw-loader' }],
},
};
以上配置中,对一个单独的 module 对象定义了 rules
属性,里面包含两个必须属性:test
和 use
。这告诉 webpack 编译器(compiler) 如下信息:
“嘿,webpack 编译器,当你碰到「在
require()
/import
语句中被解析为 ‘.txt’ 的路径」时,在你对它打包之前,先 use(使用)raw-loader
转换一下。”
1.1 加载css - css-loader
css-loader
会对 @import
和 url()
进行处理,就像 js 解析 import/require()
一样。
npm install --save-dev css-loader style-loader
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
注意这里的style-loader
、css-loader
顺序不要写错,loader是从右向左加载的,并且为链式调用。后执行的loader会以前面loader生成的结果进行处理资源
在assets
目录中新建css/style-1.css
在src/index.js
中引用assets/css/style-1.css
import './assets/css/style-1.css'
const text = document.createElement('p')
text.style.cssText = 'width: 200px;height: 200px;background-color: pink;'
text.innerText = helloWebpack
text.classList.add('hello')
document.body.appendChild(text)
执行npx webpack-dev-server
可以看到样式已经生效
1.2 处理less - less-loader
npm install less less-loader --save-dev
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(css|less)$/i,
use: [
// compiles Less to CSS
'style-loader',
'css-loader',
'less-loader',
],
},
],
},
};
在assets/css
新建style-2.less
@color: #a9a9e7;
body {
background-color: @color;
}
在src/index.js
引用style.less
import './assets/css/style-2.less'
执行npx webpcak-dev-sercer
,打开index.html 可以看到body的样式已经变化了
2. 加载css
2.1 抽离css
仅仅使用style-loader
css只会内嵌在打包出的js文件中,最终以style
标签作用在页面中。但这样的缺点是会使js文件变大、无法按需加载。
本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。
本插件基于webpack 5的新特性构建,并且需要 webpack 5 才能正常工作。
与 extract-text-webpack-plugin
相比:
- 异步加载
- 没有重复的编译(性能)
- 更容易使用
- 特别针对 CSS 开发
npm install --save-dev mini-css-extract-plugin
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// ...
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"], // MiniCssExtractPlugin.loader 替换 style-loader
},
// 或者
{
test: /\.(css|less)/i,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
],
},
};
执行命令webpack
,可以看到dist
中生成了一个main.css
执行命令npx webpack-dev-server
可以看到样式依旧加载正常
自定义分类的css文件名
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
// ...
plugins: [new MiniCssExtractPlugin({
filename: 'styles/[contenthash].css' // [contenthash]启动长期缓存,将根据资源内容创建出唯一 hash
})],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"], // MiniCssExtractPlugin.loader 替换 style-loader
}
],
},
};
执行webpack
命令可以看到dist/styles
中生成新的css文件
执行npx webpcak-dev-server
打开index.html可看到页面样式正常显示
2.2 压缩css
npm install css-minimizer-webpack-plugin --save-dev
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
+ const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
+ optimization: {
+ minimizer: [
+ new CssMinimizerPlugin(),
+ ],
+ },
plugins: [new MiniCssExtractPlugin()],
};
这将仅在mode: production
生产环境
开启 CSS 优化
如果还想在开发环境
下启用 CSS 优化,optimization.minimize
设置为 true
:
webpack.config.js
// [...]
module.exports = {
optimization: {
// [...]
minimize: true,
},
};
运行命令 webpack
可以看到代码已压缩优化
3. 压缩 js
在上面,我们通过 optimization.minimizer
配置插件实现了css代码压缩,那js该怎么压缩呢?
webpack 有开箱即用的 terser
插件实现 js 代码压缩,可以在 mode: 'production'
生产环境实现 js 代码压缩
因为 optimization.minimizer
我们已经自定义配置了 css 压缩,因此我们需要单独配置一下 terser
npm i terser-webpack-plugin -D
webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
+ const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
module: {
rules: [
{
test: /.s?css$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
},
],
},
optimization: {
minimizer: [
new CssMinimizerPlugin(),
new TerserPlugin()
],
},
plugins: [new MiniCssExtractPlugin()],
};
执行 webpack
,可以看到
压缩前:
压缩后:
4. 加载images图像
前面webpack基础篇(二):资源模块asset module我们已经学习了weback内置的模块asste modules
资源模块,成功处理了如png|svg|jpe?g
等图片资源,那它能处理css种的图片资源吗
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
+ {
+ test: /\.(png|svg|jpg|jpeg|gif)$/i,
+ type: 'asset/resource',
+ },
],
},
};
在src/assets/css/style-1.css
加入
.text-bg {
background-image: url("../empty.svg") !important;
}
在src/index.js
中修改之前的 text 元素
const text = document.createElement('p')
text.style.cssText = 'width: 200px;height: 200px;background-color: pink;'
text.innerText = helloWebpack
text.classList.add('hello')
// 添加样式
text.classList.add('text-bg')
document.body.appendChild(text)
执行webpack
看到背景图片已经被打包到css中了
执行npx webpack-dev-server
可以看到背景图片已经成功加载
因为我们前面已经配置过asset module
资源模块,所以css中的图片资源能够正常加载。这说明asset module
也能处理css中的图片资源。
5. 加载 fonts 字体
那么,像字体这样的其他资源如何处理呢?使用 Asset Modules 可以接收并加载任何文件,然后将其输出到构建目录。这就是说,我们可以将它们用于任何类型的文件,也包括字体。让我们更新 webpack.config.js
来处理字体文件:
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
+ {
+ test: /\.(woff|woff2|eot|ttf|otf)$/i,
+ type: 'asset/resource',
+ },
],
},
};
在项目中添加一些字体文件:这里我引用了iconfont在线资源
在src/assets/css
中新建fonts.css
/*fonts.css*/
@font-face {
font-family: "webpack-iconfont"; /* Project id 2975967 */
src: url('//at.alicdn.com/t/font_2975967_payhpcjfltf.woff2?t=1638248030621') format('woff2'),
url('//at.alicdn.com/t/font_2975967_payhpcjfltf.woff?t=1638248030621') format('woff'),
url('//at.alicdn.com/t/font_2975967_payhpcjfltf.ttf?t=1638248030621') format('truetype');
}
.webpack-iconfont {
font-family: "webpack-iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.webpack-icon-webpack:before {
content: "\e799";
}
在src/index.js
引入fonts.css
import './assets/css/fonts.css'
在index.html
中使用字体
<i class="webpack-iconfont webpack-icon-webpack"></i>
执行webpack
命令,可以看到
图片资源已经被打包进css中
执行npx webpcak-dev-server
打开index.html可以看到,字体图标已经加载显示了
6. 加载数据
此外,可以加载的有用资源还有数据,如 JSON 文件,CSV、TSV 和 XML。类似于 NodeJS,JSON 支持实际上是内置的,也就是说 import Data from './data.json'
默认将正常运行。要导入 CSV、TSV 和 XML,你可以使用 csv-loader 和 xml-loader。让我们处理加载这三类文件:
npm install --save-dev csv-loader xml-loader
webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
// ...
+ {
+ test: /\.(csv|tsv)$/i,
+ use: ['csv-loader'],
+ },
+ {
+ test: /\.xml$/i,
+ use: ['xml-loader'],
+ },
],
},
};
在项目中添加一些数据文件:
src/assets/data.xml
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Mary</to>
<from>John</from>
<heading>Reminder</heading>
<body>Call Cindy on Tuesday</body>
</note>
src/assets/data.csv
to,from,heading,body
Mary,John,Reminder,Call Cindy on Tuesday
Zoe,Bill,Reminder,Buy orange juice
Autumn,Lindsey,Letter,I miss you
现在,你可以 import
这四种类型的数据(JSON, CSV, TSV, XML)中的任何一种,所导入的 Data
变量,将包含可直接使用的已解析 JSON:
src/index.js
import dataXml from './assets/data.xml'
import dataCsv from './assets/data.csv'
console.log('dataXml', dataXml);
console.log('dataCsv', dataCsv);
执行npm webpack-dev-server
命令,打开index.html打开工作台可以看到,两个数据已经被成功加载
6.1 自定义 JSON 模块 parser
通过使用 自定义 parser 替代特定的 webpack loader,可以将任何 toml
、yaml
或 json5
文件作为 JSON 模块导入。
假设你在 src/assets
文件夹下有一个 data.toml
、一个 data.yaml
以及一个 data.json5
文件:
src/assets/data.toml
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z
src/assets/data.yaml
title: YAML Example
owner:
name: Tom Preston-Werner
organization: GitHub
bio: |-
GitHub Cofounder & CEO
Likes tater tots and beer.
dob: 1979-05-27T07:32:00.000Z
src/assets/data.json5
{
// comment
title: 'JSON5 Example',
owner: {
name: 'Tom Preston-Werner',
organization: 'GitHub',
bio: 'GitHub Cofounder & CEO\n\
Likes tater tots and beer.',
dob: '1979-05-27T07:32:00.000Z',
},
}
首先安装 toml
,yamljs
和 json5
的 packages:
npm install toml yamljs json5 --save-dev
webpack.config.js
const path = require('path');
+const toml = require('toml');
+const yaml = require('yamljs');
+const json5 = require('json5');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
{
test: /\.(csv|tsv)$/i,
use: ['csv-loader'],
},
{
test: /\.xml$/i,
use: ['xml-loader'],
},
+ {
+ test: /\.toml$/i,
+ type: 'json',
+ parser: {
+ parse: toml.parse,
+ },
+ },
+ {
+ test: /\.yaml$/i,
+ type: 'json',
+ parser: {
+ parse: yaml.parse,
+ },
+ },
+ {
+ test: /\.json5$/i,
+ type: 'json',
+ parser: {
+ parse: json5.parse,
+ },
+ },
],
},
};
src/index.js
import toml from './assets/data.toml';
import yaml from './assets/data.yaml';
import json5 from './assets/data.json5';
console.log('toml', toml);
console.log('yaml', yaml);
console.log('json5', json5);
执行npx webpack-dev-server
打开控制台可以看到数据已经加载成功
源码地址:https://gitee.com/yanhuakang/webpack-test
如果有用,就点个赞吧(*^▽^*)