【webpack系列】從零搭建 webpack4+react 腳手架(三)
1 支援css本章節,我們對如何在腳手架中引入CSS,如何壓縮CSS,如何使用CSS Modules,如何使用less,如何使用postcss等問題進行展開學習。
(1)在app目錄,新建一個css,命名為index.css,輸入樣式:
h1{ display: flex; height: 200px; align-items: center; justify-content: center; color: #8FBC8F; }
(2)在index.js中引入css
import './index.css'
(3)配置loader
在第一節,我們知道,webpack只能編譯js檔案,不能編譯css,它不認識css檔案,所以需要配置loader載入器來預處理。
首先安裝style-loader和css-loader:
npm install --save-dev style-loader css-loader
(4)配置module.rules:
在webpack.prod.conf.js中配置:
module: { rules: [ { test:/\.(css)$/, use: [ 'style-loader', 'css-loader', ] } ] },
loader的載入順序是從右邊到左邊,css-loader是載入通過import引入的css檔案,而style-loader的作用是把樣式插入到DOM中。
最後,執行npm run build試試看樣式是否生效。
npm run build
開啟頁面,發現樣式已經生效了。開啟控制檯檢視,你會發現css的確是通過style在頁面上方插入的。
2 匯出CSS檔案 如果我們希望把樣式匯出到css檔案,並且在頁面引用該css檔案,又要怎麼做呢?
這裡先提在webpack4版本以前一個外掛,叫extract-text-webpack-plugin,熟悉webpack3的同學,可能知道,這個外掛主要是為了抽離css樣式,防止將樣式打包在js中引起頁面樣式載入錯亂的現象。然而,在webpack4版本下,該外掛已經不再相容,官方提示我們去下載使用另外一個外掛,叫mini-css-extract-plugin。
(1)安裝mini-css-extract-plugin
npm install mini-css-extract-plugin --save-dev
(2)引入mini-css-extract-plugin
在webpack.prod.conf.js中引入
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
(3)修改配置loader
module: { rules: [ { test: /\.(css)$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', } ] } ] },
(4)配置plugin
//匯出css new MiniCssExtractPlugin({ filename: 'css/[name].[hash].css', chunkFilename: 'css/[id].[hash].css', }),
最後你的webpack.prod.conf.js看起來是這樣
const merge = require('webpack-merge'); const baseWebpackConfig = require('./webpack.base.conf'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); module.exports = merge(baseWebpackConfig, { mode: 'production', output: { filename: "js/[name].[chunkhash:16].js", }, module: { rules: [ { test: /\.(css)$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', } ] } ] }, plugins: [ new HtmlWebpackPlugin({ template: 'public/index.html', inject: 'body', minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true }, }), new CleanWebpackPlugin(['../dist'], { allowExternal: true }), //匯出css new MiniCssExtractPlugin({ filename: 'css/[name].[hash].css', chunkFilename: 'css/[id].[hash].css', }), ], optimization: { minimizer: [ new UglifyJSPlugin() ], splitChunks: { chunks: "all", minChunks: 1, cacheGroups: { framework: { priority: 200, test: "framework", name: "framework", enforce: true, reuseExistingChunk: true }, vendor: { priority: 10, test: /node_modules/, name: "vendor", enforce: true, reuseExistingChunk: true } } } } });
(5)編譯build命令
npm run build
檢視下dist目錄,你會看到css已經被編譯到css資料夾中,並且在html檔案中成功引入。
3 壓縮css 開啟編譯後的css檔案,你會發現css沒有壓縮處理。在webpack4版本中,只要定義了mode為production,那麼webpack是預設會呼叫UglifyJsPlugin對js檔案進行程式碼壓縮的,無需我們手動引入。但是css還是需要我們手動引入外掛。在webpack4版本中,使用optimize-css-assets-webpack-plugin這個外掛處理壓縮css檔案。
(1)安裝optimize-css-assets-webpack-plugin
npm install optimize-css-assets-webpack-plugin --save-dev
(2)引入optimize-css-assets-webpack-plugin
在webpack.prod.conf.js中引入optimize-css-assets-webpack-plugin :
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
(3)配置minimizer引數
minimizer引數是配置在optimization引數內,和splitChunks同級。
minimizer: [ new UglifyJSPlugin(), new OptimizeCSSAssetsPlugin({ cssProcessorOptions: true ? { map: { inline: false } } : {} }) ],
(4)編譯build命令
npm run build
再次檢視dist/css目錄下的css檔案,你會發現已經是壓縮後的了。
4 支援 css modules css modules是react官方提倡的一種css解決方案,把import後的物件賦值給一個變數。在jsx中直接使用這個變數下的class名稱來設定css。編譯後,會在css屬性加上唯一的hash編碼,防止css全域性汙染。它的好處和壞處這裡不再作更多的闡述。
(1)配置css-loader引數
配置loader,傳入的是陣列,它的子項,可以是字串,比如'css-loader',也可以是一個物件,支援其他引數的設定,設定loader為:
{ loader: 'css-loader', options: { modules: true, localIdentName: '[local]__[hash:7]' } }
modules引數,定義是否開啟css modules,預設是否。localIdentName定義生成class的名稱格式,這樣設定後,如果你定義了一個叫main的class,最後生成的是main__i72tywq這樣的格式。
(2)試試看
修改index.js
import React from "react"; import ReactDom from "react-dom"; import indexStyle from './index.css'; ReactDom.render( <h1 className={indexStyle.main}>hello, world!</h1>, document.getElementById("root") );
定義一個main的class
.main{ display: flex; height: 200px; align-items: center; justify-content: center; color: #8FBC8F; }
(3)編譯build命令
npm run build
在dist目錄開啟編譯後的index.css檔案,檢視css,發現 class名稱後都加了hash字尾,而且html中的引用也是加了字尾。
5 Less or Sass 作為一個前端,你肯定不滿足於現有的css方案,less或者sass是一個不錯的選擇。
如何讓它支援less,或者sass?webpack不認識less,需要配置loader。
(1)安裝less-loader
npm install less less-loader --save-dev
(2)配置loader
在webpack.prod.conf.js中的module.rules內增加一個物件:
{ test: /\.(less)$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { modules: true, localIdentName: '[local]__[hash:7]' } }, { loader: 'less-loader' } ] }
(3)編譯build命令
npm run build
在dist目錄開啟編譯後的index.css檔案,檢視css,less檔案成功被編譯。引入sass也是類似。這裡不再闡述。
6 使用postcss PostCSS是什麼?或許,你會認為它是前處理器、或者後處理器等等。其實,它什麼都不是。它可以理解為一種外掛系統。
你可以在使用前處理器的情況下使用它,也可以在原生的css中使用它。它都是支援的,並且它具備著一個龐大的生態系統,例如你可能常用的Autoprefixer,就是PostCSS的一個非常受歡迎的外掛。
(1)安裝postcss
npm install postcss postcss-loader --save-dev
(2)安裝postcss某個外掛,這裡我用Autoprefixer舉例
npm install autoprefixer --save-dev
(3)配置postcss.config.js
在根目錄新建postcss.config.js
module.exports = () => ({ plugins: { autoprefixer: { browsers: ['last 5 version', '>1%', 'ie >=8'] }, } });
(4)設定loader
修改webpack.prod.conf.js中的中的module.rules
module: { rules: [ { test: /\.(css)$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 1, modules: true, localIdentName: '[local]__[hash:7]' } }, { loader: 'postcss-loader' } ] }, { test: /\.(less)$/, use: [ MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 1, modules: true, localIdentName: '[local]__[hash:7]' } }, { loader: 'postcss-loader' }, { loader: 'less-loader' } ] } ] },
(4)編譯build命令
npm run build
看下編譯生成的css檔案,檢視程式碼,已經自動加了瀏覽器字首。
最後你可以把webpack.prod.conf.js內關於module rules的設定拷貝到webpack.dev.conf.js,修改第一個為style-loader
module: { rules: [ { test: /\.(css)$/, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1, modules: true, localIdentName: '[local]__[hash:7]' } }, { loader: 'postcss-loader' } ] }, { test: /\.(less)$/, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1, modules: true, localIdentName: '[local]__[hash:7]' } }, { loader: 'postcss-loader' }, { loader: 'less-loader' } ] } ] },
你可以執行 npm run dev來啟動開發環境。