继以前的一篇《记前端项目首屏加载优化(打包篇)》以后,此次来说一讲个人首屏加载在网络方面的优化😏。javascript
资源加载是一个网站的展现在用户浏览器的必经之路,资源的请求次数和响应时间决定了网站的加载体验。本篇主要针对请求次数和响应时间聊一聊优化过程。css
有不少工具能够检测网站的网络请求:好比WebPage Speed Test,Instant Website Test,这些工具能够分析网站的加载速度、安全性、可靠性等不少方面。而我是但愿可以在本地开发过程当中分析并优化,因此我仍是选择Chrome Devtool 里的Network panel 进行分析。html
本地开发环境的资源跟线上是有所不一样的,本地的资源通常没有压缩,而线上有压缩,这样就会形成测试环境不真实,因此须要在本地模拟线上的打包环境,编译出跟线上环境同样的包来加载,这样分析出来的结果才有意义。前端
在上一篇《记前端项目首屏加载优化(打包篇)》有写到过在本地打包一个和线上环境一致的压缩配置,在package.json加入下面的配置:java
"scripts": { ... "local_production": "cross-env NODE_ENV=local_production npm run build" }
而后在webpack配置里面判断process.env.NODE_ENV === 'local_production',便构建出production环境的包便可。node
打包出来的包大小1.7M,全部的依赖包index.xxx.js有748k这么大,因此须要开启gzip压缩,能够大大减少加载大小,首先安装express 的gzip包 compression
:react
npm install -D compression
而后添加express中间件:jquery
var compression = require('compression'); app.use(compression());
打包后启动服务器,浏览器访问,这时候index.xxx.js已经压缩到212kb😎webpack
http1.x时代的优化折磨好长一段时间,各类奇淫技巧为了弥补http1的短板,影响着咱们的开发专一度,好在http2已经开始盛行,相信不久的未来能够彻底替代http1。web
如今基本主流的浏览器都支持http2.0了
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:
顺便提一句,不少第三方的SDK都没有开启http2🤔
项目开发中用到的静态资源和打包后的资源均可以传到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)/, },
有些时候咱们引入的第三方插件是不能被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加载,等之后慢慢磨合🙂。