1. 影响页面加载时长的 Top3 因素

  1. 页面初载时,加载大量 JavaScript 脚本;
  2. 页面初载时,加载大量 CSS 文件;
  3. 页面初载时,加载大量网络资源;

页面加载的越久,页面不可交互的时间就越长,用户的体验就越差。


2. 页面优化的目标

  1. 页面初载时,未压缩的 JavaScript 脚本大小: <=200KB ;
  2. 页面初载时,未压缩的 CSS 资源大小: <=100KB ;
  3. HTTP 协议下,请求资源数: <=6 个 ;
  4. HTTP/2 协议下,请求资源数: <=20 个 ;
  5. 90% 的代码覆盖率(仅允许 10% 的未使用代码);

只有 Chrome 能够查看你的代码覆盖率。

遵从这个目标,应用将能在任何平台(PC,Mobile Phone...)都拥有良好的性能:

  1. 未来的网络世界在移动端;
  2. 平均每个移动端网站需要花费 14 秒时间达到可交互状态;
  3. 加载的代码越少,页面达到可交互的时间越短;

3. 查看代码覆盖率

  1. 打开 Chrome Dev Tool;
  2. 按下 Cmd + Shift + P or Ctrl + Shift + P ;
  3. 输入 Coverage ,选择第一个出现的选项:

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


4. 如何做到?

(1)代码分割(code splitting)

什么是 code splitting?

将部分代码在构建时转变为异步加载的过程。

(1.1)代码分割原理

代码分割的核心是异步加载资源,而异步加载功能使用到 stage 3 规范:whatwg/loader。
import() 允许你在浏览器端运行时动态获取资源,虽然它存在以下一些问题:

  1. 安全问题;
  2. 浏览器支持问题;

(1.2)代码分割的两种类型

  1. 静态的;
  2. “动态的”(在 webpack 中,并不是真的动态):“动态”是指你能够在代码运行时决定应该引入什么 JavaScript 模块;

(1.3)静态代码分割

何时使用静态的代码分割?
  1. **你正在使用一个非常大的库或框架 **:如果在页面初始化时你不需要使用它,就不要在页面初载时加载它;
  2. **任何临时的资源 **:指不在页面初始化时被使用,被使用后又会立即被销毁的资源,例如模态框,对话框,tooltip等(任何一开始不显示在页面上的东西都可以有条件的加载);
  3. 路由 :既然用户不会一下子看到所有页面,那么只把当前页面相关资源给用户就是个明智的做法;
代码示例
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)
})
})

注意:

  1. 在 Vue 中,可以直接使用 import() 关键字,在 React 中,使用 react-loadable 完成同样的事;
  2. 每当你使用动态代码分割时,函数将返回一个 Promise 对象;

(1.4)“动态”代码分割

何时使用“动态”代码分割?
  1. **A/B Test **:你不需要在代码中引入不需要的 UI 代码;
  2. **主题 **:动态加载相应的主题;
  3. 为了方便 :本质上,你可以用静态代码分割代替“动态”代码分割,但是后者比前者拥有更少的代码量;
代码示例
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. 参考链接

