免费 CDN 玩法 —— 将整个网站打包成一个图片文件 - EtherDream
2021-09-08 15:46:00 Author: www.cnblogs.com(查看原文) 阅读量:74 收藏

前端开发者都知道,过多的请求对性能影响很大。而且有些 CDN 不仅按流量收费,请求数也收费,如果网页里有大量小文件,显然不划算。

为此不少开发者将零碎的小文件进行合并优化,例如 JS/CSS 合并在一起,图片合并成精灵图等。

不过传统的合并方式有一定的局限性,只能合并同类型的文件。例如 JS、CSS 等文本格式的数据可以合并,但 JS 和图片显然无法合并,毕竟一个是文本格式,一个是二进制格式。而且合并过程需对现有资源进行修改,最终发布的文件与原始文件差异很大。

有没有什么办法,可将任何类型的资源并成在一起,并且不改变原始文件?

Google 推出了一个 Web Bundles 方案,可将任意类型的资源打包成一个文件:

细节可参考:https://web.dev/web-bundles/

不过 Web Bundles 注重的是离线分享。如文中所提到,在没有网络的飞机上,可将网页小游戏通过单个文件的方式分享给旁边的人一起玩。

演示可见,通过本地文件打开的网站仍保留原始 URL。

由于 Web Bundles 目前仍未正式启用,需在 flags 中手动开启,因此该方案仍无法解决本文提出的问题。

事实上,我们大可不必关心资源类型,将所有文件都当做二进制文件合并在一起,运行时再通过 JS 提取。

但是,网页里的资源引用的仍是原始 URL,例如 <img src="a.gif">。怎样才能让网页使用 JS 提供的数据,而不是从原始 URL 加载?

这就需要借助 HTML5 的一个黑科技 —— Service Worker。它能拦截网页产生的 HTTP 请求,并能控制返回内容。这样即可实现所有资源都从单个文件中提取!

初始化

既然要调用 Service Worker,那么是否得修改现有的 HTML 文件,在其中添加脚本?

事实上不需要!用户首次访问时,无论访问哪个路径,后端都返回 Service Worker 安装页;安装完成后页面自动刷新,这时请求即可被 Service Worker 拦截,从而使用资源包中的 HTML 文件。

至于实现其实很简单,使用 404.html 即可!

免费空间

虽然我们将资源请求数降低到只有 1 个,但流量仍然是存在的。并且任何一个资源更新都得重新下载整个资源包,导致流量成本进一步增长。

有没有什么办法,可大幅降低流量成本?很简单,使用免费 CDN 即可。你可将资源包发布 GitHub、NPM 等空间,然后通过 jsdelivr、unpkg 等免费 CDN 加速。

这样,你的网站只需提供 404.html 和 sw.js 两个极小的文件即可,其他所有内容都可从免费空间获取!

演示站点:https://fanhtml5.github.io/

原始文件:https://github.com/fanhtml5/test-site (多个文件,总共数 MB)

发布文件:https://github.com/fanhtml5/fanhtml5.github.io (只有两个,压缩后不到 2kB)

图片空间

类似 jsdelivr、unpkg 这么好用的免费 CDN 并不多,用在这里太过浪费,作为开发者也不建议过度使用它们。

我们可使用更低廉更广泛的免费空间 —— 各大网站的贴图相册,例如知乎、B 站、简书等文章的贴图,它们不仅支持 CORS,而且允许空 referrer,完全可用于存储数据。

参照之前写的《利用 canvas 实现数据压缩》文章,我们可将原始数据编码成图片像素,从而可将任意文件写入图片并上传到相册;运行时再解码还原,将原始文件写入 Storage Cache 供 Service Worker 使用。

至于稳定性,可将图片上传到多个站点作冗余。如果加载失败或 Hash 不正确则使用下一个备用图片,从而大幅提升稳定性和安全性。

基于上述思路,这里实现了一个简单的工具,暂且称之 web2img

GitHub: https://github.com/EtherDream/web2img

工具演示:


文章来源: http://www.cnblogs.com/index-html/p/bundle-website-into-an-image.html
如有侵权请联系:admin#unsafe.sh