在此 Codelab 中,您可以通过 移除任何不使用和不需要的依赖项。
测量
建议您先衡量网站的效果 添加优化建议。
- 如需预览网站,请按查看应用。然后按 全屏 。
继续操作,点击你最喜欢的小猫!Firebase Realtime Database 是 因此得分会实时更新, 与使用该应用的所有其他用户同步。🐈
- 按 `Ctrl+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
- 点击网络标签页。
- 选中停用缓存复选框。
- 重新加载应用。
要加载这个简单的应用,需要大约 1 MB 的 JavaScript 代码!
查看开发者工具中的项目警告。
- 点击 Console(控制台)标签页。
- 确保已启用“
Warnings
”的Filter
输入。
- 查看显示的警告。
Firebase 是此应用中使用的库之一 通过提供警告让开发者知道不要导入自己的 整个软件包,但只包含所使用的组件。也就是说, 可以移除此应用以加载 。
在有些情况下,使用了特定的库 一个更简单的替代方案。移除不需要的库的概念是 详细介绍
分析软件包
该应用中有两个主要依赖项:
- Firebase:该平台可提供许多 适用于 iOS、Android 或 Web 应用的实用服务。在这里,其实时 数据库用于 实时存储和同步每只小猫的信息。
- Moment.js:一个实用程序库,可让您更轻松地
在 JavaScript 中处理日期。每只小猫的出生日期都存储在
Firebase 数据库,且
moment
用于以周为单位计算其存在时间。
为什么只有两个依赖项会合为将近 1 MB 的 bundle 大小? 其中一个原因是,任何依赖项都可以反过来 所以如果模型的每个深度/分支都存在依赖关系, 依赖项“tree”。应用很容易变大 如果包含许多依赖项,速度相对较快。
分析捆绑器以更好地了解正在执行什么操作。这里有许多
可以帮助实现此目的的各种社区工具,例如
webpack-bundle-analyzer
。
此工具的软件包已作为 devDependency
包含在应用中。
"devDependencies": {
//...
"webpack-bundle-analyzer": "^2.13.1"
},
这意味着,您可以直接在 webpack 配置文件中使用它。
在 webpack.config.js
的开头导入此文件:
const path = require("path");
//...
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
现在,在 plugins
数组内的文件末尾将其作为插件添加:
module.exports = {
//...
plugins: [
//...
new BundleAnalyzerPlugin()
]
};
应用重新加载时,您应该会看到整个应用的 而非应用本身
这不像看到猫咪那样可爱 ⧫,但对它还是很有帮助的。 将鼠标悬停在任一软件包上,即可显示其大小(以 3 个为单位) 方法:
统计数据大小 | 进行任何缩减或压缩之前的大小。 |
---|---|
解析后的大小 | 编译完成后,软件包中实际软件包的大小。 webpack 版本 4(在此应用中使用)缩减了 自动编译的文件,这就是它比统计信息 。 |
Gzip 压缩大小 | 使用 gzip 编码压缩的软件包的大小。这个 请参阅另一指南。 |
借助 webpack-bundle-analyzer 工具,您可以更轻松地识别 构成了软件包的很大一部分不需要的软件包。
移除未使用的软件包
可视化图表显示 firebase
软件包还包含许多其他内容
而不仅仅是数据库它包含其他软件包,例如:
firestore
auth
storage
messaging
functions
这些都是 Firebase 提供的出色服务(请参阅 文档 但在应用中并未使用任何技术 没有理由将其全部导入。
还原 webpack.config.js
中的更改以再次看到应用:
- 移除插件列表中的
BundleAnalyzerPlugin
:
plugins: [
//...
new BundleAnalyzerPlugin()
];
- 现在,从文件顶部移除未使用的导入内容:
const path = require("path");
//...
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
现在,应用应该可以正常加载了。修改 src/index.js
以更新
Firebase 导入。
import firebase from 'firebase';
import firebase from 'firebase/app';
import 'firebase/database';
现在,当应用重新加载时,DevTools 警告不会显示。打开 开发者工具的 Network 面板还显示了软件包大小的很好缩减:
移除了超过一半的软件包大小。Firebase 提供了许多不同的
并允许开发者仅将实际应用
所需的资源。在此应用中,仅使用 firebase/database
来存储和同步
所有数据firebase/app
导入,用于为以下对象设置 API Surface:
都是必不可少的
许多其他热门库(如 lodash
)也允许开发者
有选择地导入其软件包的不同部分。不必执行太多工作
更新应用中的库导入,使其仅包含正在使用的库
可以大幅提升性能。
虽然 bundle 大小已大幅缩减,但 要做的事!😈
移除不需要的软件包
与 Firebase 不同,moment
库的部分内容无法
而且或许能将其彻底删除呢?
每只可爱小猫的生日以 Unix 格式(以毫秒为单位)存储, Firebase 数据库。
这是特定日期和时间的时间戳,以 自世界协调时间 (UTC) 1970 年 1 月 1 日 00:00 起经过的毫秒数。如果当前 日期和时间可以采用相同的格式进行计算, 我们可以构建每只小猫的年龄。
与往常一样,按照本文中的说明操作时,请尽量不要进行复制和粘贴。起始内容
从 src/index.js
的导入中移除了 moment
。
import firebase from 'firebase/app';
import 'firebase/database';
import * as moment from 'moment';
Firebase 事件监听器可处理数据库中的值更改:
favoritesRef.on("value", (snapshot) => { ... })
在此基础上,添加一个小函数,用于计算 指定日期:
const ageInWeeks = birthDate => {
const WEEK_IN_MILLISECONDS = 1000 * 60 * 60 * 24 * 7;
const diff = Math.abs((new Date).getTime() - birthDate);
return Math.floor(diff / WEEK_IN_MILLISECONDS);
}
在此函数中,当前日期与
时间 (new Date).getTime()
和出生日期(birthDate
参数,已经
(以毫秒为单位)的计算方法,
一个星期。
最后,可以通过以下方式在事件监听器中移除 moment
的所有实例:
此函数:
favoritesRef.on("value", (snapshot) => { const { kitties, favorites, names, birthDates } = snapshot.val(); favoritesScores = favorites; kittiesList.innerHTML = kitties.map((kittiePic, index) => {const birthday = moment(birthDates[index]);return ` <li> <img src=${kittiePic} onclick="favKittie(${index})"> <div class="extra"> <div class="details"> <p class="name">${names[index]}</p><p class="age">${moment().diff(birthday, 'weeks')} weeks old</p><p class="age">${ageInWeeks(birthDates[index])} weeks old</p> </div> <p class="score">${favorites[index]} ❤</p> </div> </li> `}) });
现在重新加载应用,然后再次查看 Network 面板。
我们的套装又缩减了一半!
总结
在此 Codelab 中,您应该对如何分析 以及为什么移除未使用的或不需要的软件包 软件包在开始用这种方法优化应用之前,请先 需要注意的是,在大型企业中,这可能要复杂得多 应用。
关于移除未使用的库,请尝试找出 哪些部分使用了,哪些没有。神秘主题 请退一步检查 哪些顶级依赖项可能需要它试着找到一种方法 使它们相互分离。
在移除不需要的库方面,方法可能稍微复杂一些
复杂。一定要与团队密切合作,看看能否
有助于简化代码库的某些部分。正在移除此文件夹中的moment
可能看似每次都做正确的事,
是否有需要处理的时区和不同的语言区域?或
如果有更复杂的日期操作,该怎么办?事情可能
处理和解析日期/时间以及 moment
等库时比较棘手
和 date-fns
可以大大简化这一过程。
一切都需要权衡,因此评估是否值得 部署自定义解决方案,而不依赖于 第三方库