在 Part 5 有用到 laravel-mix,但沒有很仔細的講解他的用法,這章節就是要來補充缺少的內容及概念。

Laravel Mix 簡介

我遇過一些使用Laravel框架的開發者,有用 Laravel Mix 來處理前端的套件或是框架等(JS、CSS),但個人覺得其實還蠻麻煩的啦!但是既然他有提供這個 API 為何不用?
既然要使用了,我們簡單說明一下 Webpack 吧!

:::info

什麼是 Webpack

Webpack 是一個 模組打包工具(module bundler)

其實現在的前端,不再像以前一樣JS、CSS拉一拉引入進來,就可以使用了,但現在可能會遇到例如SCSS、React、Vue、圖片之類的,這些 Browser,看得懂嗎?當然是看不懂。

這時我們使用 Webpack 幫我處理 Browser 看不懂的內容,進行編譯打包成一包就可以讓 Browser 看懂。

:::

回到 Laravel Mix ,他只是應用 Webpack 其中的工具罷了。

但我看到 Webpack 去做打包前的程序及 Laravel Mix 確實差蠻多,感覺 Laravel Mix 就會簡單些。

Mix 資料夾架構

每一個專案裡面,都會有一個 resources 的資料夾,這個資料夾主要存放你要再做打包前的前端程式。
例如:

  • 專案 > resource > sass
  • 專案 > resource > js
  • 專案 > resource > lass (自行新增)
  • 專案 > resource > css (自行新增)

這些一旦打包後,就會存放在 public 資料夾底下。

  • 專案 > public > css
  • 專案 > public > js

安裝、設置與執行 Mix

確認你電腦裡是否有安裝npm,如果沒有安裝的可以 參考這篇 開發專案必須學會的套件管理工具(NPM)

1
2
3
4
5
6
7
xxxxxxx@DESKTOP-LUMBRQB MINGW64 /c/laravel/mix0816
$ node -v
v12.16.1

xxxxxxx@DESKTOP-LUMBRQB MINGW64 /c/laravel/mix0816
$ npm -v
6.13.4

在專案目錄下,執行安裝專案用到的套件包,基本上這個指令會依照 package.jsonpackage-lock.json 去執行我們需要的套件包。

1
2
3
$ npm install
// 如果在Windows 伺服器開發或架設,使用此指令
$ npm install --no-bin-links

※ –no-bin-links 的意思避免 npm 去幫你產生 symlinks,因為在Windows下不支援 symlinks。但如果在 Linux 是可行的。

這時候會多出以下資料夾
專案 > node_modules

執行 Mix

Laravel Mix 存在於 Webpack 的上一層

開啟 package.json
專案 > package.json (指令設置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"private": true,
"scripts": {
"dev": "npm run development",
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"watch": "npm run development -- --watch",
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --disable-host-check --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.19",
"cross-env": "^7.0",
"laravel-mix": "^5.0.1",
"lodash": "^4.17.19",
"resolve-url-loader": "^3.1.0",
"sass": "^1.15.2",
"sass-loader": "^8.0.0"
}
}

執行 Laravel Mix,只需要執行 package.json 程式中的 script 裡的 dev 【指令設置 Line:4】

1
2
// 執行 mix
$ npm run dev

執行以上指令,會將需要打包的程式resources (預存程式) 編譯打包後 放置到網頁執行的進入點裡 public。 但這邊會依照 webpack.mix.js 所設定的去做編譯。

下圖為要打包的資料夾來源。
專案 > resources

下方程式碼定義要打包哪些來源程式。
專案 > webpack.mix.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const mix = require('laravel-mix');

/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/

mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');

打包前後的結果,放置網頁執行的進入點。
專案 > public
| 執行前 | 執行後 |
| ——– | ——– |
| | |

執行上圖 scriptprod 【指令設置 Line:10】

自於為什麼要做這個功能?因為網頁瀏覽為了提升一點讀取速度,多半會將 CSS 或JS 進行壓縮,相對檔案就會小很多,載入速度就會快了一些,也可以減少不必多出的網路流量。

1
2
// 壓縮編譯過的JS 或 CSS 的程式
$ npm run prod

以Bootstrap的css舉例一下

原始CSS,大家一看就一目了然。
:::info

:::

壓縮過的CSS,看都看不懂。
:::info

:::

監控前端程式異動及編譯

終端機持續執行,並監控前端模組或套件即自行定義的CSS、JS的變化。

並且自動重新編譯到進入點能看到的樣子(也是web原始碼可以看到的樣子)。

可能會有很多人有疑問,這到底是什麼?直接實作起來

Step1 -> 先輸入指令

1
2
3
$ npm run watch
// 明明有修改,但上面指令卻不會更新,就使用下面這段指令
$ npm run watch-poll

狀態執行中(尚未停止)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

