Laravel Elixir


简介

Laravel Elixir 提供了简洁流畅的 API,让你能够为你的 Laravel 应用程序定义基本的 Gulp 任务。Elixir 支持许多常见的 CSS 与 JavaScrtip 预处理器,甚至包含了测试工具。

如果你曾经对于使用 Gulp 及编译资源感到困惑,那么你绝对会爱上 Laravel Elixir!

安装与配置

安装 Node

在开始使用 Elixir 之前,你必须先确定你的开发环境上有安装 Node.js。

  1. node -v

默认情况下,Laravel Homestead 会包含你所需的一切;当然,如果你没有使用 Vagrant,那么你可以浏览 Node 的下载页进行安装。别担心,安装是很简单又快速的!

Gulp

接着你需要全局安装 Gulp 的 NPM 安装包,如这样:

  1. npm install --global gulp

Laravel Elixir

最后的步骤就是安装 Elixir!伴随着新安装的 Laravel,你会发现根目录有个名为 package.json 的文件。想像它就如同你的 composer.json 文件,只是它定义的是 Node 的依赖,而不是 PHP。你可以使用以下的命令进行安装依赖的动作:

  1. npm install

使用方式

现在你已经安装好 Elixir,未来任何时候你都能进行编译及合并文件! 在项目根目录下的 gulpfile.js 已经包含了所有的 Elixir 任务。

编译 Less

  1. elixir(function(mix) {
  2. mix.less("app.less");
  3. });

在上述例子中,Elixir 会假设你的 Less 文件保存在 resources/assets/less 里。

编译多个 Less 文件

  1. elixir(function(mix) {
  2. mix.less([
  3. 'app.less',
  4. 'something-else.less'
  5. ]);
  6. });

编译 Sass

  1. elixir(function(mix) {
  2. mix.sass("app.sass");
  3. });

在上述例子中,Elixir 会假设你的 Sass 文件保存在 resources/assets/sass 里。

默认情况下, Elixir 会使用 LibSass 作为编译引擎。 在某些情况下, 使用 Ruby 版本的 Sass 编译可能更有优势,虽然运行不是很快但是有更多的特性。假设你已经安装了 Ruby 和 Sass gem (gem install sass), 你可以使用 Ruby 模式,比如像这样:

  1. elixir(function(mix) {
  2. mix.rubySass("app.sass");
  3. });

无 Source Maps 编译

  1. elixir.config.sourcemaps = false;
  2. elixir(function(mix) {
  3. mix.sass("app.scss");
  4. });

Source maps 默认情况下是开启的。因此, 每当一个文件被编译,你都会在当前目录下看到 *.css.map 文件。这个映射文件允许你在进行 debugging 的时候,追溯编译后的样式选择器到原有的 Sass 或者 Less 文件!如果你想要关闭这个功能,可以使用上面的代码。

编译 CoffeeScript

  1. elixir(function(mix) {
  2. mix.coffee();
  3. });

在上述例子中,Elixir 会假设你的 CoffeeScript 文件保存在 resources/assets/coffee 里。

编译所有的 Less 及 CoffeeScript

  1. elixir(function(mix) {
  2. mix.less()
  3. .coffee();
  4. });

触发 PHPUnit 测试

  1. elixir(function(mix) {
  2. mix.phpUnit();
  3. });

触发 PHPSpec 测试

  1. elixir(function(mix) {
  2. mix.phpSpec();
  3. });

合并样式文件

  1. elixir(function(mix) {
  2. mix.styles([
  3. "normalize.css",
  4. "main.css"
  5. ]);
  6. });

传递给此方法的文件路径均相对于 resources/asssets/css 目录。

合并样式文件且保存在自定义的路径

  1. elixir(function(mix) {
  2. mix.styles([
  3. "normalize.css",
  4. "main.css"
  5. ], 'public/build/css/everything.css');
  6. });

从特定相对目录合并样式文件

  1. elixir(function(mix) {
  2. mix.styles([
  3. "normalize.css",
  4. "main.css"
  5. ], 'public/build/css/everything.css', 'public/css');
  6. });

stylesscrtips 方法可以通过传入第三个参数来决定来源文件的相对目录。

合并指定目录里所有的样式文件

  1. elixir(function(mix) {
  2. mix.stylesIn("public/css");
  3. });

合并脚本文件

  1. elixir(function(mix) {
  2. mix.scripts([
  3. "jquery.js",
  4. "app.js"
  5. ]);
  6. });

同样的,传递给此方法的文件路径均相对于 resources/assets/js 目录

合并指定目录里所有的脚本文件

  1. elixir(function(mix) {
  2. mix.scriptsIn("public/js/some/directory");
  3. });

合并多组脚本文件

  1. elixir(function(mix) {
  2. mix.scripts(['jquery.js', 'main.js'], 'public/js/main.js')
  3. .scripts(['forum.js', 'threads.js'], 'public/js/forum.js');
  4. });

