原文地址: secure.phabricator.com/book/phabfl…

译者水平有限,如果有错误欢迎指正!

未来你会编写越来越多的 JS 和 CSS ,并且最终将找到一个合适的系统来管理它们。

这个是未雨绸缪专栏,汇总了一些web工程化问题,你应该在遇到它们之前就思考它们。

自动化处理依赖

在页面中添加静态资源最简单的办法,就是在页面渲染之前,在页面顶部一个个的引入它们,看 Facebook 之前的方式:

<?phprequire_js('js/base.js');
require_js('js/utils.js');
require_js('js/ajax.js');
require_js('js/dialog.js');
// ...
复制代码

这样做在早期是可行的,但从 2007 年开始情况变得不可控了。因为你需要按正确的顺序逐条手动列出这些静态文件,导致其他人需要把这一坨文件复制粘贴到各个页面。这样页面需要加载大量的 JS,影响了前端性能。

于是我们转向了一个被称作 Haste 的系统,该系统使用类似 docblock 的头部声明 JS 依赖:

/*** @provides dialog* @requires utils ajax base*/
复制代码

我们给每个文件手动添加注释,虽然理论上可以用静态分析工具代替(我们没有真正这么做是因为我们的 JS 是非结构化的)。这样我们可以通过一次调用请求组件的所有依赖链:

require_static('dialog');
复制代码

...而不是复制粘贴那一大坨依赖文件。

按需加载

早期的方法带来的另一个问题是,所有的静态资源都在页面顶部引入,而不是在实际需要的时候引用。这意味着2点:

  • 你需要引入所有可能在页面上出现的资源;
  • 如果你要在2个及以上的页面添加新内容,你最好把它放到 base.js 里。

这样每个页面都会有一坨蠢代码,例如 CAPTCHA(因为某些工作流涉及未验证的用户,理论上应该在所有页面上向所有用户展示CAPTCHA),以及其他人在 base.js 里时不时添加的东西。

我们转用了一个系统,JS 和 CSS 标签在页面加载完之后被输出(它们还是出现在页面顶部,只是在输出到浏览器之前被预先准备好,而不是被附加进去,这里有些复杂,超出本文讨论范围),所以require_static()可能出现在代码的任何地方。然后我们移动所有的require_static()到调用的地方(只有对话框代码会引入其依赖的 CSS 和 JS,因为并不是每个页面都有对话框),并且把 base.js 拆分成一系列更小的文件。

打包

大部分情况下最大的前端性能杀手是大量的http请求,针对这个问题最有力的武器是把单独的 JS 和 CSS 打包成一个大文件,这样就可以加载一个大的 JS 核心文件而不是加载一堆小文件。一旦其他基本工作到位,这是一个相对容易的更改。我们从手动定义包开始,最终转向基于生产数据的自动生成。

缓存与服务器内容

用最简单的方法引入静态资源,比如用 src="/js/base.js" 写下一个原生 JS 标签。随着站点规模的扩大,这将带来灾难性的问题,因为客户端使用的可能是老版本资源。这会引起一系列微妙的问题(尤其是使用了 CDN 时),最大的问题是当你 push/deploy 站点时用户正访问你的站点,客户端不会为已有的缓存资源发起请求,因此即使你的服务器能正确响应 If-None-Match (ETags) 和 If-Modified-Since (Expires),当你正将静态资源变更 push 到站点时,此时的浏览者将见不到这些变化后的静态资源。

解决这个问题最好的方法是给 URI 加版本号,这样各版本资源文件对应一个独立的 URI,如:

rsrc/af04d14/js/base.js

当你 push 站点时,用户将访问引用新 URI 的页面,浏览器会重新加载资源。

但是,还有一个大问题,一旦你有一堆前端页面:

当你 push 站点时,用户可能会发出一个请求,这个请求由运行新版本代码的服务器处理,返回了一个包含新 URI 的页面。然后浏览器发起了对新 URI 的请求,却被分发到了还未安装新版本代码的服务器上,服务器返回了旧版本的资源。这样客户端就有了脏缓存:新版本的 URI 下缓存了旧版本代码。

有很多巧妙的方法来解决这个问题,Facebook 解决的方法是用数据库而不是硬盘提供静态资源。当一个 push 开始之前,新的静态资源被写在数据库里,这样每个服务器都可以同时处理新旧资源的请求。

这种方式也使一些处理流程变得相对容易(例如删除注释和空格),只需要把压缩/加工的 CSS 和 JS 版本插入数据库即可。

参考实现:Celerity

