开始
把博客升级到webpack4的时候CSS打包部分各种报错,总结了一下webpack4打包CSS的部分。
项目中涉及到的模块如下:
名称
作用
文档
css-loader
处理import或require的CSS文件
style-loader
把CSS用
less-loader
Less转化成CSS
vue-style-loader
style-loader的封装,把css用
extract-text-webpack-plugin
抽离单独文件,暂时不支持webpack4
mini-css-extract-plugin
抽取css成单独文件,支持webpack4
optimize-css-assets-webpack-plugin
CSS压缩
postcss-loader
使用PostCSS的loader
loader概念
loader是一个node模块,exports出来的是一个函数。
module.exports = function(source) {
// source 为一个文件的原内容字符串(或者二进制数据)
// do something
return xxx;
};
复制代码
加载CSS
css-loader
先看文档介绍:
The css-loader interprets @import and url() like import/require() and will resolve them.
css-loader是一个处理import或require的css文件的loader,配合 \.css$规则。
option 配置地址
style-loader
Adds CSS to the DOM by injecting a
把css用
option 配置地址
demo
demo1地址
main.js // 入口文件
import './main.css';
const p = document.createElement('p');
p.innerHTML = 'this is a p tag';
document.body.append(p);
console.log('this is a test');
复制代码
main.css
p {
color: red;
}
.testPrefix {
display: flex;
transform: all 1s;
}
复制代码
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './main.js',
output: {
filename: 'output.js',
},
module: {
rules: [
{
test: /\.css$/,
loader: [
'style-loader',
'css-loader', // 会先执行css-loader
],
}
]
},
plugins: [
new HtmlWebpackPlugin(),
],
};
复制代码
前面说到loader是输入字符串,然后输出的函数,注意loader数组的执行顺序是反的。
执行webpack-dev-server --open,可以看到效果如下:
把style-loader去掉:
loader: [
// 'style-loader' 注释掉style-loader
'css-loader',
],
复制代码
可以看到没有style-loader,样式不会添加到Dom。
预处理转化
以less为例,其他类似。
less-loader
Compiles Less to CSS.
demo
把less转化成css。
demo2地址
loader: [
'style-loader',
'css-loader',
'less-loader',
],
复制代码
抽离CSS
如果你的样式文件大小较大,这会做更快提前加载,因为 CSS bundle 会跟 JS bundle 并行加载。
css不会阻塞HTML解析,会阻塞DOM渲染。加载css的时候会继续解析HTML,遇到JS会加载,所以是多个请求并行加载。
extract-text-webpack-plugin
Extract text from a bundle, or bundles, into a separate file.
抽离内容成单独文件的一个loader。
报错
webpack4 使用会遇到报错:
Use Chunks.groupsIterable and filter by instanceof Entrypoint instead。
需要使用beta版或者用mini-css-extract-plugin代替。
npm i extract-text-webpack-plugin@next -D
demo
demo3地址
webpack.config.js配置如下:
...
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
'less-loader',
],
}),
复制代码
css被抽离成单独的文件了。
mini-css-extract-plugin
This plugin extracts CSS into separate files.
和extract-text-webpack-plugin类似。
Compared to the extract-text-webpack-plugin:
Async loading
No duplicate compilation (performance)
Easier to use
Specific to CSS
与extract-text-webpack-plugin对比: 异步,无重复,易于使用,针对css
用法
...
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
],
}
]
},
plugins: [
new HtmlWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
...
复制代码
PostCSS
postcss-loader
Loader for webpack to process CSS with PostCSS
使用PostCSS的loader。
PostCSS文档
PostCSS也是把CSS解析成AST,然后通过插件来输出想要的结果。
用法
demo4地址
这里用了两个PostCSS插件autoprefixer和cssnano。
作用分别是添加兼容prefix和压缩CSS
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
mode: 'development',
entry: './entry.js',
output: {
filename: 'main.js',
},
module: {
rules: [
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: [
require('autoprefixer'),
require('cssnano'),
],
},
},
'less-loader',
],
}
]
},
plugins: [
new HtmlWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
};
复制代码
打包出来的CSS文件:
main.css
p{color:red}.testPrefix{display:flex;-webkit-transform:all 1s;transform:all 1s}
复制代码
可以看到添加了webkit前缀和压缩效果。
Vue Cli中CSS打包
使用vue inspect > output.js输出Vue-cli中webpack默认配置:
文档
以less的规则为例子
test: /\.less$/,
...
{
resourceQuery: /\?vue/,
use: [
/* config.module.rule('less').oneOf('vue').use('vue-style-loader') */
{
loader: 'vue-style-loader',
options: {
sourceMap: false,
shadowMode: false
}
},
/* config.module.rule('less').oneOf('vue').use('css-loader') */
{
loader: 'css-loader',
options: {
sourceMap: false,
importLoaders: 2
}
},
/* config.module.rule('less').oneOf('vue').use('postcss-loader') */
{
loader: 'postcss-loader',
options: {
sourceMap: false
}
},
/* config.module.rule('less').oneOf('vue').use('less-loader') */
{
loader: 'less-loader',
options: {
sourceMap: false
}
}
]
},
复制代码
loader顺序为:
less-loader
postcss-loader // 默认开启autoprefixer插件
css-loader
vue-style-loader
没有抽离CSS。
参考链接