[ Laravel 5.3 文档 ] JavaScript & CSS —— 编译资源(Laravel Elixir)

1、简介

Laravel Elixir 提供了一套干净、平滑的 API 用于为 Laravel 应用定义基本的Gulp任务。Elixir 支持一些通用的 CSS 和 JavaScript 预处理器,甚至测试工具。使用方法链,Elixir 允许你平滑的定义资源管道。例如:

elixir(function(mix) {
    mix.sass('app.scss')
       .coffee('app.coffee');
});

如果你曾经对如何使用 Gulp 和编译前端资源感到困惑,那么你会爱上 Laravel  Elixir。不过,并不是强制要求在开发期间使用它。你可以自由选择使用任何前端资源管道工具,或者压根不使用。

2、安装 & 设置

安装 Node

在开始 Elixir 之前,必须首先确保 Node.js 在机器上已经安装:

node -v
npm -v

默认情况下,Laravel Homestead 包含你需要的一切;然而,如果你不使用 Vagrant,你也可以通过访问Node的下载页面轻松的安装 Node。

Gulp

接下来,需要安装 Gulp 作为全局 NPM 包:

npm install --global gulp-cli

Laravel Elixir

最后,在新安装的 Laravel 根目录下,你会发现有一个 package.json 文件。该文件和 composer.json 一样,只不过是用来定义 Node 依赖而非 PHP 依赖,你可以通过运行如下命令来安装需要的依赖:

npm install

如果你正在 Windows 系统上开发,需要在运行 npm install 命令时带上 --no-bin-links

npm install --no-bin-links

3、运行Elixir

Elixir 基于 Gulp,所以要运行 Elixir 命令你只需要在终端中运行 gulp 命令即可。添加 --production 标识到命令将会最小化 CSS 和 JavaScript 文件:

// Run all tasks...
gulp

// Run all tasks and minify all CSS and JavaScript...
gulp --production

运行这个命令的时候,你会看到一个显示刚刚发生事件的格式良好的表格。

监控前端资源改变

由于每次修改前端资源后都要运行 gulp 很不方便,可以使用 gulp watch 命令。该命令将会一直在终端运行并监控前端文件的改动。当改变发生时,新文件将会自动被编译:

gulp watch

4、处理样式表

项目根目录下的 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 文件。同样,该文件会被放到 public/css/app.css

elixir(function(mix) {
    mix.less([
        'app.less',
        'controllers.less'
    ]);
});

如果你想要自定义编译后文件的输出位置,可以传递第二个参数到 less 方法:

elixir(function(mix) {
    mix.less('app.less', 'public/stylesheets');
});

// Specifying a specific output filename...
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 方法一样,你可以将多个脚本编译成单个 CSS 文件,甚至自定义结果 CSS 的输出路径:

elixir(function(mix) {
    mix.sass([
        'app.scss',
        'controllers.scss'
    ], 'public/assets/css');
});

自定义路径

尽管我们推荐你使用默认的前端资源目录,但是如果你确实需要设置其它目录,可以在相应文件路径前加上 ./ ,这表明Elixir将会从项目根目录开始寻找文件,而不是使用默认的根目录。

例如,要编译 app/assets/sass/app.scss 然后将编译后文件输出到 public/css/app.css ,可以这样调用 sass 方法:

elixir(function(mix) {
    mix.sass('./app/assets/sass/app.scss');
});

Stylus

stylus方法可用于将Stylus编译成CSS。假设你的Stylus文件存放在 resources/assets/stylus ,那么可以这样调用该方法:

elixir(function(mix) {
    mix.stylus('app.styl');
});

注:该方法的调用和 mix.less()mix.sass() 类似。

原生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');
});

源地图

在Elixir中,源地图 默认 被启用,以便在编译前端资源的时候为浏览器开发者工具提供更好的调试信息。对于每一个被编译过的文件都可以在同一目录下找到一个对应的 *.css.map 或 *.js.map 文件。

如果你不想让应用 生成源地图,可以通过 sourcemaps 配置选项关闭它们:

elixir.config.sourcemaps = false;

elixir(function(mix) {
    mix.sass('app.scss');
});

