Node.js+TypeScript项目报错Cannot find module './package.json'求正确方案
先对应你的环境情况整理如下:
- Node.js版本:
v10.1.0ubuntu@ip-10-0-0-196:~/code/makeIt/chrome-render$ node -v v10.1.0 - TypeScript版本:
2.8.3ubuntu@ip-10-0-0-196:~/code/makeIt/chrome-render$ tsc -v Version 2.8.3 - 项目目录结构:
ubuntu@ip-10-0-0-196:~/code/makeIt/chrome-render$ find . ./tsconfig.json ./node_modules # 省略node_modules内大量文件 ./yarn.lock ./src ./src/makeIt.ts ./src/server.ts ./dist ./dist/src ./dist/src/server.js ./dist/src/makeIt.js ./dist/src/server.js.map ./package.json ./dist/src/makeIt.js.map
遇到的问题
用tsc编译代码完全无报错,但运行编译后的dist/src/server.js时出现模块找不到错误:
ubuntu@ip-10-0-0-196:~/code/makeIt/chrome-render$ node dist/src/server.js internal/modules/cjs/loader.js:573 throw err; ^ Error: Cannot find module './package.json' at Function.Module._resolveFilename (internal/modules/cjs/loader.js:571:15) at Function.Module._load (internal/modules/cjs/loader.js:497:25) at Module.require (internal/modules/cjs/loader.js:626:17) at require (internal/modules/cjs/helpers.js:20:18) at Object.<anonymous> (/home/ubuntu/code/makeIt/chrome-render/dist/src/server.js:39:20) at Module._compile (internal/modules/cjs/loader.js:678:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10) at Module.load (internal/modules/cjs/loader.js:589:32) at tryModuleLoad (internal/modules/cjs/loader.js:528:12) at Function.Module._load (internal/modules/cjs/loader.js:520:3)
将package.json移至dist/src/目录后可正常运行,但显然这不是合理方案,希望package.json保留在项目根目录。
问题根源
问题出在你的代码中(大概率是src/server.ts)使用了相对路径./package.json引入文件。编译后server.js位于dist/src/目录下,此时./package.json指向的是dist/src/package.json,但实际package.json在项目根目录,因此会出现找不到模块的错误。
可行的解决方案
方案1:使用绝对路径拼接引入
在TypeScript代码中,借助path模块和__dirname来定位根目录的package.json:
首先导入path模块:
import * as path from 'path';
然后替换原来的require('./package.json')为:
const pkg = require(path.resolve(__dirname, '../../package.json'));
这里../../是从dist/src/回退到项目根目录的层级,你可以根据自己的实际目录结构调整层级数。
方案2:配置TypeScript路径别名(推荐)
修改项目根目录的tsconfig.json,添加baseUrl和paths配置,让TypeScript能直接解析根目录的文件:
{ "compilerOptions": { "baseUrl": ".", "paths": { "@root/*": ["*"] }, // 保留你原有的其他配置,比如outDir "outDir": "./dist" } }
之后在代码中这样引入package.json:
const pkg = require('@root/package.json');
由于Node.js运行时本身不识别这个别名,需要安装tsconfig-paths来处理:
npm install tsconfig-paths --save-dev
运行代码时使用:
node -r tsconfig-paths/register dist/src/server.js
如果平时用ts-node直接运行TypeScript代码,可使用:
ts-node -r tsconfig-paths/register src/server.ts
方案3:调整编译输出结构
修改tsconfig.json的outDir和rootDir配置,让编译后的文件直接输出到dist根目录,而非dist/src:
{ "compilerOptions": { "outDir": "./dist", "rootDir": "./src" // 其他原有配置... } }
编译后server.js会位于dist/server.js,此时代码里用../package.json即可指向根目录的文件:
const pkg = require('../package.json');
这种方式需要将运行命令改为node dist/server.js,同时确保rootDir设置正确,避免编译时将非src目录的文件也输出到dist中。
总结
个人最推荐方案2,路径别名既让代码更易读,又无需手动计算相对路径层级;如果不想添加额外依赖,方案1或方案3也能有效解决问题。
内容的提问来源于stack exchange,提问作者Duke Dougal

