记前端项目首屏加载优化(网络篇)

继之前的一篇《记前端项目首屏加载优化(打包篇)》之后,这次来讲一讲我的首屏加载在网络方面的优化😏。

写在前面

资源加载是一个网站的展示在用户浏览器的必经之路,资源的请求次数和响应时间决定了网站的加载体验。本篇主要针对请求次数和响应时间聊一聊优化过程。

网站分析与测试环境

有很多工具可以检测网站的网络请求:比如WebPage Speed TestInstant Website Test,这些工具可以分析网站的加载速度、安全性、可靠性等很多方面。而我是希望能够在本地开发过程中分析并优化,所以我还是选择Chrome Devtool 里的Network panel 进行分析。

本地开发环境的资源跟线上是有所不同的,本地的资源一般没有压缩,而线上有压缩,这样就会造成测试环境不真实,所以需要在本地模拟线上的打包环境,编译出跟线上环境一样的包来加载,这样分析出来的结果才有意义。

在上一篇《记前端项目首屏加载优化(打包篇)》有写到过在本地打包一个和线上环境一致的压缩配置,在package.json加入下面的配置:

"scripts": {
    ...
    "local_production": "cross-env NODE_ENV=local_production npm run build"
}

然后在webpack配置里面判断process.env.NODE_ENV === 'local_production',便构建出production环境的包即可。

gzip压缩

打包出来的包大小1.7M,所有的依赖包index.xxx.js有748k这么大,所以需要开启gzip压缩,可以大大减小加载大小,首先安装express 的gzip包 compression:

npm install -D compression

然后添加express中间件:

var compression = require('compression');
app.use(compression());

打包后启动服务器,浏览器访问,这时候index.xxx.js已经压缩到212kb😎

image.png

开启http2.0

http1.x时代的优化折磨好长一段时间,各种奇淫技巧为了弥补http1的短板,影响着我们的开发专注度,好在http2已经开始盛行,相信不久的将来可以完全替代http1。

现在基本主流的浏览器都支持http2.0了
http2-浏览器支持

http2.0大幅提升了加载性能,相比http1增加了多路复用、二进制分帧、header压缩等特性

开启http2也很简单,前提是开启了https协议,只要在Nginx配置文件中找到你要开启http2.0的域名server模块,然后将 listen 443 ssl;改成 listen 443 ssl http2; 即可。

server {

    listen 443 ssl http2;
    server_name domain.com;

    ssl_certificate /path/to/public.crt;
    ssl_certificate_key /path/to/private.key;
    
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #允许的协议 
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; #加密算法(CloudFlare 推荐的加密套件组) 
    ssl_prefer_server_ciphers on; #优化 SSL 加密套件 
    ssl_session_timeout 10m; #客户端会话缓存时间 
    ssl_session_cache builtin:1000 shared:SSL:10m; #SSL 会话缓存类型和大小 
    ssl_buffer_size 1400; # 1400 bytes to fit in one MTU

检查请求是否已经开启http2,可以在chrome的network面板点鼠标右键,选中protocol,就可以看到该请求是否开启了http2,图中h2就代表http2:


http2

顺便提一句,很多第三方的SDK都没有开启http2🤔

CDN加速

项目开发中用到的静态资源和打包后的资源都可以传到cdn以提高加载速度,我的项目是用七牛的上传脚本,在npm run build之后执行上传脚本将dist目录上传到cdn上,注意在webpack配置里要配置publish_path对应上传cdn后的域名路径。具体看七牛的上传脚本文档

构建线上环境的publicPath的值可以是cdn的域名+路径的形式,结尾要加/
"https://cdn.xxx.com/static/

webpack的output里配置publicPath

output: {
    path: DIST_PATH,
    publicPath: publicPath,
  },

webpack的图片资源Loader应添加相应配置publicPath

    {
      test: /\.(jpg|gif|ico|png|svg|mp4|mp3)$/,
        use: `url-loader?limit=10&name=asset/[name]_[hash:5].[ext]&publicPath=${config.PUBLIC_PATH_ASSET}`,
        exclude: /(node_modules)/,
      },
      {
        test: /\.(woff|eot|ttf)\??.*$/i,
        loader: `url-loader?limit=1000&name=fonts/[name].[hash].[ext]&publicPath=${config.PUBLIC_PATH_ASSET}`,
        exclude: /(node_modules)/,
      },

无模块化js的按需加载

有些时候我们引入的第三方插件是不能被webpack优化按需加载,或者是没有提供模块化加载的(只能通过script标签引入的)插件,比如像tinymce富文本编辑器,由于它的加载方式是靠script标签引入tinymce.js,并靠tinymce.js里自身的加载机制去另外加载主题theme.js或者相关plugin.js。

这种第三方插件无法做成模块化。这样的话我们是不是就只能在入口index.html加script标签引入它,被迫在首屏加载这个暂时用不到的大文件🤔?

我找到了webpack-require-http来帮忙😎,他可以帮我用require语句帮我加载远程js,并提供了回调🤝,于是我便可以控制在什么时候加载tinymce🤘。

我的项目是按路由按需加载的,首页没有用到富文本编辑器所以没必要加载,而论坛页需要用到富文本编辑器,于是我们可以在react-router路由配置里的添加onEnter钩子,在进入论坛页的时候才加载tinymce。

// 在需要tinymce编辑器的路由时提前加载
const require_tinymce = (nextState, replace, cb) => {
  require('https://cdn.bootcss.com/tinymce/4.7.13/jquery.tinymce.min.js').then(() => {
    cb();
  });
};

// router-config.js
{
    path: 'forum/:forum_id',
    component: forum_route,
    onEnter: require_tinymce,
},

这样子如果访问首页的话,首屏就少加载了这个big guy,经测试,在模拟1M/s 的网速下访问网站,出现首屏界面的时间快了2s左右,2s! 😱...,这可以说是最大力度的一次优化了。

缓存

缓存有很多种方式,大部分是服务器端处理的,而客户端处理的则一般是把资源缓存在本地。

比较有效的本地缓存一般是用application-cache或者service worker将网站的资源缓存到本地,再次访问时直接调用本地的缓存资源,几乎是本地打开的速度,但是我的项目里的资源用到了CDN配置,所有的资源都在CDN外链中,而刚才提到的两种缓存方式都不支持缓存跨域资源😞。

这时候就得权衡一下了🤔,如果是首次访问网站的浏览器,加载时间cdn服务器会比自身服务器快一些,而二次加载则后者更快,只是网站缓存需要自己维护一套配置,如果配置不得当,会落下很严重的坑😂,所以目前我还是先选择相对保守的CDN加载,等以后慢慢磨合🙂。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容