大家好,我卡頌。
你是否好奇 —— codesandbox是如何在線運(yùn)行代碼的?
要回答這個(gè)問題,我們先看看前端項(xiàng)目是如何在本地跑起來的。簡單來說分為3步:
codesandbox能在線運(yùn)行代碼,顯然他也實(shí)現(xiàn)了上述步驟,具體來說,codesandbox內(nèi)置了2個(gè)在線服務(wù):
本文我們來聊聊如何實(shí)現(xiàn)并部署自己的npm解析服務(wù)。
下面是一個(gè)常見的codesandbox界面,包含兩部分:
其中「效果預(yù)覽區(qū)域」是一個(gè)iframe,對(duì)于上圖中的例子,iframe的地址是https://pjdp86.csb.app/。如果你打開這個(gè)地址,會(huì)發(fā)現(xiàn)他就是代碼的預(yù)覽效果:
但這并不意味著codesandbox幫我們部署了項(xiàng)目。實(shí)際上,這個(gè)地址中前端代碼是在頁面打開后再編譯、打包的。
打開codesandbox項(xiàng)目時(shí)經(jīng)常看到的下述界面,就是前端編譯代碼的畫面:
具體來說,當(dāng)我們打開一個(gè)codesandbox項(xiàng)目,iframe對(duì)應(yīng)地址初始化時(shí),會(huì)執(zhí)行如下操作:
正是有了在線打包、編譯的流程,codesandbox才能在線運(yùn)行:
回到本文的主題 —— 「npm解析服務(wù)」。當(dāng)我們從項(xiàng)目package.json中獲取到依賴庫的名稱后,完全可以從CDN直接請(qǐng)求依賴庫對(duì)應(yīng)的代碼,為什么還需要一個(gè)獨(dú)立的「npm解析服務(wù)」呢?
之所以需要獨(dú)立的「npm解析服務(wù)」,主要是因?yàn)?—— npm包本身可能還依賴別的npm包,如果每次初始化iframe時(shí)依次下載:
那會(huì)極大拖慢項(xiàng)目初始化的時(shí)間。同時(shí),這樣做也可能會(huì)下載大量實(shí)際不會(huì)使用的代碼。
所以,需要一個(gè)「npm解析服務(wù)」,當(dāng)?shù)谝粋€(gè)用戶第一次請(qǐng)求某個(gè)庫時(shí),依次完成:
那么,后續(xù)所有用戶在請(qǐng)求這個(gè)庫時(shí),都能直接從對(duì)象存儲(chǔ)中直接獲取解析好的JSON文件,這能極大提高在線安裝依賴的速度。
比如,react@18.2.0經(jīng)由「npm解析服務(wù)」解析后會(huì)返回如下JSON:
{ "contents": { "/node_modules/react/index.js": { // 庫的代碼 "content": "...省略", "isModule": false, // 依賴的其他模塊 "requires": [ "./cjs/react.production.min.js", "./cjs/react.development.js" ] }, "/node_modules/react/cjs/react.production.min.js": {/*省略*/}, "/node_modules/react/cjs/react.development.js": {/*省略*/}, "/node_modules/js-tokens/package.json": {/*省略*/}, "/node_modules/loose-envify/package.json": {/*省略*/}, "/node_modules/react/package.json": {/*省略*/} }, // 庫的版本信息 "dependency": { "name": "react", "version": "18.2.0" }, "peerDependencies": {}, // 依賴的依賴 "dependencyDependencies": { "loose-envify": {/*省略*/}, "js-tokens": {/*省略*/} }, "dependencyAliases": {}}
上述JSON中,入口代碼在/node_modules/react/index.js,通過遞歸分析他的AST,發(fā)現(xiàn)他依賴了:
于是,這2個(gè)文件對(duì)應(yīng)代碼也包含在JSON中。
當(dāng)下一個(gè)用戶加載的項(xiàng)目依賴react@18.2.0,就能直接從對(duì)象存儲(chǔ)中獲取上述JSON。
codesandbox在線打包相關(guān)的代碼都是開源的,比如:
所以,我們可以基于dependency-packager部署自己的「npm解析服務(wù)」。
dependency-packager是一個(gè)serverless服務(wù),通過AWS Lambda部署。由于采用的是開源的serverless框架,所以我們可以很方便的將項(xiàng)目中AWS Lambda的部分替換成其他serverless服務(wù)商(比如阿里云函數(shù)計(jì)算)。
整個(gè)dependency-packager包含兩個(gè)serverless函數(shù):
他們的關(guān)系如下:
其中,生成的JSON保存在AWS S3中。同樣,這里也可以替換成其他云服務(wù)廠家的存儲(chǔ)方案。
packager服務(wù)的工作流程如下:
其中,「驗(yàn)證依賴的入口文件」會(huì)嘗試下面這些文件后綴:
const found = [ path.join(basedir, pkg.module), path.join(basedir, pkg.module + ".js"), path.join(basedir, pkg.module + ".cjs"), path.join(basedir, pkg.module + ".mjs"), path.join(basedir, pkg.module, "index.js"), path.join(basedir, pkg.module, "index.mjs"),].find((p) => { try { const l = fs.statSync(p); return l.isFile(); } catch (e) { return false; }});
驗(yàn)證完成后,會(huì)以package.json中的module或main字段作為入口文件,將代碼轉(zhuǎn)換為AST,分析AST中的require語句(cjs語法中引入模塊的語法),找到依賴的模塊。最終將這些模塊匯總在JSON中。
codesandbox在線打包相關(guān)的代碼都是開源的,包括:
其中,npm解析服務(wù)作為一個(gè)serverless服務(wù)包括兩部分:
packager服務(wù)代碼量不多,如果想嘗試部署自己的serverless服務(wù),是個(gè)不錯(cuò)的選擇。
[1]sandpack-react:https://github.com/codesandbox/sandpack/tree/main/sandpack-react。
[2]dependency-packager:https://github.com/codesandbox/dependency-packager。
[3]codesandbox-client:https://github.com/codesandbox/codesandbox-client。
本文鏈接:http://www.tebozhan.com/showinfo-26-12437-0.html如何實(shí)現(xiàn)并部署自己的Npm解析服務(wù)
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com