> @ watch C:\laravel\mix0816
> npm run development -- --watch


> @ development C:\laravel\mix0816
> cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress -g.js "--watch"

.....
中間省略
.....

DONE Compiled successfully in 1272ms21:34:38

<s> [webpack.Progress] 100%

Asset Size Chunks Chunk Names
/css/app.css 36 bytes /js/app [emitted] /js/app
/js/app.js 594 KiB /js/app [emitted] /js/app

Step2 -> 輸入完指令,修改以下檔案,並儲存
專案 > resources > sass > app.scss

1
2
3
4
5
$color: blue;

body{
background-color: $color;
}

Step3 -> 因為指令沒有停止運作,他為自動把修改的SCSS進行編譯轉換成 Broswer 看得懂的CSS
專案 > public > css > app.scss

1
2
3
body {
background-color: blue;
}

如何打包不一樣的檔案類型

下面會說明 CSS、Sass、Less、Stylus、JS、React,做法其實都大同小異,重點是要如何去寫mix註冊。

先學會如何打包一組套件

下載安裝 Uikit HTML框架套件

1
$ npm install uikit --save

檢查是否有列在 package.json 套件版本列表。
專案 > package.json

1
2
3
4
5
... 省略
"dependencies": {
"uikit": "^3.5.7-dev.554b4fee0"
}
... 省略

專案 > resources > sass > 新增 uikit.scss 檔案
開啟 uikit.scss ,我們可以將Uikit 官網提供 Sass 的路徑貼到 這個檔案裡。
這邊路徑我有增加 node_modules 的前導路徑。

1
2
3
4
5
6
7
8
9
10
11
12
// 1. Your custom variables and variable overwrites.
$global-link-color: #DA7D02;

// 2. Import default variables and available mixins.
@import "node_modules/uikit/src/scss/variables-theme.scss";
@import "node_modules/uikit/src/scss/mixins-theme.scss";

