【插件系列】为了愉快的薅羊毛,小羽专门写了一个使用免费CDN的插件
如果生活有奇迹,那一定是努力的轨迹!
前言
Hello,大家好,我是小羽同学,一个平凡而又不甘于平凡的前端开发工程师~
前段时间,小羽复习了下 webpack
相关的知识,然后突然发现自己好像还没写过webpack插件
的,手就有那么一点儿痒痒的,想动手自己撸一个webpack插件
出来耍耍。
正当小羽在绞尽脑汁,想到底写个啥插件出来耍耍的时候,某个前端吹水群里讨论起cdn以及前段时间jsdelivr
挂掉的事情。哎,这不正好吗?我给它整一个webpack插件
,专门薅jsdelivr
的羊毛,以后还可以使用。看这想法不是挺棒的嘛~
因此,本篇文章也是围绕该webpack插件展开的。
通过本篇文章你可能可以学到如下知识:
github
+jsdelivr
使用免费的cdn- 撰写一个简单的
webpack插件
(再也不怕面试官问我webpack插件了!!!) - 利用
github api
上传/修改文件 - 利用
html-webpack-plugin
修改输出的文件内容 jsdelivr
挂掉了的降级处理方案
- 利用
github-jsdelivr-upload
直接使用cdn
1.如何使用免费cdn?
首先咱们想使用免费的cdn
,就得先知道jsdelivr
是怎么样使用滴~
在jsdelivr官网中我们可以看到jsdelivr是通过npm
、github
、wordpress
三种途径进行加速的。
现在我们主要讲的是github这种途径。
使用github的方式,咱们是可以通过版本
或者直接使用路径
的方式来进行加速的。
这两种的区别就是版本的方式他会是将文件进行锁定,而直接使用路径的话则会根据你文件的变化而随之变化。
emmm,既然是使用github的方式,那咱们先创建一个仓库吧。
ps:
这里建议小伙伴们新开一个github账号,
这里建议小伙伴们新开一个github账号
这里建议小伙伴们新开一个github账号
重要的事情说三遍
因为后面的插件会使用到github的token,而拥有该token的用户则可以对你的仓库进行各种操作,懂得都懂。
在创建的时候记得将仓库设置为public
,这样子jsdelivr才可以读取到咱们github中的文件,然后顺便勾上add a readme file。这个是给咱们的仓库默认添加一个readme.md的文件,方便咱们测试jsdelivr。
ok,现在仓库建好了,咱们先测试一下是否可以通过jsdelivr
来读取咱们的readme.md
文件
这里就直接使用通过路径
的方式了。
然后可以看到刚刚新建的README.md可以被正常读取了。
jsdelivr链接中的参数
如下图所示,小伙伴这么聪明应该一看就懂吧?
2.通过github-jsdelivr-upload免费使用cdn
这里的话,小羽就直接使用基于vue-cli
创建的开源项目——小羽直播平台,进行演示。(经测试vue
、react
都是可以正常使用的,angular的小伙伴就不好意思了,小羽不懂angular,但理论上也是可以使用的,毕竟是一个webpack的插件)
使用一个npm包的第一步就是查看
相关的文档
。
emmm,然后发现咱们有这么两个问题
需要处理,否则可能无法使用插件。
vue-cli
创建的项目中html-webpack-plugin
版本较低,为3.x
版本- 需要一个
github token
第一个问题比较简单,直播平台中的webpack
是4.x
版本,因此直接升级html-webpack-plugin
的版本即可
npm i html-webpack-plugin@4.5.0
第一个问题解决了,那咱们的github token
怎么获取呢?
跟着下面几幅图来操作就好,最后生成的token记得保存下来,因为关闭后就不会再显示这个token了~
再次声明,这个token是可以用来修改你的个人仓库的,所以为了避免token泄露可能造成不必要的损失。强烈建议小伙伴们新申请一个github账号。
好了,准备工作都完成了。咱们就开始使用github-jsdelivr-upload
这个插件吧。
首先安装
npm i github-jsdelivr-upload
然后根据npm中的文档,在vue.config.js
中进行相应的配置
注意,vue-cli
创建的项目这里需要手动引入html-webpack-plugin
,否则会使用默认的html-wepback-plugin3.x
版本。
然后npm run build
。查看一下咱们的打包结果,格式化一下。
emmm,可以发现咱们的链接全部换成带jsdelivr域名
下的链接,很nice,说明咱们的cdn插件
已经生效。
ok,到这里就可以够小伙伴们的日常开发和使用
了,如果想了解如何开发一个webpcak插件
以及github-jsdelivr-upload
的实现原理
的小伙伴们,请继续往下看~
3.撰写一个简单的webpack插件
咱们先来写一个最简单
的webpack插件
。
在跟目录下新建myWebpackPlugin.js,内容如下:
class MyPlugin {
constructor(data) {
const {
name,
} = data;
this.name = name
this.pluginName = 'MyPlugin'
}
apply(compiler) {
compiler.hooks.emit.tap(this.pluginName, () => {
console.log("这是小羽的个人webpack插件")
console.log("this.name", this.name)
})
}
}
module.exports = MyPlugin
然后在vue.config.js
中引入该plugin
,然后再npm run build
此时我们会发现咱们的控制台
中输出了咱们在插件中撰写的内容
好了,一个简单的插件这样子就完成了。
而一个复杂的插件无非就是在合适的时候调用合适的compiler
和complation
钩子,然后进行相应的操作。
4.利用github api上传/修改文件
小伙伴们还记得咱们平时是怎么将咱们的文件推送到github上不?
git add *
git commit -m 'xxx'
git push origin master
一般都是这样命令行
或者使用可视化工具
进行操作的,对吧?
那咱们的github-jsdelivr-upload
也是这样子操作的吗?
emmm,刚开始小羽的确有想过这么处理,因为这样子的逻辑是最简单
的,直接添加一个命令行
的npm包
即可。但是这样子的话会存在一些问题
。比如咱们所有可以打包的机器都必须带有github仓库允许提交密钥,这样一来就不是很方便了。
因此,小羽就另辟蹊径
,看看能不能直接将文件上传到github。然后就发现了原来github
是有给咱们提供了api接口,利用这些api接口,咱们就可以完成了上传。而这些接口就需要到github token
。这也是为啥github-jsdelivr-upload
需要github token
的原因.
upload(path, content, message = 'update cdn') {
return this.octokit.request('PUT /repos/{owner}/{repo}/contents/{path}', {
owner: this.owner,
repo: this.repo,
path,
message,
content
}).catch(err => {
console.log(JSON.parse(JSON.stringify(err)))
})
}
5.利用html-webpack-plugin修改输出的文件内容
还记得咱们在第二小节时候,使用了github-jsdelivr-upload
这个插件。然后这个插件会自动帮咱们将文件路径替换为jsdelivr
中的路径。emmm,这个是怎么处理的呢?
这里是利用了html-webpack-plugin
提供的 getHooks方法
,获取html
中的内容,并进行修改。
伪代码如下:
compiler.hooks.compilation.tap(this.pluginName, (compilation) => {
HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(this.pluginName, async (data, cb) => {
const assets = getAssets(compilation) // 获取文件路径
const cdnUrl = `${this.baseCdnUrl}/${this.owner}/${this.repo}${this.cdnType === 'staticaly'?'/main':''}/${this.basePath}`
const newAssetJson = ['/']
for(let i in assets){
for(let item of assets[i]){
// 正则替换对应的文件路径
}
}
data.plugin.assetJson = newAssetJson
cb(null, data)
})
})
6.jsdelivr挂掉的降级处理方案
emmm,前段时间jsdelivr在全国范围内,大面积挂掉
。导致很多使用jsdelivr的小伙伴们苦不堪言
。
既然咱们写了这么一个薅羊毛的插件,那咱们是不是也需要考虑到这种情况
当文件加载异常的时候,script、link这些标签都会触发一个onerror
的事件。
ok,那咱们就利用这个onerror
事件来搞事情。
封装一个errorCDN
的方法,在所有替换链接为jsdelivr的同时,添加data-cdn
以及errorCDN
方法。
当咱们的jsdelivr对应的文件加载异常
的时候就会触发errorCDN方法,而errorCDN将会将咱们加载异常的标签进行替换
为本地路径
(部署的服务器),即降级为使用本地的文件。
这时候咱们的页面只会出现文件加载异常的报错,但是并不会影响到咱们页面的运行。
function errorCDN(e) {
var target = e.getAttribute("data-cdn");
var tagName = e.tagName
var cdnDOM = document.createElement(tagName);
if(tagName === 'SCRIPT'){
cdnDOM.src = "./" + target;
}else{
cdnDOM.href = "./" + target;
}
document.head.appendChild(cdnDOM);
e.remove();
}
后语
本文小羽和小伙伴们分享了怎样使用免费的cdn
,并且对github-jsdelivr-upload
这个webpack插件的原理
进行了简单的分析,并且聊了下github-jsdelivr-upload
是怎么对jsdelivr
挂掉进行降级处理。
如果看这篇文章后,感觉有收获的小伙伴们可以点赞
+关注
哦~
如果想和小羽
交流技术可以加下wx,然后小羽最近建立了一个技术交流群
(有很多大佬在群里哦~),想进群的小伙伴们可以扫码,嘿嘿~
ps:本文原创,转载请标明出处。
最后奉上github-jsdelivr-upload
的相关连接
npm链接:www.npmjs.com/package/git…
GitHub链接:github.com/sulgweb/git…
如果条件允许的话,希望小伙伴们给小羽的github添加一颗小星星哦~
转载自:https://juejin.cn/post/7050257265877581832