imgcook이 자동으로 종속성을 생성하도록 돕기 위해 Node.js를 사용하는 방법은 무엇입니까? 다음 글에서는 생성 방법에 대해 소개하겠습니다. 참고할 만한 가치가 있으니 여러분에게 도움이 되길 바랍니다!
imgcook의 Taobao 내부 버전은 imgcook 편집기에서 기능을 작성할 때 axios, 밑줄, @rax/video 등과 같은 다른 종속성 패키지를 도입하는 데 사용되는 종속성 관리와 유사한 기능을 제공합니다.
그러나 사용자 경험 측면에서는 편집기가 모든 사람이 package.json에서 종속성을 선언하는 습관을 형성하는 것을 허용하지 않기 때문에 여전히 상대적으로 번거롭고 편집기가 GUI 인터페이스이기 때문에 코드를 열면 됩니다. 즉, imgcook 모듈을 개발한 후 매번 다른 패키지에 의존하는 경우(대부분의 경우 필수) 함수를 하나씩 열고 확인해야 한다는 의미입니다. 버전 번호를 확인하고 종속성 관리에서 종속성 관리를 수행합니다. 이는 사용할 때 종종 고통스러운 프로세스입니다.
imgcook은 스키마 소스 코드 개발 모드를 제공합니다. 편집기에서 모듈 프로토콜(Schema)을 직접 수정하여 GUI 작업 단계를 대체할 수 있습니다. 그러다가 종속성을 검색해 보니 종속성 관리가 가능하다는 것을 알았습니다. 기능은 프로토콜을 통해 구현됩니다. 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#12 和 imgcook/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 = ''; process.stdin.on('data', (buf) => { originJson += buf.toString('utf8'); }); process.stdin.on('end', () => { 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 = ''; process.stdin.on('data', (buf) => { originJson += buf.toString('utf8'); }); process.stdin.on('end', () => { 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('@swc/core'); 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('@swc/core/visitor'); /** * 用于保存通过函数解析, 获得的依赖对象列表 */ const liveDependencies = []; /** * 定义访问器 */ class ImportsExtractor extends Visitor { visitImportDeclaration(node) { let alias = 'Default'; liveDependencies.push({ alias, packageRax1: node.source.value, versionRax1: '', packageRaxEagle: node.source.value, versionRaxEagle: '', checkDepence: true, }); return node; } } // 使用方式 const importsExtractor = new ImportsExtractor(); importsExtractor.visitModule(ast);
类 ImportsExtractor
继承自 @swc/core/visitor 的 Visitor
,由于是要遍历 import 声明语句,它的语法类型名称是 ImportDeclaration
,因此只需要实现 visitImportDeclaration(node)
const axios = require('axios'); async function fillVersions(dep) { const pkgJson = await axios.get(`https://registry.npmjs.org/${dep.packageRax1}`, { type: 'json' }); if (pkgJson.data['dist-tags']) { const latestVersion = pkgJson.data['dist-tags'].latest; dep.versionRax1 = `^${latestVersion}`; dep.versionRaxEagle = `^${latestVersion}`; } return dep; }
async function transform() { // ... origin.imgcook.dependencies = newDeps; console.log(JSON.stringify(origin)); }
$ imgcook pull <id> -o json | ckdeps > { ..., "dependencies": [{ ...}] }
process.stdin
을 통해 파이프라인(Pipeline)의 업스트림 데이터를 받습니다. imgcook 모듈 프로토콜 콘텐츠를 확인한 후 end< /code> 이벤트에서 출력을 구문 분석하고 아름답게 하려면 다음 명령을 실행하세요. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">#!/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)}`);
}</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜 아름다운 출력 결과를 보려면 이것은 Unix Pipeline 프로그램의 간단한 예입니다. 🎜🎜 다음으로 이런 식으로 종속성 자동 생성을 완료하는 방법을 살펴보겠습니다. 위의 예와 유사하게 ckdeps라는 또 다른 파일을 만듭니다. 🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">$ imgcook pull <id> -o json | ckdeps | imgcook-save
> export default { ... }</pre><div class="contentsignin">로그인 후 복사</div></div><div class="contentsignin">로그인 후 복사</div></div>🎜 <code>origin.imgcook.functions
를 통해 다음과 같은 함수의 코드 내용을 얻을 수 있습니다. 🎜$ imgcook pull <id> -o json | ckdeps -f | imgcook-save
content
를 구문 분석하고 코드에서 import 문을 얻은 다음 해당 종속성 개체를 origin.imgcook.dependent
에 생성하려면 @swc/core를 참조해야 합니다. JavaScript 코드 구문 분석: 🎜 $ imgcook pull <id> -o json | ckdeps | imgcook-save | pbcopy
ImportsExtractor
는 @swc/core/visitor의 Visitor
에서 상속됩니다. 가져오기 선언문을 순회해야 하기 때문에 해당 구문 유형 이름은 ImportDeclaration
이므로 다음 사항만 필요합니다. visitImportDeclaration(node)
메소드를 구현하면 메소드의 모든 import 문을 가져온 다음 해당 노드의 구조에 따라 종속 객체로 변환하고 업데이트할 수 있습니다. 추출기를 정의한 후 남은 유일한 것은 ast를 추출기에 공급하여 후속 종속성 생성을 위해 모듈의 모든 종속성을 수집할 수 있도록 하는 것입니다. 🎜🎜위 코드에서 볼 수 있듯이 현재 버전 번호는 빈 문자열을 사용하므로 프로토콜 내용을 업데이트하면 종속 버전 정보가 손실되므로 버전을 얻는 방법을 정의해야 합니다. 🎜🎜프런트 엔드 종속성은 모두 NPM 레지스트리에 저장되므로 다음과 같은 HTTP 인터페이스를 통해 버전을 얻을 수 있습니다. 🎜const axios = require('axios'); async function fillVersions(dep) { const pkgJson = await axios.get(`https://registry.npmjs.org/${dep.packageRax1}`, { type: 'json' }); if (pkgJson.data['dist-tags']) { const latestVersion = pkgJson.data['dist-tags'].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 = ''; process.stdin.on('data', (buf) => { originJson += buf.toString('utf8'); }); process.stdin.on('end', () => { 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 { ... }
这样,我们就可以直接拷贝内容到编辑器。
比如,我在喔其中一个项目的 created 函数中增加了 axios 的依赖,关闭窗口后点击保存(确保 Schema 保存),然后通过命令:
$ imgcook pull <id> -o json | ckdeps -f | imgcook-save
然后在编辑器中打开 Schema 编辑,复制生成的内容并保存,然后打开“依赖管理”可以看到:
通过解析生成的代码已经更新到依赖面板了,这下终于可以解放双手,去做其他的事情了。
是不是这样就结束了呢?在 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!