Webpack 5 走起! - Loaders(9) - Sass/SCSS

前言

講下來將會介紹跟 Sass/SCSS 有關的處理。

Loaders

基本上在一開始我想先介紹一下 Loaders 是什麼東西以及為什麼我們要用 Loaders。

前面我們基本上都知道 Webpack 是一個打包工具,但 Webpack 僅僅只能夠支援 JavaScript 與 JSON,如果你要對其他類型的檔案做處理的話,那麼就必須設置一個加載器來處理,這一段其實在官方文件上也有說明

Out of the box, webpack only understands JavaScript and JSON files.

那麼接下來這邊就會先以 Sass/SCSS 的 Loaders 來做介紹,首先你必須先輸入以下指令安裝套件

1
npm install --save-dev style-loader css-loader sass-loader node-sass
  • node-sass 是 CSS 的預處理器,而另一個是 Dart-sass,但以目前來講開發都是首選 node-sass。
  • sass-loader 基本上也會依賴於上方的套件,也就是將 Sass/SCSS 編譯成 CSS 的處理套件。
  • css-loader 基本上這個與 style-loader 會搭再一起使用,簡單來講就是讀取出 CSS 樣式出來用的套件
  • style-loader 搭配上 css-loader 之後,將讀取出來的 CSS 樣式透過該套件注入到 style 標籤內。

與其看文字上說明搞不懂狀況,不如實際來操作一次會更清楚,首先方才已經安裝完相關套件,那麼就必須一樣來到 webpack.config.js 修改套件,修改的地方其實沒什麼太大差異,一樣是在 rules 底下增加即可

1
2
3
4
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},

基本上上面這一段都可以在 sass-loader 的文件上找得到。

只是這邊要附帶一提就是 use 在讀取時,是從後面開始讀取,因此我們這邊要使用 Sass/SCSS 的話,就必須將 sass-loader 放在最後一個代表著他會優先執行編譯。

接下來在 src/assets 底下建立一個 SCSS 資料夾,然後建立一個檔案叫做 all.scss,而內容如下

1
2
3
4
5
6
7
8
.box {
width: 100px;
height: 100px;
background-color: #00cc99;
p {
font-size: 32px;
}
}

一樣要到 main.js 注入,否則鬼才知道你要幹嘛

1
import './assets/scss/all.scss';

接下來當你輸入 npm run dev 就可以看到剛剛撰寫的 SCSS 已經被編譯成 CSS 並寫注入到 HTML 的 style 標籤內,而這過程就與我們安裝的套件是相同的,先 sass-loader -> 讀取出 CSS css-loader -> 注入到 HTML 的 style style-loader。

css

但是通常來講我們有時候的開發習慣會希望 CSS 是打包成一包,而不是注入在 HTML 上那麼這一段該如何處理呢?這一段就必須安裝另一個套件來處理,在官方文件上是推薦安裝 MiniCssExtractPlugin,除此之外也會建議你搭配著 css-loader 一起使用

1
npm install --save-dev  css-loader mini-css-extract-plugin

接下來回到 webpack.config.js 將原本的程式碼

1
2
3
4
{
test: /\.s[ac]ss$/i,
use: ['style-loader', 'css-loader', 'sass-loader'],
},

改成

1
2
3
4
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},

並且在程式碼最前面宣告該套件的變數,然後底下 plugins 也要加入該套件的實例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

...
{
test: /\.s[ac]ss$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
...
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack 5',
template: path.resolve(__dirname, './src/template/index.html'),
filename: 'index.html',
inject: 'body',
}),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin()
]

最後的最後,為了驗證我們編譯後 CSS 有正常套用,會建議你可以修改一下 template/index.html 的檔案內容

1
2
3
<div id="app">
<div class="box"></div>
</div>

接下來你就可以輸入 npm run dev 來看結果,基本上你會看到注入結果與樣式如我們預期一樣

結果

當然 MiniCssExtractPlugin 身為也可以像 JavaScript 檔案一樣重新命名,因此我們可以改成以下即可。

1
2
3
4
5
6
7
8
9
10
11
12
plugins: [
new HtmlWebpackPlugin({
title: 'Webpack 5',
template: path.resolve(__dirname, './src/template/index.html'),
filename: 'index.html',
inject: 'body',
}),
new CleanWebpackPlugin(),
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
}),
]

看起來這邊已經非常的完善,但其實還缺少一個東西也就是後處理器,那麼前面並沒有特別說明什麼是預處理,所謂的預處理就是在指 Sass/SCSS、LESS,透過預處理器我們可以用更接近程式語言的方式去撰寫 CSS,例如迴圈、變數以及判斷式等,概念你可以把預處理的概念想像成轉換成純粹 CSS 的一個行為。

