把博客升級到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。