编译资源 (Mix)
介绍
Laravel Mix 提供了一种流畅的 API,用于为您的 Laravel 应用程序定义 Webpack 构建步骤,使用多种常见的 CSS 和 JavaScript 预处理器。通过简单的方法链,您可以流畅地定义您的资源管道。例如:
mix.js('resources/js/app.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css');
如果您曾经对如何开始使用 Webpack 和资源编译感到困惑和不知所措,您会喜欢 Laravel Mix。然而,在开发应用程序时,您并不需要使用它;您可以自由选择任何资源管道工具,甚至可以不使用任何工具。
安装与设置
安装 Node
在触发 Mix 之前,您必须首先确保您的机器上安装了 Node.js 和 NPM。
node -v
npm -v
默认情况下,Laravel Homestead 包含您所需的一切;然而,如果您不使用 Vagrant,您可以通过 下载页面 的简单图形安装程序轻松安装最新版本的 Node 和 NPM。
Laravel Mix
剩下的唯一步骤是安装 Laravel Mix。在 Laravel 的全新安装中,您会在目录结构的根目录中找到一个 package.json
文件。默认的 package.json
文件包含了您开始所需的一切。可以将其视为 composer.json
文件,但它定义的是 Node 依赖项而不是 PHP。您可以通过运行以下命令安装它引用的依赖项:
npm install
运行 Mix
Mix 是 Webpack 之上的一个配置层,因此要运行您的 Mix 任务,您只需执行默认 Laravel package.json
文件中包含的一个 NPM 脚本:
// 运行所有 Mix 任务...
npm run dev
// 运行所有 Mix 任务并压缩输出...
npm run production
监视资源的变化
npm run watch
命令将在您的终端中持续运行,并监视所有相关文件的变化。当检测到变化时,Webpack 将自动重新编译您的资源:
npm run watch
您可能会发现,在某些环境中,当文件更改时,Webpack 并没有更新。如果在您的系统上出现这种情况,请考虑使用 watch-poll
命令:
npm run watch-poll
处理样式表
webpack.mix.js
文件是您所有资源编译的入口点。可以将其视为 Webpack 的轻量配置包装器。Mix 任务可以链接在一起,以定义您的资源应如何编译。
Less
less
方法可用于将 Less 编译为 CSS。让我们将主要的 app.less
文件编译为 public/css/app.css
。
mix.less('resources/less/app.less', 'public/css');
可以多次调用 less
方法来编译多个文件:
mix.less('resources/less/app.less', 'public/css')
.less('resources/less/admin.less', 'public/css');
如果您希望自定义编译 CSS 的文件名,可以将完整的文件路径作为 less
方法的第二个参数传递:
mix.less('resources/less/app.less', 'public/stylesheets/styles.css');
如果您需要覆盖 底层 Less 插件选项,可以将对象作为第三个参数传递给 mix.less()
:
mix.less('resources/less/app.less', 'public/css', {
strictMath: true
});
Sass
sass
方法允许您将 Sass 编译为 CSS。您可以这样使用该方法:
mix.sass('resources/sass/app.scss', 'public/css');
同样,像 less
方法一样,您可以将多个 Sass 文件编译为各自的 CSS 文件,甚至可以自定义生成的 CSS 的输出目录:
mix.sass('resources/sass/app.sass', 'public/css')
.sass('resources/sass/admin.sass', 'public/css/admin');
可以提供额外的 Node-Sass 插件选项 作为第三个参数:
mix.sass('resources/sass/app.sass', 'public/css', {
precision: 5
});
Stylus
与 Less 和 Sass 类似,stylus
方法允许您将 Stylus 编译为 CSS:
mix.stylus('resources/stylus/app.styl', 'public/css');
您还可以安装额外的 Stylus 插件,例如 Rupture。首先,通过 NPM 安装所需的插件 (npm install rupture
),然后在调用 mix.stylus()
时引用它:
mix.stylus('resources/stylus/app.styl', 'public/css', {
use: [
require('rupture')()
]
});
PostCSS
PostCSS,一个强大的 CSS 转换工具,已在 Laravel Mix 中开箱即用。默认情况下,Mix 利用流行的 Autoprefixer 插件自动应用所有必要的 CSS3 供应商前缀。然而,您可以自由添加任何适合您应用程序的额外插件。首先,通过 NPM 安装所需的插件,然后在 webpack.mix.js
文件中引用它:
mix.sass('resources/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()
调用。虽然这听起来可能有些奇怪,但它是一个非常强大的功能。想象一下,我们想要编译包含相对 URL 的 Sass:
.example {
background: url('../images/example.png');
}
任何给定 url()
的绝对路径将被排除在 URL 重写之外。例如,url('/images/thing.png')
或 url('http://example.com/images/thing.png')
不会被修改。
默认情况下,Laravel Mix 和 Webpack 将找到 example.png
,将其复制到您的 public/images
文件夹,然后重写生成的样式表中的 url()
。因此,编译后的 CSS 将是:
.example {
background: url(/images/example.png?d41d8cd98f00b204e9800998ecf8427e);
}
虽然这个功能非常有用,但可能您的现有文件夹结构已经配置得很好。如果是这种情况,您可以像这样禁用 url()
重写:
mix.sass('resources/app/app.scss', 'public/css')
.options({
processCssUrls: false
});
通过在 webpack.mix.js
文件中添加此项,Mix 将不再匹配任何 url()
或将资源复制到您的公共目录。换句话说,编译后的 CSS 将看起来就像您最初输入的那样:
.example {
background: url("../images/thing.png");
}
源映射
虽然默认情况下是禁用的,但可以通过在 webpack.mix.js
文件中调用 mix.sourceMaps()
方法来激活源映射。虽然这会带来编译/性能成本,但这将为您在使用编译资源时提供额外的调试信息。
mix.js('resources/js/app.js', 'public/js')
.sourceMaps();
处理 JavaScript
Mix 提供了多种功能来帮助您处理 JavaScript 文件,例如编译 ECMAScript 2015、模块打包、压缩和连接纯 JavaScript 文件。更好的是,这一切都能无缝工作,无需任何自定义配置:
mix.js('resources/js/app.js', 'public/js');
通过这一行代码,您现在可以利用:
- ES2015 语法。
- 模块
.vue
文件的编译。- 生产环境的压缩。
供应商提取
将所有应用程序特定的 JavaScript 与供应商库捆绑在一起的一个潜在缺点是,它使长期缓存变得更加困难。例如,对应用程序代码的单次更新将迫使浏览器重新下载所有供应商库,即使它们没有更改。
如果您打算频繁更新应用程序的 JavaScript,您应该考虑将所有供应商库提取到自己的文件中。这样,对应用程序代码的更改将不会影响大型 vendor.js
文件的缓存。Mix 的 extract
方法使这变得轻而易举:
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 错误,请确保按正确的顺序加载这些文件:
<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()
:
mix.react('resources/js/app.jsx', 'public/js');
在后台,Mix 将下载并包含适当的 babel-preset-react
Babel 插件。
Vanilla JS
类似于使用 mix.styles()
组合样式表,您也可以使用 scripts()
方法组合和压缩任意数量的 JavaScript 文件:
mix.scripts([
'public/js/admin.js',
'public/js/dashboard.js'
], 'public/js/all.js');
此选项对于不需要 Webpack 编译 JavaScript 的遗留项目特别有用。
mix.scripts()
的一个轻微变体是 mix.babel()
。其方法签名与 scripts
相同;然而,连接的文件将接收 Babel 编译,这将任何 ES2015 代码转换为所有浏览器都能理解的普通 JavaScript。
自定义 Webpack 配置
在后台,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
引用指向新复制的配置文件。如果您选择这种自定义方法,Mix 的 webpack.config.js
的任何未来上游更新都必须手动合并到您的自定义文件中。
复制文件和目录
copy
方法可用于将文件和目录复制到新位置。当 node_modules
目录中的特定资源需要重新定位到 public
文件夹时,这可能很有用。
mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');
在复制目录时,copy
方法将扁平化目录的结构。要保持目录的原始结构,您应该使用 copyDirectory
方法:
mix.copyDirectory('resources/img', 'public/img');
版本控制 / 缓存清除
许多开发人员在编译的资源后缀上添加时间戳或唯一标记,以强制浏览器加载新鲜的资源,而不是提供陈旧的代码副本。Mix 可以使用 version
方法为您处理此问题。
version
方法将自动将唯一的哈希附加到所有编译文件的文件名中,从而更方便地进行缓存清除:
mix.js('resources/js/app.js', 'public/js')
.version();
生成版本化文件后,您将不知道确切的文件名。因此,您应该在 视图 中使用 Laravel 的全局 mix
函数来加载适当的哈希资源。mix
函数将自动确定哈希文件的当前名称:
<script src="{{ mix('/js/app.js') }}"></script>
由于在开发中通常不需要版本化文件,您可以指示版本化过程仅在 npm run production
期间运行:
mix.js('resources/js/app.js', 'public/js');
if (mix.inProduction()) {
mix.version();
}
Browsersync 重新加载
BrowserSync 可以自动监视您的文件变化,并将您的更改注入浏览器,而无需手动刷新。您可以通过调用 mix.browserSync()
方法启用支持:
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:
MIX_SENTRY_DSN_PUBLIC=http://example.com
在 .env
文件中定义变量后,您可以通过 process.env
对象访问它。如果在运行 watch
任务时值发生变化,您需要重新启动任务:
process.env.MIX_SENTRY_DSN_PUBLIC
通知
在可用时,Mix 将自动为每个包显示操作系统通知。这将为您提供即时反馈,告知编译是否成功。然而,在某些情况下,您可能希望禁用这些通知。例如,在生产服务器上触发 Mix。可以通过 disableNotifications
方法停用通知。
mix.disableNotifications();