You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
'use strict';/** deps */varpath=require('path'),express=require('express'),mime=require('express/lib/express').mime,/** cache values */ONE_HOUR=60*60,ONE_WEEK=ONE_HOUR*24*7,ONE_MONTH=ONE_WEEK*4,ONE_YEAR=ONE_MONTH*12,/** mime type regexps */RE_MIME_IMAGE=/^image/,RE_MIME_FONT=/^(?:application\/(?:font-woff|x-font-ttf|vnd\.ms-fontobject)|font\/opentype)$/,RE_MIME_DATA=/^(?:text\/(?:cache-manifest|html|xml)|application\/(?:(?:rdf\+)?xml|json))/,RE_MIME_FEED=/^application\/(?:rss|atom)\+xml$/,RE_MIME_FAVICON=/^image\/x-icon$/,RE_MIME_MEDIA=/(image|video|audio|text\/x-component|application\/(?:font-woff|x-font-ttf|vnd\.ms-fontobject)|font\/opentype)/,RE_MIME_CSSJS=/^(?:text\/(?:css|x-component)|application\/javascript)/,/** misc regexps */RE_WWW=/^www\./,RE_MSIE=/MSIE/,RE_HIDDEN=/(^|\/)\./,RE_SRCBAK=/\.(?:bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~/;// load additional node mime typesmime.load(path.join(__dirname,'node.types'));// apply `ServerResponse` patchrequire('../patch');/** * Configures headers layer. * @type {Function} */module.exports=function(options){/** * The actual headers layer, invoked for each request hit. * Applies all h5bp goodness relative to response headers. */returnfunctionheadersLayer(req,res,next){varurl=req.url,pathname=req.path||'/',host=req.headers.host,ua=req.headers['user-agent'],cc='',type;// Block access to "hidden" directories or files whose names begin with a// period. This includes directories used by version control systems such as// Subversion or Git.// 隐藏文件,403拒绝访问if(!options.dotfiles&&RE_HIDDEN.test(pathname)){next(403);return;}// Block access to backup and source files. These files may be left by some// text/html editors and pose a great security danger, when anyone can access// them.// 备份、源文件,403拒绝访问if(RE_SRCBAK.test(pathname)){next(403);return;}/** * Suppress or force the "www." at the beginning of URLs */// The same content should never be available under two different URLs -// especially not with and without "www." at the beginning, since this can cause// SEO problems (duplicate content). That's why you should choose one of the// alternatives and redirect the other one.// By default option 1 (no "www.") is activated.// no-www.org/faq.php?q=class_b// If you'd prefer to use option 2, just comment out all option 1 lines// and uncomment option 2.// ----------------------------------------------------------------------// Option 1:// Rewrite "www.example.com -> example.com".// 重定向if(false===options.www&&RE_WWW.test(host)){res.setHeader('Location','//'+host.replace(RE_WWW,'')+url);next(301);return;}// ----------------------------------------------------------------------// Option 2:// Rewrite "example.com -> www.example.com".// Be aware that the following rule might not be a good idea if you use "real"// subdomains for certain parts of your website.if(true===options.www&&!RE_WWW.test(host)){res.setHeader('Location','//www.'+host.replace(RE_WWW,'')+url);next(301);return;}/** * Built-in filename-based cache busting */// If you're not using the build script to manage your filename version revving,// you might want to consider enabling this, which will route requests for// /css/style.20110203.css to /css/style.css// To understand why this is important and a better idea than all.css?v1231,// read: github.com/h5bp/html5-boilerplate/wiki/cachebustingreq.baseUrl=req.url;req.url=req.url.replace(/^(.+)\.(\d+)\.(js|css|png|jpg|gif)$/,'$1.$3');// Headers stuff!!// Subscribes to the `header` event in order to:// - let content generator middlewares set the appropriate content-type.// - "ensures" that `h5bp` is the last to write headers.res.on('header',function(){/** * Proper MIME type for all files */// Here we delegate it to `node-mime` which already does that for us and maintain a list of fresh// content types.// https://github.com/broofa/node-mimetype=res.getHeader('Content-Type');// normalize unknown types to empty stringif(!type||!mime.extension(type.split(';')[0])){type='';}/** * Better website experience for IE users */// Force the latest IE version, in various cases when it may fall back to IE7 mode// github.com/rails/rails/commit/123eb25#commitcomment-118920// https://www.cnblogs.com/menyiin/p/6527339.html// chrome IE壳if(RE_MSIE.test(ua)&&~type.indexOf('text/html')){res.setHeader('X-UA-Compatible','IE=Edge,chrome=1');}/** * Cross-domain AJAX requests */// Serve cross-domain Ajax requests, disabled by default.// enable-cors.org// code.google.com/p/html5security/wiki/CrossOriginRequestSecurity// cors 跨域if(options.cors){res.setHeader('Access-Control-Allow-Origin','*');}/** * CORS-enabled images (@crossorigin) */// Send CORS headers if browsers request them; enabled by default for images.// developer.mozilla.org/en/CORS_Enabled_Image// blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html// hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/// wiki.mozilla.org/Security/Reviews/crossoriginAttribute// 图片可跨域if(RE_MIME_IMAGE.test(type)){res.setHeader('Access-Control-Allow-Origin','*');}/** * Webfont access */// Allow access from all domains for webfonts.// Alternatively you could only whitelist your// subdomains like "subdomain.example.com".// 字体可跨域if(RE_MIME_FONT.test(type)||'/font.css'==pathname){res.setHeader('Access-Control-Allow-Origin','*');}/** * Expires headers (for better cache control) */// These are pretty far-future expires headers.// They assume you control versioning with filename-based cache busting// Additionally, consider that outdated proxies may miscache// www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/// If you don't use filenames to version, lower the CSS and JS to something like// "access plus 1 week".// note: we don't use express.static maxAge feature because it does not allow fine tune// Perhaps better to whitelist expires rules? Perhaps.// cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)// Your document html// Dataif(!type||RE_MIME_DATA.test(type)){cc='public,max-age=0';}// Feedelseif(RE_MIME_FEED.test(type)){cc='public,max-age='+ONE_HOUR;}// Favicon (cannot be renamed)elseif(RE_MIME_FAVICON.test(type)){cc='public,max-age='+ONE_WEEK;}// Media: images, video, audio// HTC files (css3pie)// Webfontselseif(RE_MIME_MEDIA.test(type)){cc='public,max-age='+ONE_MONTH;}// CSS and JavaScriptelseif(RE_MIME_CSSJS.test(type)){cc='public,max-age='+ONE_YEAR;}// Miscelse{cc='public,max-age='+ONE_MONTH;}/** * Prevent mobile network providers from modifying your site */// The following header prevents modification of your code over 3G on some// European providers.// This is the official 'bypass' suggested by O2 in the UK.//no-siteapp// 禁止网站转码cc+=(cc ? ',' : '')+'no-transform';res.setHeader('Cache-Control',cc);/** * ETag removal */// Since we're sending far-future expires, we don't need ETags for// static content.// developer.yahoo.com/performance/rules.html#etags// 干掉Tag,避免浪费服务资源,良好的缓存机制既能做到实时正确更新又能尽可能利用缓存优势res.removeHeader('ETag');/** * Stop screen flicker in IE on CSS rollovers */// The following directives stop screen flicker in IE on CSS rollovers - in// combination with the "ExpiresByType" rules for images (see above).// TODO/** * Set Keep-Alive Header */// Keep-Alive allows the server to send multiple requests through one// TCP-expression. Be aware of possible disadvantages of this setting. Turn on// if you serve a lot of static content.// 保持长联,减少多回三次握手带来的性能损失,但要有可靠的超时机制res.setHeader('Connection','keep-alive');/** * Cookie setting from iframes */// Allow cookies to be set from iframes (for IE only)// If needed, specify a path or regex in the Location directive.// TODO/** * A little more security */// do we want to advertise what kind of server we're running?if('express'==options.server){res.removeHeader('X-Powered-By');}});next(null,req,res);};};
The text was updated successfully, but these errors were encountered:
HTTP Cache
原文链接
什么是 HTTP Cache
关键字
简单流程图
代码准备
index.html
img.png
server.js
为了不影响阅读代码贴在页尾,注意需要自行安装
mime
npm包。不设置
明确禁止缓存
效果和不设置一样,只是明确告诉浏览器禁止缓存资源。
private与public
Cache-Control: public
表示一些中间代理、CDN等可以缓存资源,即便是带有一些敏感 HTTP 验证身份信息甚至响应状态代码通常无法缓存的也可以缓存。通常 public 是非必须的,因为响应头 max-age 信息已经明确告知可以缓存了。Cache-Control: private
明确告知此资源只能单个用户可以缓存,其他中间代理不能缓存。原始发起的浏览器可以缓存,中间代理不能缓存。例如:百度搜索时,特定搜索信息只能被发起请求的浏览器缓存。缓存过期策略
一般缓存机制只作用于
get
请求1、三种方式设置服务器告知浏览器缓存过期时间
设置响应头(注意浏览器有自己的缓存替换策略,即便资源过期,不一定被浏览器删除。同样资源未过期,可能由于缓存空间不足而被其他网页新的缓存资源所替换而被删除。):
Cache-Control: max-age=1000
响应头中的Date
经过1000s
过期Expires
此时间与本地时间(响应头中的 Date )对比,小于本地时间表示过期,由于本地时钟与服务器时钟无法保持一致,导致比较不精确Last-Modified
,浏览器隐式的设置资源过期时间为(Date - Last-Modified) * 10%
缓存过期时间。2、两种方式校验资源过期
设置请求头:
If-None-Match
如果缓存资源过期,浏览器发起请求会自动把原来缓存响应头里的ETag
值设置为请求头If-None-Match
的值发送给服务器用于比较。一般设置为文件的 hash 码或其他标识能够精确判断文件是否被更新,为强校验。If-Modified-Since
同样对应缓存响应头里的Last-Modified
的值。此值可能取得 ctime 的值,该值可能被修改但文件内容未变,导致对比不准确,为弱校验。下面以常用设置了
Cache-Control: max-age=100
和If-None-Match
的图示说明:浏览器缓存此响应,缓存寿命为接收到此响应开始计时 100s 。
这里不清楚为什么,同样的配置,index.html 文件即便有缓存也 304。
)返回 304 时设置 Age: 0 与不设置效果一样, 猜测是浏览器会自动维护。
强制校验缓存
有时我们既想享受缓存带来的性能优势,可有时又不确认资源内容的更新频度或是其他资源的入口,我们想此服务器资源一旦更新能立马更新浏览器的缓存,这时我们可以设置
再次发起请求,无论缓存资源有没有过期都发起验证请求,未更新返回 304,否则返回新资源。
性能优化
现在一些单页面技术,构建工具十分流行。一般一个 html 文件,每次打包构建工具都会动态默认把众多脚本样式文件打包成一个 bundle.hashxxx.js 。虽然一个 js 文件看似减少了 HTTP 请求数量,但对于有些三方库资源等长期不变的资源可以拆分出来,并设置长期缓存,充分利用缓存性能优势。这时我们完全可以对经常变动的 html 设置
Cache-Control: no-cahce
实时验证是否更新。而对于链接在 html 文件的资源名称均带上唯一的文件指纹(时间戳、版本号、文件hash等),设置 max-age 足够大。资源一旦变动即标识码也会变动,作为入口的 html 文件外链改变,html 变动验证返回全新的资源,拉取最新的外链资源,达到及时更新的效果。老的资源会被浏览器缓存替换机制清除。流程如下:期中总结:HTTP 缓存性能检查清单
Request URL
为键值(区分大小写)缓存资源,不同的网址提供相同的内容会导致多次获取缓存相同的资源。ps:常见的更新缓存的方式:在网址后面来加个 v=1,例如 https://xxx.com?v=1 来更新新的资源,但是这样的更新方式有极大的弊端。
ETag
:提供资源对比机制。ps:服务器每次验证文件的话,太耗性能,现代前端构建工具都能自动更新文件hash,不需要设置Tag了,直接设置长缓存时间。
private
,对于公共资源例如 CDN 资源可以设置public
。max-age 或 Expires
,对于不经常变动或不变的资源设置尽可能大的缓存时间,充分利用缓存性能。no-cache
强制缓存验证,以确保外链资源的及时更新。前端工程化
弊端:
(熟悉的声音:是你缓存有问题吧,清下缓存...)。
这就是为什么要等到三更半夜,等用户休息了,先发静态资源,再发动态页面。
非覆盖式更新,改变某文件,生成新的文件并更新页面引用链接一并上传服务新文件,不影响以前用户,又能实时更新文件,完美!
问题来了,那我怎么写代码,图片、CSS、JS等静态资源怎么去维护,修改了生成新的文件,更新新的外链。。。这就不是人力所能为了。
前端工程化议题应运而生,欢迎补玉。
参考
mozilla:HTTP 缓存
谷歌有关性能的文字:HTTP 缓存
node中的缓存机制
w3c Header定义
彻底弄懂 Http 缓存机制 - 基于缓存策略三要素分解法
听说你用webpack处理文件名的hash?那么建议你看看你生成的hash对不对
附代码
index.html
server.js
标准配置
The text was updated successfully, but these errors were encountered: