关于javascript:使用-webpack-代码分割和魔术注释提升应用性能

3次阅读

共计 3721 个字符,预计需要花费 10 分钟才能阅读完成。

1. Web 利用性能优化的要害

对于 Web 利用性能优化,有一点是毫无疑问的:「页面加载越久,用户体验就越差 」。咱们简直能够说 Web 利用性能优化的要害之处就在于:缩小页面初载时,所需加载资源的「 数量 」和「 体积」。

那么当所需加载的资源数量达到多少或资源体积小于多少,咱们才能够自信地声称咱们的 Web 利用领有杰出的性能呢?上面是给出的一些参考值,该参考值思考到了挪动端与国外等多种拜访环境:

  • 页面初载时,所有未压缩的 JavaScript 脚本大小:<=200KB
  • 页面初载时,所有未压缩的 CSS 资源大小:<=100KB
  • HTTP 协定下,申请资源数:<=6 个
  • HTTP/2 协定下,申请资源数:<=20 个
  • 90% 的代码利用率(也就是说,仅容许 10% 的未应用代码);

或者你会感觉这个规范有点过于刻薄了,是有一点点,但为了创立出高性能的 Web 利用,你的理论资源加载状况应该尽可能凑近这个指标。

2. 如何查看代码利用率

兴许你留神到了,咱们刚刚最初提到的一个指标是「代码利用率」,你可能是第一次据说这个概念,这里我解释一下它的计算形式:

代码利用率 = 你页面中理论被执行的代码 / 你页面中引入的代码 * 100%

你可能会困惑在理论开发中如何失去这个值,别放心,通过应用 Chrome 开发者工具(很遗憾,目前只有 Chrome 反对这一性能),你就能够迅速对你的 Web 利用进行剖析,失去以后页面下的代码利用率状态,步骤如下:

  1. 关上 Chrome Dev Tool;
  2. 按下 Cmd + Shift + P or Ctrl + Shift + P ;
  3. 输出 Coverage,并抉择第一个呈现的选项(图 1);

<p style=”text-align: center; color: #999;”> 图 1:间接输出 coverage 即可开启该看板 </p>

  1. 点击面板上的 reload 按钮,查看整个利用 JavaScript 的代码利用率(图 2);

<p style=”text-align: center; color: #999;”> 图 2:点击 reload 按钮,开始剖析 JavaScript 代码利用率 </p>

3. 进步代码使用率的关键技术 - 代码宰割(code splitting)

3.1 什么是「代码宰割」(code splitting)?

代码宰割是指,将脚本中无需立刻调用的代码在代码构建时转变为异步加载的过程。

在 Webpack 构建时,会防止加载已申明要异步加载的代码,异步代码会被独自拆散出一个文件,当代码理论调用时被加载至页面。

3.2 代码宰割的原理

代码宰割技术的外围是「异步加载资源」,可喜的是,浏览器容许咱们这么做,W3C stage 3 标准:whatwg/loader 对其进行了定义:你能够通过 import() 关键字让浏览器在程序执行时异步加载相干资源。

<p style=”text-align: center; color: #999;”> 图 3:import() 的浏览器支持性 </p>

没错,正如你所看到的,IE 浏览器目前并不反对这一个性,但这并不意味着你的异步加载性能在 IE 浏览会生效(那太可怕了 ????‍♂️),实际上,Webpack 底层帮你将异步加载的代码抽离成一份新的文件,并在你须要时通过 JSONP 的形式去获取文件资源,因而,你能够在任何浏览器上实现代码的异步加载,并且在未来所有浏览器都实现 import() 办法时平滑过渡,cool!????

3.3 代码宰割的类型

代码宰割能够分为「动态宰割」和「“ 动静 ” 宰割」两种形式,留神这里打了引号的 “ 动静 ”,因为实际上它并不意味着异步调用的代码是 “ 动静 ” 生成的,咱们之后会看到 Webpack 是如何做到这一点的,在那之前,让咱们先看看「动态代码宰割」。