用 Webpack 解决应用性能问题的更多相关文章

  1. 第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题

    一. 开篇说明 EF的性能问题一直以来经常被人所吐槽,究其原因在于“复杂的操作在生成SQL阶段耗时长,且执行效率不高”,但并不是没有办法解决,从EF本身举几个简单的优化例子: ①:如果仅是查询数据,并 ...

  2. Webpack——解决疑惑,让你明白

    Webpack——解决疑惑,让你明白 极客教程 作者 关注 2016.09.29 17:46* 字数 2868 阅读 22204评论 22喜欢 80 Webpack是目前基于React和Redux开发 ...

  3. 【译文】使用webpack提高网页性能优化

    这篇文章原文来自https://developers.google.com/web/fundamentals/performance/webpack/. 说是译文其实更像是笔者做的笔记,如有错误之处请 ...

  4. 解决Linux性能问题的前60秒

    为了解决性能问题,你登入了一台Linux服务器,在最开始的一分钟内需要查看什么? 在Netflix我们有一个庞大的EC2 Linux集群,还有非常多的性能分析工具来监控和调查它的性能.其中包括用于云监 ...

  5. webpack之前端性能优化(史上最全,不断更新中。。。)

    最近在用webpack优化首屏加载性能,通过几种插件之后我们上线前后的速度快了一倍,在此就简单的分享下吧,先上个优化前后首屏渲染的对比图. 可以看到总下载时间从3800ms缩短到1600ms. 我们在 ...

  6. webpack 解决 semantic ui 中 google fonts 引用的问题

    semantic ui css 的第一行引用了 google web font api,由于不可告人而又众所周知的原因,这条链接在国内无法访问: @import url('https://fonts. ...

  7. [转] webpack之前端性能优化(史上最全,不断更新中。。。)

    最近在用webpack优化首屏加载性能,通过几种插件之后我们上线前后的速度快了一倍,在此就简单的分享下吧,先上个优化前后首屏渲染的对比图. 可以看到总下载时间从3800ms缩短到1600ms. 我们在 ...

  8. webpack 解决跨域问题

    一.webpack 内置了 http-proxy-middleware 可以解决 请求的 URL 代理的问题 安装:npm install --save http-proxy-middleware 二 ...

  9. webpack解决单页面路由问题

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

随机推荐

  1. python - lambda 函数使用

    # if we need it only once and it's quite simple def make_incrementor(n): return lambda x: x + n f = ...

  2. 阶段3 2.Spring_07.银行转账案例_5 编写业务层和持久层事务控制代码并配置spring的ioc

    Service中就需要用到 TransactionManager中的方法.提供set方法等着spring注入 这里面所有的操作都可以加上事物控制 其他的方法都是相同的操作 这里没有返回结果 转账的方法 ...

  3. 【疑难杂症】new Date() 造成的线程阻塞问题

    代码如下 package com.learn.concurrent.probolem; import java.util.Date; import java.util.concurrent.Count ...

  4. shadow使用方法

    cd shadow/resource/examples for d in shadow.data/host/*client*: do grep "transfer-complete" ...

  5. TCP/IP笔记——TCP特点、首部格式、滑动窗口

    这次总结一下TCP相关的知识. TCP主要特点 面向连接:在通信前必须建立连接(只是逻辑上存在,而不是物理连接) 只能有两个端点:即只能一对一通信(所以通常p2p是用UDP实现的) 提供可靠交付服务: ...

  6. DHCP迁移

    情况1:windows 2003迁移到windows 2003或者windows 2008,按照需要以下几个步骤:1.在源DHCP服务器导出DHCP数据文件,执行以下命令netsh dhcp serv ...

  7. 2019.8中关村、OGeek(oppo)比赛

    中关村writeup https://mp.weixin.qq.com/s?__biz=MzU3MzczNDg1OQ==&mid=2247484106&idx=1&sn=62a ...

  8. USACO4.3 Letter Game【枚举·细节】

    题意 这道题的题目描述让我好一阵蒙,简述一下题意吧: 给定一些字母的价值(如图所示),给出一个字符串(长度在$3$到$7$之间,可以出现重复的字母)和一个单词库.定义一个单词的价值就是它的字母的价值之 ...

  9. 【神经网络与深度学习】【CUDA开发】【VS开发】Caffe+VS2013+CUDA7.5+cuDNN配置过程说明

    [神经网络与深度学习][CUDA开发][VS开发]Caffe+VS2013+CUDA7.5+cuDNN配置过程说明 标签:[Qt开发] 说明:这个工具在Windows上的配置真的是让我纠结万分,大部分 ...

  10. python关键字以及含义,用法

    Python常用的关键字   1.and , or and , or 为逻辑关系用语,Python具有短路逻辑,False and 返回 False 不执行后面的语句, True or 直接返回Tru ...