Web工程功用优化

从事前端开发的很难脱离功用优化这个词,可是关于前端功用方面,其实常识点是适当琐碎的,以至于咱们总是感觉做的不够好 接下来咱们从一道面试题说起:

从输入 URL 到页面加载完成,发生了什么?

这个题的答案,其实很简略,相信许多开发的小伙伴都能够很快速的讲出来。今日咱们不去单纯的去聊发生了什么,从功用的层面去考虑。

首要,咱们需求经过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确认的那台服务器建立起 TCP 网络衔接,随后咱们向服务端抛出咱们的 HTTP 恳求,服务端处理完咱们的恳求之后,把目标数据放在 HTTP 呼应里回来给客户端,拿到呼应数据的浏览器就能够开端走一个烘托的流程。烘托结束,页面便呈现给了用户。这是一个大致的流程。接下来咱们把其间的要点剖析一下:

  • DNS解析时刻:DNS解析的时刻会影响整个页面加载的速度。能够经过削减DNS查询次数、运用DNS缓存等办法来优化DNS解析时刻。

  • TCP衔接时刻:建立TCP衔接需求进行三次握手,这个进程会消耗必定的时刻。能够经过运用HTTP/2协议、TCP衔接复用等办法来削减TCP衔接时刻。

  • 恳求呼应时刻:服务器处理恳求和回来呼应的时刻也会影响页面加载速度。能够经过优化服务器端的代码、削减恳求的数量和巨细等办法来削减恳求呼应时刻。

  • 资源加载时刻:资源的加载时刻也会影响页面加载速度。能够经过运用CDN加速、紧缩资源、兼并恳求等办法来优化资源加载时刻。

  • 页面烘托时刻:页面的烘托时刻也会影响用户的感知。能够经过优化CSS和JavaScript的加载和履行、削减DOM操作等办法来优化页面烘托时刻。

当咱们从功用方面剖析出来之后,咱们发现有许多当地都触及到了功用优化的常识点。首要是

  1. HTTP协议和TCP衔接、Vite构建工具
  2. 图片的合理运用
  3. 代码优化(兼并恳求、削减DOM)
  4. 服务端加载(SSR)技能、CDN加速
  5. 浏览器缓存机制

以上都是咱们对功用优化所触及到的常识。

HTTP && Vite方面(资源整合/依靠剖析/Gzip紧缩/Tree Shaking/生产构建优化)

从输入URL到显示页面这一步骤,咱们能够将其分为三个首要阶段:

  • DNS解析
  • TCP衔接
  • HTTP恳求/呼应

在前端开发中,关于DNS解析和TCP衔接这两个阶段,咱们的干涉和改进有限。相比之下,HTTP层面的优化才是网络功用优化的中心。因而,咱们能够开门见山地从HTTP优化开端谈起,由于这是咱们能够主动改进的方面。

HTTP优化首要环绕两个中心方向打开:

  1. 削减恳求次数:这包含削减需求从服务器恳求的资源数量,以下降页面加载时刻。
  2. 削减单个恳求所需的时刻:这触及优化每个恳求的呼应时刻,以加快页面烘托速度。

这两个优化方向直接引导咱们关注在日常开发中常见的操作,即资源的紧缩和兼并,以进步网站功用!

关于资源整合,这是咱们日常用构建工具经常去做的工作,现在较为盛行的构建工具也便是WebpackVite(在当时卷之又卷的年代,构建工具也是层出不穷,这儿就不再介绍了)关于Webpack相信许多小伙伴也都非常的了解了,这儿也不再独自去聊了,今日咱们专门来聊一聊Vite的功用优化都有哪些?

快速编译和热模块更换

Vite 运用原生 ES 模块和现代浏览器 API 来动态编译代码,然后在浏览器中供给快速的构建时刻和即时更新。这种办法消除了在开发进程中对绑缚程序的需求,这能够显著削减构建和布置运用程序所花费的时刻。Vite 内置的开发服务器针对快速从头加载和热模块替换进行了优化,答应开发人员实时查看他们对代码所做的更改,而无需改写整个页面。

模块的推迟加载

Vite 完成了模块的推迟加载,代码只在实际需求时才加载。这样能够减小捆包尺度并进步功用,特别是关于较大的运用程序。推迟加载还答运用户更快地初始加载时刻,由于运用程序非要害部分的代码仅在需求时加载。

Tree Shaking和代码拆分

Vite 的摇树和代码拆分是有助于减小代码巨细和进步功用的优化技能。摇树从运用程序中删去未运用的代码,而代码拆分答应您将代码划分为更小、更易于管理的块,并按需加载。这些功用协同工作,以确保您的用户只下载当时页面所需的代码,然后缩短加载时刻并进步整体功用

