Skip to content

编译资源 (Mix)

介绍

Laravel Mix 提供了一种流畅的 API,用于为您的 Laravel 应用程序定义 Webpack 构建步骤,使用多种常见的 CSS 和 JavaScript 预处理器。通过简单的方法链,您可以流畅地定义您的资源管道。例如:

php
mix.js('resources/js/app.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

如果您曾经对如何开始使用 Webpack 和资源编译感到困惑和不知所措,您会喜欢 Laravel Mix。然而,在开发应用程序时,您并不需要使用它;您可以自由选择任何资源管道工具,甚至可以不使用任何工具。

安装与设置

安装 Node

在触发 Mix 之前,您必须首先确保您的机器上安装了 Node.js 和 NPM。

php
node -v
npm -v

默认情况下,Laravel Homestead 包含您所需的一切;然而,如果您不使用 Vagrant,您可以通过 下载页面 的简单图形安装程序轻松安装最新版本的 Node 和 NPM。

Laravel Mix

剩下的唯一步骤是安装 Laravel Mix。在 Laravel 的全新安装中,您会在目录结构的根目录中找到一个 package.json 文件。默认的 package.json 文件包含了您开始所需的一切。可以将其视为 composer.json 文件,但它定义的是 Node 依赖项而不是 PHP。您可以通过运行以下命令安装它引用的依赖项:

php
npm install

运行 Mix

Mix 是 Webpack 之上的一个配置层,因此要运行您的 Mix 任务,您只需执行默认 Laravel package.json 文件中包含的一个 NPM 脚本:

php
// 运行所有 Mix 任务...
npm run dev

// 运行所有 Mix 任务并压缩输出...
npm run production

监视资源的变化

npm run watch 命令将在您的终端中持续运行,并监视所有相关文件的变化。当检测到变化时,Webpack 将自动重新编译您的资源:

php
npm run watch

您可能会发现,在某些环境中,当文件更改时,Webpack 并没有更新。如果在您的系统上出现这种情况,请考虑使用 watch-poll 命令:

php
npm run watch-poll

处理样式表

webpack.mix.js 文件是您所有资源编译的入口点。可以将其视为 Webpack 的轻量配置包装器。Mix 任务可以链接在一起,以定义您的资源应如何编译。

Less

less 方法可用于将 Less 编译为 CSS。让我们将主要的 app.less 文件编译为 public/css/app.css

php
mix.less('resources/less/app.less', 'public/css');

可以多次调用 less 方法来编译多个文件:

php
mix.less('resources/less/app.less', 'public/css')
   .less('resources/less/admin.less', 'public/css');

如果您希望自定义编译 CSS 的文件名,可以将完整的文件路径作为 less 方法的第二个参数传递:

php
mix.less('resources/less/app.less', 'public/stylesheets/styles.css');

如果您需要覆盖 底层 Less 插件选项,可以将对象作为第三个参数传递给 mix.less()

php
mix.less('resources/less/app.less', 'public/css', {
    strictMath: true
});

Sass

sass 方法允许您将 Sass 编译为 CSS。您可以这样使用该方法:

php
mix.sass('resources/sass/app.scss', 'public/css');

同样,像 less 方法一样,您可以将多个 Sass 文件编译为各自的 CSS 文件,甚至可以自定义生成的 CSS 的输出目录:

php
mix.sass('resources/sass/app.sass', 'public/css')
   .sass('resources/sass/admin.sass', 'public/css/admin');

可以提供额外的 Node-Sass 插件选项 作为第三个参数:

php
mix.sass('resources/sass/app.sass', 'public/css', {
    precision: 5
});

Stylus

与 Less 和 Sass 类似,stylus 方法允许您将 Stylus 编译为 CSS:

php
mix.stylus('resources/stylus/app.styl', 'public/css');

您还可以安装额外的 Stylus 插件,例如 Rupture。首先,通过 NPM 安装所需的插件 (npm install rupture),然后在调用 mix.stylus() 时引用它:

php
mix.stylus('resources/stylus/app.styl', 'public/css', {
    use: [
        require('rupture')()
    ]
});

PostCSS

PostCSS,一个强大的 CSS 转换工具,已在 Laravel Mix 中开箱即用。默认情况下,Mix 利用流行的 Autoprefixer 插件自动应用所有必要的 CSS3 供应商前缀。然而,您可以自由添加任何适合您应用程序的额外插件。首先,通过 NPM 安装所需的插件,然后在 webpack.mix.js 文件中引用它:

php
mix.sass('resources/sass/app.scss', 'public/css')
   .options({
        postCss: [
            require('postcss-css-variables')()
        ]
   });

纯 CSS

如果您只想将一些纯 CSS 样式表连接成一个文件,可以使用 styles 方法。

php
mix.styles([
    'public/css/vendor/normalize.css',
    'public/css/vendor/videojs.css'
], 'public/css/all.css');

URL 处理

由于 Laravel Mix 构建在 Webpack 之上,理解一些 Webpack 概念是很重要的。对于 CSS 编译,Webpack 将重写并优化样式表中的任何 url() 调用。虽然这听起来可能有些奇怪,但它是一个非常强大的功能。想象一下,我们想要编译包含相对 URL 的 Sass:

php
.example {
    background: url('../images/example.png');
}
exclamation

任何给定 url() 的绝对路径将被排除在 URL 重写之外。例如,url('/images/thing.png')url('http://example.com/images/thing.png') 不会被修改。

默认情况下,Laravel Mix 和 Webpack 将找到 example.png,将其复制到您的 public/images 文件夹,然后重写生成的样式表中的 url()。因此,编译后的 CSS 将是:

php
.example {
    background: url(/images/example.png?d41d8cd98f00b204e9800998ecf8427e);
}

虽然这个功能非常有用,但可能您的现有文件夹结构已经配置得很好。如果是这种情况,您可以像这样禁用 url() 重写:

php
mix.sass('resources/app/app.scss', 'public/css')
   .options({
      processCssUrls: false
   });

通过在 webpack.mix.js 文件中添加此项,Mix 将不再匹配任何 url() 或将资源复制到您的公共目录。换句话说,编译后的 CSS 将看起来就像您最初输入的那样:

php
.example {
    background: url("../images/thing.png");
}

源映射

虽然默认情况下是禁用的,但可以通过在 webpack.mix.js 文件中调用 mix.sourceMaps() 方法来激活源映射。虽然这会带来编译/性能成本,但这将为您在使用编译资源时提供额外的调试信息。

php
mix.js('resources/js/app.js', 'public/js')
   .sourceMaps();

处理 JavaScript

Mix 提供了多种功能来帮助您处理 JavaScript 文件,例如编译 ECMAScript 2015、模块打包、压缩和连接纯 JavaScript 文件。更好的是,这一切都能无缝工作,无需任何自定义配置:

php
mix.js('resources/js/app.js', 'public/js');

通过这一行代码,您现在可以利用:

  • ES2015 语法。
  • 模块
  • .vue 文件的编译。
  • 生产环境的压缩。

供应商提取

将所有应用程序特定的 JavaScript 与供应商库捆绑在一起的一个潜在缺点是,它使长期缓存变得更加困难。例如,对应用程序代码的单次更新将迫使浏览器重新下载所有供应商库,即使它们没有更改。

如果您打算频繁更新应用程序的 JavaScript,您应该考虑将所有供应商库提取到自己的文件中。这样,对应用程序代码的更改将不会影响大型 vendor.js 文件的缓存。Mix 的 extract 方法使这变得轻而易举:

php
mix.js('resources/js/app.js', 'public/js')
   .extract(['vue'])

extract 方法接受一个数组,其中包含您希望提取到 vendor.js 文件中的所有库或模块。使用上述代码片段作为示例,Mix 将生成以下文件:

  • public/js/manifest.js: Webpack 清单运行时
  • public/js/vendor.js: 您的供应商库
  • public/js/app.js: 您的应用程序代码

为了避免 JavaScript 错误,请确保按正确的顺序加载这些文件:

php
<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script>
<script src="/js/app.js"></script>

React

Mix 可以自动安装 React 支持所需的 Babel 插件。要开始,请将您的 mix.js() 调用替换为 mix.react()

php
mix.react('resources/js/app.jsx', 'public/js');

在后台,Mix 将下载并包含适当的 babel-preset-react Babel 插件。

Vanilla JS

类似于使用 mix.styles() 组合样式表,您也可以使用 scripts() 方法组合和压缩任意数量的 JavaScript 文件:

php
mix.scripts([
    'public/js/admin.js',
    'public/js/dashboard.js'
], 'public/js/all.js');

此选项对于不需要 Webpack 编译 JavaScript 的遗留项目特别有用。

lightbulb

mix.scripts() 的一个轻微变体是 mix.babel()。其方法签名与 scripts 相同;然而,连接的文件将接收 Babel 编译,这将任何 ES2015 代码转换为所有浏览器都能理解的普通 JavaScript。

自定义 Webpack 配置

在后台,Laravel Mix 引用了一个预配置的 webpack.config.js 文件,以便您能够快速启动并运行。偶尔,您可能需要手动修改此文件。您可能有一个需要引用的特殊加载器或插件,或者您可能更喜欢使用 Stylus 而不是 Sass。在这种情况下,您有两个选择:

合并自定义配置

Mix 提供了一个有用的 webpackConfig 方法,允许您合并任何简短的 Webpack 配置覆盖。这是一个特别有吸引力的选择,因为它不需要您复制和维护自己的 webpack.config.js 文件副本。webpackConfig 方法接受一个对象,该对象应包含您希望应用的任何 Webpack 特定配置

php
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 引用指向新复制的配置文件。如果您选择这种自定义方法,Mix 的 webpack.config.js 的任何未来上游更新都必须手动合并到您的自定义文件中。

复制文件和目录

copy 方法可用于将文件和目录复制到新位置。当 node_modules 目录中的特定资源需要重新定位到 public 文件夹时,这可能很有用。

php
mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');

在复制目录时,copy 方法将扁平化目录的结构。要保持目录的原始结构,您应该使用 copyDirectory 方法:

php
mix.copyDirectory('resources/img', 'public/img');

版本控制 / 缓存清除

许多开发人员在编译的资源后缀上添加时间戳或唯一标记,以强制浏览器加载新鲜的资源,而不是提供陈旧的代码副本。Mix 可以使用 version 方法为您处理此问题。

version 方法将自动将唯一的哈希附加到所有编译文件的文件名中,从而更方便地进行缓存清除:

php
mix.js('resources/js/app.js', 'public/js')
   .version();

生成版本化文件后,您将不知道确切的文件名。因此,您应该在 视图 中使用 Laravel 的全局 mix 函数来加载适当的哈希资源。mix 函数将自动确定哈希文件的当前名称:

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

由于在开发中通常不需要版本化文件,您可以指示版本化过程仅在 npm run production 期间运行:

php
mix.js('resources/js/app.js', 'public/js');

if (mix.inProduction()) {
    mix.version();
}

Browsersync 重新加载

BrowserSync 可以自动监视您的文件变化,并将您的更改注入浏览器,而无需手动刷新。您可以通过调用 mix.browserSync() 方法启用支持:

php
mix.browserSync('my-domain.test');

// 或者...

// https://browsersync.io/docs/options
mix.browserSync({
    proxy: 'my-domain.test'
});

您可以将字符串(代理)或对象(BrowserSync 设置)传递给此方法。接下来,使用 npm run watch 命令启动 Webpack 的开发服务器。现在,当您修改脚本或 PHP 文件时,浏览器会立即刷新页面以反映您的更改。

环境变量

您可以通过在 .env 文件中为键添加 MIX_ 前缀来将环境变量注入 Mix:

php
MIX_SENTRY_DSN_PUBLIC=http://example.com

.env 文件中定义变量后,您可以通过 process.env 对象访问它。如果在运行 watch 任务时值发生变化,您需要重新启动任务:

php
process.env.MIX_SENTRY_DSN_PUBLIC

通知

在可用时,Mix 将自动为每个包显示操作系统通知。这将为您提供即时反馈,告知编译是否成功。然而,在某些情况下,您可能希望禁用这些通知。例如,在生产服务器上触发 Mix。可以通过 disableNotifications 方法停用通知。

php
mix.disableNotifications();