编译资源 (Mix)
介绍
Laravel Mix 是由 Laracasts 创始人 Jeffrey Way 开发的一个包,它为定义 Laravel 应用程序的 webpack 构建步骤提供了一个流畅的 API,使用了几种常见的 CSS 和 JavaScript 预处理器。
换句话说,Mix 使得编译和压缩应用程序的 CSS 和 JavaScript 文件变得轻而易举。通过简单的方法链,您可以流畅地定义您的资源管道。例如:
mix.js('resources/js/app.js', 'public/js')
.postCss('resources/css/app.css', 'public/css');
如果您曾经对如何开始使用 webpack 和资源编译感到困惑和不知所措,您会喜欢 Laravel Mix。然而,在开发应用程序时,您并不需要使用它;您可以自由选择任何资源管道工具,甚至可以不使用任何工具。
如果您需要一个使用 Laravel 和 Tailwind CSS 构建应用程序的快速入门,请查看我们的 应用程序启动套件。
安装与设置
安装 Node
在运行 Mix 之前,您必须首先确保您的机器上安装了 Node.js 和 NPM:
node -v
npm -v
您可以通过 Node 官方网站 的简单图形安装程序轻松安装最新版本的 Node 和 NPM。或者,如果您使用 Laravel Sail,您可以通过 Sail 调用 Node 和 NPM:
./sail node -v
./sail npm -v
安装 Laravel Mix
剩下的唯一步骤是安装 Laravel Mix。在 Laravel 的全新安装中,您会在目录结构的根目录中找到一个 package.json
文件。默认的 package.json
文件已经包含了开始使用 Laravel Mix 所需的一切。可以将此文件视为 composer.json
文件,但它定义的是 Node 依赖项而不是 PHP 依赖项。您可以通过运行以下命令安装它引用的依赖项:
npm install
运行 Mix
Mix 是 webpack 之上的一个配置层,因此要运行您的 Mix 任务,您只需执行默认 Laravel package.json
文件中包含的 NPM 脚本之一。当您运行 dev
或 production
脚本时,所有应用程序的 CSS 和 JavaScript 资源将被编译并放置在应用程序的 public
目录中:
// 运行所有 Mix 任务...
npm run dev
// 运行所有 Mix 任务并压缩输出...
npm run prod
监视资源的更改
npm run watch
命令将在您的终端中继续运行,并监视所有相关的 CSS 和 JavaScript 文件的更改。当检测到这些文件之一的更改时,Webpack 将自动重新编译您的资源:
npm run watch
在某些本地开发环境中,Webpack 可能无法检测到您的文件更改。如果您的系统上出现这种情况,请考虑使用 watch-poll
命令:
npm run watch-poll
处理样式表
应用程序的 webpack.mix.js
文件是所有资源编译的入口点。可以将其视为 webpack 之上的轻量配置包装器。Mix 任务可以链接在一起,以定义资源应如何编译。
Tailwind CSS
Tailwind CSS 是一个现代的、以实用为先的框架,用于在不离开 HTML 的情况下构建出色的网站。让我们深入了解如何在 Laravel 项目中使用 Laravel Mix 开始使用它。首先,我们应该使用 NPM 安装 Tailwind 并生成我们的 Tailwind 配置文件:
npm install
npm install -D tailwindcss
npx tailwindcss init
init
命令将生成一个 tailwind.config.js
文件。此文件的 content
部分允许您配置所有 HTML 模板、JavaScript 组件和任何其他包含 Tailwind 类名的源文件的路径,以便在生产 CSS 构建中删除未在这些文件中使用的任何 CSS 类:
content: [
'./storage/framework/views/*.php',
'./resources/**/*.blade.php',
'./resources/**/*.js',
'./resources/**/*.vue',
],
接下来,您应该将 Tailwind 的每个“层”添加到应用程序的 resources/css/app.css
文件中:
@tailwind base;
@tailwind components;
@tailwind utilities;
一旦您配置了 Tailwind 的层,您就可以更新应用程序的 webpack.mix.js
文件以编译您的 Tailwind 驱动的 CSS:
mix.js('resources/js/app.js', 'public/js')
.postCss('resources/css/app.css', 'public/css', [
require('tailwindcss'),
]);
最后,您应该在应用程序的主布局模板中引用您的样式表。许多应用程序选择将此模板存储在 resources/views/layouts/app.blade.php
中。此外,请确保添加响应式视口 meta
标签(如果尚未存在):
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="/css/app.css" rel="stylesheet">
</head>
PostCSS
PostCSS 是一个强大的 CSS 转换工具,Laravel Mix 开箱即用地包含了它。默认情况下,Mix 利用流行的 Autoprefixer 插件自动应用所有必要的 CSS3 供应商前缀。然而,您可以自由添加任何适合您应用程序的其他插件。
首先,通过 NPM 安装所需的插件,并在调用 Mix 的 postCss
方法时将其包含在插件数组中。postCss
方法接受 CSS 文件的路径作为第一个参数,并接受编译文件应放置的目录作为第二个参数:
mix.postCss('resources/css/app.css', 'public/css', [
require('postcss-custom-properties')
]);
或者,您可以在没有其他插件的情况下执行 postCss
以实现简单的 CSS 编译和压缩:
mix.postCss('resources/css/app.css', 'public/css');
Sass
sass
方法允许您将 Sass 编译为浏览器可以理解的 CSS。sass
方法接受 Sass 文件的路径作为第一个参数,并接受编译文件应放置的目录作为第二个参数:
mix.sass('resources/sass/app.scss', 'public/css');
您可以将多个 Sass 文件编译为各自的 CSS 文件,甚至可以通过多次调用 sass
方法自定义生成的 CSS 的输出目录:
mix.sass('resources/sass/app.sass', 'public/css')
.sass('resources/sass/admin.sass', 'public/css/admin');
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/sass/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();
源映射的样式
Webpack 提供了多种 源映射样式。默认情况下,Mix 的源映射样式设置为 eval-source-map
,这提供了快速的重建时间。如果您想更改映射样式,可以使用 sourceMaps
方法:
let productionSourceMaps = false;
mix.js('resources/js/app.js', 'public/js')
.sourceMaps(productionSourceMaps, 'source-map');
处理 JavaScript
Mix 提供了多种功能来帮助您处理 JavaScript 文件,例如编译现代 ECMAScript、模块打包、压缩和连接普通 JavaScript 文件。更好的是,这一切都可以无缝工作,无需任何自定义配置:
mix.js('resources/js/app.js', 'public/js');
通过这一行代码,您现在可以利用:
- 最新的 EcmaScript 语法。
- 模块
- 生产环境的压缩。
Vue
使用 vue
方法时,Mix 将自动安装支持 Vue 单文件组件编译所需的 Babel 插件。无需进一步配置:
mix.js('resources/js/app.js', 'public/js')
.vue();
一旦您的 JavaScript 编译完成,您可以在应用程序中引用它:
<head>
<!-- ... -->
<script src="/js/app.js"></script>
</head>
React
Mix 可以自动安装支持 React 所需的 Babel 插件。要开始,请添加对 react
方法的调用:
mix.js('resources/js/app.jsx', 'public/js')
.react();
在后台,Mix 将下载并包含适当的 babel-preset-react
Babel 插件。一旦您的 JavaScript 编译完成,您可以在应用程序中引用它:
<head>
<!-- ... -->
<script src="/js/app.js"></script>
</head>
供应商提取
将所有应用程序特定的 JavaScript 与供应商库(如 React 和 Vue)捆绑在一起的一个潜在缺点是,它使长期缓存变得更加困难。例如,对应用程序代码的单次更新将迫使浏览器重新下载所有供应商库,即使它们没有更改。
如果您打算频繁更新应用程序的 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>
自定义 Webpack 配置
有时,您可能需要手动修改底层的 Webpack 配置。例如,您可能有一个需要引用的特殊加载器或插件。
Mix 提供了一个有用的 webpackConfig
方法,允许您合并任何简短的 Webpack 配置覆盖。这特别有吸引力,因为它不需要您复制和维护自己的 webpack.config.js
文件副本。webpackConfig
方法接受一个对象,该对象应包含您希望应用的任何 Webpack 特定配置。
mix.webpackConfig({
resolve: {
modules: [
path.resolve(__dirname, 'vendor/laravel/spark/resources/assets/js')
]
}
});
版本控制 / 缓存清除
许多开发人员在编译的资源后缀上添加时间戳或唯一标记,以强制浏览器加载新鲜的资源,而不是提供陈旧的代码副本。Mix 可以使用 version
方法自动处理此问题。
version
方法将为所有编译文件附加一个唯一的哈希,以便更方便地进行缓存清除:
mix.js('resources/js/app.js', 'public/js')
.version();
生成版本化文件后,您将不知道确切的文件名。因此,您应该在 视图 中使用 Laravel 的全局 mix
函数来加载适当的哈希资源。mix
函数将自动确定哈希文件的当前名称:
<script src="{{ mix('/js/app.js') }}"></script>
由于在开发中通常不需要版本化文件,您可以指示版本化过程仅在 npm run prod
期间运行:
mix.js('resources/js/app.js', 'public/js');
if (mix.inProduction()) {
mix.version();
}
自定义 Mix 基础 URL
如果您的 Mix 编译资源部署到与应用程序分开的 CDN,您将需要更改 mix
函数生成的基础 URL。您可以通过在应用程序的 config/app.php
配置文件中添加 mix_url
配置选项来实现:
'mix_url' => env('MIX_ASSET_URL', null)
配置 Mix URL 后,mix
函数将在生成资源的 URL 时添加配置的 URL 前缀:
https://cdn.example.com/js/app.js?id=1964becbdd96414518cd
Browsersync 重新加载
BrowserSync 可以自动监视您的文件更改,并将更改注入浏览器,而无需手动刷新。您可以通过调用 mix.browserSync()
方法启用对此的支持:
mix.browserSync('laravel.test');
可以通过将 JavaScript 对象传递给 browserSync
方法来指定 BrowserSync 选项:
mix.browserSync({
proxy: 'laravel.test'
});
接下来,使用 npm run watch
命令启动 webpack 的开发服务器。现在,当您修改脚本或 PHP 文件时,您可以看到浏览器立即刷新页面以反映您的更改。
环境变量
您可以通过在 .env
文件中的环境变量前加上 MIX_
前缀,将环境变量注入到 webpack.mix.js
脚本中:
MIX_SENTRY_DSN_PUBLIC=http://example.com
在 .env
文件中定义变量后,您可以通过 process.env
对象访问它。然而,如果环境变量的值在任务运行时发生变化,您将需要重新启动任务:
process.env.MIX_SENTRY_DSN_PUBLIC
通知
在可用时,Mix 将在编译时自动显示操作系统通知,立即反馈编译是否成功。然而,在某些情况下,您可能希望禁用这些通知。例如,在生产服务器上触发 Mix。可以使用 disableNotifications
方法停用通知:
mix.disableNotifications();