如何在符号链接目录执行脚本并解决模块查找失败问题?
我之前处理过类似的Git目录拆分+Node模块路径问题,核心是Node.js的模块解析只认物理文件路径,不认软链接的逻辑路径——原来app-mock在mock-utils内部时,../../common/utils.js的物理路径确实指向mock-utils/common;但现在app-mock移到外部,软链只是mock-utils里的“快捷方式”,test.js的实际物理位置不在mock-utils目录下,所以../../common会走到app-mock的父目录,自然找不到模块。
给你三个可行的方案,都能保住你想要的目录结构:
方案1:修改test.js的导入路径(最简单直接)
重新计算从test.js物理路径到mock-utils/common的相对路径。假设你的实际目录结构是:
/workspace/ ├─ mock-utils/ │ ├─ app-mock -> /workspace/app-mock (软链) │ ├─ common/ │ │ └─ utils.js │ └─ package.json └─ app-mock/ └─ tests/ └─ test.js
那从app-mock/tests/test.js到mock-utils/common/utils.js的相对路径是../../mock-utils/common/utils.js,把test.js里的导入改成:
var shield = require('../../mock-utils/common/utils.js')
这样不管从哪里执行,只要物理路径不变,就能正确加载模块。
方案2:利用NODE_PATH环境变量(无需修改代码)
如果你不想改代码,可以把mock-utils的根目录加到Node的模块搜索路径里。
临时执行方式:
# Linux/Mac NODE_PATH=/workspace/mock-utils node app-mock/tests/test.js # Windows PowerShell $env:NODE_PATH = "C:\workspace\mock-utils"; node app-mock/tests/test.js
此时你甚至可以把test.js里的导入简化成:
var shield = require('common/utils.js')
持久化方式(推荐):
在mock-utils的package.json里添加一个scripts命令:
{ "scripts": { "test": "NODE_PATH=. node app-mock/tests/test.js" } }
之后直接在mock-utils目录下运行npm test即可,.代表当前目录(mock-utils根目录),无需每次手动设置环境变量。
方案3:创建跨目录软链(完全保留原导入路径)
如果你想100%保留原来的../../common/utils.js导入路径,可以在app-mock的父目录下创建一个指向mock-utils/common的软链:
# 进入app-mock的父目录 cd /workspace/ # 创建软链 ln -s mock-utils/common common
此时你的目录结构会变成:
/workspace/ ├─ mock-utils/ │ ├─ app-mock -> /workspace/app-mock │ ├─ common/ │ │ └─ utils.js │ └─ package.json ├─ app-mock/ │ └─ tests/ │ └─ test.js └─ common -> mock-utils/common (软链)
这样test.js里的../../common/utils.js就会指向这个新软链,从而正确加载模块。注意要把这个新软链加入.gitignore,避免Git提交(因为common属于mock-utils的内容)。
内容的提问来源于stack exchange,提问作者Carlos Miguel Colanta

