Laravel 文档阅读:用 Laravel Mix 编译资产
简介#
这里的编译的「资产」可以简单理解为项目中的样式表文件和 JavaScript 脚本文件。
Laravel Mix 是 Laravel 提供的前端脚本构建工具,能够用几种常用的 CSS 和 JavaScript 预处理器处理项目脚本。 它构建在 Webpack 之上,隐藏了 Webpack 底层的复杂配置,暴露出简单易用的 API,让你轻松编译前端脚本不是梦!
下面是一个例子,流畅的链式方法调用,对 JavaScript 和 Sass 这两种不同资产类型做管道处理,在一条语句内完成,非常简单:
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
如果你以前用过 Webpack,就知道它的配置是多么的复杂了,因此当你第一眼看见 Laravel Mix 的时候,你就会情不自禁的爱上她。你也并非一定要用 Laravel Mix 开发,可以选择任何你希望使用的构建工具(像 Gulp),甚至不用任何构建工具都可以。
安装 & 设置#
安装 Node#
开始用 Mix 前,必须要保证在你的机器上安装了 Node.js 和 NPM 哦。
node -v
npm -v
如果你是用 Homestead 的话,就可以省略这一步了,因为 Homestead 中包含开发 Laravel 程序所需要的一切环境。
Laravel Mix#
对,没有错,这一步就可以直接安装 Laravel Mix 了。在你刚创建的一个 Laravel 项目里,根目录配置文件 package.json
中,已经为你预设好了。
"devDependencies": {
"axios": "^0.16.2",
"bootstrap-sass": "^3.3.7",
"cross-env": "^5.0.1",
"jquery": "^3.1.1",
"laravel-mix": "^1.0",
"lodash": "^4.17.4",
"vue": "^2.1.10"
}
package.json
就像是 composer.json
文件。不过前者是安装 Node 依赖包使用的,后者是安装 PHP 依赖包使用的。好,下面开始安装:
npm install
如果你是用 Windows 系统开发的,或者是用了安装在 Windows 系统上的虚拟机(VM)。你就可能需要在执行 npm install
命令的时候带上 --no-bin-links
选项:
npm install --no-bin-links
运行 Mix#
Mix 是构建在 Webpack 上的一个配置层。所以执行 Mix 任务时,需要使用 NPM 脚本命令,这些命令在 package.json
文件中定义:
// Run all Mix tasks...
npm run dev
// Run all Mix tasks and minify output...
npm run production
监听资产变化#
npm run watch
与前两条命令不同的是,它会在你的终端一直运行、监听所有相关文件的改变,一旦有文件改变,就会自动重新编译:
npm run watch
在某些情况下,这条命令对于 Webpack 不好使,它不给你重新编译的,针对这种情况,考虑使用 watch-poll
命令:
npm run watch-poll
使用样式表#
webpack.min.js
是所有资产编译的入口文件,可以把它看做是包裹了 Webpack 底层复杂配置的一个轻量的配置文件(同样是配置文件,差距就是那么大呢)。在这里面定义了链式的 Mix 任务,每个 Mix 任务就相当于是一个编译规则呢。
Less#
less
方法用来把 Less 文件编译为 CSS。下面,让我们把原本的 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');
如果要自定义编译出来的 CSS 文件名,那么在第二个参数里带上文件完整路径名就 OK 了:
mix.less('resources/assets/less/app.less', 'public/stylesheets/styles.css');
less
方法底层使用的是 Webpack 的 Less loader 插件,如果你要深度定制这个插件的配置信息,为 min.less()
传递第三个参数(对象类型)就 OK 了。
mix.less('resources/assets/less/app.less', 'public/css', {
strictMath: true
});
Sass#
sass
方法用来把 Sass 文件编译为 CSS。它像下面这样用:
min.sass('resources/assets/sass/app.scss', 'public/css');
哎哟,不错哦,你有没有感觉跟 less
方法很像呢,确实!多次链式调用 sass
方法同时编译出多个 CSS 文件也是 OK 的:
mix.sass('resources/assets/sass/app.sass', 'public/css')
.sass('resources/assets/sass/admin.sass', 'public/css/admin');
有没有看到,第二个 sass
方法,我们还自定义了 CSS 输出目录,前面的 less
方法也可以这么玩啊(好吧,我不说了……)。
注意啊,sass
方法底层可不是使用 Webpack 的一个什么插件,而是直接使用了 Node.js 的 node-sass 插件。同样,如果要深入定制她的话,给她传递第三个参数就 OK 了:
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 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()
规则。想象我们要编译的 Sass 文件里使用了相对路径引入了图片文件:
.example {
background: url('../images/example.png');
}
注意,url()
里使用绝对路径引入图片的情况不会被处理。比如,url('/images/thing.png')
和 url('http://example.com/images/thing.png')
就保持原样,不被处理。
默认,Laravel Mix 和 Webpack 会找到 eaxmple.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
中添设定了这个选项后,url()
里的规则保持原样不变。还是下面这样:
.example {
background: url("../images/thing.png");
}
Source Maps#
编译资产时,Source Map 默认是禁用的,你可以使用 mix.sourceMaps()
方法启用它。虽然在编译时,这样会带来额外的开销,但是在你 debug 的时候非常有用。
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
文件。 - 生产环境下的代码压缩。
第三方提取#
把项目的脚本代码和第三方库代码合并到一起有一个缺点:很难长期缓存文件。例如,项目中单个文件代码的修改就会导致,那些第三方库代码也跟着重新编译(不管有没有改动代码),然后浏览器重新加载编译后的文件。
如果你项目中的 JavaScript 代码经常修改,你就应该考虑把第三方看库文件提取出来放在属于他们的文件里。这样一来,你项目的脚本代码的修改和重新编译,不会影响到体积较大的 vendor.js
文件。Mix 的 extract
方法就是做这个的:
mix.js('resources/assets/js/app.js', 'public/js')
.extract(['vue'])
extract
方法的接受的数组参数里,就是你最终要放到 vendor.js
文件里的所有库和模块。使用上面的逻辑编译脚本文件后,会产出以下 3 个文件:
public/js/mainfest.js
:Webpack 运行时清单。public/js/vendor.js
:第三方库。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 也会自动安装 React 所需要的 Babel 插件。在你使用 mix.react()
而非 min.js()
时
mix.react('resources/assets/js/app.jsx', 'public/js');
在背后,Mix 会下载和引入正确的 babel-preset-react
这个 Babel 插件。
原生 JS#
类似 mix.styles()
方法,你可以使用 scripts()
方法合并和压缩任意数量的 JavaScript 文件:
mix.scripts([
'public/js/admin.js',
'public/js/dashboard.js'
], 'public/js/all.js');
这个方法并没有使用到 Webpack 编译 JavaScript 脚本文件。
注意,还有一个 mix.babel()
方法,它是在 mix.scripts
方法的基础上做了一些的修改,但支持 ES2015 语法的编译,而且两者的方法签名都是一样的。经过 mix.babel()
方法合并的脚本文件会经过 Babel 的编译,将任何 ES2015 代码转换为浏览器支持的原生 JavaScript 代码。
自定义 Webpack 配置#
在上面这些开箱提供的简单 API 背后,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')
]
}
});
自定义配置文件#
如果你要完全自定义你的 Webpack 配置文件的话,就要把 node_modules/laravel-mix/setup/webpack.config.js
复制到你的项目根目录下,然后修改 package.json
文件里 --config
后面的配置文件路径(--config=webpack.config.js
)。
如果你采用这种方式的话,未来所有在 Mix 上的更新都要手工合并到你的自定义配置文件里。
复制文件 & 目录#
copy
方法用来复制文件从一个位置到另一个位置。当你需要把 node_modules
文件夹里的文件复制到 public
下时很有用。
mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');
复制整个文件夹的话,就使用 copyDirectory
方法:
mix.copyDirectory('assets/img', 'public/img');
加版本号 / 清除缓存#
许多开发者会在编译资产文件前加上时间戳或者唯一令牌号,来强制浏览器加载最新编译的脚本文件而不是使用之前的老版本。Mix 用 version
方法来解决这个问题。
version
方法会自动给编译出来的脚本文件名附加一个 hash 值,强制浏览器加载最新编译的脚本文件。
mix.js('resources/assets/js/app.js', 'public/js')
.version();
带版本号的脚本文件编译好后,你是不知道确切的文件名的。这是使用 Laravel 全局的 mix
方法在视图里加载正确的带版本号的脚本文件。mix
方法会自动确定正确的 hash 文件:
<link rel="stylesheet" href="{{ mix('/css/app.css') }}">
因为版本文件在开发期间不常使用,所以可以设定只在执行 npm run production
命令时才给资产文件添加版本号:
mix.js('resources/assets/js/app.js', 'public/js');
if (mix.inProduction()) {
mix.version();
}
浏览器同步加载#
BrowserSync 可以用来自动监听文件改变,在不需要手工刷新的情况下,在浏览器中同步加载更新的文件内容。这时,你要使用 mix.browserSync()
方法做到:
mix.browserSync('my-domain.dev');
// Or...
// 更多配置项参考:https://browsersync.io/docs/options
mix.browserSync({
proxy: 'my-domain.dev'
});
browserSync
方法接收的参数可以是一个(代理)字符串或者是(BrowserSync 配置)对象。接下来,当你使用 npm run watch
命令后,每当你修改一个脚本或者 PHP 文件,在浏览器中的页面都会立即更新。
环境变量#
我们可以向 Mix 中注入环境变量,这是通过在 .env
文件中设定以 MIX_
作为前缀的 Key 做到的:
MIX_SENTRY_DSN_PUBLIC=http://example.com
在 .env
文件中,定义好变量后,就可以通过 process.env
对象获得这个变量。如果你在 watch
时改变了这个值,是需要停止、然后重启 watch
才能让变化后的变量值生效。
process.env.MIX_SENTRY_DSN_PUBLIC
通知#
如果可用的话,Mix 会在每次编译任务完成后,自动操作系统级别的通知, 给你即时的反馈说编译是否成功了。 不过,如果你希望停用这些通知 —— 比如,你遇到过在你的生产环境的服务器上这可能会再一次触发 Mix,这时,就需要用 disableNotifications
方法禁用它了。
mix.disableNotifications();
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: