上篇文章帶大家使用 webpack 5
整合 React
與TypeScript
,同時為了提高我們的程式碼品質,我們會在構建中新增型別檢查和程式碼規範校驗。這次我們在上篇的基礎上介紹如何整合 css
、less
與sass
。
為了在 JavaScript
模組中import
一個 CSS
檔案,你需要安裝 style-loader
和 css-loader
,並在 module
設定 中新增這些 loader
。
我們需要安裝css-loader
和style-loader
:
yarn add css-loader style-loader -D
修改組態檔:
module: {
rules: [
...,
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
這樣設定後,當 webpack
再遇到.css
檔案時,它將使用css-loader
和style-loader
進行處理(use
陣列中的載入器從後向前執行)。
css-loader
在 import
語句(在我們的範例中為app.css
)中讀取參照的 CSS
檔案並解析成 JavaScript
程式碼。style-loader
將 JavaScript
程式碼中的 CSS
以 style
標籤的形式插入到 html
檔案中。接下來再通過yarn start
開啟即可看到我們引入外部.css
檔案生效。
在生產環境下,我們需要進行壓縮CSS
,以便在生產環境中節省載入時間,同時還可以將CSS
檔案抽離成一個單獨的檔案。實現這個功能,需要 mini-css-extract-plugin
這個外掛來幫忙。安裝外掛:
yarn add mini-css-extract-plugin -D
本外掛會將 CSS
提取到單獨的檔案中,為每個包含 CSS
的JS
檔案建立一個 CSS
檔案,並且支援 CSS
和 SourceMaps
的按需載入。
本外掛基於 webpack 5
的新特性構建,並且需要webpack 5
才能正常工作。
之後將loader
與 plugin
新增到你的 webpack
組態檔中。
在 webpack.config.pred.js
中做如下新增如下設定:
const miniCssExtractPlugin = require('mini-css-extract-plugin');
// ...
module.exports = {
// ....
module: {
rules: [
// ...
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
]
},
plugins: [
// ...
new MiniCssExtractPlugin({
filename: 'styles/[name].[contenthash].css'
}),
],
mode: 'production',
}
接下來再通過yarn build
打包即可看到我們的輸出目錄多了一個styles資料夾,裡面是我們抽離出來的CSS
檔案,但我們卻看到CSS
檔案並沒有被壓縮,為了壓縮輸出的CSS
檔案,我們需要css-minimizer-webpack-plugin
這個外掛來幫忙。安裝外掛:
yarn add css-minimizer-webpack-plugin -D
在 webpack.config.pred.js
中做如下新增如下設定:
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
// ...
module.exports = {
// ....
// 優化設定
optimization: {
minimizer: [
new CssMinimizerPlugin(),
],
},
}
接下來再通過yarn build
打包即可看到我們的輸出styles檔案裡面的CSS
檔案已經被壓縮了。
當開發人員命名的類有衝突時,後面的樣式會覆蓋前面的樣式。
那麼該如何解決呢?當然你可以選擇命名的時候避免衝突,還有一種方法便是使用 CSS modules
,這裡便不再詳細介紹它了,只講如何設定環境。
首先,我們需要先改變參照的方式:
src/index.module.css
.h1 {
background-color: red;
}
scr/index.tsx
import React from "react";
import ReactDOM from "react-dom";
import index from './index.module.css'
const App = () => (
<h1 className={index.h1}>Hello World!</h1>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
可以看到 import
語句跟原來的略有不同。 我們通過參照.module.css
字尾的檔案,並從中匯入為一個變數
這個變數是一個物件,包含了對應樣式檔案的所有CSS
類名稱, 然後在元件中參照對應的類名變數。我們還需要將index.css
重新命名為index.module.css
。
但是TypeScript
編譯出現錯誤 「無法找到模組’.module.css’或對應的型別宣告」錯誤,因為 TS 無法解析CSS modules
為了解決這個錯誤,我們需要建立一個src/typings.d.ts
型別宣告檔案並加入以下內容:
declare module "*.module.css";
之後重新啟動應用,再次檢視介面效果,就可以看見正常了:
我們看到 CSS
類名稱被賦予了一個看起來很隨機的名稱。 因為這樣可以確保不同元件中的樣式名稱不會衝突。
通過上述方法,每次都需要通過 *.module.css
的方式實現 CSS modules
不免有些麻煩。其實,我們可以通過修改 Webpack
設定簡化 CSS modules
的寫法。
在webpack.config.dev.js
中我們做如下修改:
module: {
rules: [
...,
{
test: /\.css$/i,
use: ["style-loader", {
loader: "css-loader",
options: {
modules: true,
},
}],
},
],
},
在webpack.config.prod.js
中我們做如下修改:
module: {
rules: [
...,
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, {
loader: "css-loader",
options: {
modules: true,
},
}],
},
],
},
修改typings.d.ts
的設定:
declare module "*.css";
這樣,我們就可以以如下方式進行使用了:
import React from "react";
import ReactDOM from "react-dom";
import index from './index.css'
const App = () => (
<h1 className={index.h1}>Hello World!</h1>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
如果你想在專案中使用less
,那麼我們就需要less-loader
這個工具。
首先,我們先安裝一下:
yarn add less less-loader -D
在webpack.config.dev.js
中我們做如下修改:
module: {
rules: [
...,
{
test: /\.less$/i,
use: ["style-loader", {
loader: "css-loader",
options: {
modules: true,
},
}, 'less-loader'],
},
],
},
在webpack.config.prod.js
中我們做如下修改:
module: {
rules: [
...,
{
test: /\.less$/i,
use: [MiniCssExtractPlugin.loader, {
loader: "css-loader",
options: {
modules: true,
},
}, 'less-loader'],
},
],
},
同時,為了配合 CSS modules
,我們需要在typings.d.ts
中加入以下內容,否則 Typescript
無法識別 Less
型別:
declare module "*.less";
如此,我們就可以在專案中使用Less
了。
接下來我們看看如何設定 Sass
,其實與 Less
的設定方式是類似的。
如果你想在專案中使用Sass
,那麼我們就需要sass-loader
這個工具。
首先,我們先安裝一下:
yarn add sass sass-loader -D
在webpack.config.dev.js
中我們做如下修改:
module: {
rules: [
...,
{
test: /\.s[ac]ss$/i,
use: ["style-loader", {
loader: "css-loader",
options: {
modules: true,
},
}, 'sass-loader'],
},
],
},
在webpack.config.prod.js
中我們做如下修改:
module: {
rules: [
...,
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, {
loader: "css-loader",
options: {
modules: true,
},
}, 'sass-loader'],
},
],
},
同時,為了配合 CSS modules
,我們需要在typings.d.ts
中加入以下內容,否則 Typescript
無法識別 sass
和 scss
型別:
declare module "*.sass";
declare module "*.scss";
如此,我們就可以在專案中使用Sass
了。
這樣以來,我們的專案環境就整合 css
、less
與sass
,同時還支援css module
。