blog
blog copied to clipboard
你所不知道的模块调试技巧 - npm link
1. 背景
node 应用开发中,我们不可避免的需要使用或拆分为 npm 模块,经常遇到的一个问题是:
新开发或修改的 npm 模块,如何在项目中试验?
新同学一般会有以下几种方式:
为了方便示范,我们假设项目是 my-project, 需要用到一个独立的 my-utils 模块
1.1 发布一个 beta 版本
- 优点:你高兴就好。
- 缺点: 无趣+无趣+无趣,麻烦+麻烦+麻烦。
1.2 直接用相对路径安装
$ cd path/to/my-project
$ npm install path/to/my-utils
- 优点:简单明了
- 缺点: 调试过程中往往需要微调,此时需要切换到 my-utils 目录修改,然后反复重新 install,很麻烦
1.3 使用软链
$ cd path/to/my-project/node_modules
$ ln -s path/to/my-utils my-utils
- 优点:软链后,两边修改直接同步
- 缺点: 指令操作麻烦,不同操作系统语法不一样
2. 正解 - npm link
但其实 npm 本身已经对此类情况提供了专门的 npm link 指令。
相关文档: https://docs.npmjs.com/cli/link
下面我们简单介绍下用法:
$ cd path/to/my-project
$ npm link path/to/my-utils
简单的替换一个单词,就搞定了,cool~
如果这两种的目录不在一起,那还有一种方法:
$ # 先去到模块目录,把它 link 到全局
$ cd path/to/my-utils
$ npm link
$
$ # 再去项目目录通过包名来 link
$ cd path/to/my-project
$ npm link my-utils
该指令还可以用来调试 node cli 模块,譬如需要本地调试我们的 egg-init,可以这样:
$ cd path/to/egg-init
$ npm link
$ # 此时全局的 egg-init 指令就已经指向你的本地开发目录了
$ egg-init # 即可
想去掉 link 也很简单:
$ npm unlink my-utils
3. 写在最后
- 该方法只是为了最后一步调试,模块本身的正确性,应该更多的通过单元测试来保证。
- 单元测试相关内容,可以参见:单元测试
👍,当年修改 node_modules 后发布了一次导致 node_modules 里面的代码直接没了给我留下了 深刻 的记忆 😂
问题是一个项目里面被 flatten 出来几千个目录,你就算开个软连,编辑器里面展开 node_modules 目录也会被卡死。
@XadillaX 这个跟 link 关系不大,是 npm@2,npm@3,cnpm 的包安装方式区别导致的吧。
这是编辑器的问题,很容易解决的,vscode 和 webstorm 配置几个 ignore 就 ok 了。(局部 ignore,不用全部屏蔽整个 node_modules)
@atian25 为什么大家都喜欢把 NPM 自身机制问题总要归结到编辑器问题上去呢 -。 -
因为 NPM 我们改变不了,只好改编辑器了 (摊手)
发自我的 iPhone
在 2017年2月28日,18:44,Flandre Scarlet [email protected] 写道:
@atian25 为什么大家都喜欢把 NPM 自身机制问题总要归结到编辑器问题上去呢 -。 -
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.
呀, 感觉如果是用yarn install的话用yarn link会好一点的呢。具体原因不太清楚, 在yarn下载然后用npm(npm5) link感觉npm会去处理环境生成一个lock文件, 处理起来有点慢的呢, 用yarn就一秒左右就搞定了。不过确实link的方式在开发的时候确实是不错的思路。感谢分享。
那,如果我的js插件直接放到项目目录下呢
@lightWey 然后你的问题是?
🤔 我居然每次都 npm install path/to/my-project --save 一次,没有想到用 link...
有一个模块,开始是直接通过npm install gitlab地址,运行项目没错,但是在本地,我通过npm link之后,运行就出错了,
@sunlandong 这种反馈对交流是没有任何帮助的,出什么错?错误信息是啥?复现步骤是啥?挤牙膏似的交流是最没效率的。
你好,我目前也是需要把一些基础的vue组件分离出去单独做一个npm的包,试了npm link这个办法,理论上是没有问题的,可以达到想要的目的。但是我遇到的问题可能和vuejs/babel更相关一些,由于vue组件在分离前,有webpack配置好了babel去解析,但是在分离出去之后,似乎要给新的npm模块单独做一个构建的流程?我现在只是单纯的把一些vue文件抽离了,放到另一个git仓库了,然后用一个入口文件import/export 所有的组件,然后问题是启动webpack server的时候会无限卡在等待打包的过程。我感觉就是缺了对分离出去的npm模块的解析过程。
请问有没有类似vue/react组件本地开发流程的经验分享?谢谢啦
应该没区别的,npm link 只是对目录做了一个软链而已,文件系统层面的,工具层面的应该是无感知的,除非工具那边不支持跟随软链(应该不会)。
npm link 只是在需要本地测试的时候用到的。
是否每次install的时候都需要设置下软链,软链会不会被记录在lock.json文件中,如果能记录是不是说明能够解决特定的npm package放到自己的项目中维护
link 只是用于调试用的。
好吧,我本来以为能解决自己维护 package 的问题
既然提到了ln,那还是直接ln -s吧?跟ln有什么区别?
@qwIvan
npm link后,该项目会被 link 到全局去,你就能测试命令行了- 在上面那句后,可以直接
npm link pkgName来在应用中 link,不需要 ln 复杂的相对路径。 ln不同操作系统的语法不同
大神你好,我这里遇到一个问题,npm install 之后,在node_modules/.bin/ 里面没有创建软连接,都是硬链。(node V8.4.0 npm V5.3.0)这个情况是在 生成环境打包时候发现的,本地和测试环境都没问题,我还尝试过,把生成打的包下载之后,删除node_modules 和 package-lock.json文件,然后本地npm install,这样生成.bin文件夹里会自动创建软链。所以 请问一下大神,有没有碰到过这样的情况,npm 在什么情况下不会自动创建软链的?
没遇过。
@llsldwy 你那个问题很大可能是你打包的问题, tar 或 zip 的时候多了一个参数
你好 ,有个问题,我在npmlink后,不能彼此共享node_modules,执行脚本的时候找不到安装依赖
@sunha1yang 啥叫共享 node_modules?
sorry, 我表述上有点问题,我要测试pkg有一些依赖,如webpack等第三方包,我在另一个文件夹(此文件夹下有node_modules文件,pkgName需要的依赖包都存在)下npm link pkgName后,我的pkg引不到此文件下node_modules文件,然后就会报错,我的问题是如何能让我的pkg能够引到当前文件夹下的node_modules文件?
不知道我有没有表述清楚......
还是没懂,搞个 tree 图呗

