概覽
API
常用插件
高級配置
基本示例
larave-mix是位於webpack頂層的一個簡潔的配置層,在80%的的情況下使用laravel mix會使操作變的非常簡單。盡管webpack非常的強大,但大部分人都認為webpack的學習曲線非常陡峭。但是如果你不必用再擔心這些了呢?
看一下基本的webpack.mix.js文件,讓我們想象一下我們現在只需要編譯javascript(ES6)和sass文件:
let mix = require('laravel-mix'); mix.sass('src/app.sass', 'dist') .js('src/app.js', 'dist');
怎么樣,簡單嗎?
1. 編譯sass文件, ./src/app.sass到 ./dist/app.css
2. 打包在./src/app.js的所有js(包括任何依賴)到 ./dist/app.js。
使用這個配置文件,可以在命令行觸發webpack指令:node_modules/bin/webpack
在開發模式下,並不需要壓縮輸出文件,如果在執行webpack的時候加上環境變量:export NODE_ENV=production && webpack,文件會自動壓縮
less
但是如果你更喜歡使用Less而不是Sass呢?沒問題,只要把mix.sass()換成mix.less()就OK了。
使用laravel-mix,你會使發現大部分webpack任務會變得更又把握
安裝
盡管laravel-mix對於laravel使用來說最優的,但也能被用於任何其他的應用。
laravel項目
laravel已經包含了你所需要的一切,簡易步驟:
1. 安裝laravel
2. 運行 npm install
3. 看一下你的webpack.mix.js ,然后就done了
你可以在命令行運行 npm run watch 來監視你的前段資源改變,然后重新編譯。
注:在項目根目錄下並沒有webpack.config.js配置文件,laravel默認指向根目錄下的配置文件。如果你需要自己配置它,你可以把它拷貝到根目錄下,同時修改package.json里的npm腳本: cp node_modules/laravel-mix/setup/webpack.config.js ./
.
獨立項目
首先使用npm或者yarn安裝laravel-mix,然后把示例配置文件復制到項目根目錄下
mkdir my-app && cd my-app npm init -y npm install laravel-mix --save-dev cp -r node_modules/laravel-mix/setup/** ./
現在你會有如下的目錄結構
- node_modules/
- package.json
- webpack.config.js
- webpack.mix.js
laravel-mix 包括兩個核心組件
- webpack.mix.js: 這是你在webpack上層的配置文件,大部分時間你需要修改的是這個文件
- webpack.config.js: 這是傳統的webpack配置文件,只有在有更高級的配置需求時才需要更改
打開你的webpack.mix.js文件:
let mix = require('laravel-mix'); mix.js('src/app.js', 'dist') .sass('src/app.scss', 'dist');
注意源文件的路徑,然后創建匹配的目錄結構(你也可以改成你喜歡的結構)。現在都准備好了,在命令行運行node_modules/.bin/webpack 編譯所有文件,然后你將會看到:
- dist/app.css
- dist/app.js
- dist/mix-manifest.json(你的asset輸出文件,稍后討論)
干得漂亮!現在可以干活了。
NPM Scripts
把下面的npm腳本添加到你的package.json文件中可以讓你的工作更快,laravel安裝的時候已經包含了這個東西了
"scripts": { "dev": "cross-env NODE_ENV=development webpack --progress --hide-modules", "watch": "cross-env NODE_ENV=development webpack --watch --progress --hide-modules", "hot": "cross-env NODE_ENV=development webpack-dev-server --inline --hot", "production": "cross-env NODE_ENV=production webpack --progress --hide-modules" }
laravel工作流程
我們先回顧一下通用的工作流程以便你能在自己的項目上采用
1 . 安裝laravel
laravel new my-app
2 . 安裝Node依賴
npm install
3 . 配置webpack.mix.js
這個文件所有前端資源編譯的入口
let mix = require('laravel-mix'); mix.js('resources/assets/js/app.js', 'public/js'); mix.sass('resources/assets/sass/app.scss', 'public/css');
默認會啟用ES2015模塊綁定,就行sass編譯一樣。
4 . 編譯
用如下指令編譯
node_modules/.bin/webpack
也可以使用package.json 里的npm腳本:
npm run dev
然后會看到編譯好的文件:
- ./public/js/app.js
- ./public/css/app.css
監視前端資源更改:
npm run watch
laravel裝載了一個./resources/assets/js/components/Example.vue文件,do它,編譯完成后會有一個系統通知。
5 . 修改視圖
laravel自帶一個歡迎頁面,我們可以用這個來做示例,修改一下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Laravel</title> <link rel="stylesheet" href="{{ mix('css/app.css') }}"> </head> <body> <div id="app"> <example></example> </div> <script src="{{ mix('js/app.js') }}"></script> </body> </html>
刷新頁面,干得漂亮!
6 . 熱加載
當我們修改了已個vue組件的時候可以立即在瀏覽器看到他的變化而不是需要手動去刷新是非常酷的,更酷的是,刷新不會重置我們組件的狀態。HMR來拯救你了!
返回命令行,Ctrl+c強制結束webpack監視器,然后輸入:
npm run hot
“hot”表示HMR(Hot module replacement),這個指令是你激活熱加載唯一需要做的事情
刷新瀏覽器,然后修改./resources/assets/js/components/Example.vue文件,一旦你點擊保存,瀏覽器就會立馬有反應,酷不酷!
Larave Mix vs. Laravel Elixir
mix和elixir有哪些不同呢?
你可能已經知道一個叫做laravel elixir的工具已經存在一段時間了(也是我們寫的), laravel mix 是它的升級版,盡管他們的API是幾乎一樣的,但還有少數關鍵的不同你需要知道一下,如果你要替換他們的話。
1 . laravel mix 是建立在webpack的頂層,而不是Gulp
最重要的變化當然是我們把底層實現用webpack替代了gulp,這樣帶來的結果是不僅更健壯,更靈活,而且更簡單,更可配置(你所需要的)的代碼。請注意一下所有的laravel elixir插件都使用gulp,因為laravel mix 使用的是webpack,所以laravel elixir的插件在這里都不能用了,那就是為什么我們改了名字,避免大家蒙圈。另一方面,laravel mix不需要插件,所以你可以自由的編寫webpack.config.js。
2 . gulpfile.js變成webpack.mix.js
因為laravel mix 建立在webpack上,所以安裝laravel的時候你並不能找到gulpfile.js,而是:
- webpack.mix.js 這個文件等同於gulpfile.js,實際上你會發現API幾乎是一樣的
3 . webpack 不是一個通常意義上的任務構建工具 ,like gulp
對於一般的任務,gulp是非常nice的,移動文件,壓縮腳本,編譯js,還能版本化特定文件,然而,webpack只是一個JavaScript入口,在這里,你可以選擇多種編譯方式或者插件。這是一個很重要的區別。
話雖然是這么說,我們還是要給你介紹一些跟webpack模塊無關的操作來合並多個文件,或者壓縮樣式表,這意味着,mix.copy(),mix.combine(),mix.minify() 仍然是可以用的
例如:在laravel elixir下,你可能會使用mix.version('./public/some/random/files.js') ,它會給文件名附加hash值。但在laravel mix下,你只需要簡單的調用mix.version()就行了,工具會自動的版本化所有的關聯文件。
4.更靈活
因為我們現在使用webpack,會有一些新的功能,例如mix.extract(['vendor', 'libs']), 它會把所有指定的第三方庫拆分成獨立的文件,為了長期緩存。
常見問題
laravel-mix必須在laravel下使用嗎?
不,在laravel下使用使最好的,但也可以用在別的任何項目
我的代碼沒有壓縮
只有在node環境變量為生產環境時才會被壓縮,這樣會加速編譯過程,但在開發過程中是不必要的,下面是在生成環境下運行webpack的示例
export NODE_ENV=production && webpack --progress --hide-modules
強烈推薦你把下面的npm腳本添加到你的package.json文件中,注意laravel已經包括了這些了
"scripts": { "dev": "cross-env NODE_ENV=development webpack --progress --hide-modules", "watch": "cross-env NODE_ENV=development webpack --watch --progress --hide-modules", "hot": "cross-env NODE_ENV=development webpack-dev-server --inline --hot", "production": "cross-env NODE_ENV=production webpack --progress --hide-modules" },
我使用的是VM,webpack不能檢測到我的文件變化
如果你在VM下執行 npm run dev,你會發現webpack並不能監視到你的文件改變。如果這樣的話,修改一下你的npm腳本,使用--watch-poll和--watch標簽,像這樣:
"scripts": { "watch": "NODE_ENV=development webpack --watch --watch-poll", }
如果你還是有問題,去這兒溜達溜達吧。
為什么在我的css文件里顯示圖片在node_modules里找不到
你可能用的是相對路徑,但是在的resources/assets/sass/app.css里並不存在:
body { background: url('../img/example.jpg'); }
當引用相對路徑的時候,會根據當前文件的路徑來搜索,同樣的,webpack會首先搜索resources/assets/img/example.jpg,如果找不到,會繼續搜索文件位置,包括node_modules,如果還找不到,就報錯:
ERROR Failed to compile with 1 errors This dependency was not found in node_modules:
有兩個解決辦法:
1 . 讓resources/assets/img/example.jpg能找得到就行了,就是把文件放這兒。
2 . 編譯css的時候添加下面的選項,禁用css的url處理:
mix.sass('resources/assets/sass/app.scss', 'public/css') .options({ processCssUrls: false });
這對於一些文件This is particularly useful for legacy projects where your folder structure is already exactly as you desire.完全符合你的要求的遺留項目是非常有用的。
我不想把mix-manifest.json文件放在項目根目錄下
如果你沒有使用laravel,你的mix-manifest.json文件會被放到項目根目錄下,如果你不喜歡的話,可以調用mix.setPublicPath('dist/'),然后manifest文件就會被放到dist目錄下。
怎樣使用webpack自動加載模塊
webpack 使用ProvidePlugin插件加載一些需要的模塊,常用的一個例子就是加載jQuery:
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }); // in a module $('#item'); // <= just works jQuery('#item'); // <= just works
//$和jQuery被自動設置為‘jQuery’的出口
當laravel-mix自動加載模塊的時候(像上面說的那樣),你如果想禁用(傳一個空對象)或者用你自己的模塊覆蓋它,可以調用mix.autoload()方法:
mix.autoload({ jquery: ['$', 'window.jQuery', 'jQuery'], // more than one moment: 'moment' // only one })
怎樣手動添加CoffeeScript編譯器
非常簡單!你只需要在webpack.mix.js里調用mix.webpackConfig()方法就可以了,它會自動和mix的默認配置合並。
// npm install coffee-loader coffee-script
mix.js('resources/assets/js/app.coffee', 'public/js') .webpackConfig({ module: { rules: [ { test: /\.coffee$/, loader: 'coffee-loader' } ] } });
API
Javascript
mix.js(src|[src], output)
簡單的一行代碼,larave mix可以執行很多重要的操作
- ES2015模塊編譯
- 創建並且編譯vue組件(通過vue-loader)
- 模塊熱替換(HMR)
- Tree-shaking打包技術,webpack2里新增的(移除無用的庫)
- 提取和拆分vendor庫(通過mix.extract方法), 使長期緩存變的容易
- 自動版本化(文件哈希),通過mix.version()
用法
let mix = require('laravel-mix'); // 1. 單個文件 mix.js('src/app.js', 'dist/app.js'); // 2. 多個文件編譯成一個文件 mix.js([ 'src/app.js', 'src/another.js' ], 'dist/app.js'); // 3. 編譯多個文件 mix.js('src/app.js', 'dist/') .js('src/forum.js', 'dist/');
laravel 示例
考慮到典型的laravel默認安裝的時候會把入口定位在 ./resources/assets/js/app.js,所以我們先准備一個webpack.mix.js把app.js編譯到 ./public/js/app.js。
let mix = require('laravel-mix'); mix.js('resources/assets/js/app.js', 'public/js');
現在上面所有的項你都可以用了,只需要調用一個方法。
在命令行調用npm run dev 執行編譯。
Vue 組件
laravel mix 包羅萬象,支持vue組件編譯,如果你不使用vue的話,可以忽略這塊。
單文件組件是vue最重要的特征。在一個文件里為一個組件定義模板,腳本,樣式表。
./resources/assets/js/app.js
import Vue from 'vue'; import Notification from './components/Notification.vue'; new Vue({ el: '#app', components: { Notification } });
在上面,我們導入了vue(首先你需要執行npm install vue --save-dev安裝vue),然后引入了一個叫Notification的vue組件並且注冊了root vue實例。
./resources/asset/js/components/Notification.vue
<template> <div class="notification"> {{ body }} </div> </template> <script> export default { data() { return { body: 'I am a notification.' } } } </script> <style> .notification { background: grey; } </style>
如果你了解vue,這些你都會很熟悉,繼續。
./webpack.mix.js
let mix = require('laravel-mix');
mix.js('resources/assets/js/app.js', 'public/js');
執行npm run dev 編譯文件,這樣就簡單的創建了一個HTML文件,引入./js/app.js 文件,然后在瀏覽器里查看吧!
React 支持
laravel mix 也裝載了基本的react支持,只要把mix.js()改成mix.react()並且使用相同的參數。在底層,mix會引用react需要的任何babel插件。
mix.react('resources/assets/js/app.jsx', 'public/js/app.js');
當然,你仍然需要使用npm安裝react和reactDOM,不過要注意小心行事。
代碼分離
mix.js(src, output) .extract(['any', 'vendor', 'library']);
把所有的js都打包成一個文件會伴隨着潛在的風險:每次更新項目中就算很小的一部分都需要破壞所有用戶的緩存,這意味着你的第三方庫需要重新被下載和緩存。這樣很不好。
一個解決的辦法是分離或者提取你的庫文件。
- 應用代碼:app.js
- vendor庫:vendor.js
- Manifest(webpack runtime): manifest.js
mix.extract(['vue', 'jquery']);
extract方法接受一個你想要從打包文件里提取出的庫的數組,使用這個方法,Vue和jQuery的源代碼都會被放在vendor.js里。如果在未來你需要對應用代碼做一些微小的變動,並不會對大的vendor庫產生影響,它們依然會留在長期緩存。
一旦執行webpack打包文件,你會發現三個新的文件,你可以在HTML頁面引用它們。
<script src="/js/manifest.js"></script> <script src="/js/vendor.js"></script> <script src="/js/app.js"></script>
實際上,我們付出了一些HTTP請求的代價(就是會多請求幾次)來換取長期緩存的提升。
Manifest文件是什么
webpack編譯的時候會有一些run-time代碼協助其工作。如果沒有使用mix.extract(),這些代碼你是看不到的,它會在打包文件里,然而,如果我們分離了代碼並且允許長期緩存,在某些地方就需要這些run-time代碼,所以,mix會把它提取出來,這樣一來,vendor庫和manifest文件都會被緩存很長時間。
瀏覽器自動刷新
BrowserSync能讓瀏覽器實時的,快速的響應您的文件的更改 --完全不需要手動刷新。你可以調用mix.browserSync()方法來開啟這個功能:
mix.browserSync('my-domain.dev'); // Or: // https://browsersync.io/docs/options/ mix.browserSync({ proxy: 'my-domain.dev' })
參數可以傳字符串,也可以傳對象。你聲明的域名作為proxy是非常重要的,Browsersync將包裹你的虛擬主機(webpack dev server)使用代理網址查看您的網站。
Hot Module Replacement
laravel mix對模塊熱替換提供了無縫的支持。
模塊熱替換(或者叫熱加載),意思就是當javascript改變刷新頁面的時候可以維持組件的狀態,例如現在有一個計數器,按一下按鈕,計數器會加1,想象一下你點了很多次然后修改一下組件的相關文件,瀏覽器會實時的反映出你所做出的更改而保持計數器不變,計數器不會被重置,這就是熱加載的意義最在。
在laravel里的用法
看一下laravel里的package.json文件,在scripts模塊,你可以看到:
"scripts": { "dev": "cross-env NODE_ENV=development webpack --progress --hide-modules", "watch": "cross-env NODE_ENV=development webpack --watch --progress --hide-modules", "hot": "cross-env NODE_ENV=development webpack-dev-server --inline --hot", "production": "cross-env NODE_ENV=production webpack --progress --hide-modules" }
注意一下hot指令,這個地方就是你所需要的,在命令行執行npm run hot會啟動一個node服務器並且監視你的bundle文件,接下來,在瀏覽器打開你的laravel應用,一般應該是http://my-app.dev。
在laravel應用里使用熱加載很重要的一點是要保證所有的腳本資源引用的是前面啟動的node服務器的url:http://localhost:8080,現在你可以手動更新你的HTML\Blade文件了:
<body> <div id="app">...</div> <script src="http://localhost:8080/js/bundle.js"></script> </body>
假設你有一些組件,嘗試在瀏覽器里更改他們的狀態,然后更新他們的模板文件,你可以看到瀏覽器會立刻反應出你的更新,但是狀態並沒有被改變。
但是,在開發部署環境下手動更新url會是一個負擔,所以,laravel提供了一個mix()方法,他會動態的構建js或者樣式表的引用,然后輸出。上面的代碼因此可以修改成:
<body> <div id="app"></div> <script src="{{ mix('js/bundle.js') }}"></script> </body>
當你執行npm run hot的時候,這個方法會把http://localhost:8080設置為base url,當你運行npm run dev或者npm run pro的時候,它會使用你根目錄的地址。
在spa里的用法
laravel mix包含了流行的vue-loader包,這意味着,如果是單頁應用,你什么都不需要做,它是開包即用的。