Laravel Elixir
介绍
Laravel Elixir 为你的 Laravel 应用程序提供了一个简洁、流畅的 API,用于定义基本的 Gulp 任务。Elixir 支持多种常见的 CSS 和 JavaScript 预处理器,甚至包括测试工具。通过方法链,Elixir 允许你流畅地定义你的资源管道。例如:
elixir(function(mix) {
mix.sass('app.scss')
.coffee('app.coffee');
});
如果你曾经对如何开始使用 Gulp 和资源编译感到困惑,你会喜欢 Laravel Elixir。不过,在开发应用程序时,你并不需要使用它。你可以自由选择任何资源管道工具,甚至可以不使用任何工具。
安装与设置
安装 Node
在触发 Elixir 之前,你必须先确保你的机器上安装了 Node.js。
node -v
默认情况下,Laravel Homestead 包含了你所需的一切;然而,如果你不使用 Vagrant,你可以通过访问 Node.js 下载页面轻松安装 Node。
Gulp
接下来,你需要将 Gulp 作为全局 NPM 包引入:
npm install --global gulp-cli
如果你使用版本控制系统,你可能希望运行 npm shrinkwrap
来锁定你的 NPM 需求:
npm shrinkwrap
一旦你运行了这个命令,可以将 npm-shrinkwrap.json 提交到源代码控制中。
Laravel Elixir
剩下的唯一步骤就是安装 Elixir!在 Laravel 的新安装中,你会在根目录找到一个 package.json
文件。可以将其视为你的 composer.json
文件,只不过它定义的是 Node 依赖而不是 PHP。你可以通过运行以下命令安装它引用的依赖:
npm install
如果你在 Windows 系统上开发,或者在 Windows 主机系统上运行你的虚拟机,你可能需要在启用 --no-bin-links
开关的情况下运行 npm install
命令:
npm install --no-bin-links
运行 Elixir
Elixir 构建在 Gulp 之上,因此要运行你的 Elixir 任务,你只需在终端中运行 gulp
命令。将 --production
标志添加到命令中将指示 Elixir 压缩你的 CSS 和 JavaScript 文件:
// 运行所有任务...
gulp
// 运行所有任务并压缩所有 CSS 和 JavaScript...
gulp --production
监视资源的变化
由于在每次更改资源后在终端中运行 gulp
命令很不方便,你可以使用 gulp watch
命令。此命令将在你的终端中持续运行,并监视你的资源是否有任何更改。当发生更改时,新文件将自动编译:
gulp watch
处理样式表
项目根目录中的 gulpfile.js
文件包含了你所有的 Elixir 任务。Elixir 任务可以链式调用,以定义你的资源应如何编译。
Less
要将 Less 编译为 CSS,你可以使用 less
方法。less
方法假定你的 Less 文件存储在 resources/assets/less
中。默认情况下,此示例的编译 CSS 将放置在 public/css/app.css
中:
elixir(function(mix) {
mix.less('app.less');
});
你还可以将多个 Less 文件合并为一个 CSS 文件。同样,生成的 CSS 将放置在 public/css/app.css
中:
elixir(function(mix) {
mix.less([
'app.less',
'controllers.less'
]);
});
如果你希望自定义编译 CSS 的输出位置,可以将第二个参数传递给 less
方法:
elixir(function(mix) {
mix.less('app.less', 'public/stylesheets');
});
// 指定特定的输出文件名...
elixir(function(mix) {
mix.less('app.less', 'public/stylesheets/style.css');
});
Sass
sass
方法允许你将 Sass 编译为 CSS。假设你的 Sass 文件存储在 resources/assets/sass
中,你可以这样使用该方法:
elixir(function(mix) {
mix.sass('app.scss');
});
同样,像 less
方法一样,你可以将多个 Sass 文件编译为一个 CSS 文件,甚至可以自定义生成的 CSS 的输出目录:
elixir(function(mix) {
mix.sass([
'app.scss',
'controllers.scss'
], 'public/assets/css');
});
纯 CSS
如果你只想将一些纯 CSS 样式表合并为一个文件,可以使用 styles
方法。传递给此方法的路径是相对于 resources/assets/css
目录的,生成的 CSS 将放置在 public/css/all.css
中:
elixir(function(mix) {
mix.styles([
'normalize.css',
'main.css'
]);
});
当然,你也可以通过将第二个参数传递给 styles
方法来自定义生成文件的输出位置:
elixir(function(mix) {
mix.styles([
'normalize.css',
'main.css'
], 'public/assets/css');
});
源映射
源映射默认启用。因此,对于每个编译的文件,你将在同一目录中找到一个伴随的 *.css.map
文件。此映射允许你在浏览器中调试时将编译的样式表选择器追溯到原始的 Sass 或 Less。
如果你不希望为 CSS 生成源映射,可以使用一个简单的配置选项禁用它们:
elixir.config.sourcemaps = false;
elixir(function(mix) {
mix.sass('app.scss');
});
处理脚本
Elixir 还提供了几个函数来帮助你处理 JavaScript 文件,例如编译 ECMAScript 6、编译 CoffeeScript、Browserify、压缩以及简单地连接纯 JavaScript 文件。
CoffeeScript
coffee
方法可用于将 CoffeeScript 编译为纯 JavaScript。coffee
函数接受一个字符串或 CoffeeScript 文件数组,相对于 resources/assets/coffee
目录,并在 public/js
目录中生成一个 app.js
文件:
elixir(function(mix) {
mix.coffee(['app.coffee', 'controllers.coffee']);
});
Browserify
Elixir 还附带了一个 browserify
方法,它为你提供了在浏览器中使用模块和 ECMAScript 6 以及 JSX 的所有好处。
此任务假定你的脚本存储在 resources/assets/js
中,并将生成的文件放置在 public/js/main.js
中。你可以将自定义输出位置作为可选的第二个参数传递:
elixir(function(mix) {
mix.browserify('main.js');
});
// 指定特定的输出文件名...
elixir(function(mix) {
mix.browserify('main.js', 'public/javascripts/main.js');
});
虽然 Browserify 附带了 Partialify 和 Babelify 转换器,但你可以自由安装和添加更多转换器:
npm install aliasify --save-dev
elixir.config.js.browserify.transformers.push({
name: 'aliasify',
options: {}
});
elixir(function(mix) {
mix.browserify('main.js');
});
Babel
babel
方法可用于将 ECMAScript 6 和 7 和 JSX 编译为纯 JavaScript。此函数接受一个文件数组,相对于 resources/assets/js
目录,并在 public/js
目录中生成一个 all.js
文件:
elixir(function(mix) {
mix.babel([
'order.js',
'product.js',
'react-component.jsx'
]);
});
要选择不同的输出位置,只需将所需的路径指定为第二个参数。此方法的签名和功能与 mix.scripts()
相同,但不包括 Babel 编译。
脚本
如果你有多个 JavaScript 文件想要合并为一个文件,可以使用 scripts
方法。
scripts
方法假定所有路径都是相对于 resources/assets/js
目录的,并默认将生成的 JavaScript 放置在 public/js/all.js
中:
elixir(function(mix) {
mix.scripts([
'jquery.js',
'app.js'
]);
});
如果你需要将多个脚本集合并为不同的文件,可以多次调用 scripts
方法。传递给方法的第二个参数决定了每次连接的结果文件名:
elixir(function(mix) {
mix.scripts(['app.js', 'controllers.js'], 'public/js/app.js')
.scripts(['forum.js', 'threads.js'], 'public/js/forum.js');
});
如果你需要合并给定目录中的所有脚本,可以使用 scriptsIn
方法。生成的 JavaScript 将放置在 public/js/all.js
中:
elixir(function(mix) {
mix.scriptsIn('public/js/some/directory');
});
复制文件和目录
copy
方法可用于将文件和目录复制到新位置。所有操作都是相对于项目的根目录进行的:
elixir(function(mix) {
mix.copy('vendor/foo/bar.css', 'public/css/bar.css');
});
elixir(function(mix) {
mix.copy('vendor/package/views', 'resources/views');
});
版本控制 / 缓存清除
许多开发人员在编译的资源后面加上时间戳或唯一标记,以强制浏览器加载新资源,而不是提供过时的代码副本。Elixir 可以使用 version
方法为你处理此问题。
version
方法接受一个相对于 public
目录的文件名,并将一个唯一的哈希附加到文件名上,以实现缓存清除。例如,生成的文件名将类似于:all-16d570a7.css
:
elixir(function(mix) {
mix.version('css/all.css');
});
生成版本化文件后,你可以在 视图 中使用 Laravel 的全局 elixir
PHP 辅助函数来加载适当的哈希资源。elixir
函数将自动确定哈希文件的名称:
<link rel="stylesheet" href="{{ elixir('css/all.css') }}">
版本控制多个文件
你可以将一个数组传递给 version
方法以对多个文件进行版本控制:
elixir(function(mix) {
mix.version(['css/all.css', 'js/app.js']);
});
一旦文件被版本化,你可以使用 elixir
辅助函数生成指向正确哈希文件的链接。请记住,你只需将未哈希文件的名称传递给 elixir
辅助函数。辅助函数将使用未哈希的名称来确定文件的当前哈希版本:
<link rel="stylesheet" href="{{ elixir('css/all.css') }}">
<script src="{{ elixir('js/app.js') }}"></script>
BrowserSync
BrowserSync 在你对前端资源进行更改后会自动刷新你的网页浏览器。你可以使用 browserSync
方法来指示 Elixir 在运行 gulp watch
命令时启动一个 BrowserSync 服务器:
elixir(function(mix) {
mix.browserSync();
});
一旦你运行 gulp watch
,使用端口 3000 访问你的 Web 应用程序以启用浏览器同步:http://homestead.app:3000
。如果你在本地开发中使用的域名不是 homestead.app
,你可以将一个 选项 数组作为第一个参数传递给 browserSync
方法:
elixir(function(mix) {
mix.browserSync({
proxy: 'project.app'
});
});
调用现有的 Gulp 任务
如果你需要从 Elixir 调用现有的 Gulp 任务,可以使用 task
方法。举个例子,假设你有一个 Gulp 任务,在调用时简单地说出一些文本:
gulp.task('speak', function() {
var message = 'Tea...Earl Grey...Hot';
gulp.src('').pipe(shell('say ' + message));
});
如果你希望从 Elixir 调用此任务,请使用 mix.task
方法,并将任务名称作为唯一参数传递给该方法:
elixir(function(mix) {
mix.task('speak');
});
自定义监视器
如果你需要注册一个监视器以在某些文件被修改时运行你的自定义任务,请将正则表达式作为第二个参数传递给 task
方法:
elixir(function(mix) {
mix.task('speak', 'app/**/*.php');
});
编写 Elixir 扩展
如果你需要比 Elixir 的 task
方法提供的更灵活的功能,可以创建自定义 Elixir 扩展。Elixir 扩展允许你向自定义任务传递参数。例如,你可以这样编写一个扩展:
// 文件:elixir-extensions.js
var gulp = require('gulp');
var shell = require('gulp-shell');
var Elixir = require('laravel-elixir');
var Task = Elixir.Task;
Elixir.extend('speak', function(message) {
new Task('speak', function() {
return gulp.src('').pipe(shell('say ' + message));
});
});
// mix.speak('Hello World');
就是这样!请注意,你的 Gulp 特定逻辑应放置在传递给 Task
构造函数的第二个参数的函数中。你可以将其放在 Gulpfile 的顶部,或者将其提取到自定义任务文件中。例如,如果你将扩展放在 elixir-extensions.js
中,可以从主 Gulpfile
中引入该文件,如下所示:
// 文件:Gulpfile.js
var elixir = require('laravel-elixir');
require('./elixir-extensions')
elixir(function(mix) {
mix.speak('Tea, Earl Grey, Hot');
});
自定义监视器
如果你希望在运行 gulp watch
时重新触发自定义任务,可以注册一个监视器:
new Task('speak', function() {
return gulp.src('').pipe(shell('say ' + message));
})
.watch('./app/**');