内置开发服务器

Vite 包含一个内置的开发服务器,针对快速从头加载和热模块更换进行了优化。经过此服务器,能够轻松开发和测试运用程序,并答应您实时查看对代码所做的更改,而无需改写整个页面。开发服务器还支撑主动从头加载代码,因而您能够快速迭代更改,而无需手动从头加载。

上面介绍了一些Vite的一些特点,可是咱们怎样在项目中更好的运用这些特点呐?

首要便是资源兼并:

// vite.config.js
build: {
				//  argument:boolean | 'terser' | 'esbuild'
				minify: 'esbuild',
				emptyOutDir: true,
				// Do not open when packing
				sourcemap: false,
				target: 'es2015',
				cssTarget: 'chrome80',
				rollupOptions: {
					onwarn(warning, warn) {
						if (warning.code === 'EVAL') return
						// Use the default warning handling
						warn(warning)
					},
					treeshake: true,
					output: {
						manualChunks: {
							XXX0: ['vue', 'vuex', 'vue-router', 'dayjs', 'axios', 'vue-i18n'],
							XXX1: ['element-plus', '@element-plus/icons-vue'],
							XXX2: ['@nutflow/nf-form-elp'],
							XXX3: ['@smallwei/avue', 'avue-plugin-ueditor'], // 头号目标 1
							XXX4: ['@nutflow/nf-design-elp'], // 2
							XXX5: ['@saber/nf-design-base-elp'], // 3
							XXX6: ['@nutflow/nf-form-design-elp'] // 4
						}
					}
				}
			},

上面代码我运用了 Vite 的资源兼并功用。在rollupOptionsoutput部分,界说了manualChunks,并指定了不同的模块名称和它们所依靠的模块。这样做能够将这些模块兼并到独自的文件中,以削减打包后的文件数量和巨细。这是Vite依据Rollup去整合的,并不是Vite本身的功用,Vite运用了Rollup作为默许打包工具,而且也供给了许多选项来进行一些定制。

在上面的代码中,想必大家也看到了treeshake: true这个设置

Tree Shaking:

// vite.config.js
build: {
  rollupOptions: { 
    // 不考虑模块中导出的属性(也便是对象的属性)是否有副作用
    propertySideEffects: false,
    // 不考虑模块是否具有副作用
    moduleSideEffects: false,
  },
}

在上面的装备中,也能够运用treeshake选项来装备 Tree Shaking。其间,propertySideEffectsmoduleSideEffects属性用于指定哪些属性或模块应该被视为有副作用,然后扫除它们不进行 Tree Shaking,以削减最终生成的包的巨细。

模块的推迟加载

  components: {
    top: defineAsyncComponent(() => import('./top/index.vue')),
    logo: defineAsyncComponent(() => import('./logo.vue')),
    tags: defineAsyncComponent(() => import('./tags.vue')),
    search: defineAsyncComponent(() => import('./search.vue')),
    sidebar: defineAsyncComponent(() => import('./sidebar/index.vue'))
  },

异步组件,代码只在实际需求时才加载

优化项意图依靠项

// vite.config.js
optimizeDeps: {
			include: [
				'echarts',
				'xxxx',
				'xxxx',
				'xxxx',
			]
		}

咱们经过optimizeDeps的装备,Vite就会将指定的依靠项进行预构建,以进步项意图发动功用。这样能够削减不必要的构建时刻和资源消耗。能够有用的帮助你更精确地控制优化的范围,以防止不必要的构建和资源糟蹋

Vite的紧缩和服务端的紧缩

HTTP 紧缩是一种内置到网页服务器和网页客户端中以改进传输速度和带宽运用率的办法。在运用 HTTP 紧缩的情况下,HTTP 数据在从服务器发送前就已紧缩:兼容的浏览器将在下载所需的格局前宣告支撑何种办法给服务器;不支撑紧缩办法的浏览器将下载未经紧缩的数据。最常见的紧缩计划包含 Gzip 和 Deflate。
以上是摘自百科的解释,事实上,大家能够这么了解:

HTTP 紧缩便是以缩小体积为意图,对 HTTP 内容进行从头编码的进程

Gzip 的内核便是 Deflate,现在咱们紧缩文件用得最多的便是 Gzip。能够说,Gzip 便是 HTTP 紧缩的经典例题。

Vite打包时常见的紧缩办法: gzip | brotli

