荆州市网站建设_网站建设公司_自助建站_seo优化
2026/1/16 21:55:11 网站建设 项目流程

node 环境,项目形式是 monorepo。

工程可以认为是某种开放的引擎(有一个 packages 文件夹装所有的库,以及一个用户的目录)

我的 cli 库需要动态执行用户的一些文件(.ts)。

压根没料到这么麻烦

这个事情看起来很简单,如果 cli 也在用户目录下,我们直接运行 tsx 之类的工具就行。

不过现在的情况是,因为仓库是 monorepo,这里 cli 库是一个子库,于是流程是

  • 用 vite 把 cli 提前打包成 bin
  • 在用户目录里安装到 devDependencies

这样就遇到了两个很神秘的问题。

--import tsx

用 node 执行 cli.js (里面包含 import("xxx.ts") 语句) 会报错,因为原生肯定不支持 ts。
一个解决方案是 node --import tsx cli.js,这样肯定能工作,然而

简单研究了一下,vite 打包成 bin 以后没办法加参数 --import tsx,除非手工改产物(也可能是我不知道怎么做)

解决方案就比较邪恶,我们把入口文件换成一个 bin.js(而不是 cli.js)
我们 spawn 一个子进程,把参数加上去以后,运行 dist/cli.js

#!/usr/bin/env nodeimport { spawn } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import path from 'node:path';const __dirname = path.dirname(fileURLToPath(import.meta.url));const CLI_DIST = path.join(__dirname, 'dist', 'cli.js');const args = ['--no-warnings', '--import', 'tsx', CLI_DIST, ...process.argv.slice(2)];const child = spawn(process.execPath, args, {stdio: 'inherit',shell: false,
});child.on('exit', (code) => process.exit(code ?? 0));

这个代码是个原型,如果你写正式工程,这里还要提前判用户 node 版本(因为低版本没有 --import)

这样的好处是 cli 打包结果很纯洁,非常小,不含 tsx 等解释器的东西(peer 装到用户那边)。
同时 cli 实际拿到的 process.argv 依然是不含 --import tsx 的,保留了原样。

执行环境不同

这里遇到了第二个问题,执行环境不同

// cli 的代码
import { some } from '@repo/lib'
await import('user.ts');
console.log(some)// user.ts 的代码
import { some } from '@repo/lib'
console.log(some)

这两个 some 不是同一个,估计是因为 user.ts 是被动态导入的。

解决方法是我们让 cli 拿到用户侧导入的库的储存地址,然后 import 进来就行

import { createRequire } from 'module';
import { pathToFileURL } from 'url';const require = createRequire(import.meta.url);
const libPath = require.resolve('@repo/lib'); // 拿到用户的那个 lib 的 pathconst { some } = (await import(pathToFileURL(path).href)).default as typeof import('@repo/lib');

这样是 some 就是同一个了,有点神秘啊这个做法。。。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询