// 3. Your custom mixin overwrites.
@mixin hook-card() { color: #000; }

// 4. Import UIkit.
@import "node_modules/uikit/src/scss/uikit-theme.scss";

專案 > resources > js > 新增 uikit.js 檔案

這個 require 就是你在 node_modules 資料夾底下套件的名稱。

1
window.Uikit = require("uikit");

開啟 webpack.mix.js,我們將剛剛安裝的套件,註冊到 Mix 裡。

※ 暫時將註解省略

專案 > webpack.mix.js

修改前

1
2
3
4
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');

修改後

1
2
3
4
5
6
const mix = require('laravel-mix');

mix.js('resources/js/app.js', 'public/js')
.js('resources/js/uikit.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.sass('resources/sass/uikit.scss', 'public/css');

記得去Run一下,編譯一下。

1
2
// 執行 mix
$ npm run dev

回到此資料夾就會看到我們產出編譯完成的檔案。
專案 > public

CSS

mix.styles()

專案 > resources > css > main.css

1
2
3
body{
font-size: 16px;
}

專案 > resources > css > style.css

1
2
3
4
* {
margin: 0;
padding: 0;
}

將上面兩個檔案進行註冊及合併
專案 > webpack.mix.js

1
2
3
4
mix.styles([
'resources/css/main.css',
'resources/css/style.css'
], 'public/css/all.css');

RUN一下吧!

1
2
// 執行 mix
$ npm run dev

得到結果

專案 > public > css > all.css

1
2
3
4
5
6
7
body{
font-size: 16px;
}
* {
margin: 0;
padding: 0;
}

Less

mix.less()

自行 建立less資料夾 及 list.less 檔案

專案 > resources > less > list.less

1
2
3
4
5
6
7
8
9
10
11
div{
span{
font-size:20px;
b{
color:red;
}
}
i{
font-size:12px;
}
}

對less進行mix註冊
專案 > webpack.mix.js

1
mix.less('resources/less/app.less', 'public/css');

在RUN一下吧(編譯)!

1
2
// 執行 mix
$ npm run dev

專案 > public > css > list.css

1
2
3
4
5
6
7
8
9
div span {
font-size: 20px;
}
div span b {
color: red;
}
div i {
font-size: 12px;
}

Sass

mix.sass()

流程跟CSS、LESS 差不多。
專案 > webpack.mix.js

1
mix.sass('resources/sass/app.scss', 'public/css');

mix.sass 有第三個參數,可以至 sass/node-sass 參觀使用。
專案 > webpack.mix.js

1
2
3
mix.sass('resources/sass/app.sass', 'public/css', {
outputStyle: 'nested'
});

Stylus

mix.stylus()

1
mix.stylus('resources/stylus/app.styl', 'public/css');

Stylus 可以另外引入相關的插件,例如 jescalan/rupture的插件。

1
2
3
4
5
mix.stylus('resources/stylus/app.styl', 'public/css', {
use: [
require('rupture')()
]
});

JavaScript

mix.js()

JS可以直接編寫ES2015、Vue等語法或框架,Mix就可以直接做編譯。

專案 > webpack.mix.js

1
mix.js('resources/js/app.js', 'public/js');

React

mix.react()
Mix會自己下載 Babel 插件,支援 React 框架。

專案 > webpack.mix.js

1
mix.react('resources/js/app.jsx', 'public/js');

Source Map

sourceMaps() 可以任何一個需要做處理的程式去使用,編譯後的檔案程式,方便 Borswer 網頁在讀取檔案的正確位置,包含他的程式是第幾行產生的。

sourceMaps() 已經取消預設。Webpack 提供了多種 Devtool,自行參觀使用。

要打包並註冊編譯的前端檔案,在 Mix 呼叫式最後面加上 .sourceMaps() ,在 RUN 編譯的過程就會一併執行。在RUN的過程中 缺點就出現了,就是會造成編譯效能及速度的負擔。

專案 > webpack.mix.js

1
2
3
4
5
6
7
8
9
10
11
const mix = require('laravel-mix');

//...註解省略...

let productionSourceMaps = false;

mix.js('resources/js/app.js', 'public/js')
.js('resources/js/uikit.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css')
.sass('resources/sass/uikit.scss', 'public/css')
.sourceMaps(productionSourceMaps, 'source-map');;

RUN過以後,旁邊都會產生 檔名.副檔名.map 檔,他是 sourceMaps 所產生出來的。

Copy

copy()

我們以 bxslider 套件為這個方法的舉例。

我在 resource 的地方要 require('bxslider'),但一直找不到這個套件,所以如果有人遇到這種狀況的,可以使用copy。

用 npm 下載安裝 bxslider

1
$ npm install bxslider

上方執行完畢,在 webpack.mix.js 使用 .copy() 找尋他的 css 路徑。
專案 > webpack.mix.js

1
mix.copy('node_modules/bxslider/src/css/jquery.bxslider.css', 'public/css/');

記得去Run一下,編譯一下。

1
2
// 執行 mix
$ npm run dev

結果就會是我們要的CSS。

copyDirectory()

但有人一定會問說,難道我不能複製整個資料夾嗎?答案當然是可以呀!

將要複製的資料夾給他找出來,在去做個註冊且註明要在哪個資料夾。
專案 > webpack.mix.js

1
mix.copyDirectory('node_modules/bxslider', 'public/js/bxslider');

編譯下去

1
2
// 執行 mix
$ npm run dev

那整個 bxslider 都抓過來了!但前提是檔案裡面要是瀏覽器能看得懂的程式或檔案。

版本管理

version()

用戶端使用 Borswer 在瀏覽網頁的時候,大部分第一次登入就會記錄下網頁的當頁快取,但是開發者如果更新 CSS 或JS 的時候,用戶端重新瀏覽時,怎都畫面或是功能還是一樣,沒什麼改變呀!但用戶端怎會知道要使用 Ctrl + F5 刷新網頁?這時候我們就要在 <link> <script> 的標籤herf 及 href 加入參數,如下面範例 路徑後面放上 ?data=0200816

1
2
<link rel="stylesheet" type="text/css" href="/css/style.css?date=20200816" />  
<script src="/js/main.js?date=20200816"></script>

這時候 Mix 幫你準備好方法,version() 方法就可以在後面加上版本號,當更新一次CSS OR JS,他就會更新版本號。

專案 > webpack.mix.js

1
2
3
4
5
6
mix.styles([
'resources/css/main.css',
'resources/css/style.css'
],
'public/css/all.css')
.version();

記得去Run一下,編譯一下。

1
2
// 執行 mix
$ npm run dev

<head> 標籤內使用 mix函數 加入編譯好的 all.css,它會指向你指定的路徑。

專案 > resources > views > welcome.blade.php

1
<link rel="stylesheet" href="{{ mix('/css/all.css') }}">

執行專案

1
$ php artisan serve

http://127.0.0.1:8000/ ->任一處右鍵原始碼 就會看到 用 mix函數加入的all.css,後面也加入了一串版本號。

在下方的檔案是在做mix 註冊編譯後所產生的檔案,可以在程式裡看到我們編譯後的all.css + 版本號。
專案 > public > mix-manifest.json

1
2
3
{
"/css/all.css": "/css/all.css?id=45540ddd7a6ac79e1b7a"
}

結論

其實有些人在做前端引入的時候,可能會直接引用cdn,或是自己把檔案載下來去引入,其實沒有對錯,主要看開發專案的工程師方不方便,所以我們要引入好資料,把該放的放進去,該處理的處理好,大致上對於各個工程師後續維護會比較輕鬆些。

參考文獻

標籤: w3HexSchool PHP Laravel