在类似的情况下,我使用 Terra 的解决方案已经有一段时间了,这很好用,但对我来说有一个缺点,即如果共享代码也需要它们自己的 node_modules 内容,那么智能感知不起作用,什么时候构建项目,即使在浏览器中一切正常,也会出现错误(找不到模块...)。也许是因为我使用的是 TypeScript?无论哪种方式,使用单独的包或像 bit 这样的高级工具似乎都太麻烦了,所以我去寻找一个更简单的解决方案,没有缺点。
我已经将我的尝试放在这个存储库中:https://github.com/brease-colin/vue-typescript-shared 其中有一个项目文件夹 (project1) 和三个共享文件夹尝试,都同时链接到 project1 中,都有自己的缺点,但我'我计划使用尝试 3,因为这对我们来说并不是真正的缺点。
顺便说一句,这三个问题都有一个共同点,但也许那是我的 VSCode 表现得很奇怪。如果在 VSCode 中打开根文件夹,则 Vue 文件中的 Intellisense 不理解这三个解决方案的任何导入,而如果在 VSCode 中打开 project1 文件夹,它会理解所有三个解决方案的导入。以下对每次尝试的描述均假设在 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:shared1 与别名 @s1
这是 Terra 答案的 Typescript 版本。我只向 tsconfig 文件添加了一个路径和两个包含路径,以使智能感知工作。还要查看 shared1/tsconfig.json,因为我在那里添加了相同的别名 (@s1),所以共享文件之间的引用很顺利。
优点:无需额外设置,在浏览器中一切正常,在控制台中没有警告/错误,您可以在 VSCode 工作区中轻松打开 shared1 作为附加文件夹,因此您可以编辑所有 shared1文件。
缺点:对 node_modules 的引用在 VSCode 中不起作用,并且终端也会为此输出错误。因此,在使用项目文件夹中的类时没有智能感知/没有类型安全。最后一部分对我来说是一个很大的骗局。
尝试 2:shared2 与别名 @s2
为了尝试修复它,我在共享文件夹中添加了一个 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>
我尝试通过更改模块 resolve / resolveLoader 来解决此问题,确保它在尝试以“常规”方式查找之前首先检查主目录的 node_modules,但它似乎没有帮助。
modules: [
path.resolve(__dirname, 'node_modules'),
'node_modules',
],
也许有人有办法正确修复它?
优点:Intellisense 有效,不再出现构建错误。
缺点:运行时错误、没有可用的应用程序,以及额外的复杂性/风险,因为必须在 project1/shared2 之间保持模块的版本号相同,以保持智能感知始终如一地工作。
尝试 3:shared3 与别名 @s3
代码方面,尝试 3 与尝试 1 没有太大区别,但使用一个简单的技巧,一切都按我的意愿进行。诀窍是使用 symlink,我使用了一个名为 symlink-dir 的多平台 npm 包来轻松完成此操作。我实际上已将它作为开发依赖项添加到 project1 的 package.json 中:
npm install --save-dev symlink-dir
之后,我制作了如下符号链接,每次克隆存储库时都必须执行一次。
npx symlink-dir ../shared3/ shared3/
现在,为了防止两次签入代码,您必须在 .gitignore 中添加一行:
// .gitignore
*/shared3/
因为共享代码现在在您的项目文件夹中,您甚至可以在没有别名的情况下访问它,但是为了更容易让共享文件夹中的文件相互访问,我更喜欢固定别名,所以我通过添加它添加了对 vue.config.js 和 tsconfig.json 进行如下配置:
// vue.config.js
configureWebpack: {
resolve: {
alias: {
'@s3': path.resolve(__dirname, 'shared3'),
},
}
},
// tsconfig.json
"compilerOptions": {
// only needed for auto completion(?)
"paths": {
"@s3/*": ["shared3/*"],
},
},
虽然我更喜欢仅配置解决方案来改进 shared1,但我仍然对这个最终结果非常满意,因为它非常适合我们这个小团队。
优点:没有警告、错误等:一切都像代码在项目中一样工作,是哪种情况,同时仍然可以在其他项目中访问代码。
缺点:每个开发人员都需要手动创建符号链接,然后他们的代码才能编译/使用智能感知。再说一次,他们还必须为此运行 npm install。