- 项目结构**
我有一个monorepo(使用npm workspaces),它包含一个目录api
(一个用类型脚本编写的express API)。api
使用一个本地包@myapp/server-lib
(类型脚本代码)。
目录结构为:
.
├── api/
└── libs/
└── server-lib/
- 问题**
当我使用tsc
构建api
时,构建输出包含@myapp/server-lib
(server-lib
包)的require
语句。然而,当部署API时,服务器不能解析@myapp/server-lib
(因为它不打算从npm注册表安装)。
如何让tsc
编译@myapp/server-lib
,删除构建代码中@myapp/server-lib
的require
语句,并将其替换为对导入代码的引用?
我希望实现的行为是next-transpile-modules
为Next.js所做的。
我尝试使用typescript项目引用,但没有编译导入的@myapp/server-lib
。我还阅读了为什么我在NextJS前端没有遇到这个问题(也位于同一个monorepo中,依赖于不同但非常相似的本地包),这就是我如何登陆next-transpile-modules
的原因。
希望得到任何关于如何使用本地包构建 typescript 项目的帮助或提示。谢谢!!
更新(2022年12月28日)
我通过使用esbuild
将api
构建到一个out.js
文件中来解决这个问题。
整个构建过程现在如下所示:
npx tsc --noEmit # checks types but does not output files
node build.js # uses esbuild to build the project
其中build.js
脚本为:
const nativeNodeModulesPlugin = {
name: 'native-node-modules',
setup(build) {
// If a ".node" file is imported within a module in the "file" namespace, resolve
// it to an absolute path and put it into the "node-file" virtual namespace.
build.onResolve({ filter: /\.node$/, namespace: 'file' }, args => ({
path: require.resolve(args.path, { paths: [args.resolveDir] }),
namespace: 'node-file',
}))
// Files in the "node-file" virtual namespace call "require()" on the
// path from esbuild of the ".node" file in the output directory.
build.onLoad({ filter: /.*/, namespace: 'node-file' }, args => ({
contents: `
import path from ${JSON.stringify(args.path)}
try { module.exports = require(path) }
catch {}
`,
}))
// If a ".node" file is imported within a module in the "node-file" namespace, put
// it in the "file" namespace where esbuild's default loading behavior will handle
// it. It is already an absolute path since we resolved it to one above.
build.onResolve({ filter: /\.node$/, namespace: 'node-file' }, args => ({
path: args.path,
namespace: 'file',
}))
// Tell esbuild's default loading behavior to use the "file" loader for
// these ".node" files.
let opts = build.initialOptions
opts.loader = opts.loader || {}
opts.loader['.node'] = 'file'
},
}
require("esbuild").build({
entryPoints: ["./src/server.ts"], // the entrypoint of the server
platform: "node",
target: "node16.0",
outfile: "./build/out.js", // the single file it will bundle everything into
bundle: true,
loader: {".ts": "ts"},
plugins: [nativeNodeModulesPlugin], // addresses native node modules (like fs)
})
.then((res) => console.log(`⚡ Bundled!`))
.catch(() => process.exit(1));
1条答案
按热度按时间sbtkgmzw1#
已解决(2022年12月28日)
我通过使用
esbuild
将api
构建到单个out.js
文件中来解决这个问题。整个构建过程现在如下所示:
其中
build.js
脚本为:在我的服务器上,
package.json
中的start
脚本只是node out.js
,没有**dependencies
或devDependencies
,因为所有脚本都捆绑到out.js
中。