首頁  >  文章  >  web前端  >  淺析Node.js + imgcook怎麼自動產生依賴

淺析Node.js + imgcook怎麼自動產生依賴

青灯夜游
青灯夜游轉載
2021-12-01 19:33:442492瀏覽

怎麼用 Node.js 輔助 imgcook 自動產生依賴?以下這篇文章就來跟大家介紹一下生成方法,有一定的參考價值,希望對大家有幫助!

淺析Node.js + imgcook怎麼自動產生依賴

imgcook 在淘寶內部版本提供了類似依賴管理的功能,用於在imgcook 編輯器編寫函數時引入其他依賴包,例如axios、underscore、@rax/ video 等。

淺析Node.js + imgcook怎麼自動產生依賴

不過從使用體驗上,還是較為繁瑣,因為編輯器並沒有讓大家形成像在package.json 宣告依賴的習慣,而且因為編輯器是GUI 介面,所以從每個函數打開程式碼,並查看依賴的操作是比較繁瑣的,這就導致每次開發完一個imgcook 模組後,如果依賴了其他包(大部分情況下都需要),就需要一個個打開函數並確認版本號,並在依賴管理中添加,這在我使用的過程中,往往是一次痛苦的過程。

如何解決

imgcook 提供了Schema 原始碼開發模式,透過在編輯器中直接修改模組協定(Schema)就能取代GUI 的操作步驟,然後透過搜尋dependencies,我發現依賴管理功能是透過協定中的imgcook.dependencies 實現的:

{
  "alias": "Axios",   
  "packageRax1": "axios",
  "versionRax1": "^0.24.0",
  "packageRaxEagle": "axios",   
  "versionRaxEagle": "^0.24.0",   
  "checkDepence": true 
}

由於函數的程式碼也存在協定中,那麼是不是只需透過處理原始協議文檔,掃描對應的依賴並保存到節點中,再點擊「儲存」就可以看到依賴管理中的套件列表被更新了。

實作功能

為此我在@imgcook/cli 中實作了拉取模組協定內容的功能,具體Pull Request 有: imgcook/imgcook-cli#12imgcook/imgcook-cli#15,可以透過命令列工具拉取對應模組的協定(Schema)如下:

$ imgcook pull <id> -o json

執行後會把模組協定內容輸出到命令列中的stdout。

有了這個功能後,就可以實作一些命令列工具,基於Unix Pipeline 程序,與imgcook-cli 的資料來源形成協作,舉個例子,透過imgcook pull 輸出的JSON 並不易讀,那麼不妨寫一個imgcook-prettyprint 來美化輸出結果,程式碼實作如下:

#!/usr/bin/env node 
let originJson = &#39;&#39;; 
process.stdin.on(&#39;data&#39;, (buf) => {   
  originJson += buf.toString(&#39;utf8&#39;);   
}); 
process.stdin.on(&#39;end&#39;, () => {   
  const origin = JSON.parse(originJson);   
  console.log(JSON.stringify(origin, null, 2)); 
});

上面的程式透過process.stdin 接收管線(Pipeline)上游的數據,即imgcook 模組協定內容,然後在end 事件中解析並美化輸出,執行以下指令:

$ imgcook pull <id> -o json | imgcook-prettyprint

就能看到美化後的輸出結果了,這就是一個Unix Pipeline 程式的簡單範例。

接下來就來看下如何透過這種方式,完成依賴的自動產生。與上面範例類似,我們再建立一個檔案ckdeps:

#!/usr/bin/env node 
let originJson = &#39;&#39;; 
process.stdin.on(&#39;data&#39;, (buf) => {   
  originJson += buf.toString(&#39;utf8&#39;);   
}); 
process.stdin.on(&#39;end&#39;, () => {   
  transform(); 
}); 

async function transform() {   
  const origin = JSON.parse(originJson);   
  const funcs = origin.imgcook?.functions || [];   
  if (funcs.length === 0) {     
    process.stdout.write(originJson);     
    return;   
  }   
  console.log(JSON.stringify(origin)); 
}

透過origin.imgcook.functions,可以取得到函數的程式碼內容,例如:

{   
  "content": "export default function mounted() {\n\n}",   
  "name": "mounted",   
  "type": "lifeCycles" 
}

那麼接下來就是透過解析content,取得到程式碼中的import 語句,再產生對應的依賴物件到origin.imgcook.dependencies 中,那麼我們需要引用@swc/core 來解析JavaScript 程式碼:

