如何让链接的npm模块修改自动同步到运行中的Web应用?
这个问题我之前在多模块项目里也碰到过,核心原因是你npm link到module1的是module2的构建后产物,而不是它的源码本身。webpack-dev-server只会监听module1项目内的文件变化,以及node_modules里已链接模块的最终产物变化——但你修改module2源码后,产物不会自动更新,所以必须手动执行npm run build才能同步。
下面给你几个可行的解决思路,按改动从少到多排序:
方案1:给module2添加watch脚本,自动构建产物
这是最直接的方案,不需要改动现有依赖逻辑,只需要让module2在源码变化时自动重新构建,这样npm link的产物文件更新后,webpack-dev-server就能感知到并刷新应用。
- 修改module2的
package.json,新增一个watch脚本(注意去掉版本补丁的步骤,避免每次改代码都升级版本):
{ "scripts": { ... "build": "cross-env WEBPACK_ENV=prod && npm run v:patch && webpack", "watch": "cross-env WEBPACK_ENV=dev webpack --watch" } }
- 启动module2的watch模式:
cd webapp/module2 npm run watch
现在你修改module2的JavaScript源码时,webpack会自动重新构建产物,npm link的文件会同步更新,module1的webpack-dev-server检测到变化后就会自动刷新应用了。
方案2:让module1直接引用module2的源码
如果不想额外启动一个watch进程,可以让module1的webpack直接打包module2的源码,跳过构建产物这一步。
- 修改module1的webpack配置文件,在
resolve.alias里把module2指向它的源码入口文件:
const path = require('path'); module.exports = { // ...其他配置 resolve: { alias: { // 替换成module2实际的源码入口路径 'module2': path.resolve(__dirname, '../module2/src/index.js') } } }
- 重启module1的
npm start,之后修改module2的源码时,webpack-dev-server会直接检测到源码变化,自动重新编译并刷新应用。
这个方案的前提是module1的webpack配置能正确处理module2的源码(比如babel转译、资源加载等),如果module2有特殊的编译需求,可能需要把对应的loader配置同步到module1里。
方案3:配置npm link双向监听(适合复杂模块场景)
如果希望保持npm link的依赖关系,但又想直接监听源码变化,可以调整module2的入口指向,并让webpack-dev-server监听node_modules里的module2源码。
- 修改module2的
package.json,把main字段指向源码入口(而不是构建后的产物):
{ "main": "src/index.js", // ...其他配置 }
- 修改module1的webpack-dev-server配置,让它监听node_modules里的module2文件(默认webpack会忽略node_modules的监听):
module.exports = { // ...其他配置 devServer: { watchOptions: { // 忽略除了module2之外的所有node_modules文件,提升监听性能 ignored: /node_modules\/(?!module2)/ } } }
- 重新执行
npm link ../module2,重启module1的npm start。现在修改module2的源码时,webpack-dev-server会直接检测到变化,自动重新编译。
这个方案需要确保module1的webpack能正确处理module2的源码,可能需要在module1中配置对应的babel、loader等,和方案2类似,但保留了npm link的依赖结构。
内容的提问来源于stack exchange,提问作者Anton Malyshev

