性能优化:
- 减少请求
- 使用服务端渲染
- 使用 cdn
- css 头部,js 底部
- 压缩文件
- 图片优化(不用图片,延迟加载)
- 减少重绘、回流
- 使用事件委托
首屏加载优化
- cdn 分发(减少传输距离)
- 后端在业务层的缓存,接口缓存
- 静态文件缓存方案,文件 hash+强缓存的一个方案。比如 hash+ cache control: max-age=1 年。
- 前端的资源动态加载
- 路由动态加载,最常用的做法,以页面为单位,进行动态加载
- 组件动态加载(offScreen Component),对于不在当前视窗的组件,先不加载
- 图片懒加载(offScreen Image)
- 代码分割,分割业务代码和库代码,分割方式: 配置 + 同步引入 与 动态引入(无需做任何配置),SplitChunksPlugin 插件
- 页面使用骨架屏,没有骨架屏的话,一个 loading 图也是可以的。
- html-webpack-plugin 插件,在其中配置 html ,可以在文件中插入 loading 图。
- 使用 ssr 渲染
- 使用 http 压缩
- http 压缩通常是通过在 reponse header 指定 Content-Encoding 首部,告诉客户端 response 的压缩格式,这样客户端才能正确解压。
- 压缩值:Content-Encoding: gzip、Content-Encoding: br
- webpack 配置,安装 compression-webpack-plugin 插件进行压缩。
- 利用好 script 标签的 async 和 defer 这两个属性。
OSI 模型
开放式系统互联模型(英语:Open System Interconnection Model,缩写:OSI;简称为 OSI 模型)是一种概念模型,由国际标准化组织提出,一个试图使各种计算机在世界范围内互连为网络的标准框架。
层数 | 说明 | 例子 |
---|---|---|
第七层 应用层 | 应用层提供为应用软件而设计的接口,以设置与另一应用软件之间的通信。 | HTTP、HTTPS、FTP、Telnet、SSH、SMTP、POP3 |
第六层 表示层 | 表示层把数据转换为能与接收者的系统格式兼容并适合传输的格式。 | - |
第五层 会话层 | 会话层负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接 | - |
第四层 传输层 | 传输层把传输表头加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。 | TCP |
第三层 网络层 | 网络层决定数据的路径选择和转寄,将网络表头加至数据包,以形成分组。 | IP |
第二层 数据链路层 | 数据链路层负责网络寻址、错误侦测和改错 | - |
第一层 物理层 | 物理层在局部局域网上发送数据帧,它负责管理电脑通信设备和网络媒体之间的互通。 | 针脚、电压、线缆规范、集线器、中继器、网卡、主机接口卡 |
webpack
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。
loader
loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
Plugin
loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
常用插件
- DefinePlugin:编译时创建全局对象,是一个 webpack 内置的插件,不需要安装
- HtmlWebpackPlugin:在打包结束后,动态生成 html 文件,并把打包生成的 js 模块引到该 html 中。
- HotModuleReplacementPlugin:模块热更新插件。依赖于 webpack-dev-server,后者是在打包文件改变时更新打包文件或者 reload 刷新整个页面,HRM 是只更新修改的部分。
- clean-webpack-plugin:用于在打包前清理上一次项目生成的 bundle 文件,它会根据 output.path 自动清理文件夹
- terser-webpack-plugin:用来对 js 文件进行压缩,从而减小 js 文件的大小,加速 load 速度
构建流程
Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程 :
- 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
- 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译。
- 确定入口:根据配置中的 entry 找出所有的入口文件。
- 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
- 完成模块编译:在经过第 4 步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系。
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。
CDN
CDN 是将源站内容分发至全国所有的节点,从而缩短用户查看对象的延迟,提高用户访问网站的响应速度与网站的可用性的技术。它能够有效解决网络带宽小、用户访问量大、网点分布不均等问题。
其目的是使用户可就近取得所需内容,解决 Internet 网络拥挤的状况,提高用户访问网站的响应速度。
- 用户向浏览器输入域名,浏览器第一次发现本地没有 dns 缓存,则向网站的 DNS 服务器请求;
- 网站的 DNS 域名解析器设置了 CNAME,请求指向了 CDN 网络中的智能 DNS 负载均衡系统;
- 智能 DNS 负载均衡系统解析域名,把对用户响应速度最快的 IP 节点返回给用户;
- 用户向该 IP 节点(CDN 服务器)发出请求;
- 由于是第一次访问,CDN 服务器会向原 web 站点请求,并缓存内容;
- 请求结果发给用户。
tree shaking 的原理是什么?
ES6 Module 引入进行静态分析,故而编译的时候正确判断到底加载了那些模块,静态分析程序流,判断那些模块和变量未被使用或者引用,进而删除对应代码。
- CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
- CommonJs 是单个值导出,ES6 Module 可以导出多个
- CommonJs 是动态语法可以写在判断里,ES6 Module 静态语法只能写在顶层
- CommonJs 的 this 是当前模块,ES6 Module 的 this 是 undefined
禁止 Babel 将 ES6 编译到 CommonJS。
webpack4 的 mode 集成了多个优化项,在 produciton 模式下默认开启了 Tree Shaking。
sideEffects 可以配置文件导出默认都是无副作用的,在项目中启用后可以减少打包体积。
按需导入。
兼容性问题
- 对一行文字设置了 line-height 等于 height 垂直居中,但是在 Android 的浏览器上会偏上一点。
- 将字体、高度放大一倍后缩小,transform: scale(0.5)
- 使用 vertical-align 属性居中
- (百度)安卓手机 line-height 设置比 height 大 1px
- click 事件 300ms 延迟。为了监听是否是双击缩放事件。
- 禁用缩放
- 用 touchstart 代替
- iphone x 上判断滚动到底, scrollTop + clientHeight !== scrollHeight,差一像素。
http2
- 多路复用:在 HTTP/2.0 中,每个请求/响应都可以看作一个流(stream),并给每个 stream 分配 id,一个 TCP 连接上以有多个 stream,stream 中的帧都是乱序的,到对端后 再根据帧的 stream_id 重新组装,这样可以避免队首阻塞问题,极大地提高传输性能,
- 二进制传输:在 HTTP/1.x 中,通过文本形式传输数据,而在 HTTP/2.0 中,所有数据都会被分割,并在应用层和传输层之间增加一个二进制分帧层,首部信息被封装到 Header 帧,请求主体被封装到 Data 帧,采用二进制编码
- 首部压缩:在 HTTP/2.0 中,使用 HPACK 压缩格式对 header 进行编码,减少 header 大小,并在通信两端维护索引表,记录出现过的 header,对于相同的 header,不必多次发送
- 服务器推送:服务器可以在客户端某个请求后,主动推送其他资源
- 更安全:浏览器强制要求使用 HTTP/2.0 时必须要用上 SSL
http1.1 的长链接和 http2 的多路复用
- HTTP/1.x 一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接
- HTTP/1.1 Pipeling 解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会,因为传输格式是文本的,一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞
- HTTP/2 多个请求可同时在一个连接上并行执行(由于支持二进制的格式,可以无序)某个请求任务耗时严重,不会影响到其它连接的正常执行