從 Laravel-mix 0.8 升級到 1.4 版的記錄與坑
相信現在許多在使用 Laravel 的朋友,應該都是使用 laravel-mix 來處理前端的相關資源的打包,
不知道大家覺得 laravel-mix 用起來的感覺是如何?我自己覺得用起來真的沒有想像的好用,
雖然 Laravel 官方有提供文件說明操作的方法,但是我自己覺得它的擴展性很差,而且又把它再抽象化了 :skull:。
webpack 雖然設定起來比較繁瑣,但其實你會遇到的問題,可能很多人都有遇過了,
也或許有人提出相關 issue,所以要尋找一些解決方式我自己覺得相對容易,
webpack2 (現在是 webpack 3 囉!) 的文件相較於 webpack1 也真的友善許多 :smirk:,
老實說,我第一次看到 webpack 的文件真的覺得是天書,對新手開發者來說真的是一個痛點!
但是現在官方文件真的寫得清楚容易多了,像是 Guides 的部分我覺得就蠻不錯的,
對岸也有人將它翻譯成簡體文件,閱讀英文較吃力的朋友不妨可以參考。
升級的一些地雷
最近把公司專案的 laravel-mix 從 0.8.1 升級至目前最新的 1.4.2 版本,遇到的一些問題,
稍微做個整理和記錄,如果有打算升級 laravel-mix 的朋友,若有遇到相關問題可以參考看看 :metal:。
:bomb: 地雷一 - cross-env
比較早之前 Laravel 內的 package.json
版本的 scripts 大概是這樣:
{
"scripts": {
"dev": "node node_modules/cross-env/dist/bin/cross-env.js NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
}
}
透過 cross-env
來解決跨平台設定 NODE_ENV
的問題,但是較早的版本是引用 node_modules
內的 js,
在新版的部分都會另外安裝 cross-env
,所以設定要改成如下:
{
"scripts": {
"dev": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
}
}
:bomb: 地雷二 - mix.extract() & mix.autoload()
在前端,我們可能會用了不少的 library 來幫助我們做到介面上的美化,或是與使用者的互動,
但這些套件全部一次打包到一個 xxx.min.js
其實不是非常的好,當網站在載入的時候,會浪費非常多時間,
而且當你只是修改一小部分的 JavaScript 就必須要整個重新打包(包含那些 library),使用者載入網站就必須要再重新下載整個 bundle 檔,原先 cache 的檔案就沒用了!
laravel-mix 提供了一個 extract
的方法,讓你可以把一些 libray 給抽取出來,把它打包成 vendor.js
,
就是一個 Code Splitting 的概念,但是請記得按照以下順序把你的 JavaScript 給 inclue 到你的網頁中:
<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script>
<script src="/js/app.js"></script>
一般在這裡會把 Vue
、axios
、lodash
等等 library 給提取出來,我自己在這裡也把 jQuery
也給提出出來,就遇到了一些問題,你必須還要再寫一個 mix.autoload
的方法,讓你所需要的 library 自動被 include(因為所用到的 Bootstrap 依賴 jQuery),目前在 Laravel 官方文件還看不到 autoload
方法的說明,請直接到 laravel-mix - Autoloading 查看文件!
mix
.js('resources/assets/js/app.js', 'public/js/app.js')
.extract([
'jquery',
'bootstrap-sass',
'axios',
'vue',
'lodash'
])
.autoload({
jquery: ['$', 'window.jQuery', 'jQuery', 'jquery'],
vue: ['Vue', 'window.Vue'],
axios: ['axios', 'window.axios'],
lodash: ['lodash', 'window._']
})
.sass('resources/assets/sass/app.scss', 'public/css/app.css');
autoload
內是一個 object 的形式,每個 key 是你 library 名稱,value 的地方就是代表這些形式的變數會直接載入對應(key)的 libray;意思是,當我某個地方用到了 $
或是 jQuery
,webpack 會自動幫我把 library 給準備好,讓我可以使用,同理像是 Vue
、axios
也是一樣的道理。
但是!我這麼做了之後發現一載入到網站還是找不到 jQuery,在看 error log 得到了以下的訊息:
// other error messages...
} else {
// Browser globals
factory(jQuery);
}
解決方式是需要把 window 修改為 global:
- window.$ = window.jQuery = require('jquery');
+ global.$ = global.jQuery = require('jquery');
如果有遇到這樣問題的朋友,或許可以試試看這個方法。
:bomb: 地雷三:如果用到了 async/await
我在撰寫 Vue Component 的時候,用到了 async/await
的語法,在 development 模式下沒什麼問題,但是跑 CI 卻炸掉了,
在本機沒有先測試過 npm run production
的結果,在 CI 是 run production 的 script,後來 debug 找到的錯誤訊息是:
ReferenceError: regeneratorRuntime is not defined
大概知道是因為 async/await
的關係,造成在 runtime 的時候錯誤,我的解決方式再去額外安裝 babel 的 transform-runtime:
$ yarn add babel-plugin-transform-runtime --dev
$ yarn add babel-runtime
為了確保在 development 和 production 都可以運作正常,所以兩個都安裝,接著建立一個 .babelrc
:
{
"plugins": ["transform-runtime"]
}
在 plugins
內把 transform-runtime
加入進去就沒問題了。
一些使用的心得
在 Laravel 官方 mix 文件有個部分是 Copying Files & Directories,這裡主要是 mix 提供了方法讓你可以去 copy 檔案到你要的目錄下,如果是 copy node_modules
下的檔案,我覺得這有點多此一舉,其實可以用更容易的方式來做,應該可以節省一些 compile 的時間 :stuck_out_tongue:!
善用 path.join
Nodejs 內建的 path 的模組非常好用,這裡我們使用 join
的方法直接連結到 node_modules
目錄下的檔案:
const path = require('path');
mix.styles(
[
path.join(__dirname, 'node_modules/sweetalert/dist/sweetalert.css'),
path.join(__dirname, 'node_modules/select2/dist/css/select2.min.css'),
],
'public/css/all.css'
);
mix.combine(
[
path.join(__dirname, 'node_modules/sweetalert/dist/sweetalert.min.js'),
path.join(__dirname, 'node_modules/select2/dist/js/select2.min.js'),
],
'public/js/all.js'
);
這樣就可以不需要再多寫 mix.copy()
啦!順帶一提,mix.combine()
也是新的方法,類似 scripts()
,但是使用 combine
方法可以幫你將必要的檔案給 bundle 並 minify,詳細可以參考文件:Concatenation and Minification。
其他更多相關的方法我就沒使用過了,未來有機會用到或是遇到相關的問題再補上來。
如果文章內有任何說明上的錯誤,歡迎提出告訴我,希望大家可以一起多交流!:v:
推荐文章: