整体思路

  • 加载性能

    1. 体量维度(工程化、代码设计):资源压缩;分包 splitChunk;externals+cdn;模块化;路由懒加载;组件化,加载最小依赖等等
    2. 网络维度:较少 tcp 连接次数;较少 http 请求数量;开 gzip;缓存;http-dns;
    3. 浏览器维度:http 缓存协议(强弱缓存)、service worker;PC 端域名发散,移动端域名收敛等等
    4. 业务维度:首屏 SSR,次屏浏览器渲染;懒加载,预加载;loading 无感知等等
  • 体验性能

    1. 计算线程不阻塞主线程(web worker);最小局部渲染,不回流(动画 绝对定位等)

首屏 SSR,次屏浏览器渲染

首屏服务器渲染(Server Side Rendering,简称 SSR)意味着网页的首屏内容是由服务器生成的 HTML,这个过程发生在用户请求网页时。服务器渲染的主要优点是可以提升首屏加载速度,提高 SEO 效果,因为搜索引擎可以直接抓取渲染后的页面。

次屏浏览器渲染(Client Side Rendering,简称 CSR)则是指在用户滚动页面,浏览非首屏内容时,内容是通过浏览器动态生成的。这种方式的优点是可以减轻服务器压力,提升用户体验,因为用户在滚动页面时,浏览器可以立即渲染出内容,无需再次向服务器请求。

如果我们有一个新闻网站,我们可能会将新闻列表的首屏通过服务器渲染,然后将用户滚动加载的其他新闻通过浏览器渲染。

在服务器端,我们可能会有类似下面的代码:

app.get("/", (req, res) => {
const news = getFirstScreenNews(); // 获取首屏新闻
res.render("index", { news }); // 使用首屏新闻渲染模板
});

在客户端,我们可能会有类似下面的代码:

window.addEventListener("scroll", () => {
if (needLoadMoreNews()) {
// 检测是否需要加载更多新闻
const news = loadMoreNews(); // 加载更多新闻
renderNews(news); // 渲染新闻
}
});

这只是一个非常简化的示例,实际的应用会更复杂。包括错误处理、缓存、性能优化等都需要考虑。

基础优化

像代码优化,避免使用复杂的 js css 代码,善用 keep-alive,减少重复沉余操作等等基础的优化这里就不详细说啦,但同样重要!

今天主要讲一下几种优化项目的方式。

减少 HTTP 请求

不影响需求的前提下,尽可能减少 http 请求

改善响应时间最简单,最直接的途径当是较少 http 请求啦,有一些一个链接能搞定的就不要分几个链接来请求,也可以用巧用一些缓存来避免重复的 http 请求。

路由懒加载(很重要)

配置路由各位前端得伙伴应该不陌生吧,但配置路由假如用的时一般加载,如果项目得模块少还好,要是十几个,再大点几十个上百个,一下子把所有组件都加载一遍,估计等项目加载完用户都怀疑是不是网络出问题了,自己开发预览也会很难受吧。

//一般加载 import component1 from "....." { // path: // name:
component:component1 } //懒加载 { // path: // name:
component:()=>import('.....') }
//import是ES6的一个语法标准,如果需要浏览器兼容,需要转化成es5的语法。

其实项目编译打包后,会把每个路由组件的代码分割成一一个 js 文件,初始化时不会加载这些 js 文件,只有当激活路由组件才会去加载对应的 js 文件。

gzip 静态资源压缩

有些文件确实不能再优化了,那我们是不是可以考虑把它压缩了呢。

其实原理很简单,开启 gzip 压缩把那些大得 js,css 文件进行压缩,压缩比率在 3 到 10 倍左右,这样从服务器获取数据的时候(需要服务器配置),再由浏览器去解压加载,这样可以大大节省服务器的网络带宽,提高资源获取的速度。

因为vue中一些小的静态资源文件是会打包成 base64 的文件存在 css 中的或者 js 中,这里就是控制需要转换的大小,这样减少了 js 的大小

不同的脚手架可能配置不太一样,但都大同小异,我这里用的是 webpack,大家可以参考一下。

打开 config/index.js 文件

//找到下面啊的代码
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false, //把这里改成true
productionGzipExtensions: ['js', 'css'],

然后安装依赖:

npm install --save-dev compression-webpack-plugin@1.1.12  //注意高版本安装可能会报错,不过不确定是不是高版本不适配的原因,这里指定版本@1.1.12

打开/build/webpack.base.config.js 文件,找到 module.exports 的 module 中的 rules,把 limit 从 10000 改小一点,这里改成 1000


module: {
rules: [{
test: /\.scss?$/,
loaders: ["style", "css", "sass"]
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 1000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 1000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 1000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},

为什么要改这里呢?

因为vue中一些小的静态资源文件是会打包成 base64 的文件存在 css 中的或者 js 中,这里就是控制需要转换的大小,这样减少了 js 的大小。

服务器端(下面以 Nginx 为例)

打开配置文件

一般都会默认开启 gzip 的,但是 gzip_static 是没有开启的,所有需要加上 gzip_static on;

如果没有开启 gzip 的话可以在手动在 http{}里添加

http {
gzip on;
gzip_static on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript
text/javascript text/css application/xml;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
}

webpack 的 Gzip 和服务端的 Gzip

其实服务端配置好 Gzip 就可以实现用户向服务器请求,服务器把资源压缩发送了,那为什么 webpack 也要设置呢?主要是为了减轻服务器压缩资源的负担,如果我们生产环境的资源本身就是压缩了的,那么服务器就不用压缩啦,自然就减轻了服务端的压力。建议两边都配置一下。

使用 CDN

如果应用程序 web 服务器离用户更近,那么一个 HTTP 请求的响应时间将缩短。另一方面,如果组件 web 服务器离用户更近,则多个 HTTP 请求的响应时间将缩短。

CDN(内容发布网络)是一组分布在多个不同地理位置的 Web 服务器,用于更加有效地向用户发布内容。在优化性能时,向特定用户发布内容的服务器的选择基于对网络慕课拥堵的测量。例如,CDN 可能选择网络阶跃数最小的服务器,或者具有最短响应时间的服务器。

CDN 还可以进行数据备份、扩展存储能力,进行缓存,同时有助于缓和 Web 流量峰值压力。

CDN 的缺点:

1、响应时间可能会受到其他网站流量的影响。CDN 服务提供商在其所有客户之间共享 Web 服务器组。

2、如果 CDN 服务质量下降了,那么你的工作质量也将下降

3、无法直接控制组件服务器

按需加载第三方库

有时候我们开发的页面白屏时间长,打开开发者工具,看 network 那里,一般都是 vender.js 这个资源获取时间长达几 s,第三方库一般都会打包到 vender.js ,就像我们常用到的 element.ui ,其实它的库是很大的,一般不设置都是整个库加载上来,自然加载慢了。我们可以把第三方库通过 CDN 的方式引入第三方库,这样 vendor.js 会减少,大大提升首屏加载速度,可以使用 Externals 技术,具体怎么使用大家可以搜一下,这里就不详细介绍啦。

图片压缩

这个是我自己以身示范的一个坑,在一个项目的登录界面我用了一张照片做背景,后来发现每次加载登录的界面都是超级慢,细究才发现,我这张照片 10 几 m….加载时间自然短不了,所以照片压缩很必要。

参考链接

  1. Web 前端性能优化——如何提高页面加载速度
  2. vue 项目 webpack 打包 app.js 文件太大导致首次加载非常缓慢的解决方案