webpack 快速入门 系列 —— 性能 (3)

重启服务,通过错误提示点击进去,则会看到如下代码:

class Dog { constructor(name) { this.name = name; } say() { console.log(this.name)(); // {1} } } new Dog('xiaole').say();

不在是编译后的代码,而是我们的源码,而且在行{1}处,对错误也有清晰的提示。

不同的值

source map 格式有多种不同的值,以下是笔者对其中几种值的研究结论:

devtool: 'source-map'

> npm run build 1. 会生成一个 dist/main.js.map 文件 2. 在 dist/main.js 最后一行,有如下一行代码: //# sourceMappingURL=main.js.map 3. 上文我们知道,调试能看到源码,官网文档的描述是 `quality 是 original` 4. 构建(build)速度和重建(rebuild)速度都是最慢(slowest) 5. 官网推荐其可作为生产的选择

devtool: inline-source-map

> npm run build 1. 没生成一个 dist/main.js.map 文件 2. 在 dist/main.js 最后一行,有如下一行代码: //# sourceMappingURL=data:application/json;charset= 3. 调试能看到源码 4. 构建(build)速度和重建(rebuild)速度都是最慢(slowest)

devtool: eval-source-map

> npm run build 1. 没生成一个 dist/main.js.map 文件 2. 在 dist/main.js 中有 15 处 sourceMappingURL。而 inline-source-map 只有一处。 3. 调试能看到源码 4. 构建(build)速度最慢(slowest),但重建(rebuild)速度正常(ok) 5. 官网推荐其可作为开发的选择

devtool: hidden-source-map

> npm run build 1. 生成一个 dist/main.js.map 文件 2. 点击错误提示,看到的是编译后的代码 Uncaught TypeError: console.log(...) is not a function main.js:11508 3. 构建(build)速度和重建(rebuild)速度都是最慢(slowest)

注:官网说 hidden-source-map 的品质是 original,但笔者这里却是编译后的!

如何选择

source map 有很多不同的值,我们该如何选择?

幸好官网给出了建议。

开发环境,我们要求构建速度要快,方便调试:

eval-source-map,每个模块使用 eval() 执行,并且 source map 转换为 DataUrl 后添加到 eval() 中。初始化 source map 时比较慢,但是会在重新构建时提供比较快的速度,并且生成实际的文件。行数能够正确映射,因为会映射到原始代码中。它会生成用于开发环境的最佳品质的 source map。

生成环境,考虑到代码是否要隐藏,是否需要方便调试:

source-map,整个 source map 作为一个单独的文件生成。它为 bundle 添加了一个引用注释,以便开发工具知道在哪里可以找到它。官网推荐其可作为生产的选择。

(none)(省略 devtool 选项),不生成 source map,也是一个不错的选择

Tip:若你还有一些特别的需求,就去官网寻找答案

oneOf

oneof 与下面程序的 break 作用类似:

let count = 1 for(; count < 10; count++){ if(count === 3){ break; } } console.log(`匹配了${count}次`) // 匹配了3次

这段代码,只要 count 等于 3,就会被 break 中断退出循环。

通常,我们会这样定义多个规则:

module: { rules: [{ test: /\.css$/i, loader: ... }, { test: /\.css$/i, loader: ... }, { test: /\.less$/i, loader: ... }, { test: /\.(png|jpg|gif)$/i, loader: ... } ... ]

当 a.css 匹配了第一个规则,还会继续尝试匹配剩余的规则。而我希望提高一下性能,只要匹配上,就不在匹配剩余规则。则可以使用 Rule.oneOf,就像这样:

module: { rules: [ { oneOf: [{ test: /\.css$/i, loader: ... }, { test: /\.less$/i, loader: ... }, { test: /\.(png|jpg|gif)$/i, loader: ... } ... ] } ]

如果同一种文件需要执行多个 loader,就像这里 css 有 2 个 loader。我们可以把其中一个 loader 提到 rules 中,就像这样:

module: { rules: [ { test: /\.css$/i, // 优先执行 enforce: 'pre' loader: ... }, { oneOf: [{ test: /\.css$/i, loader: ... }, ... ] } ]

Tip: 可以通过配置 enforce 指定优先执行该loader

缓存 babel 缓存

让第二次构建速度更快。

配置很简单,就是给 babel-loader 添加一个选项:

{ loader: 'babel-loader', options: { presets: [ ... ], // 开启缓存 cacheDirectory: true } }

Tip:因为要经过 babel-loader 编译,如果代码量太少,就不太准确,建议找大量的 es6 代码自行测试。

静态资源的缓存

Tip: 本小节讲的其实就是 hash、chunkhash和conenthash。

通常我们将代码编译到 dist 目录中,然后发布到服务器上,对于一些静态资源,我们会设置其缓存。

具体做法如下:

通过命令 npm run build 将代码编译到 dist 目录;

接着通过 express 启动服务,该服务会读取 dist 中的内容,相当于把代码发布到服务器上:

// 安装依赖 > npm i -D express@4 // 在项目根目录下创建一个服务:server.js const express = require('express') const app = express() const port = 3001 app.use(express.static('dist')); // 监听服务 app.listen(port, () => { console.log(`Example app listening at :${port}`) }) > nodemon server.js [nodemon] 2.0.7 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node server.js` Example app listening at :3001

通过浏览器访问 :3001,多刷新几次,在网络中会看见 main.js 的状态是 304,笔者这里的时间在2ms或5ms之间。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzzjsp.html