const swc = require(&#39;@swc/core&#39;); 

await Promise.all(funcs.map(async ({ content }) => {   
  const ast = await swc.parse(content);   
	// the module AST(Abstract Syntax Tree) 
}));

取得到ast 後,就能透過程式碼取得import 語句的資訊了,不過由於ast 比較複雜,@swc/core 提供了專用的遍歷機制如下:

const { Visitor } = require(&#39;@swc/core/visitor&#39;); 

/**  
 * 用于保存通过函数解析, 获得的依赖对象列表  
 */ 
const liveDependencies = []; 

/**  * 定义访问器  */ 
class ImportsExtractor extends Visitor {   
  visitImportDeclaration(node) {     
    let alias = &#39;Default&#39;;     
    liveDependencies.push({       
      alias,       
      packageRax1: node.source.value,       
      versionRax1: &#39;&#39;,       
      packageRaxEagle: node.source.value,       
      versionRaxEagle: &#39;&#39;,       
      checkDepence: true,     
    });     
    return node;   
  } 
} 

// 使用方式 
const importsExtractor = new ImportsExtractor(); 
importsExtractor.visitModule(ast);

類別ImportsExtractor 繼承自@swc/core/visitor 的Visitor,由於是要遍歷import 宣告語句,它的語法型別名稱是ImportDeclaration,因此只需要實作visitImportDeclaration(node) 方法,即可在方法內取得所有的import 語句,再依照對應節點的結構轉換成依賴物件並更新就好。定義好抽取器後,剩下的事情就是把 ast 餵給抽取器,這樣就能把模組所有的依賴都收集起來,用於後面依賴的生成。

從上面的程式碼可以看到,版本號目前使用了空字串,這會導致我們如果更新協定內容,依賴的版本資訊會遺失,因此我們需要定義一種取得版本的方法。

由於前端的依賴都是儲存在 NPM Registry 上的,因此我們可以透過 HTTP 介面來取得版本,例如:

const axios = require(&#39;axios&#39;); 
async function fillVersions(dep) {   
  const pkgJson = await axios.get(`https://registry.npmjs.org/${dep.packageRax1}`, { type: &#39;json&#39; });   
  if (pkgJson.data[&#39;dist-tags&#39;]) {     
    const latestVersion = pkgJson.data[&#39;dist-tags&#39;].latest;     
    dep.versionRax1 = `^${latestVersion}`;     
    dep.versionRaxEagle = `^${latestVersion}`;  
  }  
  return dep; 
}

我们按照 https://registry.npmjs.org/${packageName} 的规则,就能拿到存储在 Registry 中的包信息,然后 data['dist-tags'].latest 代表的是 latest 标签对应的版本,简单来说就是当前包的最新版本,然后再基于这个版本号增加一个 ^ 版本前缀即可(你也可以按照自己的诉求修改最终的版本以及 NPM Registry)。

最后一步,就是把我们从函数代码中抓取的依赖信息更新,并输出出来:

async function transform() {   
  // ...   
  origin.imgcook.dependencies = newDeps;   
  console.log(JSON.stringify(origin)); 
}

然后通过运行:

$ imgcook pull <id> -o json | ckdeps 
> { ..., "dependencies": [{ ... }] }

然后,开发者只需要把输出的 JSON 拷贝到编辑器中保存。哦,等等,在编辑器中并不能直接使用 JSON 保存,而是需要使用 ECMAScript Module 的方式(export default { ... }),那这样是不是意味着每次都需要手动编辑一下呢,答案是否,Unix Pipeline 的思路非常利于解决这种流程问题,我们只需要再新建一个节点脚本 imgcook-save 即可:

#!/usr/bin/env node 
let originJson = &#39;&#39;; 
process.stdin.on(&#39;data&#39;, (buf) => {  
  originJson += buf.toString(&#39;utf8&#39;);  
}); 
process.stdin.on(&#39;end&#39;, () => {  
  transform(); 
}); 

async function transform() {   
  const origin = JSON.parse(originJson);  
  console.log(`export default ${JSON.stringify(origin, null, 2)}`);
}

最后完整的命令是:

$ imgcook pull <id> -o json | ckdeps | imgcook-save 
> export default {   ... }

这样,我们就可以直接拷贝内容到编辑器。

效果体验

淺析Node.js + imgcook怎麼自動產生依賴

比如,我在喔其中一个项目的 created 函数中增加了 axios 的依赖,关闭窗口后点击保存(确保 Schema 保存),然后通过命令:

$ imgcook pull <id> -o json | ckdeps -f | imgcook-save

然后在编辑器中打开 Schema 编辑,复制生成的内容并保存,然后打开“依赖管理”可以看到:

淺析Node.js + imgcook怎麼自動產生依賴

通过解析生成的代码已经更新到依赖面板了,这下终于可以解放双手,去做其他的事情了。

One more thing?

是不是这样就结束了呢?在 macOS 中,提供了 pbcopy 命令,可以复制 stdin 到剪贴板,那么跟 imgcook 的例子结合一下:

$ imgcook pull <id> -o json | ckdeps | imgcook-save | pbcopy

这样就省掉了自己拷贝的工作,命令执行完直接打开编辑器 ⌘V 即可。

最后的最后,我要升华一下主题,在 @imgcook/cli 支持了输出 JSON 文本的功能后,就意味着 imgcook 接入了 Unix Pipeline 的生态,通过这种方式,我们可以在这个过程中构建很多有趣实用的工具,并与很多 Unix 工具协作使用(比如 bpcopy、grep、cat、sort 等)。

本文只是通过依赖的自动生成为例,使用 Unix Pipeline 的方式,验证了其可行性以及和 imgcook 编辑器配合使用的体验,目前来说,我可以通过这种方式,弥补不少编辑器上的体验缺失,让我更方便地使用 imgcook 的核心功能。

更多node相关知识,请访问:nodejs 教程!!

以上是淺析Node.js + imgcook怎麼自動產生依賴的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除