5、处理脚本

Elixir 还提供了多个函数帮助你处理 JavaScript 文件,例如编译 ECMAScript 2015,模块管理,最小化以及合并原生JavaScript文件。

使用模块编写ES2015的时候,可以选择 Webpack 或 Rollup ,如果你对这些工具很陌生,别担心,Elixir会为你处理所有背后的复杂逻辑。默认情况下,Laravel的 gulpfile 使用 webpack 来编译JavaScript,当然,你也可以选择使用自己喜欢的模块管理器。

Webpack

webpack 方法用于将 ECMAScript 2015 编译打包成原生JavaScript,该方法接收一个相对于 resources/assets/js 目录的文件路径,然后在 public/js 目录下生成单个打包文件:

elixir(function(mix) {
    mix.webpack('app.js');
});

要选择其他输出目录,只需在目标路径前加上 . 前缀,然后指定一个相对于应用根目录的相对路径。例如,要编译 app/assets/js/app.jspublic/dist/app.js

elixir(function(mix) {
    mix.webpack(
        './resources/assets/js/app.js',
        './public/dist'
    );
});

如果你想要使用Webpack的更多功能,可以利用应用根目录下的 webpack.config.js 文件,Elixir将会读取该文件并将其中的配置用于构建过程。

Rollup

和Webpack相似,Rollup是为ES2015准备的下一代模块管理器,该方法接收一个相对于 resources/assets/js 目录的文件数组,然后在 public/js 目录下生成单个文件:

elixir(function(mix) {
    mix.rollup('app.js');
});

webpack 方法一样,你也可以自定义传递给 rollup 方法的输入输出文件路径:

elixir(function(mix) {
    mix.rollup(
        './resources/assets/js/app.js',
        './public/dist'
    );
});

脚本

如果你有多个 JavaScript 文件想要编译成单个文件,可以使用 scripts 方法。

scripts 方法假定所有路径相对于 resources/assets/js 目录,而且所有结果 JavaScript 默认存放在public/js/all.js

elixir(function(mix) {
    mix.scripts([
        'order.js',
        'forum.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');
});

注:如果你要合并多个已经最小化的vendor库文件,例如jQuery,可以考虑使用 mix.combine() ,这将会合并这些文件,略过源地图和最小化步骤。最终,编译消耗时间将会大幅减小。

6、拷贝文件/目录

你可以使用 copy 方法拷贝文件/目录到新路径,所有操作都相对于项目根目录:

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

7、版本号/缓存刷新

很多开发者会给编译的前端资源添加时间戳或者唯一令牌后缀以强制浏览器加载最新版本而不是代码的缓存副本。Elixir 可以使用 version 方法为你处理这种情况。

version 方法接收相对于 public 目录的文件名,附加唯一hash到文件名,从而实现缓存刷新。例如,生成的文件名看上去是这样——all-16d570a7.css

elixir(function(mix) {
    mix.version('css/all.css');
});

生成版本文件后,可以在视图中使用 Elixir 全局的 PHP 帮助函数 elixir 方法来加载相应的带hash值的前端资源,elixir 函数会自动判断hash文件名:

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

给多个文件加上版本号

你可以传递一个数组到 version 方法来为多个文件添加版本号:

elixir(function(mix) {
    mix.version(['css/all.css', 'js/app.js']);
});

文件被加上版本号后,就可以使用辅助函数 elixir 来生成指向该hash文件的链接。记住,你只需要传递没有hash值的文件名到elixir方法。该帮助函数使用未加hash值的文件名来判断文件当前的hash版本:

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

<script src="{{ elixir('js/app.js') }}"></script>

8、BrowserSync

BrowserSync 会在你修改前端资源后自动刷新浏览器, browserSync 方法接收一个JavaScript对象,该对象有一个包含本地应用URL的属性—— proxy 。当你运行 gulp watch 命令时,可以通过3000端口( http://project.dev:3000 )享受浏览器同步:

elixir(function(mix) {
    mix.browserSync({
        proxy: 'project.dev'
    });
});

学院君

学院君 has written 550 articles

资深PHP工程师,Laravel学院院长