压缩文件并加上哈希的版本号

  1. elixir(function(mix) {
  2. mix.version("css/all.css");
  3. });

这个动作会为你的文件名称加上独特的哈希值,以防止文件被缓存。举例来说,产生出来的文件名称可能像这样:all-16d570a7.css

接着在你的视图中,你能够使用 elixir() 函数来正确加载名称被哈希后的文件。举例如下:

  1. <link rel="stylesheet" href="{{ elixir("css/all.css") }}">

程序的作用下,elixir() 函数会将参数内的源文件名转换成被哈希后的文件名并加载。是否有如释重担的感觉呢?

您也可以传给一个数组给 version 方法来为多个文件进行版本管理:

  1. elixir(function(mix) {
  2. mix.version(["css/all.css", "js/app.js"]);
  3. });
  1. <link rel="stylesheet" href="{{ elixir("css/all.css") }}">
  2. <script src="{{ elixir("js/app.js") }}"></script>

复制文件到新的位置

  1. elixir(function(mix) {
  2. mix.copy('vendor/foo/bar.css', 'public/css/bar.css');
  3. });

将整个目录都复制到新的位置

  1. elixir(function(mix) {
  2. mix.copy('vendor/package/views', 'resources/views');
  3. });

Trigger Browserify

  1. elixir(function(mix) {
  2. mix.browserify('index.js');
  3. });

Want to require modules in the browser? Hoping to use EcmaScript 6 sooner than later? Need a built-in JSX transformer? If so, Browserify, along with the browserify Elixir task, will handle the job nicely.

This task assumes that your scripts are stored in resources/assets/js, though you're free to override the default.

方法连接

当然,你能够串连 Elixir 大部份的方法来建立一连串的任务:

  1. elixir(function(mix) {
  2. mix.less("app.less")
  3. .coffee()
  4. .phpUnit()
  5. .version("css/bootstrap.css");
  6. });

Gulp

现在你已经告诉 Elixir 要执行的任务,接着只需要在命令行执行 Gulp。

执行一次所有注册的任务

  1. gulp

监控文件变更

  1. gulp watch

仅编译 javascript

  1. gulp scripts

仅编译 css 样式

  1. gulp styles

监控测试以及 PHP 类的变更

  1. gulp tdd

提示: 所有的任务都会使用开发环境进行,所以压缩功能不会被执行。如果要使用上线环境,可以使用 gulp --production

Custom Tasks and Extensions

Sometimes, you'll want to hook your own Gulp tasks into Elixir. Perhaps you have a special bit of functionality that you'd like Elixir to mix and watch for you. No problem!

As an example, imagine that you have a general task that simply speaks a bit of text when called.

  1. gulp.task("speak", function() {
  2. var message = "Tea...Earl Grey...Hot";
  3. gulp.src("").pipe(shell("say " + message));
  4. });

Easy enough. From the command line, you may, of course, call gulp speak to trigger the task. To add it to Elixir, however, use the mix.task() method:

  1. elixir(function(mix) {
  2. mix.task('speak');
  3. });

That's it! Now, each time you run Gulp, your custom "speak" task will be executed alongside any other Elixir tasks that you've mixed in. To additionally register a watcher, so that your custom tasks will be re-triggered each time one or more files are modified, you may pass a regular expression as the second argument.

  1. elixir(function(mix) {
  2. mix.task('speak', 'app/**/*.php');
  3. });

By adding this second argument, we've instructed Elixir to re-trigger the "speak" task each time a PHP file in the "app/" directory is saved.

For even more flexibility, you can create full Elixir extensions. Using the previous "speak" example, you may write an extension, like so:

  1. var gulp = require("gulp");
  2. var shell = require("gulp-shell");
  3. var elixir = require("laravel-elixir");
  4. elixir.extend("speak", function(message) {
  5. gulp.task("speak", function() {
  6. gulp.src("").pipe(shell("say " + message));
  7. });
  8. return this.queueTask("speak");
  9. });

请注意我们 扩增( extend ) Elixir 的 API 时所使用的第一个参数,稍后我们需要在 Gulpfile 中使用它,以及建立 Gulp 任务所使用的回调函数。

如果你想要让你的自定义任务能被监控,只要在监控器注册就行了。

  1. this.registerWatcher("speak", "app/**/*.php");

这行程序的意思是指,当符合正则表达式 app/**/*.php 的文件一经修改,就会触发 message 任务。

很好!接着你可以将这行程序写在 Gulpfile 的顶端,或者将它放到自定义任务的文件里。如果你选择后者,那么你必须将它加载至你的 Gulpfile,例如:

  1. require("./custom-tasks")

大功告成!最后你只需要将他们结合。

  1. elixir(function(mix) {
  2. mix.speak("Tea, Earl Grey, Hot");
  3. });

加入之后,每当你触发 Gulp,Picard 就会要求一些茶。