这个是我的操作步骤
我指的是这样描述下。。。
.
├── app
├── config
├── node_modules
│ └── aaa -> link to ./app/xx/xx
└── package.json
目录结构是这样的:
.
├── fe
├── awt ->npm link
├── project -> 在项目目录下 npm link awt
│ ├── app
│ ├── node_modules
│ └── package.json
| └── config
└── otherproject
└── home.html
很有用,基本你上面提到的第一种方法,以及后面的都用过 哈哈
问一下,typescript的项目,怎么解决这个问题
没啥区别吧
楼主你好。我现在遇到一个问题
我现在有一个模块lib文件夹(lib中package.json库名称是"@sml/lib")跟project项目文件夹
我切换到lib下执行npm link 然后再切换到project文件夹下执行 npm link @sml/lib
在项目中引入lib后刷新就报错了。
Unable to resolve module @sml/lib from /Users/sml2/Documents/iOSDemos/RNBaseProject/App.js: Module @sml/lib does not exist in the Haste module map
这是为什么呢
@sunha1yang npm link 会遇到依赖找不到的问题,不是好用(没有问题的话还是尽量使用 npm link)
https://medium.com/@vcarl/problems-with-npm-link-and-an-alternative-4dbdd3e66811
依赖找不到的问题,可以用https://nodejs.org/api/cli.html#cli_preserve_symlinks 这个解决的,朋友们
@brizer 请问这个--preserve-symlinks 是node命令,怎么使用?
@brizer 请问这个--preserve-symlinks 是node命令,怎么使用?
举个例子,你用vscode调试的时候,a依赖了b,而b是npm link的,那么在a项目的调试配置中加一句:
"runtimeArgs":[
"--preserve-symlinks"
]
就可以修改b,顺便调试a了。
@brizer 我这是一个webpack构建的web项目,比如a依赖b, a和b都依赖vue这个框架,我通过构建a跑在webpack-dev-server上,用chrome打开调试,这个我该如何操作呢
@brizer 我这是一个webpack构建的web项目,比如a依赖b, a和b都依赖vue这个框架,我通过构建a跑在webpack-dev-server上,用chrome打开调试,这个我该如何操作呢
微信 brizer1992 单独聊,没太明白你问题是什么。
@brizer 我在此处找到了问题的解决,万分感谢提供解答与搜索思路。
@VictorWu90 优秀
在webpack构建的项目中,可以使用resolve-alias字段使用绝对路径强制指定调试时第三框框架的源目录,
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue-router': resolve('node_modules/vue-router'),
vuex: resolve('node_modules/vuex'),
'vue$': resolve('node_modules/vue/dist/vue.esm.js'),
// 'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src')
}
}
请教一下,如果我的一个项目依赖了A组件,A模块又依赖了B组件,那么我如果要在项目中调试B组件,应该怎么快速的link?
cd a/node_modules && npm link c
这里有另一种方式,我们在项目里经常用到,就是直接通过 npm 的 package.json 中的依赖版本来指定。比如我当前开发的项目依赖一个组件库 element-react-dataview,那么我会将此组件库的代码 clone 到 lib/element-react-dataview,然后将 package.json 中的引用改成:
{
"dependencies": {
"element-react-dataview": "file:lib/element-react-dataview"
}
}
项目目录下运行 npm i 之后再删除掉 lib/element-react-dataview/package.json(因为 npm 发布版引用的是编译后的 dist 文件,没有此情况的可以不用删除),启动项目的 webpack-dev-server 之后引用的就是对应库的源码了,可以随时修改并进行调试。
这其实也是另一种形式的 npm link。
lerna
学到了,thx
对npm install指令和npm link指令更加理解了。
1.通过npm link给公共组件建立软链接
2.在项目中通过npm link 包名引入后,Module not found: Error: Can't resolve 'vue-loader/node_modules/vue-hot-reload-api出现这个报错是什么情况,有朋友解答下么,这个依赖在vuecli创建的时候就已经有了啊
可能是 vuecli 对软链的处理不好。
可能是 vuecli 对软链的处理不好。
找到问题了,需要把webpack配置中的 symlinks设为false,否则就会报错,为了解决这个问题头都秃了。。。
可能是 vuecli 对软链的处理不好。
找到问题了,需要把webpack配置中的
symlinks设为false,否则就会报错,为了解决这个问题头都秃了。。。
是的,很好
wml这个才是最屌的,因为React Native 不支持 npm link,https://www.bram.us/2018/03/10/working-with-symlinked-packages-in-react-native/
Metro 不支持跟随软链: https://github.com/facebook/metro/issues/1
npm link贼好用
可能是 vuecli 对软链的处理不好。
找到问题了,需要把webpack配置中的
symlinks设为false,否则就会报错,为了解决这个问题头都秃了。。。
💥就是这个害我浪费了半天时间
我发现 1.2 相对路径安装 修改代码后不需要重新 install 呀
在引用的项目中使用安装插件导致被引用的插件废掉,被引用的模块需要清理掉node_modules重新安装才能成功启动