问题描述

多个项目,为了开发方便,不同项目中的模块存在相互引用。开发工具初始用的是Visual Studio Code 1.39.2版本,之前打包运行都是正常,但是当Visual Studio Code1.39.2升级到1.52.1,发现引用部分模块功能不可用,问题主要体现在axiosvue封装插件中,部分修改变量获取不到修改后的值。

问题原因

初步定位问题原因为,不同项目之间公共包作用域不同,npm默认是查找规则为以当前package.json为基准,从同目录下的node_modules开始,如果没有找到依赖文件,逐步向上查找,直至查到至全局的node_modules上。如果项目2引入项目1api项目1中存在axios,则查找的就是项目1中,项目1中没有,才会查找项目2中的axios,两者都有,就各找各的。

V1.39.2的版本为何能正常解析?

1.39.2版本的Visual Studio Code中,我们默认增加了"npm.enableScriptExplorer": true配置,这个配置的主要功能为查找依赖包时,默认要查找至最顶层的package.json中的依赖包 && 显示侧边栏npm scripts,即在项目1中引用了项目2中的一个模块,项目2中引入了vue.js,项目1中也引入了vue.js,则顶层package.json是在项目1中,最后查找到的package.json也在项目1中,所以功能可正常使用,否则则不行。
1.52.1中,npm插件中废除了此项配置,NPM:auto Detect可以控制侧边栏npm scripts的显示。因此会导致打包结果依赖分离,APP运行异常。
实际上,目前开发引用模块的方式本质就是错的,只是误打误撞,碰巧以为是对的。归根结底,还是npm引用包查询方式与ES6模块机制理解不够透彻!

解决办法

  • Webpack中可以固定关键包的查找作用域,引用其他APP模块,对于公共依赖可以配置别名alias,指定查找路径,如下所示:
configureWebpack: {
    resolve: {
      alias: {
        'axios': path.resolve(__dirname, './node_modules/axios/')
      }
    }
  }
  • 将公共模块封装成插件,需要依赖以参数的形式注入
export default function (Vue) {
  // vue相关插件代码
  // xxxx
}

建议不同模块间包的引用最好不要掺杂第三方依赖。

延伸阅读

  • ES6模块(import/export)机制原理是新导入的包,是对原有包模块的一种引用,原有包数据的改变,会反应到引用的包里。所以在相同项目中,不同地方都导入了axios,有一个地方改变了axios.defaults.baseURL,其他地方虽然导入的是axios包,但是修改的默认地址仍然会获取到。
  • CommonJS模块(require/module.exports)规范是导入的包,是对原有包的值的拷贝,原有包的模块内容改变,不会反应到导入的文件中。

参考资料