背景是这样的,如下图,右边是 vscode 插件打开的一个 webview 界面,已经实现了在页面选择了一个方法,填入参数后,可以加载左边的 materials/blocks/表单/script/index.js
代码并执行里面对应的方法,返回执行结果。
materials/blocks/表单/script/index.js
内容如下:
module.exports = {
beforeCompile: context => {
context.outputChannel.appendLine('compile 表单 start')
},
afterCompile: context => {
context.outputChannel.appendLine('compile 表单 end')
},
IntFromOcrText: context => {
context.outputChannel.appendLine(Object.keys(context))
context.outputChannel.appendLine(JSON.stringify(context.model))
context.outputChannel.appendLine(context.params)
return { ...context.model, name: '测试一下' }
}
}
ts 写多了,写 js 真的效率低下。就想着能不能把方法里的逻辑单独放到 ts 文件里,这样还能给 context 写上类型声明。
直接问 ChatGPT 怎么在 js 文件直接调用 ts,它告诉我要先用 tsc 编译。
明显不是我想要的答案。
还好我知识储备丰富?,想到了这个库 TypeStrong/ts-node: TypeScript execution and REPL for node.js (github.com)。认真看了一遍文档,发现都是命令行的用法,我之前也只是在命令行里面用过。拿着 require
关键字去搜(在 js 里调用肯定是用 require),终于发现有用的信息。
跟着链接跳过去
再跳
就这,怎么用嘛,换个姿势问 ChatGPT
被它坑过一次,给我一个完全不存在的调用方法,不太相信它,让它给我相关的文章
只能去翻翻 issues,还真找到了
把 realappie/tsnode-example: This is repository is an example of how to use ts-node programmatically (github.com) 弄到本地成功运行,看起来之前 ChatGPT 没骗我。
其实到这里问题已经解决了,但是我手贱,改了默认参数,想看看生成结果,index.js
代码如下
require('ts-node').register({
transpileOnly: false,
emit: true,
compilerHost: true
})
const path = require('path')
const handle = require('./handle.ts')
console.log(handle.getTitle('lowcode'))
module.exports = {
beforeCompile: context => {
context.outputChannel.appendLine('compile 表单 start')
},
afterCompile: context => {
context.outputChannel.appendLine('compile 表单 end')
},
IntFromOcrText: context => {
context.outputChannel.appendLine(Object.keys(context))
context.outputChannel.appendLine(JSON.stringify(context.model))
context.outputChannel.appendLine(context.params)
context.outputChannel.appendLine(handle.getTitle('lowcode'))
return { ...context.model, name: '测试一下' }
}
}
先用 node.js 直接运行
还生成了编译后文件,没问题,插件里调用看看
Error: EPERM: operation not permitted, mkdir ‘H:/Microsoft VS Code/.ts-node’,mac 上也是这个错。那就是 ts-node 的锅了,又去翻 issues,搜到了有个参数cwd
貌似有用
调整下参数
require('ts-node').register({
transpileOnly: false,
emit: true,
compilerHost: true,
cwd: __dirname
})
还是一样的报错,然后全部恢复默认参数,依旧报错。
经过漫长的网上冲浪找答案,最终关了 vscode 重新打开居然就好了。
然后又发现改了 ts 文件,执行的并不是最新的代码,要重新打开 vscode 才行
这个问题我熟啊,插件里动态加载 index.js 文件的时候就遇到过,是 node.js 缓存的机制,加一行代码就解决了
delete require.cache[require.resolve(path.join(__dirname, 'handle.ts'))]
最终代码
require('ts-node').register({
transpileOnly: false,
emit: false,
compilerHost: false, // 和 emit 一起设置为 true,会在 .ts-node 文件夹输出编译后的代码
cwd: __dirname // 要输出编译后代码必须配置,否则会报错 EROFS: read-only file system, mkdir '/.ts-node'。不输出也要配置不然会出现各种奇奇怪怪的报错
})
const path = require('path')
// 清除缓存,保证每次修改代码后实时生效
delete require.cache[require.resolve(path.join(__dirname, 'handle.ts'))]
const title = require('./handle.ts')
module.exports = {
beforeCompile: context => {
context.outputChannel.appendLine('compile 表单 start')
},
afterCompile: context => {
context.outputChannel.appendLine('compile 表单 end')
},
IntFromOcrText: context => {
context.outputChannel.appendLine(Object.keys(context))
context.outputChannel.appendLine(JSON.stringify(context.model))
context.outputChannel.appendLine(context.params)
context.outputChannel.appendLine(title.getTitle('lowcode'))
return { ...context.model, name: '测试一下' }
}
}
如果你看到了这里,你可以直接问 ChatGPT
- 使用 ts-node 在 js 文件中直接调用 ts
- 使用 babel 在 js 文件中直接调用 ts
- 使用 swc 在 js 文件中直接调用 ts
- 使用 esbuild 在 js 文件中直接调用 ts