3.3.1 动态代码宰割

动态代码宰割是指,在代码中明确申明须要异步加载的代码

上面 ???? 的代码阐明了咱们应该如何应用这一技术:

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)  
      })
  }
)

正如你所看到的:

每当你调用一个申明了异步加载代码的变量时,它总是返回一个 Promise 对象。

⚠️ 留神:在 Vue 中,能够间接应用 import() 关键字做到这一点,而在 React 中,你须要应用 react-loadable 去实现同样的事。

最初,让咱们谈谈何时应用动态代码宰割技术,这一技术适宜以下的场景:

  1. 你正在应用一个十分大的库或框架:如果在页面初始化时你不须要应用它,就不要在页面初载时加载它;
  2. 加载任何长期的资源:指不在页面初始化时被应用,被应用后又会立刻被销毁的资源,例如模态框,对话框,tooltip 等(任何一开始不显示在页面上的货色都能够有条件的加载);
  3. 页面路由:既然用户不会一下子看到所有页面,那么只把以后页面相干资源给用户就是个理智的做法;

好了,当初你把握了动态代码宰割技术,当初让咱们看看什么是「” 动静代 ” 代码宰割」技术。

3.3.2 动静代码宰割

动静代码宰割是指:在代码调用时依据以后的状态,「动静地」异步加载对应的代码块

上面 ???? 的代码阐明了它具体是如何被实现的:

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 会在构建时将你申明的目录下的所有可能拆散的代码都形象为一个文件(这被称为 contextModule 模块),因而无论你最终申明了调用哪个文件,实质上就和动态代码宰割一样,在申请一个早已筹备好的,动态的文件。

上面是一些应用 “ 动静 ” 代码宰割技术的场景:

  1. A/B Test:你不须要在代码中引入不须要的 UI 代码;
  2. 加载主题:依据用户的设置,动静加载相应的主题;
  3. 为了不便:实质上,你能够用动态代码宰割代替「动静」代码宰割,然而后者比前者领有更少的代码量;

4. 魔术正文

魔术正文是由 Webpack 提供的,能够为代码宰割服务的一种技术。通过在 import 关键字后的括号中应用指定正文,咱们能够对代码宰割后的 chunk 有更多的控制权,让咱们看一个例子:

// index.js
import (
  /* webpackChunkName: "my-chunk-name" */
  './footer'
)
同时,也要在 webpack.config.js 中做一些改变:// webpack.config.js
{
  output: {
    filename: "bundle.js",
    chunkFilename: "[name].lazy-chunk.js"
  }
}

通过这样的配置,咱们能够对拆散出的 chunk 进行命名,这对于咱们 debug 而言十分不便。

4.1 Webpack Modes

除了下面提到过的 webpackChunkName 正文外,Webpack 还提供了一些其余正文让咱们可能对异步加载模块领有更多控制权,例如下方这个例子:

import (
  /* webpackChunkName: "my-chunk-name" */
  /* webpackMode: lazy */
  './someModule'
)

webpackMode 的默认值为 lazy 它会使所有异步模块都会被独自抽离成繁多的 chunk,若设置该值为 lazy-once,Webpack 就会将所有带有标记的异步加载模块放在同一个 chunk 中。

4.2 Prefetch or Preload

通过增加 webpackPrefetch 魔术正文,Webpack 令咱们能够应用与 <link rel=”prefetch”> 雷同的个性。让浏览器会在 Idle 状态时事后帮咱们加载所需的资源,善用这个技术能够使咱们的利用交互变得更加晦涩。

import(
  /* webpackPrefetch: true */
  './someModule'
)

⚠️ 留神:请确保你的代码在将来肯定会用到时,再开启该性能。

5. 小结

至此,咱们解说了所有无关 Code Splitting 的常识,并通知你了一些神奇的「魔法正文」让你对宰割后的代码有更多的掌控,心愿你能将下面的技术灵活运用在你的我的项目中,开发出更加激动人心,如丝般顺滑的利用!

Good Luck!????

正文完
 0