Giter Club home page Giter Club logo

blog's People

Contributors

anhulife avatar

Stargazers

 avatar

Watchers

 avatar  avatar

blog's Issues

以MD5值命名静态资源的必要性

网站性能优化中比较重要的一点是高效利用浏览器缓存,浏览器缓存可以减少网络请求数和流量,用以提高页面加载速度。

高效利用浏览器缓存的原则是:只有当文件内容变化时,缓存才失效

现状

但是大多数网站都没有做到这点,因为他们的方式是给静态资源添加版本号,然后开始永久缓存

这个版本号有些是开发者手工维护,有些是后端动态提供。版本号多数是时间戳或是序号的形式。

.bg{
    background: url(../img/bg.png?20150124) no-repeat;
}
<script src="<%= cdnURL%>/js/index.js?<%= cdnVersion%>"></script>

手工维护虽然可以实现以上原则,但是手工维护的成本高,而且有被遗漏的风险。

后端多数会提供一个统一的版本号,所有静态文件共用这一个版本号。所以一旦发版,静态文件都会更换版本号,导致缓存全部失效。而多数公司一周至少发一次版,静态文件实际上只能缓存几天。

尝试优化

面对上述状况,我们尝试去优化,版本号就是优化的切入点,我们需要解决的问题如下:

  1. 自动添加版本号
  2. 每个静态文件对应各自的版本号
  3. 只有当文件内容变化时版本号才能改变

这三个问题都很好解决,解决方案如下:

  1. 引入前端构建工具
  2. 用静态文件的MD5值做版本号

使用MD5作为版本号,可以很好的解决问题2和3,MD5作为信息摘要可以很好的反映文件内容是否改变。而引入前端构建工具,在发布时,执行构建分析每个引用的静态文件的内容,生成MD5值,然后追加到引用地址后面。

还不够好

上面的方案看起来很美,但是问题也是有的,只不过很隐蔽。通过上述方法,我们可以得到发布后的静态文件引用结果:

.bg{
    background: url(../img/bg.png?d41d8cd98f00b204e9800998ecf8427e) no-repeat;
}
<script src="<%= cdnURL%>/js/index.js?1055d3e698d289f2af8663725127bd4b"></script>

不完美的地方是MD5值以链接参数的形式出现,这样做的隐患有以下两个

首先静态文件必须先于模板文件发布。因为如果模板文件先发布,那模板文件中的静态文件链接如果被用户访问了,得到的内容还是旧的,浏览器缓存就把旧的内容缓存起来,导致了静态文件就算发布了,也不会生效。而且如果CDN服务器也开启了服务器缓存,那无论什么时候访问,内容都是旧的。

其次测试时,如果切换错host到线上CDN服务器的host,就会导致包含新MD5值的链接提前被线上CDN服务器缓存起来(如果CDN服务器开启了服务器缓存),而线上CDN服务器上的静态文件是旧的,所以就导致发布静态文件不会生效,而且这个问题也不好排查。

终极解决方案

总结上述两个隐患,其原因就在于:MD5值作为链接参数。解决方案很简单,就是以MD5值作为文件名的一部分,发布后的静态文件引用如下:

.bg{
    background: url(../img/bg_d41d8cd98f00b204e9800998ecf8427e.png) no-repeat;
}
<script src="<%= cdnURL%>/js/index_1055d3e698d289f2af8663725127bd4b.js"></script>

这样做就可以解决上述两个问题,好处是显而易见的,如果修改后的文件没有发布到CDN服务器,那访问对应的链接会报404错误,结果不会被服务器和浏览器缓存。当然如果发布的时候,先发模板文件,那在静态文件发布前,用户访问页面时会出现静态文件访问不到的情况。考虑到这个时间间隔不会太大,并且多数发布都是在用户访问不频繁的时间,所以这个问题可以忽略。

综上所述,使用MD5值作为文件名的一部分,可以充分利用浏览器缓存,实现只有当文件内容变化时,缓存才失效的原则。

touchend在安卓上失效

平台

安卓(v4.0.3,v4.4.4)

场景

