(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(); } ~~~
';