我之前使用了 Terra 的解决方案来解决类似的问题,这个方法效果不错,但是有一个缺点,即如果共享代码也需要依赖自己的 node_modules 内容,则 IntelliSense 无法正常工作,并且在构建项目时会出现错误(Cannot find module...),尽管在浏览器中一切正常。可能是因为我正在使用 TypeScript?无论如何,使用分离的包或高级工具(如 bit)看起来都太麻烦了,因此我去寻找一个没有这个缺点的简单解决方案。
我把我的尝试放到了这个存储库中:https://github.com/brease-colin/vue-typescript-shared,其中有一个项目文件夹(project1)和三个共享文件夹尝试,同时在 project1 中链接,它们都有自己的缺点,但我计划使用第 3 种尝试,因为这对我们来说不是一个缺点。
顺便说一句,这里有一个问题,对所有三个尝试都是普遍存在的,但也许是我的 VSCode 行为怪异。如果在 VSCode 中打开根文件夹,则 Vue 文件中的 IntelliSense 不理解任何三种解决方案的导入,而如果在 VSCode 中打开项目 1 文件夹,则它可以理解所有三个尝试的导入。下面对每个尝试的描述假定在 VSCode 中打开了 project1。
需要查看的主要文件是:
- project1/src/components/HelloWorld.vue:vue 文件,尝试重用共享的组合函数和共享组件
- project1/src/data/ProjectDummies.ts:ts 文件,尝试重用共享的 ts 文件
- project1/tsconfig.json
- project1/vue.config.js
- shared[1/2/3]/components/Header[1/2/3].vue:一个共享组件,从 @vue/composition-api 中导入。
尝试 1:带有别名 @s1 的 shared1
这是 Terra 答案的 TypeScript 版本。我只添加了路径和两个包含路径到 tsconfig 文件中,以使 IntelliSense 工作。还要检查 shared1/tsconfig.json,因为我在那里添加了相同的别名(@s1),所以在共享文件之间的引用正常。
优点:不需要额外的设置,在浏览器中都能正常工作,控制台没有警告/错误,您可以轻松地将 shared1 作为附加文件夹打开到您的 VSCode 工作区中,以便您可以编辑所有 shared1 文件。
缺点:在 VSCode 中引用 node_modules 无法正常工作,并且终端也会输出错误。因此,在使用项目文件夹中的类时,没有 IntelliSense / 没有类型安全性。对我来说,最后一个部分是一个很大的缺点。
尝试 2:带有别名 @s2 的 shared2
为了尝试修复这个问题,我向共享文件夹中添加了一个package.json,并安装了所需的包(在这种情况下为:@vue/composition-api)。这使得智能感知工作正常,构建时终端输出的错误也消失了。然而,现在在浏览器运行时代码会崩溃,因为依赖项被重复添加了,并且在共享文件夹中导入的模块代码不引用相同的模块代码。这不会在所有类型的依赖项中都产生错误,但在某些情况下,一些应该在整个代码库中相同初始化的常量会产生错误。我收到的错误信息如下:
[Vue warn]: onMounted is called when there is no active component instance to be associated with. Lifecycle injection APIs can only be used during execution of setup().
[Vue warn]: Error in data(): "Error: [vue-composition-api] must call Vue.use(VueCompositionAPI) before using any function."
found in
---> <Header2> at shared2/components/Header2.vue
<HelloWorld> at src/components/HelloWorld.vue
<Home> at src/views/Home.vue
<App> at src/App.vue
<Root>
我尝试通过更改模块解析/解析加载器来修复这个问题,确保它在尝试“常规”方式之前首先检查主目录下的node_modules文件夹,但似乎并没有帮助。
modules: [
path.resolve(__dirname, 'node_modules'),
'node_modules',
],
也许有人知道如何正确地修复它?
优点:Intellisense(智能感知功能)可以正常工作,不再有构建错误。
缺点:运行时错误,没有工作的应用程序,还需要保持项目1 / 共享2模块的版本号相同以保证Intellisense一致性,因此增加了额外的复杂度和风险。
尝试3:别名为@s3的shared3
从代码角度来看,第3次尝试与第1次尝试并没有太大的区别,但是通过一个简单的技巧,我成功地实现了想要的效果。这个技巧是使用符号链接,我使用了一个名为symlink-dir的npm多平台包来轻松地实现。实际上,我已将其添加为项目1的package.json中的开发依赖项:
npm install --save-dev symlink-dir
之后,我创建了以下符号链接,每次克隆存储库时都需要执行一次。
npx symlink-dir ../shared3/ shared3/
现在,为了避免将代码检入两次,您需要在 .gitignore 文件中添加一行:
// .gitignore
*/shared3/
由于共享代码现在位于您的项目文件夹中,因此您甚至可以在没有别名的情况下访问它,但为了更轻松地让共享文件夹中的文件相互访问,我更喜欢使用固定的别名,因此我通过向vue.config.js和tsconfig.json添加以下配置来添加别名:
configureWebpack: {
resolve: {
alias: {
'@s3': path.resolve(__dirname, 'shared3'),
},
}
},
"compilerOptions": {
"paths": {
"@s3/*": ["shared3/*"],
},
},
尽管我更喜欢通过配置来改进shared1,但最终结果对我们这个小团队完美地发挥了作用,我非常满意。
优点:无警告、错误等。所有功能都正常工作,就像代码在项目中一样,而且代码仍然可在其他项目中访问。
缺点:每个开发人员需要手动创建符号链接才能使其代码编译/与Intellisense配合工作。不过,他们也必须运行npm install。