按下元素之后要重复执行回调的功能,准备监听元素的touchstart事件后使用定时器执行回调,并监听documenttouchend事件,终止执行回调。

描述

touchstart事件在用户按下的时候成功触发,如果用户滑动手指的话,touchend并不能如期触发

变通方法

touchstart的事件处理函数中执行e.preventDefault()阻止默认行为即可。

参考

如何修复移动浏览器上 touchend 事件不触发的bug
touchend event doesn't work on Android

纯前端的下载方案

场景

日常工作中我们偶尔会遇到提供资源下载给用户的场景。这个资源可能是静态文件,也可能是动态内容。如果是静态文件,那就需要先上传文件到服务器中。如果是动态内容,就需要后端童鞋写对应的功能。

这种模式在应对大型或复杂的下载资源时没有问题,但当资源比较小或简单时,就有些重量级。这种时候,如果前端能够独自生成资源供用户下载就很具有优势了。

说明

a标签的download属性是HTML5新引入的,用以告诉浏览器该标签中的链接是可下载的资源,属性值就是下载到本地的文件名。详情查看标准

<a href="http://www.foo.com/bar.txt" download="bar.txt">下载</a>

强大源于组合

download属性看起来很简单,但是有了它,前端就可以摆脱后端独自提供资源下载给用户。当然还需要搭配其他前端技术。

dataURI

dataURI是一种URI模式,可以包含文件数据。因为前端是可以独自拼接出dataURI的,所以组合download属性后,就可以动态创建一个可下载的文本文件资源了。

var url = 'data:text/plain;charset=utf-8,' + encodeURIComponent('Hello world!');
$('<a href="'+ url +'" download="hello.txt">下载</a>').appendTo('body');

Canvas

除了文本文件,我们还可以组合使用Canvas用来动态创建一个可下载的图片资源。因为Canvas不只可以绘图,还可以将图像数据导出成dataURI链接。

var canvas=document.getElementById('myCanvas');
var ctx=canvas.getContext('2d');
ctx.fillStyle='#FF0000';
ctx.fillRect(0,0,80,100);
$('<a href="'+ canvas.toDataURL() +'" download="canvas.png">下载</a>').appendTo('body');

结语

在没有后端配合的情况下,前端是可以独自动态生成可下载的文本和图片文件资源。这样做的好处是减少请求数,减轻服务器压力,去掉前后端协调成本。但是目前这种方式还不能大范围使用,因为download属性还没有得到广泛的浏览器支持,支持详情请查阅caniuse。不过倒是可以先在实验项目或是内部项目中使用。

通过EditorConfig统一团队的代码风格

团队代码风格问题

团队没有统一的风格约定, 经常会出现一个文件由于多个人维护, 导致缩进风格不统一, 一会是tab, 一会是空格, 代码逼格直接low爆了.

想要统一风格, 必须要有一个强制的约定, 但是这个约定很多时候不容易推进, 因为大家用的编辑器或IDE不同, 这个时候就需要引入工具协助开发人员执行代码风格约定.

什么是EditorConfig?

EditorConfig是一个跨编辑器和IDE的工具, 帮助开发者保持一致的代码风格.它由一种代码风格定义文件和多个编辑器及IDE(支持主流编辑器及IDE)的插件构成. 它可以将代码风格定义应用于编辑器及IDE.

EditorConfig实例

EditorConfig的配置是被放到一个名为.editorconfig的文件中的

Windows用户如果创建不了该文件, 可以在文件夹中创建名为.editorconfig.的文件, Windows会自动的将文件命名为.editorconfig

root = true

[*.{js,css}]
charset = utf-8
indent_style = tab
indent_size = 2
trim_trailing_whitespace = true

[package.json]
indent_style = space
indent_size = 2

还有哪些不足

个人觉得配置项还不够, 缺少以下配置

  1. 空格
  2. 换行
  3. 折行

虽然这些内容是代码格式化的范畴了, 但是代码格式化缺少跨编辑器和IDE的配置工具

结语

EditorConfig的配置项虽然比较简洁, 但不妨碍它帮助团队统一代码风格, 至少能统一一下缩进.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.