那麼後處理器呢?後處理器在前面有提到在轉換 CSS 之前我們稱之為預處理器,那麼後處理器則是轉換成 CSS 之後,而最知名的就是 PostCSS,PostCSS 是一個透過 JavaScript 轉換 CSS 的套件,它的用途非常多,但我們大多都是使用它來增加前綴詞,畢竟身為前端工程師,往往會遇到很多瀏覽器語法不支援的問題。

所以這邊結論一下預處理器的概念就是撰寫一些類似 CSS 的語法然後後來在轉換的成純粹 CSS 的概念,而後處理器則是轉換成 CSS 之後再做一些優化調整。

那麼接下來就來安裝 PostCSS 吧。

1
npm install --save-dev postcss-loader postcss-preset-env

接下來稍微調整一下 CSS Loaders 那一段改成以下

1
2
3
4
5
6
7
8
9
10
...
{
test: /\.s[ac]ss$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
],
},

其實這樣子就可以執行 npm run build,但是這邊我們通常在實際開發時,可能會遇到使用者的瀏覽器太低的狀況,那麼就要調整我們預計要能夠符合多少版本的瀏覽器,因此就要多一些設定與調整,那麼調整後的內容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
test: /\.s[ac]ss$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
postcssPresetEnv({ browsers: 'last 1 versions' })
]
}

}
},
'sass-loader'
],
},

這邊要注意一件事情,如果你是看官方文件照樣這樣寫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const postcssPresetEnv = require('postcss-preset-env');

module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{ loader: 'css-loader', options: { importLoaders: 1 } },
{ loader: 'postcss-loader', options: {
ident: 'postcss',
plugins: () => [
postcssPresetEnv(/* pluginOptions */)
]
} }
]
}
]
}
}

必定會出現錯誤,必須在 options 底下加一個 postcssOptions 屬性才可以。

接下來的最後,由於目前撰寫的 SCSS 瀏覽器都是可以支援的,那麼要看出 PostCSS 用處,也就是自動加上前綴詞,那就可以撰寫一些 CSS

1
2
3
4
5
6
7
8
9
10
11
.box {
width: 100px;
height: 100px;
background-color: #00cc99;
p {
font-size: 32px;
// 增加下方兩個
filter: blur(5px);
display: flex;
}
}

接下來就可以輸入 npm run build 看編譯結果

編譯結果(通常是壓縮過,為了方便展示才展開)

1
2
3
4
5
6
7
8
9
10
11
.box{
width:100px;
height:100px;
background-color:#00cc99;
}
.box p{
font-size:32px;
-webkit-filter:blur(5px);
filter:blur(5px);
display:flex;
}

如果嫌看不太出效果的話,可以將 postcssPresetEnv({ browsers: 'last 1 versions' }) 改成 postcssPresetEnv({ browsers: 'last 2 versions' }) 就可以看出差異了

1
2
3
4
5
6
7
8
9
10
11
12
13
.box{
width:100px;
height:100px;
background-color:#00cc99
}
.box p{
font-size:32px;
-webkit-filter:blur(5px);
filter:blur(5px);
display:-webkit-box;
display:-ms-flexbox;
display:flex
}

Bootstrap

那麼這邊也額外介紹安裝 Bootstrap,這邊先輸入以下 npm 指令安裝 Bootstrap

1
npm install --save-dev bootstrap@5.0.0-beta2

接下來在 all.scss 檔案將內容改成以下

1
2
3
@import '~bootstrap/scss/functions';
@import './helpers/variables';
@import '~bootstrap/scss/bootstrap';

接下來在 assets/scss 底下建立一個 helpers 資料夾,然後去 node_modules 找到 Bootstrap/scss/_variables.scss 將它複製一份到 assets/scss/helpers 底下

通常我們還會針對 Bootstrap 客製化顏色,因此可以打開 _variables.scss 將 70 行的 primary 改成以下

1
$primary:       #00cc99; //$blue !default;

接下來改一下 HTML 內容

1
2
3
4
5
6
7
<div id="app">
<div class="box">
<p>這是一段話</p>
</div>
<br/>
<button type="button" class="btn btn-primary">這是一個按鈕</button>
</div>

修改完你就可以輸入 npm run dev 看結果囉。

結果畫面

Liker 讚賞

這篇文章如果對你有幫助,你可以花 30 秒登入 LikeCoin 並點擊下方拍手按鈕(最多五下)免費支持與牡蠣鼓勵我。
或者你可以也可以請我「喝一杯咖啡(Donate)」。

Buy Me A Coffee Buy Me A Coffee

Google AD

撰寫一篇文章其實真的很花時間,如果你願意「關閉 Adblock (廣告阻擋器)」來支持我的話,我會非常感謝你 ヽ(・∀・)ノ