用 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 + P
orCtrl + 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 ...
随机推荐
- 使用ViewPager实现广告自动轮播的效果
package com.loaderman.viewpgerlunbodemo; import android.os.Bundle; import android.os.Handler; import ...
- oracle 12 安装
oracle 12 第二版本安装 下载地址 https://www.oracle.com/technetwork/cn/middleware/webcenter/content/downloads/ ...
- MYSQL5.5二进制包的安装
二进制1. 下载包 wget http://mirrors.sohu.com/mysql/MySQL-5.6/mysql-5.5.55-linux2.6-i686.tar.gz2. 解压 tar xx ...
- linux查看内存使用情况top
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管理器 可以直接使用top命令后,查看%MEM的内容.可以选择按进程查看或者按用户查看, ...
- Loading——spin.js
官网:[http://spin.js.org/] Github地址:[https://github.com/fgnass/spin.js]
- pytest -- 测试的参数化
目录 1. @pytest.mark.parametrize标记 1.1. empty_parameter_set_mark选项 1.2. 多个标记组合 1.3. 标记测试模块 2. pytest_g ...
- 龙芯软硬件培训个人总结-day2
今天最后一天,主要培训了BSP,QT,KVM云计算相关的内容.大致总结了一些自己关注的点.培训的资料已上传至服务器,如果需要可关注下方二维码,后台直接回复“资料”获取.关于实战的资料还未导出,等导出 ...
- Opencv中copyTo()函数的使用方法
在Mat矩阵类的成员函数中copyTo(roi , mask)函数是非常有用的一个函数,尤其是后面的mask可以实现蒙版的功能,我们用几个实例来说明它的作用.我们要注意mask的数据类型,必须是CV_ ...
- 【linux杂谈】安装linux虚拟机的时候发现的full name,user name有啥区别
本人为了重温linux,在新电脑上又要安装linux虚拟机,在VMware内配置快速安装的时候看到有如下说明: 大家可能跟我一样对于username比较熟悉,但是这个fullname是干嘛的?我们先进 ...
- 【Android Apk重新签名报错re-sign.jar之解决方法】
故障现象: