10倍性能提升:优化静态站点——by JonLuca De Caro

原文地址:10x Performance Increases: Optimizing a Static Site by JonLuca De Caro https://link.medium.com/KtPI4fhWdR

几个月前,我在美国境外旅行,并且我希望向我的朋友展示我的个人静态网站,我尝试导航到我的网站,但我花费了比我预期更长的时间。网站中绝对没有任何的动态内容,只是有一些动画和响应式设计,但是内容是静态保持不变的。我对这个结果表示非常震惊,DOM节点内容加载花费了4s,整个网页加载花费了6.8s。网站中有20个静态站点请求,传输总数据为1Mb,我已经习惯了连接到我在旧金山的服务器的洛杉矶的1Gb/s 低延迟物联网速度,这让这个怪物像闪电般快速。在意大利,以8Mb/秒的网速,这完全是一个不同的画面。

这是我第一次研究网络优化,到目前为止之前我无论什么时候想要添加一个库或者资源,我都会将其抛入并指向到src=‘’。我没有注意任何形式的性能,从缓存到内联到延迟加载。

我开始寻找有相似经验的人,但是很不幸,很多关于静态文件优化的文献都已经过时了,都是一些2010年或者2011年的建议或者讨论。文库或者假设都不再是真实的,只是重复以前的理论。

但是我还是找到了两个很好的信息资源——高性能浏览器网络和Dan Luu 在优化静态站点方面的类似经验。虽然在代码格式和内容方面我达不到Dan的水平,但是我确实设法让自己的页面加载速度大约快了10倍,DOM节点内容加载大约为5分之一秒,整页面加载只有388ms。(实际是有点不准确,因为它解决了延迟加载)。

过程

这个过程的第一步是分析网站轮廓。我想要弄清楚什么是加载时间最长的,以及如何最好的并行优化一切。我运行了各种工具来分析我的网站,并且在世界各地进行测试,包括:
• https://tools.pingdom.com/
• www.webpagetest.org/
• https://tools.keycdn.com/speed
• https://developers.google.com/web/tools/lighthouse/
• https://developers.google.com/speed/pagespeed/insights/
• https://webspeedtest.cloudinary.com/

其中一些提供了有关改进的建议,但是当你的网站有50个请求时,你才可以做到这一点。这从90年代遗留下来的gif空图像,是未使用的资源。(我加载了6种字体却只使用了其中一种)。


我的网站的时间线 - 我在Web Archive网络存档上对此进行了测试,因为我没有截取原始网站,但它看起来与我几个月前看到的相似。

我想改进我控制的一切 ———从内容和和通过javascript连接到Web服务器(Nginx)的速度和DNS设置。

优化

缩小和合并资源

第一件我需要注意的事情是我为CSS和JS(没有任何形式的HTTP keepalive)制作了十几个请求,对于不同站点,其中一些是https请求。这增加了对各种CDN或服务器的多次往返请求,并且一些JS文件正在请求其他的资源,所以这导致了上面看到的串联阻塞现象。

我使用webpack将我的所有资源合并到一个js文件。每当我对我的内容进行更改时,它会自动更新压缩,将所有依赖项转换为单个文件。

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const ZopfliPlugin = require("zopfli-webpack-plugin");module.exports = {entry: './js/app.js',mode: 'production',output: {path: __dirname + '/dist',filename: 'bundle.js'},module: {rules: [{test: /\.css$/,loaders: ['style-loader', 'css-loader']}, {test: /(fonts|images)/,loaders: ['url-loader']}]},plugins: [new UglifyJsPlugin({test: /\.js($|\?)/i}), new ZopfliPlugin({asset: "[path].gz[query]",algorithm: "zopfli",test: /\.(js|html)$/,threshold: 10240,minRatio: 0.8})]};

我试了不同的方案,以前这个单一的bundle文件位于我网站的head部分,会形成阻塞。它的最终大小为829kb,包括每一个非图片资源(css,字体,所有库和依赖项以及js)。这里面绝大多数是字体文件,占用了829kb中的724kb。

