把博客升级到webpack4的时候CSS打包部分各类报错,总结了一下webpack4打包CSS的部分。css
项目中涉及到的模块以下:html
名称 | 做用 | 文档 |
---|---|---|
css-loader | 处理import或require的CSS 文件 |
文档 |
style-loader | 把CSS用<style> 标签处理 |
文档 |
less-loader | Less转化成CSS | 文档 |
vue-style-loader | style-loader 的封装,把css用<style> 标签注入Html ,支持SSR |
文档 |
extract-text-webpack-plugin | 抽离单独文件,暂时不支持webpack4 | 文档 |
mini-css-extract-plugin | 抽取css成单独文件,支持webpack4 | 文档 |
optimize-css-assets-webpack-plugin | CSS压缩 | 文档 |
postcss-loader | 使用PostCSS的loader | 文档 |
loader是一个node模块,exports出来的是一个函数。vue
module.exports = function(source) {
// source 为一个文件的原内容字符串(或者二进制数据)
// do something
return xxx;
};
复制代码
先看文档介绍:node
The css-loader interprets @import and url() like import/require() and will resolve them.webpack
css-loader是一个处理import或require的css
文件的loader,配合 \.css$
规则。
option 配置地址git
Adds CSS to the DOM by injecting a
<style>
tag.github
把css用<style>
标签添加到Dom里面去。
option 配置地址web
demo1地址
main.js // 入口文件npm
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.csssegmentfault
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',
],
复制代码
以less为例,其余相似。
Compiles Less to CSS.
把less转化成css。
demo2地址
loader: [
'style-loader',
'css-loader',
'less-loader',
],
复制代码
若是你的样式文件大小较大,这会作更快提早加载,由于 CSS bundle 会跟 JS bundle 并行加载。
css不会阻塞HTML解析,会阻塞DOM渲染。加载css的时候会继续解析HTML,遇到JS会加载,因此是多个请求并行加载。
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
demo3地址
webpack.config.js配置以下:
...
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
'less-loader',
],
}),
复制代码
This plugin extracts CSS into separate files.
和extract-text-webpack-plugin
相似。
Compared to the extract-text-webpack-plugin:
与extract-text-webpack-plugin
对比: 异步,无重复,易于使用,针对css
...
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
],
}
]
},
plugins: [
new HtmlWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
...
复制代码
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 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。