这儿我个人比较喜爱运用 Brotli 进行紧缩,以下是两者的比较:

  1. 浏览器支撑:Gzip 是一种较为通用的紧缩算法,简直一切现代浏览器都支撑。而 Brotli 是一种较新的紧缩算法,尽管在紧缩比方面更好,但并不是一切浏览器都支撑。假如你的运用首要面向现代浏览器,能够考虑运用 Brotli。假如需求兼容性更广泛,能够挑选运用 Gzip。

  2. 服务器装备:运用 Brotli 紧缩需求在服务器上进行相应的装备。假如你的服务器现已装备了 Brotli 紧缩,能够考虑运用 Brotli。假如没有装备或装备比较复杂,能够挑选运用 Gzip,由于大多数服务器都支撑 Gzip 紧缩。

  3. 文件类型:不同类型的文件对紧缩算法的效果或许有所不同。一般来说,文本文件(如HTML、CSS、JS)在紧缩方面效果更好,而现已经过紧缩的文件(如图片、音视频文件)紧缩效果或许较小。

依靠剖析

依靠剖析,运用这个第三方库就能够了 rollup-plugin-visualizer

Web工程功用优化

还有二个点需求留意一下:

  1. 假如你运用了Vite,项目中最好制止运用export default导出一个对象,由于这样做会无法经过静态剖析判断出一个对象的哪些变量未被运用,所以 tree-shaking 只对运用 export 导出的变量生效
  2. 最好制止运用 eval 函数, Vite 在生产环境是默许禁用了eval函数,由于 es 模块默许是严厉模式的。所以项目中尽量去除 eval

项目中还有好多点,能够去优化比如在Axios恳求封装的时分,能够进行疏忽重复恳求、重试恳求衔接等等优化。

这儿就不逐个进行描述了,咱们继续往下探讨~

图片的合理运用

不同事务场景下的图片计划选型是不一样的,比较常见的几种图片格局:

  • JPEG/JPG :

    有损紧缩、体积小、加载快、不支撑通明

    运用场景: 布景图、产品图片等

  • GIF:

    支撑通明度和多帧动画、色彩表有限

    运用场景:loading动画、表情包等

  • PNG-8与PNG-24 :

    无损紧缩、质量高、体积大、支撑通明

    运用场景:Logo、色彩简略且对比激烈的图片或布景等

  • SVG:

    文本文件、体积小、不失真、兼容性好

    运用场景:Logo、矢量图形、图标等

  • Base64 :

    文本文件、依靠编码、小图标解决计划

    运用场景: Logo、小图标等

  • WebP:

    与 PNG 相比,WebP 无损图画的尺度缩小了 26%。在等效的 SSIM 质量指数下,WebP 有损图画比同类 JPEG 图画小 25-34%。 无损 WebP 支撑通明度(也称为 alpha 通道),仅需 22% 的额定字节。关于有损 RGB 紧缩可接受的情况,有损 WebP 也支撑通明度,与 PNG 相比,一般供给 3 倍的文件巨细。 Webp是比较年轻的,在运用之前最好是查询一下他的兼容性。 WebP相关文档

代码优化(兼并恳求、削减DOM)

