用 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 ...
随机推荐
- Android 动态申请权限
AndroidManifest.xml(清单文件)添加需要的权限 <uses-permission android:name="android.permission.ACCESS_CO ...
- IDEA工具创建项目并提交码云和一些基本使用
https://blog.csdn.net/autfish/article/details/52513465https://blog.csdn.net/zsyoung/article/details/ ...
- 【SSM】---Spring+SpringMVC+Mybatis框架整合
参考 百度经验 https://jingyan.baidu.com/article/2a1383288a85a9074a134f1b.html CSDN http://blog.csdn.net/ge ...
- java:easyui(jQueryEasyUI,分页)
1.介绍: jQuery EasyUI是一组基于jQuery的UI插件集合体,而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面.开发者不需要编写复杂的ja ...
- 使用svctraceviewer查看WCF服务异常信息
这两天遇到一个问题,调用一个WCF服务的时候,服务器端正常的返回了数据,但是客户端却遇到了一场 System.ServiceModel.CommunicationException: The unde ...
- Linux (1)
@https://blog.csdn.net/mayi_xiaochaun这人博客里有一系列linux教程 @linux中,文件名最前加/ 比如 cd /usr/local是绝对路径 若#前显示当前 ...
- Spring依赖模块
1.spring maven依赖 https://www.cnblogs.com/nwu-edu/p/9542074.html
- mysql主要性能监控指标
1.系统mysql的进程数 ps -ef | grep "mysql" | grep -v "grep" | wc –l 2.Slave_running mys ...
- 【6.24校内test】T2 不老梦
[题目背景] 于万人中万幸得以相逢,刹那间澈净明通. 成为我所向披靡的勇气和惶恐,裂山海,堕苍穹. 爱若执炬迎风,炽烈而哀恸,诸般滋味皆在其中. 韶华宛转吟诵,苍凉的光荣,急景凋年深情难共. ——银临 ...
- 单节点FastDFS安装
环境:centos7 1.什么是分布式文件系统 分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网络与节点相连. ...