在追求快速响应和优化用户体验的今天,高效构建网页已成为前端开发的重要课题。作为一名热衷于提升网站性能的开发者,我最近对公司的网页进行了全面的性能优化工作,取得了显著的成效。在此,我将从构建的角度出发,为大家分享我的优化经验。
### 优化前的资源加载情况
在着手优化之前,我们先来分析一下网页的资源加载情况。经过仔细检查,我们发现最大的vendor包居然有MB(经过gzip压缩后)的大小。在未进行任何额外配置的情况下,Webpack将所有的第三方依赖都打包进了这个包中。随着项目的发展,引入的依赖越来越多,导致这个包的体积也越来越大,严重影响了网站的加载速度。
为了直观地了解资源加载情况,我们可以借助webpack-bundle-analyzer来分析。这款插件可以将打包后的内容以树状图的形式展示出来,让我们可以很清楚地看到哪些模块较大,从而进行针对性优化。
### CDN引入
CDN(内容分发网络)是一种将源站资源缓存在全球各地的节点上的技术。当用户请求资源时,会从最近的CDN节点返回缓存的内容,这样可以避免网络拥堵、缓解源站的压力,保证用户访问资源的速度和体验。在打包后的产物中,也会上传到CDN上进行缓存。
为了进一步优化性能,我们可以将体积较大的第三方依赖单独拆出来放到CDN上,这样既不会占用打包资源,也不会影响最终包的体积。例如,对于g6这样的库,如果有直接打包压缩好的单文件CDN资源,就可以直接使用。
### externals配置
如果想引入一个库,但又不想让Webpack打包,同时不影响程序中通过import、require或window/global全局等方式的使用,可以通过配置externals来实现。这个选项提供了一种“从输出的bundle中排除依赖”的方法。相反,所创建的bundle依赖于那些存在于用户环境中的依赖。
首先将CDN引入的依赖加入到externals中。然后借助html-webpack-plugin将CDN文件打入HTML中。需要注意的是,在HTML中配置的CDN引入脚本一定要放在body的最底部。
### 拆分vendor
在某些场景下,一个第三方依赖可能拆成了多个子依赖。例如,monaco这样的库就有多个子依赖。这时,我们需要自己去配置Webpack规则,将想拆出来的依赖单独打包成一个vendor。
### 动态import
将vendor拆分后,依赖仍然会在首屏被加载。如果依赖不在首屏使用,仍然会造成网络资源的浪费,并阻塞页面渲染。对于不必要在首屏进行加载的依赖,我们可以采用动态import的方式来实现异步加载。
当然,并非所有依赖都适合异步加载。对于有较高性能要求的依赖或本身就较大的依赖,可能会产生明显的延迟。
### React懒加载
对于某些第三方依赖组件,例如monacoeditor,我们只有在很少的业务场景下才会用到,但其本身一个包占用了5MB的空间。为了提高性能,我们可以通过动态import的方式进行懒加载。但对于React组件,直接使用dynamic import可能不太合适,因为其渲染运行时是可多次触发的。
此时,我们可以使用React.lazy和Suspense函数来实现懒加载。在首次渲染时,React.lazy会自动导入包含组件的包,并通过Suspense组件进行优雅降级(如loading)处理。
### 路由懒加载
类似地,我们可以对路由进行懒加载,这样每个模块都会被单独打包为一个JS文件,首屏只会加载当前模块引入的JS。不过,这在切换模块时可能会产生一小段白屏或loading效果。
### 语言包优化
在某些场景下,语言包会占用整个包体积的一大部分。实际上库本身的逻辑并不会很大,例如moment就是一个很好的例子。通过配置ContextReplacementPlugin,我们可以对其进行优化。
最终,我们会发现模块已经被拆分得非常均匀,并且只会在对应页面渲染时加载对应模块。这对首屏的渲染速度有很大提升。
通过以上方法,我相信大家也能在构建过程中优化网站的性能,为用户提供更优质的服务。让我们一起努力,不断提高网页性能,为互联网的发展贡献自己的力量!