通常来说,打包样式文件分为以下几步:
- 安装对应的
Loader
加载器,目的是打包样式文件; - 添加样式前缀,目的是提高浏览器兼容性;
- 将打包到
js
文件中的样式代码抽离出来,保存到单独的文件中; - 压缩抽离出来的样式文件,目的是提高应用的访问速度;
一步一步地来。
第一步:安装css-loader
和style-loader
。
webpack
默认只能识别js
文件,其他类型的文件一概不认识。但无论是正经的项目还是不正经的项目,都会由五花八门的文件组成,因此要想让webpack
能够识别js
类型之外各种各样的文件,就得使用webpack
各种各样的loader
(加载器)。
执行命令,安装css-loader
和style-loader
:
yarn add css-loader style-loader -D
在webpack.config.js
中进行配置:
module.exports = {
mode: 'development',
entry: './src/index.js', // 入口,从哪个文件开始打包
output: { // 出口
filename: 'bundle.js', // 打包后的文件名
},
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader', // 将 JS 字符串生成为 style 节点
'css-loader', // 将 CSS 转化成 CommonJS 模块
]
}]
}
};
写法上一定要注意:loader
的加载顺序是从右到左或从下到上,css-loader
和style-loader
的顺序千万别写反了,要先将样式代码打包进js文件,再生成style节点。
配置完成后,在index.js
中引入样式文件style.css
:
import './style.css';
document.querySelector('#txt').innerHTML = '学习打包样式文件';
style.css
的内容:
#txt {background-color: red;}
这样,用webpack
打包后,样式代码被打包进js
文件中,当页面加载时,样式代码就会被写入到<style>
标签中。效果如下:

如果要打包
scss
文件,需要安装node-sass
和sass-loader
yarn add node-sass sass-loader -D
在
webpack.config.js
中进行配置:module: { rules: [{ test: /\.scss$/, use: [ 'style-loader', // 将 JS 字符串生成为 style 节点 'css-loader', // 将 CSS 转化成 CommonJS 模块 'sass-loader' // 将 Sass 编译成 CSS ] }
第二步:安装postcss-loader
和autoprefixer
,为样式添加浏览器前缀。
我们修改一下style.css
的内容:
::placeholder {
color: red;
}
#txt {background-color: red;}
打包后的效果如下:

可以看到,样式没有浏览器前缀,兼容性不佳。
要解决这个问题,我们执行命令,安装postcss-loader
和autoprefixer
:
yarn add postcss-loader autoprefixer -D
在项目根目录创建postcss.config.js
文件,内容如下:
module.exports = {
plugins: [require('autoprefixer')]
};

之后,在webpack.config.js
中进行配置:
...
rules: [{
test: /\.css$/,
use: [
'style-loader', // 将 JS 字符串生成为 style 节点
'css-loader', // 将 CSS 转化成 CommonJS 模块
'postcss-loader'
]
}]
...
加载的顺序一定不要写错了,要先添加浏览器前缀,再生成css代码。
打包后,效果如下:

第三步:安装mini-css-extract-plugin
插件,抽离样式代码到一个单独的文件中。
截至目前,所有的样式代码都被打包到js
文件中,这样一是会导致js
文件较大,影响加载速度,二是js
文件是在页面末尾加载的,这就导致在样式代码被写到<style>
标签前,原本页面上本该有样式的节点却没有样式可用,影响用户体验。因此,我们必须把这些样式代码抽离出来。
首先,安装mini-css-extract-plugin
插件:
yarn add mini-css-extract-plugin -D
然后,在webpack.config.js
中进行配置:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js', // 入口,从哪个文件开始打包
output: { // 出口
filename: 'bundle.js', // 打包后的文件名
},
module: {
rules: [{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
// 'style-loader', // 将 JS 字符串生成为 style 节点
'css-loader', // 将 CSS 转化成 CommonJS 模块
'postcss-loader'
]
}]
},
plugins: [ // 数组,放着所有的webpack插件
new CleanWebpackPlugin(), // 每次打包前,清空打包目录
new MiniCssExtractPlugin({
filename: 'index.css', // 打包后生成的文件
}),
new HtmlWebpackPlugin({
template: './src/index.html', // 指定要打包的模板
filename: 'index.html', // 打包后生成的文件
})
]
};
这里要注意两点:第一点是plugins
的加载顺序跟loader
不同,它是不分先后的,谁写在前边,谁写在后边没有区别;第二点是用了mini-css-extract-plugin
插件,就别用style-loader
了。
打包后,可以看到样式代码打包到一个单独的文件中,并被页面模板在<head>
标签中引入了:

第四步:压缩打包的样式文件。
把样式打包成一个单独的文件后,我们可以看到其中的代码是一行一行的:

为提高性能,我们需要压缩样式文件,也就是说把代码压缩到一行。
首先安装optimize-css-assets-webpack-plugin
和terser-webpack-plugin
插件:
yarn add optimize-css-assets-webpack-plugin terser-webpack-plugin -D
这就得解释一下,optimize-css-assets-webpack-plugin
是压缩css
文件的,而terser-webpack-plugin
是压缩js
文件的,是不是有病?我要压缩css
文件,居然还要安装一个压缩js
文件的插件。
实际的情况是,如果用optimize-css-assets-webpack-plugin
压缩css
文件,那么最后打包生成的js
文件就不是压缩的,一样会影响性能。
这是webpack官网的说明:

然后,在webpack.config.js
中进行配置:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
mode: 'production',//'development',
entry: './src/index.js', // 入口,从哪个文件开始打包
output: { // 出口
filename: 'bundle.js', // 打包后的文件名
},
optimization: {
minimizer: [
new TerserPlugin({}), // 压缩js
new OptimizeCSSAssetsPlugin({}) // 压缩css
]
},
module: {
rules: [{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
// 'style-loader', // 将 JS 字符串生成为 style 节点
'css-loader', // 将 CSS 转化成 CommonJS 模块
'postcss-loader'
]
}]
},
plugins: [ // 数组,放着所有的webpack插件
new CleanWebpackPlugin(), // 每次打包前,清空打包目录
new MiniCssExtractPlugin({
filename: 'index.css', // 打包后生成的文件
}),
new HtmlWebpackPlugin({
template: './src/index.html', // 指定要打包的模板
filename: 'index.html', // 打包后生成的文件
minify: { // 压缩操作
}
})
]
};
提醒一下,要把mode
属性改为production
,否则最后打包生成的文件依然是没有压缩的。
最终效果:


网友评论