在工程项目中,兼并恳求咱们从多个视点去考虑:

  1. 比如上面我运用到的异步组件(Vue3的defineAsyncComponent
  2. 将运用代码拆分为多个模块,按需加载,能够运用 VueRouter 的动态导入功用或者 Vite 的模块推迟加载功用来完成
  3. 运用 HTTP/2,假如你的服务器支撑 HTTP/2 协议,它能够主动兼并多个恳求,削减网络传输的开销

关于削减DOM操作,能够从:虚拟DOM、事情托付、少修改CSS的属性防止重绘、各种条件烘托等等,这儿就不再叙述了~

服务端烘托方面(SSR)、CDN加速

先说CDN:

CDN(Content Delivery Network,即内容分发网络)指的是一组散布在各个地区的服务器。这些服务器存储着数据的副本,因而服务器能够依据哪些服务器与用户距离最近,来满意数据的恳求。 CDN 供给快速服务,较少受高流量影响。

CDN 的中心点有两个,一个是缓存,一个是回源

“缓存”便是说咱们把资源 copy 一份到 CDN 服务器上这个进程,“回源”便是说 CDN 发现自己没有这个资源(一般是缓存的数据过期了),转头向根服务器(或者它的上层服务器)去要这个资源的进程。

CDN一般用于存放静态资源,而事务服务器则担任生成动态页面或回来非纯静态页面。事务服务器像一个车间,经过计算来产出所需的资源;而CDN服务器则像一个库房,只担任存放和传输资源。静态资源是不需求计算即可获取的资源,如JS、CSS、图片等;而动态资源需求后端实时生成,如JSP、ASP或依靠服务端烘托的HTML页面。

服务端烘托:

幻想一下你去一家餐厅用餐的情形。服务端烘托就像是你坐在餐厅里,服务员会为你准备好一道道的菜品,然后端上桌。你只需求等候菜品准备好,然后直接享用。这种办法下,每次你点菜时,服务员都会为你准备好新鲜的菜品,然后一次性端上桌。这样,你能够当即看到菜品的内容,可是每次都需求等候服务员的呼应。

而单页面运用则像是你去一个自助餐厅。在自助餐厅里,你能够自由地挑选各种菜品,然后自己着手取食。每个菜品都摆放在不同的区域,你能够依据自己的喜好挑选想要的菜品。这种办法下,你能够自由地挑选和切换菜品,可是需求自己着手去取食。

在网页中,服务端烘托是指在服务器端生成完好的HTML页面,并将其发送给浏览器进行展现。当你拜访一个服务端烘托的网页时,服务器会依据你的恳求动态生成页面的内容,并将完好的HTML页面回来给浏览器。这样,浏览器能够当即展现页面的内容,可是每次页面切换都需求向服务器发送恳求,等候服务器呼应。

而单页面运用则是在浏览器中加载一个初始的HTML页面,然后经过JS动态地更新页面的内容。当你拜访一个单页面运用时,浏览器会加载一个初始的HTML页面,然后经过JS来处理页面的切换和内容的更新。这样,页面的切换是在浏览器中进行的,不需求向服务器发送恳求,可是初始加载的速度或许会较慢。

总结起来,服务端烘托和单页面运用是两种不同的页面烘托办法。服务端烘托能够当即展现页面内容,但每次页面切换都需求向服务器发送恳求。而单页面运用能够快速切换页面,但初始加载或许较慢。

服务端烘托典型的:JSP、PHP、Nuxt、Next等等

单页面:React、Vue等等

服务端烘托,能够很好的支撑SEO、尤其是新闻类的网站基本都是运用了服务端烘托的办法,方便搜索引擎去搜索网站的内容。

服务端烘托尽管很快,可是假如你的服务器等级不是特别给力话,再加上在当今互联网年代,用户运用的浏览器数量确实非常庞大,而一个公司的服务器数量相对较少。假如将一切浏览器的烘托压力集中到这些有限的服务器上,明显会给服务器带来巨大的负担。(当然、现在也有许多技能去优化:负载均衡、各种缓存(Redis)技能、异步处理、云技能服务等)具体运用什么技能需求归纳考虑一下的~

浏览器缓存机制

浏览器缓存是一种简略而有用的前端功用优化手段,能够削减网络IO消耗,进步拜访速度。Chrome官方解释了缓存的必要性,指出经过网络获取内容的速度较慢且开销巨大。大型呼应需求屡次往复通信,这会推迟浏览器获取和处理内容的时刻,添加拜访者的流量费用。因而,缓存并重复运用之前获取的资源是功用优化的要害。

浏览器缓存机制包含四个方面,依照获取资源时恳求的优先级排列如下:

  1. Memory Cache(内存缓存)
  2. Service Worker Cache(Service Worker缓存)
  3. HTTP Cache(HTTP缓存)
  4. Push Cache(推送缓存)

Web工程功用优化

其间,Memory Cache对应内存缓存,Service Worker Cache对应Service Worker缓存。此外,还有从磁盘缓存(from disk cache)和从内存缓存(from memory cache)获取的资源。

HTTP缓存是咱们日常开发中最了解的一种缓存机制,包含强缓存和洽谈缓存。强缓存具有较高的优先级,只要在强缓存失效时才会运用洽谈缓存。

强缓存和洽谈缓存的具体细节这儿不再详述了。

Chrome官方供给了一张清晰权威的图示,展现了浏览器缓存机制的流程。

Web工程功用优化

在设置缓存策略时,假如资源内容不行复用,能够直接设置Cache-Control为no-store,拒绝任何方式的缓存。否则,能够考虑是否需求每次都向服务器进行缓存有用确认,假如需求,将Cache-Control设置为no-cache。然后,依据资源是否能够被代理服务器缓存,设置为private或public。接下来,依据资源的过期时刻,设置相应的max-age和s-maxage值。最后,装备洽谈缓存所需的Etag、Last-Modified等参数。

浏览器缓存机制和缓存策略触及许多常识点,这儿也只是简略的概括了一下。

除了上面说的,咱们还能够运用浏览器的Lighthouse去进行功用剖析,然后”对症下药“ 这儿就不再过多介绍了~

完。