目前市面上服务器带宽都挺贵的,为了节省服务器的带宽,咱们通常都会使用cdn的方式进行分流,从而降低带宽的压力。
但是目前市面上的公共cdn这么多,有选择困难症,怎么办?
想用公共cdn,还得自己去找对应的cdn链接,很麻烦的,有什么好的办法吗?
找到链接后,还需要自己手动添加html文件中,有更好的解决方案吗?
前段时间jsdeliver大范围挂掉,导致不少网站白屏,面对这种问题,该如何处理?
如果说,现在有一个可以解决如上问题的cdn插件,你想不想试一下?
基本使用
这个cdn插件就是白泽团队
开源的vite-add-cdn-script
,咱们先看看如何使用吧?
ps:使用webpack
or 其他打包工具
的小伙伴们,别着急,核心包
正在抽离
中,很快就可以完成适配啦~
快速上手
// 安装
pnpm install vite-add-cdn-script rollup-plugin-external-globals -D
在vite中进行配置(这里使用react+react-dom,作为最简单的例子)
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import externalGlobals from "rollup-plugin-external-globals";
import viteAddCdnScript from "vite-add-cdn-script";
const externals = {
react: "React",
"react-dom": "ReactDOM",
};
export default defineConfig({
base: "./",
plugins: [react(), viteAddCdnScript({})],
build: {
rollupOptions: {
external: [...Object.keys(externals)],
plugins: [externalGlobals(externals)],
},
},
});
然后执行打包(pnpm run build),就会发现咱们得打包产物中,已经自动添加了cdn。对的,你已经掌握
了cdn插件的使用,是不是非常简单
呢?
对比一下使用cdn插件前后的打包,可以发现
首先咱们打包的速度和体积都有所下降,这个主要是
external
和rollup-plugin-external-globals
的原因。其次,我们也不需要去纠结选择什么cdn,到哪里去找cdn的链接了,插件都帮咱们
自动引入
到打包的产物中啦。再者就是这个插件好像帮咱们做了cdn的
异常处理
咱们来试下cdn异常
的时候是什么样的效果?
这里我们将src改掉,改成一个不存在的包,再通过live server打开看看。
可以看到咱们得页面中虽然有报错,但是还是可以正常运行
的,这就非常棒~
自定义cdn
如果你觉得目前插件的公共cdn不符合你的要求,没关系,咱们也有自定义cdn
的功能。
你可以通过customScript
字段来进行定义,不过自定义cdn将会丢失
异常处理方案,即需要保证自定义cdn的稳定性。
注意事项
当然使用这个cdn插件还是有一点点需要注意的事情,就是依赖的先后顺序
问题,不过这个在你手动引入cdn的时候也是会有这个问题,因此插件层暂时也没有太好的解决方案。
比如react-router-dom需要依赖react、@remix-run/router、react-router,因此需要放在最后。
如下:
插件的实现
好了,前面就是插件的基本使用啦。
下面将会来介绍咱们插件的实现,想了解的小伙伴,咱们继续。
如果不了解vite插件的基本实现,可以看小羽的这篇文章《同事:唉,你写的代码有bug!》,这里就不讲了。
整体架构图
npm包地址:www.npmjs.com/package/vit…
github地址:github.com/baizeteam/b…
整体的架构图如下,目前我们主要完成了vite插件版本的开发。在后续的开发中,我们将会把工具层
、基建层
、数据持久层
剥离出来成为一个核心包
,从而可以轻松的适配
各种打包工具插件。
cdn的获取
cdn的获取方式,刚开始时想自己维护一套键值对,后面经过咱们团队的新成员lgldl同学
的提醒,发现各大开源的cdn都是有对应的api接口
的。直接通过api接口来处理cdn的适配,可以有效的降低我们的工作量。
然后,我们只需要通过对应api接口,整理出cdn中文件的规则
即可。
怎么插入到html文件中?
ok,现在cdn相关的链接咱们都可以获取到了,那script的拼接,相信难不倒大家了。那该如何在打包时自动把咱们的cdn拼接后的script插入到html页面
中呢?
在vite插件中,有一个叫transformIndexHtml
的钩子函数。
它可以用来对index.html进行处理,而单页面应用的时代,很少直接处理index.html了。所以,咱们可以直接用正则来替换
。
cdn的异常处理
前段时间jsdeliver
大范围挂掉
,导致不少网站白屏
,面对这种问题,我们的插件是如何处理
的?
我们定义了一个errorCDN
的方法,当cdn加载异常的时候,就会触发onerror
。而我们在cdn对应的script中绑定这个errorCDN的方法,就会自动去新建一个新的script
,并且去加载新的cdn
。
这样子下来,虽然打开控制台会看到第一个cdn加载报错,但我们在后续又直接加载了新的cdn,所以不影响
网站的使用了。
数据持久层
为啥需要这个数据持久层
?
别问,问就是性能优化
【手动狗头】
嘿嘿,待小羽解析一下~
因为每次请求cdn接口
都是需要耗费一定的时间
。
如果每次打包的时候都去请求一次接口,那么就可能会降低
我们的打包效率
,而且每次请求回来的内容都是一样的,所以添加这个数据持久层
就变得十分有必要了。
我们新增了一个cache.ts,而在vite这些基于node
的打包工具中,咱们是可以直接使用fs模块
的,想了解数据持久层具体实现
的小伙伴们可以直接去看代码
具体效果
如下,打包时会自动在项目的根目录下新建了一个.cdn-cache.json
。然后在后续的打包中,咱们的插件会先通过这个缓存文件
来寻找cdn,如果没有再去通过cdn的接口来获取,这样子就可以有限的降低打包的cdn 接口请求耗时。
ps:建议不要通过.gitignore忽略该文件,否则每次打包都是需要通过api接口获取cdn路径。
加入我们
白泽大舞台,有胆你就来!
白泽开源团队持续向大家发出邀请,欢迎各位有志之士加入到咱们的开源团队中来,舞台很大,等的就是你!!!