Webpack打包CSS

開始

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

loader是一個node模塊,exports出來的是一個函數。vue

module.exports = function(source) {
  // source 爲一個文件的原內容字符串(或者二進制數據)
  // do something
  return xxx;
};
複製代碼

加載CSS

css-loader

先看文檔介紹: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

style-loader

Adds CSS to the DOM by injecting a <style> tag.github

把css用<style>標籤添加到Dom裏面去。
option 配置地址web

demo

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,能夠看到效果以下:

demo1-1

把style-loader去掉:

loader: [
        // 'style-loader' 註釋掉style-loader
        'css-loader',
    ],
複製代碼

demo1-2
能夠看到沒有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',
    ],
}),
複製代碼

demo3
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插件autoprefixercssnano
做用分別是添加兼容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。

參考連接

segmentfault.com/a/119000001…
www.webpackjs.com/concepts/

相關文章
相關標籤/搜索