用 Webpack 解决应用性能问题
1. 影响页面加载时长的 Top3 因素
- 页面初载时,加载大量 JavaScript 脚本;
- 页面初载时,加载大量 CSS 文件;
- 页面初载时,加载大量网络资源;
页面加载的越久,页面不可交互的时间就越长,用户的体验就越差。
2. 页面优化的目标
- 页面初载时,未压缩的 JavaScript 脚本大小: <=200KB ;
- 页面初载时,未压缩的 CSS 资源大小: <=100KB ;
- HTTP 协议下,请求资源数: <=6 个 ;
- HTTP/2 协议下,请求资源数: <=20 个 ;
- 90% 的代码覆盖率(仅允许 10% 的未使用代码);
只有 Chrome 能够查看你的代码覆盖率。
遵从这个目标,应用将能在任何平台(PC,Mobile Phone...)都拥有良好的性能:
- 未来的网络世界在移动端;
- 平均每个移动端网站需要花费 14 秒时间达到可交互状态;
- 加载的代码越少,页面达到可交互的时间越短;
3. 查看代码覆盖率
- 打开 Chrome Dev Tool;
- 按下
Cmd + Shift + PorCtrl + Shift + P; - 输入
Coverage,选择第一个出现的选项:

- 点击面板上的
reload按钮,查看整个应用 JavaScript 的代码覆盖率:

