(1)配置 webpack.mix.js 指定 Mix 任务
最后更新于:2022-04-02 01:42:03
`webpack.mix.js` 文件位于项目根目录下,是所有资源编译的入口,可以将其看作 Webpack 的轻量级**配置封装层**。Mix 任务以方法链的方式,被链在一起来定义前端资源如何被编译。
默认版如下:
~~~javascript
let mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
~~~
[TOC]
## API 概览
~~~javascript
mix.js(src, output);
mix.react(src, output); // Identical to mix.js(), but registers React Babel compilation.
mix.ts(src, output); // Requires tsconfig.json to exist in the same folder as webpack.mix.js
mix.extract(vendorLibs);
mix.sass(src, output);
mix.standaloneSass('src', output); // Faster, but isolated from Webpack.
mix.fastSass('src', output); // Alias for mix.standaloneSass().
mix.less(src, output);
mix.stylus(src, output);
mix.postCss(src, output, [require('postcss-some-plugin')()]);
mix.browserSync('my-site.dev');
mix.combine(files, destination);
mix.babel(files, destination); // Identical to mix.combine(), but also includes Babel compilation.
mix.copy(from, to);
mix.copyDirectory(fromDir, toDir);
mix.minify(file);
mix.sourceMaps(); // Enable sourcemaps
mix.version(); // Enable versioning.
mix.disableNotifications();
mix.setPublicPath('path/to/public');
mix.setResourceRoot('prefix/for/resource/locators');
mix.autoload({}); // Will be passed to Webpack's ProvidePlugin.
mix.webpackConfig({}); // Override webpack.config.js, without editing the file directly.
mix.then(function () {}); // Will be triggered each time Webpack finishes building.
mix.options({
extractVueStyles: false, // Extract .vue component styling to file, rather than inline.
globalVueStyles: file, // Variables file to be imported in every component.
processCssUrls: true, // Process/optimize relative stylesheet url()'s. Set to false, if you don't want them touched.
purifyCss: false, // Remove unused CSS selectors.
uglify: {}, // Uglify-specific options. https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
postCss: [] // Post-CSS options: https://github.com/postcss/postcss/blob/master/docs/plugins.md
});
~~~
## 处理样式表
### 处理 Sass
`sass` 方法将 Sass 编译成 CSS。
1. 编译 `app.scss` 文件到 `public/css/app.css`:
~~~javascript
mix.sass('resources/assets/sass/app.scss', 'public/css');
~~~
2. 多次调用 `sass` 方法可用于编译多个文件:
~~~javascript
mix.sass('resources/assets/sass/app.sass', 'public/css')
.sass('resources/assets/sass/admin.sass', 'public/css');
~~~
3. 如果要自定义编译后文件的输出位置,可以将完整的路径信息作为第二个参数传递到 `sass` 方法:
~~~javascript
mix.sass('resources/assets/sass/app.sass', 'public/stylesheets/styles.css');
~~~
* [Node-Sass 插件选项 ](https://github.com/sass/node-sass#options) 可以作为第三个参数:
~~~javascript
mix.sass('resources/assets/sass/app.sass', 'public/css', {
precision: 5
});
~~~
### 处理 Less
`less` 方法将 Less 编译成 CSS。
1. 编译 `app.less` 文件到 `public/css/app.css`:
~~~javascript
mix.less('resources/assets/less/app.less', 'public/css');
~~~
2. 和 `sass` 方法一样,也可以多次调用 `less` 方法以编译多个文件,甚至自定义结果 CSS 的输出路径:
~~~javascript
mix.less('resources/assets/less/app.less', 'public/css')
.less('resources/assets/less/admin.less', 'public/css/admin');
~~~
* [Less 插件选项](https://github.com/webpack-contrib/less-loader#options) 可以作为第三个参数:
~~~javascript
mix.less('resources/assets/less/app.less', 'public/css', {
strictMath: true
});
~~~
### 处理原生 CSS
`styles` 方法,将多个原生 CSS 样式文件合并到一个文件:
~~~javascript
mix.styles([
'public/css/vendor/normalize.css',
'public/css/vendor/videojs.css'
], 'public/css/all.css');
~~~
### 资源映射 Source Map
Source Map 默认被禁用,但可以通过调用 `sourceMaps` 方法来激活。
尽管这会带来编译/性能开销,不过在编译资源的时候,可以提供额外的调试信息给浏览器的开发者工具。
~~~javascript
mix.js('resources/assets/js/app.js', 'public/js')
.sourceMaps();
~~~
## 处理脚本
Mix 还提供了多个特性来处理 JavaScript 文件,例如编译 ECMAScript 2015,模块捆绑,最小化以及合并原生 JavaScript 文件。
这些都是无缝集成的,不需要额外的自定义配置:
~~~javascript
mix.js('resources/assets/js/app.js', 'public/js');
~~~
通过这一行代码,你可以实现如下功能:
> 1. ES2015 语法
> 2. 模块
> 3. 编译 `.vue` 文件
> 4. 生产环境压缩代码
### 提取依赖库
捆绑所有应用特定 JavaScript 和 vendor 库的一个潜在缺点是进行长期缓存将变得更加困难,例如,单个更新应用代码将会强制浏览器下载所有 vendor 库,即使它们并没有更新。
如果你想要频繁更新应用的 JavaScript,需要考虑对 vendor 库进行提取和拆分,这样的话,一次修改应用代码不会影响 `vendor.js` 文件的缓存。
`extract` 方法可以接收包含所有库的数组,或你想要提取到 vendor.js 文件的模块:
~~~javascript
mix.js('resources/assets/js/app.js', 'public/js')
.extract(['vue', 'jquery']);
~~~
使用上述代码作为示例,Mix将会生成如下文件:
* `public/js/manifest.js`:Webpack manifest runtime
* `public/js/vendor.js`:vendor 库
* `public/js/app.js`:应用代码
为避免 JavaScript 错误,需要页面确保以正确的顺序加载这些文件:
~~~html
~~~
### 处理原生 JS
`scripts` 方法,可以合并&压缩多个 JavaScript 文件:
~~~javascript
mix.scripts([
'public/js/admin.js',
'public/js/dashboard.js'
], 'public/js/all.js');
~~~
这个选项对于不需要为 JavaScript 编写 Webpack 的旧项目非常有用。
>[info] `mix.scripts()` 的一个微小变化是 `mix.babel()`。其方法签名与 `scripts` 一样。不过,连接的文件会经过 Babel 编译,将所有 ES2015 的代码转换为所有浏览器都能识别的原生 JavaScript。
## 自定义 Webpack 配置
在场景背后,Laravel Mix 引用了预配置的 `webpack.config.js` 文件来尽可能快的启动和运行。
默认应用的配置文件为 `node_modules/laravel-mix/setup/webpack.config.js`。
使用 `webpackConfig` 方法可以覆盖默认的 Webpack 配置。方法接收一个对象,该对象包含了任意你想要应用的 [Webpack 指定配置](https://webpack.js.org/configuration/)。
## 代码压缩
### CSS 代码压缩
使用 [`optimize-css-assets-webpack-plugin`](http://npm.taobao.org/package/optimize-css-assets-webpack-plugin) 来压缩 CSS:
~~~javascript
mix.webpackConfig({
plugins: [
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true,
discardComments: {
removeAll: true
}
}
})
]
});
~~~
### JS 代码压缩
`options` 方法,传入任何需要的 [UglifyJsPlugin](https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin) 配置选项,JS 代码将在生产模式下自动被压缩。
默认配置如下:
~~~javascript
mix.options({
uglify: {
uglifyOptions: {
sourceMap: false, // 关闭资源映射
compress: {
warnings: false,
drop_console: true // 去除控制台输出代码
},
output: {
comments: false // 去除所有注释
}
}
}
});
~~~
选项解析:
属性 | 类型 | 默认值 | 描述
| --- | --- | --- | --- |
compress | boolean, object | true | [见 UglifyJS 文档](https://github.com/mishoo/UglifyJS2#compress-options)。
mangle | boolean, object | true | [见 UglifyJS 文档](https://github.com/mishoo/UglifyJS2#compress-options)。
beautify | boolean | false | 美化输出。
output | 一个提供 UglifyJS OutputStream 选项的对象 | | 更底层地访问 UglifyJS 输出。
comments | boolean, RegExp, function(astNode, comment) -> boolean | 默认保存包含 `/*!`, `/**!`, `@preserve` or `@license` 的注释 | 注释相关的配置。
sourceMap | boolean | false | 使用 SourceMaps 将错误信息的位置映射到模块。这会减慢编译的速度。
test | RegExp, Array | `/.js($|\?)/i` | 测试匹配的文件。
include | RegExp, Array | | 只测试包含的文件。
exclude | RegExp, Array | | 要从测试中排除的文件。
## 拷贝文件和目录
`copy` 方法拷贝文件和目录到新路径,这在将 `node_modules` 目录下的特定资源文件重新放置到 `public` 目录下时很有用:
~~~javascript
mix.copy('node_modules/foo/bar.css', 'public/css/bar.css');
~~~
复制目录时,`copy` 方法会平面化目录的结构。要维护目录的原始结构,应该使用 `copyDirectory` 方法:
~~~javascript
mix.copyDirectory('assets/img', 'public/img');
~~~
## 版本号和缓存刷新
`version` 方法为编译的前端资源添加时间戳或唯一令牌后缀,可以强制浏览器加载最新版本而不是代码的缓存副本。
该方法会自动附加唯一 hash 值到已编译文件名,从而方便实现缓存刷新:
~~~javascript
mix.js('resources/assets/js/app.js', 'public/js')
.version();
~~~
生成版本文件后,还不知提取的文件名,所以需要在 视图 中使用 Laravel 全局的 `mix` 函数来加载相应的带 hash 值的前端资源。`mix` 函数会自动判当前的 hash 文件名:
~~~html
~~~
由于版本文件在本地开发中没有什么用,可以使用 `inProduction` 方法,只在生产模式下进行版本处理操作:
~~~javascript
mix.js('resources/assets/js/app.js', 'public/js');
if (mix.inProduction()) {
mix.version();
}
~~~
## 修改后 `webpack.mix.js` 文件示例
~~~javascript
let mix = require('laravel-mix');
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
if (mix.inProduction()) {
// 生产模式下的特殊配置
mix.webpackConfig({
plugins: [
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true,
discardComments: {
removeAll: true
}
}
})
]
}).version();
}
~~~
';