我浏览了Font Awesome 库,并删除了除了我使用的三个图标以外的所有,只留下了fa-github,fa-envelope和fa-code图标。
我使用了一个名为fontello的服务来拉取我需要的图标,这时候字体资源只需要94kb大小。

网站目前的构建方式,如果我们只要样式表,那看起来是不正确的,所以我接受了单个bundle.js的阻塞性质。加载时间为118毫秒,比上述要好一个等级。

这也有一些额外的好处,我不再需要指向第三方资源或者CDN,因此用户不需要
1.对资源执行CDNS查询;
2.执行https握手;
3.等待资源从第三方完全下载;

虽然CDN和分布式缓存可能对大规模的分布式站点有意义,但对我的小型静态网站没有意义。额外的100毫秒左右是值得的权衡。

压缩资源

我加载了8Mb大小的头部头像,然后以10% 的宽度高度显示它。这不仅仅是缺乏优化,这几乎是对用户带宽的浪费使用。

我在这个网站压缩了所有图像,https://webspeedtest.cloudinary.com/。它还建议我切换到webp格式,但我希望保持更多可能性的浏览器兼容,所以依然坚持使用jpg格式。其实可以建立一个程序,让webp仅被传递到支持它的浏览器。
但是我希望尽可能保持简单,而且对于增加抽象层代码的优势并不明显和值得。

改进Web服务器-Http2,TLS等

我做的第一件事情是转到https,以前我在端口80上运行Nginx,只是从var/www/html加载文件。

server{listen 80;server_name jonlu.ca www.jonlu.ca;root /var/www/html;index index.html index.htm;location ~ /.git/ {deny all;}location ~ / {allow all;}
}

我首先设置了https并将所有http请求重定向到https,我从Let's Encrypt获得了我的TLS证书(一个伟大的网站,可以注册签署通配证书。)

server {listen 443 ssl http2;listen [::]:443 ssl http2;server_name jonlu.ca www.jonlu.ca;root /var/www/html;index index.html index.htm;location ~ /.git {deny all;}location / {allow all;}ssl_certificate /etc/letsencrypt/live/jonlu.ca/fullchain.pem; # managed by Certbotssl_certificate_key /etc/letsencrypt/live/jonlu.ca/privkey.pem; # managed by Certbot
}