4. 如何做到?
(1)代码分割(code splitting)
什么是 code splitting?
将部分代码在构建时转变为异步加载的过程。
(1.1)代码分割原理
代码分割的核心是异步加载资源,而异步加载功能使用到 stage 3 规范:whatwg/loader。import() 允许你在浏览器端运行时动态获取资源,虽然它存在以下一些问题:
- 安全问题;
- 浏览器支持问题;
(1.2)代码分割的两种类型
- 静态的;
- “动态的”(在 webpack 中,并不是真的动态):“动态”是指你能够在代码运行时决定应该引入什么 JavaScript 模块;
(1.3)静态代码分割
何时使用静态的代码分割?
- **你正在使用一个非常大的库或框架 **:如果在页面初始化时你不需要使用它,就不要在页面初载时加载它;
- **任何临时的资源 **:指不在页面初始化时被使用,被使用后又会立即被销毁的资源,例如模态框,对话框,tooltip等(任何一开始不显示在页面上的东西都可以有条件的加载);
- 路由 :既然用户不会一下子看到所有页面,那么只把当前页面相关资源给用户就是个明智的做法;
代码示例
import Listener from './listeners.js'
const getModal = () => import('./src/modal.js')
Listener.on('didSomethingToWarrentModalBeingLoaded', () => {
// Async fetching modal code from a separate chunk
getModal().then((module) => {
const modalTarget = document.getElementById('Modal')
module.initModal(modalTarget)
})
})
注意:
- 在 Vue 中,可以直接使用
import()关键字,在 React 中,使用react-loadable完成同样的事; - 每当你使用动态代码分割时,函数将返回一个 Promise 对象;
(1.4)“动态”代码分割
何时使用“动态”代码分割?
- **A/B Test **:你不需要在代码中引入不需要的 UI 代码;
- **主题 **:动态加载相应的主题;
- 为了方便 :本质上,你可以用静态代码分割代替“动态”代码分割,但是后者比前者拥有更少的代码量;
代码示例
const getTheme = (themeName) => import(`./src/themes/${themeName}`)
// using `import()` 'dynamically'
if (window.feeling.stylish) {
getTheme('stylish').then((module) => {
module.applyTheme()
})
} else if (window.feeling.trendy) {
getTheme('trendy').then((module) => {
module.applyTheme()
})
}
这背后的原理是,webpack 将目录中所有可以分离的 JavaScript 文件都生成了被称为 contextModule 的模块,所以本质上仍然是静态的。
(2)魔术注释
魔术注释技术是为代码分割技术服务的,它表现为在 import 关键字前使用指定注释来控制 webpack 生成的分割后代码片段。
代码示例
import (
/* webpackChunkName: "my-chunk-name" */
'./footer'
)
同时,你需要在 webapck.config.js 中添加配置:
{
output: {
filename: "bundle.js",
chunkFilename: "[name].lazy-chunk.js"
}
}
(2.1)webpack Modes
webpack 提供了一些注释让我们能够选择异步加载的模块应该被怎样组织:
import (
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: lazy */
'./someModule'
)
webpackMode 的默认值为 lazy ,指所有异步模块都会被单独抽离成单一的 chunk,通过使用 lazy-once 值,可以将所有的异步加载模块放在同一个 chunk 中。
(2.2)Prefetch & Preload
通过开启 prefetch ,我们可以通过使用 <link rel="prefetch>" 的特性,让浏览器在空闲时帮我们预先加载我们的异步资源,这有助于提升应用性能。
import(
/* webpackPrefetch: true */
'./someModule'
)
注意 :当你确保你的异步代码在未来一定会用到时,再开启该功能。
5. 参考链接
- https://developers.google.com/web/fundamentals/performance/optimizing-javascript/code-splitting/?hl=zh-cn
- https://webpack.js.org/guides/code-splitting/
- https://webpack.js.org/api/module-methods/#magic-comments
- https://medium.com/webpack/link-rel-prefetch-preload-in-webpack-51a52358f84c
用 Webpack 解决应用性能问题的更多相关文章
- 第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题
一. 开篇说明 EF的性能问题一直以来经常被人所吐槽,究其原因在于“复杂的操作在生成SQL阶段耗时长,且执行效率不高”,但并不是没有办法解决,从EF本身举几个简单的优化例子: ①:如果仅是查询数据,并 ...
- Webpack——解决疑惑,让你明白
Webpack——解决疑惑,让你明白 极客教程 作者 关注 2016.09.29 17:46* 字数 2868 阅读 22204评论 22喜欢 80 Webpack是目前基于React和Redux开发 ...
- 【译文】使用webpack提高网页性能优化
这篇文章原文来自https://developers.google.com/web/fundamentals/performance/webpack/. 说是译文其实更像是笔者做的笔记,如有错误之处请 ...
- 解决Linux性能问题的前60秒
为了解决性能问题,你登入了一台Linux服务器,在最开始的一分钟内需要查看什么? 在Netflix我们有一个庞大的EC2 Linux集群,还有非常多的性能分析工具来监控和调查它的性能.其中包括用于云监 ...
- webpack之前端性能优化(史上最全,不断更新中。。。)
最近在用webpack优化首屏加载性能,通过几种插件之后我们上线前后的速度快了一倍,在此就简单的分享下吧,先上个优化前后首屏渲染的对比图. 可以看到总下载时间从3800ms缩短到1600ms. 我们在 ...
- webpack 解决 semantic ui 中 google fonts 引用的问题
semantic ui css 的第一行引用了 google web font api,由于不可告人而又众所周知的原因,这条链接在国内无法访问: @import url('https://fonts. ...
- [转] webpack之前端性能优化(史上最全,不断更新中。。。)
最近在用webpack优化首屏加载性能,通过几种插件之后我们上线前后的速度快了一倍,在此就简单的分享下吧,先上个优化前后首屏渲染的对比图. 可以看到总下载时间从3800ms缩短到1600ms. 我们在 ...
- webpack 解决跨域问题
一.webpack 内置了 http-proxy-middleware 可以解决 请求的 URL 代理的问题 安装:npm install --save http-proxy-middleware 二 ...
- webpack解决单页面路由问题
index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
随机推荐
- Chrome OS支持在窗口中运行Linux了!!!
借助Crouton Chrome扩展,Chrome OS可以在窗口中运行Linux了.在使用该扩展之前,你需要先将自己的Chromebook设置成开发者模式(Develeper Mode). 此前,C ...
- linux创建软链接
linux软链接linux下的软链接类似于windows下的快捷方式实例:ln -s /home/gamestat /gamestatln -s a b 中的 a 就是源文件,b是链接文件名,其 ...
- shell历史命令
1.每分钟备份历史命令 制定计划任务:每分钟执行备份历史命令的脚本 注意:要用python写计划任务脚本,因为用shell脚本写的计划任务总是不执行 先写脚本: [root@master ~]# ca ...
- VBA删除空白行列
'删除空行 Sub DeleteEmptyRows() Dim LastRow As Long, r As Long LastRow = ActiveSheet.UsedRange.Rows.Coun ...
- Linux 串口调试工具汇总
minicomminicom 是一款启动速度快,功能强大的串口终端调试工具,当然缺点就是纯字符界面,没有图形界面的调试工具看起来直观方便,但是它功能十分强大,并且在一些没有屏幕的嵌入式主板上运行颇有用 ...
- Cmake + VS2013编译opencv
下载之后,使用cmake转为vs解决方案的时候,配置OPENCV_EXTRA_MODULES_PATH=<path to opencv_contrib/modules/>,然后才能使用ex ...
- Prometheus告警模型分析
Prometheus作为时下最为流行的开源监控系统,其庞大的生态体系:包括针对各种传统应用的Exporter,完整的二次开发工具链,与Kubernetes等主流平台的高度亲和以及由此带来的强大的自发现 ...
- SSH整合项目----在线商城
1.1 网上商城需求分析 1.1.1 前台:用户模块. 注册: * JS非空校验.(不是必须) * Struts2数据校验:在注册Action类同一包下新建UserAction-user_reg ...
- RPCVersionCapError: Requested message version, 4.17 is incompatible. It needs to be equal in major version and less than or equal in minor version as the specified version cap 4.11.
[问题描述] RPCVersionCapError: Requested message version, 4.17 is incompatible. It needs to be equal in ...
- (5.2.2)配置服务器参数——dbcc跟踪标记(trace)
关键字:跟踪标记,跟踪 [1]常规dbcc命令 dbcc help('?') --查看dbcc 所有命令,常规下只有32个常用的dbcc TRACEON(2588) --指定了2588标记的话,你就可 ...