簡介
Laravel Mix 提供了一套流式 API,使用一些通用的 CSS 和 JavaScript 預處理器為 Laravel 應用定義 Webpack 構建步驟。通過簡單的方法鏈,你可以流式定義資源管道。例如:
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
如果你對如何開始使用 Webpack 和前端資源編譯感到困擾,那么你會愛上 Laravel Mix。不過,並不是強制要求在開發期間使用它。你可以自由選擇使用任何前端資源管道工具,或者壓根不使用。
安裝 & 設置
安裝 Node
在開始接觸 Mix 之前,必須首先確保 Node.js 和 NPM 在機器上已經安裝:
node -v
npm -v
默認情況下,Laravel Homestead 已經包含了你所需要的一切;不過,如果你沒有使用 Homestead,你也可以從Node 的下載頁面輕松的下載安裝最新版本的 Node 和 NPM。
Laravel Mix
接下來,需要安裝 Laravel Mix,在新安裝的 Laravel 根目錄下,你會發現有一個 package.json
文件。該文件包含你所需要的一切,和 composer.json
類似,只不過是用來定義 Node 依賴而非 PHP 依賴,你可以通過運行如下命令來安裝需要的依賴:
npm install
如果你正在 Windows 系統上開發,需要在運行 npm install
命令時帶上 --no-bin-links
:
npm install --no-bin-links
運行 Mix
Mix 是位於 Webpack 頂層的配置層,所以要運行 Mix 任務你只需要在運行包含在默認 package.json
文件中的其中某個 NPM 腳本即可:
// 運行所有 Mix 任務...
npm run dev
// 運行所有 Mix 任務並減少輸出...
npm run production
監控前端資源改變
npm run watch
命令將會持續在終端運行並監聽所有相關文件的修改,Webpack將會在發現修改后自動重新編譯資源文件:
npm run watch
你可能會發現文件變更的時候特定環境的 Webpack 不會更新,如果你遇到了這樣的問題,可以考慮使用 watch-poll
命令:
npm run watch-poll
處理樣式表
webpack.mix.js
是所有資源編譯的入口,可以將其看作 Webpack 的輕量級配置封裝層。Mix 任務可以以方法鏈的方式被鏈在一起來定義前端資源如何被編譯。
Less
要將 Less 編譯成 CSS,可以使用 less
方法。下面讓我們來編譯 app.less
文件到 public/css/app.css
:
mix.less('resources/assets/less/app.less', 'public/css');
多次調用 less
方法可用於編譯多個文件:
mix.less('resources/assets/less/app.less', 'public/css')
.less('resources/assets/less/admin.less', 'public/css');
如果你想要自定義編譯后文件的輸出位置,可以將完整的路徑信息作為第二個參數傳遞到 less
方法:
mix.less('resources/assets/less/app.less', 'public/stylesheets/styles.css');
如果你需要覆蓋底層 Less 插件選項,可以傳遞一個對象作為 mix.less()
的第三個參數:
mix.less('resources/assets/less/app.less', 'public/css', {
strictMath: true
});
Sass
sass
方法允許你將 Sass 編譯成 CSS。你可以像這樣使用該方法:
mix.sass('resources/assets/sass/app.scss', 'public/css');
同樣,和 less
方法一樣,你可以將多個 Sass 文件編譯成單個 CSS 文件,甚至自定義結果 CSS 的輸出路徑:
mix.sass('resources/assets/sass/app.sass', 'public/css')
.sass('resources/assets/sass/admin.sass', 'public/css/admin');
額外的 Node-Sass 插件選項可以以第三個參數的形式提供:
mix.sass('resources/assets/sass/app.sass', 'public/css', {
precision: 5
});
Stylus
和 Less 和 Sass 類似,stylus
方法允許你將 Stylus 編譯成 CSS:
mix.stylus('resources/assets/stylus/app.styl', 'public/css');
你還可以安裝額外的 Stylus 插件,例如 Rupture,首先,通過 NPM 安裝這個插件(npm install rupture
)然后在調用 mix.stylus()
時引入它:
mix.stylus('resources/assets/stylus/app.styl', 'public/css', {
use: [
require('rupture')()
]
});
PostCSS
PostCSS,是一個轉化 CSS 的強大工具,在 Laravel Mix 中開箱可用。默認情況下,Mix 使用了流行的 Autoprefixer 插件來自動添加所需要的 CSS3 瀏覽器引擎前綴。不過,你也可以添加與應用適配的其他額外插件。首先,通過 NPM 安裝需要的插件,然后在 webpack.mix.js
文件中引用:
mix.sass('resources/assets/sass/app.scss', 'public/css')
.options({
postCss: [
require('postcss-css-variables')()
]
});
原生 CSS
如果你只想要將多個原生 CSS 樣式文件合並到一個文件,可以使用 styles
方法:
mix.styles([
'public/css/vendor/normalize.css',
'public/css/vendor/videojs.css'
], 'public/css/all.css');
URL 處理
因為 Laravel Mix 是基於 Webpack 開發的,所以了解一點關於 Webpack 的概念很重要。對 CSS 編譯而言,Webpack 會在樣式表中重寫並優化所有 url() 調用,雖然這可能最初聽上去很奇怪,但這確實個不折不扣的強大功能。假設我們想要編譯包含圖片相對 URL 的 Sass:
.example {
background: url('../images/example.png');
}
注:任意給定
url()
的絕對路徑都會從 URL 重寫中排除,例如,url('/images/thing.png')
或url('http://example.com/images/thing.png')
將不會被修改。
默認情況下,Laravel Mix 和 Webpack 會找到 example.png
,將其拷貝到 public/images
目錄下,然后在生成的樣式表中重寫 url()
,因此,編譯后的 CSS 如下所示:
.example {
background: url(/images/example.png?d41d8cd98f00b204e9800998ecf8427e);
}
和這個功能一樣有用的是,可能已存在的目錄結構已經配置成你想要的方式,這種情況下,你可以禁用 url()
重寫:
mix.sass('resources/assets/app/app.scss', 'public/css')
.options({
processCssUrls: false
});
如果添加了這項配置到 webpack.mix.js
文件,Mix 將不再匹配 url()
或拷貝資源到 public
目錄。換句話說,編譯過的 CSS 和編譯前輸入的一樣:
.example {
background: url("../images/thing.png");
}
Source Map
雖然 Source Map 默認被禁用,但是可以通過在 webpack.mix.js
文件中調用 mix.sourceMaps()
來激活。盡管這會帶來編譯/性能開銷,不過在編譯資源的時候可以提供額外的調試信息給瀏覽器的開發者工具:
mix.js('resources/assets/js/app.js', 'public/js')
.sourceMaps();
處理 JavaScript
Mix 還提供了多個特性幫助你處理 JavaScript 文件,例如編譯 ECMAScript 2015,模塊捆綁,最小化以及合並原生 JavaScript 文件。更妙的是,這些都是無縫集成的,不需要額外的自定義配置:
mix.js('resources/assets/js/app.js', 'public/js');
通過這一行代碼,你可以使用如下功能:
- ES2015 語法
- 模塊
- 編譯
.vue
文件 - 最小化生產環境
提取 Vendor 庫
捆綁所有應用特定 JavaScript 和 vendor 庫的一個潛在缺點是進行長期緩存將變得更加困難,例如,單次更新應用代碼將會強制瀏覽器下載所有 vendor 庫,即使它們並沒有更新。
如果你想要頻繁更新應用的 JavaScript,需要考慮對 vendor 庫進行提取和拆分,這樣的話,對應用代碼的一個修改不會影響 vendor.js
文件的緩存。Mix 的 extract
方法可以實現這樣的功能:
mix.js('resources/assets/js/app.js', 'public/js')
.extract(['vue'])
extract
方法接收包含所有庫的數組或你想要提取到 vendor.js
文件的模塊,使用上述代碼作為示例,Mix將會生成如下文件:
public/js/manifest.js
:Webpack manifest runtimepublic/js/vendor.js
:vendor 庫public/js/app.js
:應用代碼
要避免 JavaScript 錯誤,確保以正確順序加載這些文件:
<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script>
<script src="/js/app.js"></script>
React
Mix 可以自動為安裝 Babel 插件以便支持 React,我們可以將 mix.js()
調用替換為 mix.react()
來實現:
mix.react('resources/assets/js/app.jsx', 'public/js');
在這個場景背后,Mix 會下載並引入合適的 Babel 插件 babel-preset-react
。
Vanilla JS
和使用 mix.styles()
合並樣式表類似,你可以通過 scripts()
方法合並並最小化任意數量的 JavaScript 文件:
mix.scripts([
'public/js/admin.js',
'public/js/dashboard.js'
], 'public/js/all.js');
這一功能對那些不需要 Webpack 對 Javascript 進行編譯的傳統應用來說很有用。
注:
mix.scripts()
的一個輕微調整是mix.babel()
,它的方法簽名和scripts
一樣,不同之處是合並的文件會經過 Babel 編譯,從而將所有 ES2015 代碼轉化成所有瀏覽器都支持的原生 JavaScript。
自定義 Webpack 配置
在場景背后,Laravel Mix 引用了預配置的 webpack.config.js
文件來盡可能快的啟動和運行。個別情況下,你需要手動編輯這個文件。你可能有一個被引用的特定的加載器或插件,或者可能傾向於使用 Stylus 而不是 Sass,在這些情況下,你有兩個選擇:
合並自定義配置
Mix 提供了一個有用的 webpackConfig
方法,從而允許你合並任意簡短的 Webpack 配置覆蓋。這是一個很吸引人的選擇,因為不需要你拷貝或維護自己的webpack.config.js
文件副本,webpackConfig
方法接收一個對象,該對象包含了任意你想要應用的Webpack指定配置:
mix.webpackConfig({
resolve: {
modules: [
path.resolve(__dirname, 'vendor/laravel/spark/resources/assets/js')
]
}
});
自定義配置文件
第二個選擇是拷貝 Mix 的 webpack.config.js
到自己的項目根目錄:
cp node_modules/laravel-mix/setup/webpack.config.js ./
接下來,將 package.json
文件中的所有 --config
引用指向拷貝后的新配置文件。如果你選擇使用這種自定義方式,以后只要 Mix 的 webpack.config.js
有升級變更都要手動將變更合並到自定義的新文件。
拷貝文件/目錄
你可以使用 copy
方法拷貝文件/目錄到新路徑,這在將 node_modules
目錄下的特定資源文件重新放置到 public
目錄下時很有用:
mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');
拷貝目錄的時候,copy
方法將會鋪平目錄結構,要維持目錄的原始結構,需要使用 copyDirectory
方法:
mix.copyDirectory('assets/img', 'public/img');
版本號/緩存刷新
很多開發者會給編譯的前端資源添加時間戳或者唯一令牌后綴以強制瀏覽器加載最新版本而不是代碼的緩存副本。Mix 可以使用 version
方法為你處理這種場景。
version
方法會自動附加唯一哈希到已編譯文件名,從而方便實現緩存刷新:
mix.js('resources/assets/js/app.js', 'public/js')
.version();
生成版本文件后,還不知道提取的文件名,所以,你需要在視圖中使用 Laravel 全局的 mix
函數來加載相應的帶哈希值的前端資源。mix
函數會自動判當前的已哈希文件名:
<link rel="stylesheet" href="{{ mix('css/app.css') }}">
由於版本文件在本地開發中沒有什么用,你可以只在運行 npm run production
期間進行版本處理操作:
mix.js('resources/assets/js/app.js', 'public/js');
if (mix.config.inProduction) {
mix.version();
}
BrowserSync 重新加載
BrowserSync 會自動監控文件修改,並將修改注入瀏覽器而不需要手動刷新,你可以通過調用 mix.browserSync() 方法啟用該支持:
mix.browserSync('my-domain.test');
// Or...
// https://browsersync.io/docs/options
mix.browserSync({
proxy: 'my-domain.test'
});
你可以傳遞一個字符串(代理)或對象(BrowserSync 設置)到該方法。接下來,使用 npm run watch
命令來啟動 Webpack 的開發服務器,現在,當你編輯一個 JavaScript 腳本或 PHP 文件時,會看到瀏覽器會立即刷新以響應你的修改。
環境變量
你可以通過在 .env
文文件添加 MIX_
前綴將環境變量注入 Mix:
MIX_SENTRY_DSN_PUBLIC=http://example.com
在 .env
文件中定義好變量之后,可以通過 process.env
對象進行訪問(如果在運行 watch
任務期間變量值有變動,需要重啟任務):
process.env.MIX_SENTRY_DSN_PUBLIC
通知
在有效的情況下,Mix 會自動為每個捆綁顯示操作系統通知,這可以給你一個及時的反饋:編譯成功還是失敗。不過,某些場景下你可能希望禁止這些通知,一個典型的例子就是在生產境服務器觸發 Mix。通知可以通過 disableNotifications
方法被停用:
mix.disableNotifications();