只需添加http2指令,Nginx就可以充分利用最新HTTP功能的所有优势特性。 请注意,如果要利用HTTP2(以前的SPDY),则必须使用HTTPS。 在这里阅读(https://hpbn.co/http2/)更多相关信息。

您还可以利用带有http2_push 命令作用于images / Headshot.jpg;

注意:启用gzip和TLS可能会使您面临BREACH风险。 由于这是一个静态站点,面临BREACH的实际风险很低,所以保持压缩是是没有问题的。

利用缓存和压缩指令

通过Nginx还可以实现更多目标吗?跳出来的第一件事就是缓存和压缩指令。

我发送原始的未压缩的html,只需要一个_gzip和_line命令,就能够从160000字节变为8000字节,减少50%。

我们实际上可以能够进一步提高这个数字——如果设置Nginx的_gzip_static,它会预先查找所有请求文件的预压缩版本。这与我们上面的webpack config结合使用,我们可以用ZopicPlugin在构建时预压缩我们所有文件。这节省了计算资源,并允许我们最大限度的提高压缩率,而无需权衡速度。

此外,我的网站很少更改,所以我希望更可能长时间的缓存资源。这将使得在后期用户访问中,不需要重新下载资源(尤其是bundle.js)

我更新的服务器配置如下所示:请注意,我并没有讲解我所有的更改,例如TCP设置更改,gzip指令和文件缓存。如果您想要了解更多相关信息,请阅读有关调优Nginx的文章。

worker_processes auto;
pid /run/nginx.pid;
worker_rlimit_nofile 30000;events {worker_connections 65535;multi_accept on;use epoll;
}http {### Basic Settings##sendfile on;tcp_nopush on;tcp_nodelay on;keepalive_timeout 65;types_hash_max_size 2048;# Turn of server tokens specifying nginx versionserver_tokens off;open_file_cache max=200000 inactive=20s;open_file_cache_valid 30s;open_file_cache_min_uses 2;open_file_cache_errors on;include /etc/nginx/mime.types;default_type application/octet-stream;add_header Referrer-Policy "no-referrer";### SSL Settings##ssl_protocols TLSv1 TLSv1.1 TLSv1.2;ssl_prefer_server_ciphers on;ssl_dhparam /location/to/dhparam.pem;ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';ssl_session_timeout 1d;ssl_session_cache shared:SSL:50m;ssl_stapling on;ssl_stapling_verify on;add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';ssl_certificate /location/to/fullchain.pem;ssl_certificate_key /location/to/privkey.pem;### Logging Settings##access_log /var/log/nginx/access.log;error_log /var/log/nginx/error.log;### Gzip Settings##gzip on;gzip_disable "msie6";gzip_vary on;gzip_proxied any;gzip_comp_level 6;gzip_buffers 16 8k;gzip_http_version 1.1;gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;gzip_min_length 256;### Virtual Host Configs##include /etc/nginx/conf.d/*.conf;include /etc/nginx/sites-enabled/*;

和相应的服务器块。

server {listen 443 ssl http2;server_name jonlu.ca www.jonlu.ca;root /var/www/html;index index.html index.htm;location ~ /.git/ {deny all;}location ~* /(images|js|css|fonts|assets|dist) {gzip_static on; # Tells nginx to look for compressed versions of all requested files firstexpires 15d; # 15 day expiration for all static assets}}

延迟加载

最后,我对我的实际网站进行了一些小的改动,这也对速度有少许不可忽视的提高。有5个图像是在您按下相应的标签之前看不到,但是这些图片还是与其他所有标签同时加载。(因为他们位于<img src ="">标签中。

我写了一个简短的脚本,用lazyload类修改这些元素的属性。只有在单击相应的框时才会加载这些图像。

$(document).ready(function() {$("#about").click(function() {$('#about > .lazyload').each(function() {// set the img src from data-src$(this).attr('src', $(this).attr('data-src'));});});$("#articles").click(function() {$('#articles > .lazyload').each(function() {// set the img src from data-src$(this).attr('src', $(this).attr('data-src'));});});});

因此一旦文档完成加载,它将修改<img>标签,以便它们从<img data-src="">转到<img src="">,并将其加载到背景。

未来的改进

还有一些其他更改可以提高页面加载速度-最重要的是,使用Service Workers缓存和拦截所有请求,让站点甚至脱机运行,并在CDN上缓存内容,以便用户不需要完整在SF中往返服务器。
这些都是值得的改变,但对于作为在线简历/关于我的页面的个人静态网站而言并不是特别重要。

结论

这使得我的页面加载速度从第一页加载时的8秒以上变为350ms,后续加载时间为200毫秒。我真的建议您阅读所有高性能浏览器网络High Performance Browser Networking ,它很容易阅读完,但是却提供了一个令人难以置信的现代互联网概述,并对优化现代互联网模型的每一层提出了很好的建议。

我错过遗漏了什么吗?是否有一些违反最佳实践或可以进一步改善性能的方法?随意联系JonLuca De Caro!

【翻译】10倍性能提升:优化静态站点——by JonLuca De Caro相关推荐

  1. 10+倍性能提升全过程--优酷账号绑定淘宝账号的TPS从500到5400的优化历程

    10+倍性能提升全过程--优酷账号绑定淘宝账号的TPS从500到5400的优化历程 摘要: # 10+倍性能提升全过程--优酷账号绑定淘宝账号的TPS从500到5400的优化历程 ## 背景说明 &g ...

  2. 10倍性能提升!DLA SQL推出基于Alluxio的数据湖分析加速功能

    简介:在存储计算分离的场景下,通过网络从远端存储读取数据是一个代价较大的操作,往往会带来性能的损耗.以OSS为例,OSS数据读取延时通常较本地磁盘大很多,同时OSS对单个用户使用的带宽上限做了限制,这 ...

  3. 提升系统 10 倍性能的 10 个建议!

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 译者:为之漫笔 来源:http://www.zcfy.c ...

  4. 使用 Next.js 缓解静态站点的压力

    介绍 静态站点生成是提高应用程序速度.安全性和整体性能的强大工具.Next.js 是一种流行的静态站点生成框架,它为开发人员提供了一种利用静态站点功能的简单方法.它提供了一组强大的功能,例如自动代码拆 ...

  5. github创建静态页面_如何在10分钟内使用GitHub Pages创建免费的静态站点

    github创建静态页面 Static sites have become all the rage, and with good reason – they are blazingly fast a ...

  6. 硬核!Rust异步编程方式重大升级:新版Tokio如何提升10倍性能详解

    导读:协程或者绿色线程是近年来经常讨论的话题.Tokio作为Rust上协程调度器实现的典型代表,其设计和实现都有其特色.本文是Tokio团队在新版本调度器发布后,对其设计和实现的经验做的总结,十分值得 ...

  7. 外贸网站必看!10个谷歌排名优化提升技巧

    外贸网站是目前在网络上广泛存在的商业形态之一. 为了让更多的潜在客户找到您的网站,谷歌SEO优化技巧是必不可少的. 在这篇文章中,我们将分享10个谷歌SEO优化技巧,帮助您提高外贸网站的谷歌排名. 关 ...

  8. 博客生成静态站点工具 Top 30

    文章目录 1.Next.js 2.Hugo 3.Gatsby 4.Jekyll 5.Nuxt 6.Docusaurus 7.Hexo 8.GitBook CLI 9.Docsify 10.VuePre ...

  9. [译] 2018 年,如何选择最好的静态站点生成器

    原文地址:How to Choose the Best Static Site Generator in 2018 原文作者:Mathieu Dionne 译文出自:掘金翻译计划 本文永久链接:htt ...

最新文章

  1. MySQL: Root element is missing
  2. 【手把手教你Maven】构建过程
  3. linux默认网关地址,linux shell 获取默认网关地址
  4. 32利用文件系统保存数据_数据管理技术的产生与发展
  5. java怎么改运行图标,java修改进程图标
  6. 蓝牙耳机测试软件apk_Bose Connect(蓝牙耳机控制器)
  7. 程序设计入门c语言代码,C语言程序设计 入门源代码代码集合
  8. 无油螺杆鼓风机-市场现状及未来发展趋势
  9. Adobe PhotoShop V8.0
  10. Vanilla JS——最轻快的JavaScript框架
  11. ICMP协议及报文格式
  12. 《图解HTTP》(四)更安全的HTTPS、用户认证
  13. php中的echo单引号_PHP echo用法详解
  14. 看这一篇,你还不会Linux吗?
  15. java手机小程序 情人节_情人节快到了!表白小程序制作详解,撩翻你的女神!...
  16. 猜数游戏(无限次数和有限次数)
  17. Halcon中的测量工具(找边找圆等)——Metrology系列
  18. SAP FICO 银行对账单导入功能开发说明书(包括开发源代码、测试样例、FS)
  19. VSAN集群报配置错误处理
  20. python 3.8.0安卓_Python 3.8.0 稳定版发布,来看看Python 3.8.0的新功能吧

热门文章

  1. 怎么用python挣钱-怎么利用python赚钱
  2. 当代罪恶:山西黑砖窑
  3. 树莓派4b风扇安装方法_树莓派安装Raspberry Pi OS系统
  4. 宝尚综述-沪指回档10日均线,渔业水产品逆市领涨
  5. 今天,影响了一位试用期员工的去留
  6. 使用 Hasura 和 PostgreSQL 构建后端技巧你会吗
  7. EmbedRank论文解读
  8. Swagger-Codegen使用详解
  9. 【Unity】activeSelf和activeInHierarchy差别
  10. mysql workbench 1142,eclipse window 10 64位 jdk 1.8 亲测