这里讨论的一些想法在 Phabricator's 的 Celerity 系统中实现,该系统本质上是 Facebook使用的 Haste 系统简化版。

转载于:https://juejin.im/post/5c88a651f265da2de04af973

[译]未雨绸缪之:静态资源处理相关推荐

  1. vue-cli项目布署问题解决:空白页、静态资源文件404错误、refrenceError:promise未定义(部分浏览器不支持ES6语法)

    (前言:文章记录vue-cli项目打包使用IIS布署遇到的几个错误及解决方式) 首先简单理解webpack打包: 个人理解:项目开发中我们构建 "低耦合高内聚" 的组件/模块来代码 ...

  2. Nginx静态资源部署

    目录 Nginx静态资源概述 Nginx静态资源的配置指令 listen指令 server_name指令 location指令 设置请求资源的目录root / alias index指令 error_ ...

  3. SpringBoot-web开发(一): 静态资源的导入(源码分析)

    目录 方式一:通过WebJars 1. 什么是webjars? 2. webjars的使用 3. webjars结构 4. 解析源码 5. 测试访问 方式二:放入静态资源目录 1. 源码分析 2. 测 ...

  4. 关于SpringBoot项目通过jar包启动之后无法读取项目根路径静态资源

    前言:这个是昨天晚上在部署一个项目的时候发现的,在此记录一下 关于SpringBoot项目通过jar包启动之后无法读取项目根路径静态资源 问题描述 在部署了一个项目之后,打开项目页面进行测试,发现有一 ...

  5. 静态资源(StaticResource)和动态资源(DynamicResource)

    静态资源(StaticResource)和动态资源(DynamicResource) 资源可以作为静态资源或动态资源进行引用.这是通过使用 StaticResource 标记扩展或 DynamicRe ...

  6. springMVC静态资源访问不到

    还久没使用springMVC,空闲的时间搭了一个SSJ环境,发现静态资源全部没有找到,但是我的路径没有问题啊,最后发现是这些资源被拦截了 <!-- 配置SpringMvc 前端控制器 --> ...

  7. Spring Boot 静态资源处理,妙!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:cnblogs.com/paddix/p/8301331.h ...

  8. Nginx 静态资源缓存配置

    示例 # Media: images, icons, video, audio, HTC location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|m ...

  9. vue脚手架和html,HTML和静态资源

    HTML和静态资源 HTML Index 文件 public/index.html文件是一个会被 html-webpack-plugin 处理的模板.在构建过程中,资源链接会被自动注入.另外,Vue ...

最新文章

  1. python点击按钮浏览本地文件_Python button选取本地图片并显示的实例
  2. javaweb学习总结(三十四)——使用JDBC处理MySQL大数据
  3. GB2312,GBK,UTF-8的关系
  4. 面试题 03.04. 化栈为队/面试题09. 用两个栈实现队列/232. 用栈实现队列
  5. [导入][你必须知道的.NET] 第三回:历史纠葛:特性和属性
  6. flask 上传excel 前端_flask 笔记
  7. pycharm 远程连接Linux
  8. 代码签名工具有哪些?好用的数字签名工具推荐
  9. win7计算机的蓝牙,教你win7电脑蓝牙在哪里打开
  10. mw150um 驱动程序win10_Intel网卡驱动Win10官方下载_Intel网卡驱动Win10专版64位官方安装版-华军软件园...
  11. 用MySQl创建供应商标s_建立一个供应商、零件数据库。其中供应商表S(Sno - 问答库...
  12. [词性] 四、形容词
  13. 使用SpringBoot+Shiro实现记住我功能
  14. 静态HTML网页设计作品:旅游网站设计——开心旅游网(15页) HTML+CSS+JavaScript 主题度假酒店
  15. 怎么将小程序添加到我的小程序?
  16. 如何使用文件保险箱加密 Mac 上的启动磁盘?
  17. 微信小程序-调查问卷
  18. FlycoTabLayout - SegmentTabLayout的使用
  19. docker教程(简介)
  20. 每天一学设计模式(一、单一职责原则)

热门文章

  1. 【年终总结】2021年终总结
  2. 世平信息亮相中国中医药信息大会,助力医药行业数据安全体系建设
  3. docker容器和宿主机的主机名映射失败
  4. OPENSSL问题,使用fsockopen()函数提示错误
  5. emplace_back和push_back对比分析
  6. 工业企业外购材料退货、折让进项税额的会计处理
  7. server2012系统向KMS服务器请求失败
  8. 那些常用的HTML标签
  9. 微信小程序——每日卡路里
  10. opencv——SURF特征点检测并使用Flann算法匹配