【插件系列】為了愉快的薅羊毛,小羽專門寫了一個使用免費CDN的插件

小羽同學 2022-01-07 12:17:08 阅读数:789

插件 系列 愉快 羊毛 使用

如果生活有奇迹,那一定是努力的軌迹!

前言

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是通過npmgithubwordpress三種途徑進行加速的。

現在我們主要講的是github這種途徑。

使用github的方式,咱們是可以通過版本或者直接使用路徑的方式來進行加速的。

image-20220105210208984

這兩種的區別就是版本的方式他會是將文件進行鎖定,而直接使用路徑的話則會根據你文件的變化而隨之變化。

emmm,既然是使用github的方式,那咱們先創建一個倉庫吧。

ps:

這裏建議小夥伴們新開一個github賬號,

這裏建議小夥伴們新開一個github賬號

這裏建議小夥伴們新開一個github賬號

重要的事情說三遍

因為後面的插件會使用到github的token,而擁有該token的用戶則可以對你的倉庫進行各種操作,懂得都懂

在創建的時候記得將倉庫設置為public,這樣子jsdelivr才可以讀取到咱們github中的文件,然後順便勾上add a readme file。這個是給咱們的倉庫默認添加一個readme.md的文件,方便咱們測試jsdelivr。

image-20220105211428798

image-20220105211540996

ok,現在倉庫建好了,咱們先測試一下是否可以通過jsdelivr來讀取咱們的readme.md文件

這裏就直接使用通過路徑的方式了。

然後可以看到剛剛新建的README.md可以被正常讀取了。

jsdelivr鏈接中的參數如下圖所示,小夥伴這麼聰明應該一看就懂吧?

image-20220105211800924

image-20220105212143903

2.通過github-jsdelivr-upload免費使用cdn

這裏的話,小羽就直接使用基於vue-cli創建的開源項目——小羽直播平臺,進行演示。(經測試vuereact都是可以正常使用的,angular的小夥伴就不好意思了,小羽不懂angular,但理論上也是可以使用的,畢竟是一個webpack的插件)

使用一個npm包的第一步就是查看相關的文檔

image-20220105214918182

image-20220105220034683

emmm,然後發現咱們有這麼兩個問題需要處理,否則可能無法使用插件。

  • vue-cli創建的項目中html-webpack-plugin版本較低,為3.x版本
  • 需要一個github token

img

第一個問題比較簡單,直播平臺中的webpack4.x版本,因此直接昇級html-webpack-plugin的版本即可

npm i [email protected]
複制代碼

第一個問題解决了,那咱們的github token怎麼獲取呢?

跟著下面幾幅圖來操作就好,最後生成的token記得保存下來,因為關閉後就不會再顯示這個token了~

再次聲明,這個token是可以用來修改你的個人倉庫的,所以為了避免token泄露可能造成不必要的損失。强烈建議小夥伴們新申請一個github賬號。

image.png

image.png

image.png

image.png

好了,准備工作都完成了。咱們就開始使用github-jsdelivr-upload這個插件吧。

首先安裝

npm i github-jsdelivr-upload
複制代碼

然後根據npm中的文檔,在vue.config.js中進行相應的配置

注意,vue-cli創建的項目這裏需要手動引入html-webpack-plugin,否則會使用默認的html-wepback-plugin3.x版本。

image-20220105224632357

然後npm run build。查看一下咱們的打包結果,格式化一下。

emmm,可以發現咱們的鏈接全部換成帶jsdelivr域名下的鏈接,很nice,說明咱們的cdn插件已經生效。

image-20220105224539225

ok,到這裏就可以够小夥伴們的日常開發和使用了,如果想了解如何開發一個webpcak插件以及github-jsdelivr-upload實現原理的小夥伴們,請繼續往下看~

img

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

此時我們會發現咱們的控制臺中輸出了咱們在插件中撰寫的內容

好了,一個簡單的插件這樣子就完成了。

img

而一個複雜的插件無非就是在合適的時候調用合適的compilercomplation鉤子,然後進行相應的操作。

image-20220105230046541

image-20220105225944900

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掛掉進行降級處理。

如果看這篇文章後,感覺有收獲的小夥伴們可以點贊+關注哦~

img

如果想和小羽交流技術可以加下wx,然後小羽最近建立了一個技術交流群(有很多大佬在群裏哦~),想進群的小夥伴們可以掃碼,嘿嘿~

ps:本文原創,轉載請標明出處。

最後奉上github-jsdelivr-upload的相關連接

npm鏈接:www.npmjs.com/package/git…

GitHub鏈接:github.com/sulgweb/git…

如果條件允許的話,希望小夥伴們給小羽的github添加一顆小星星哦~

img

版权声明:本文为[小羽同學]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/01/202201071217074997.html