包括来自外部项目文件夹的可导入模块,用于 webpack HMR Vue.js



我有一个项目结构,如下所示:

.
+-- Common
|   +-- MyCommonVueComponent.Vue
+-- MainProject
|   +-- webpack.config.js
|   +-- package.json
|   +-- node_modules
|   +-- src

当我从控制台 webpack 构建时,它似乎有一个正确的路径,可以从 Common 导入到 MainProject 的组件的 node_modules 文件夹。当我尝试在浏览器中调试 Vue.js 应用程序时,出现以下错误:

../Common/MyCommonVueComponent.Vue
Module not found: Error: Can't resolve 'vue-hot-reload-api' in 'D:ProjectsCbCommonVue'

我添加了:

resolveLoader: {
modules: [path.resolve(__dirname, './node_modules')],
},

这似乎确实解决了在控制台中运行 webpack 时的路径问题,但在浏览器中调试时却没有解决。任何帮助,不胜感激。希望设置类似项目结构的人可以有所启发!

  • Vue-cli: v3.11.0
  • 网络包: v4.40.2
  • 通天塔:7.6.0
  • 节点:v10.16.3

今晚我遇到了类似的情况,我想将一些自定义库移到外部共享库目录中,以进行敏捷开发和模拟测试。 大约两周前,我刚刚开始学习 Vue/webpack 生态系统,我可以肯定地说,这是一次冒险,webpack 是一头令人生畏的野兽,它弄清楚了所有必须正确对齐的神秘旋钮和按钮。

./devel  (webpack alias: TTlib)
+-- lib
|   +-- widget.js
|   +-- frobinator.js
|   +-- suckolux3000.js
+-- share (suckolux3000.js taps into this directory)
|   +-- imgs
|   +-- icons
|   |   +-- img
|   |   +-- svg
+-- MainProject
|   +-- vue.config.js
|   +-- package.json
|   +-- node_modules
|   +-- src
+-- TestProject
|   +-- vue.config.js
|   +-- package.json
|   +-- node_modules
|   +-- src

我关心的是确保 webpack HMR 能够工作,我可以说你很接近,但还不够远。 幸运的是,修复非常简单。

以下是我的vue.config.js补充:

module.exports = {
configureWebpack: {
resolve: {
alias: {
'TTlib': '/devel/lib'
},
modules: ['/devel/lib']
},
resolveLoader: {
modules: ['/devel/lib']
}
}
};

现在,从我的任何 *Project 组件中,我都可以使用:

import frobinator from 'TTlib/frobinator'

现在,如果我编辑任何项目或(外部)lib 文件,webpack HMR 将启动并刷新正在运行的"yarn serve"守护进程并发出我所做的更改。

希望对您有所帮助!

对于类似情况,我已经使用 Terra 的解决方案一段时间了,这工作正常,但对我来说有一个缺点,即如果共享代码也需要自己的node_modules内容,那么 intellisense 不起作用,在构建项目时,会出现错误(找不到模块......也许是因为我正在使用 TypeScript?无论哪种方式,使用单独的软件包或像 bit 这样的高级工具似乎都太麻烦了,所以我去寻找一个更简单的解决方案,没有缺点。

我已经把我的尝试放在这个存储库中:https://github.com/brease-colin/vue-typescript-shared 有一个项目文件夹(project1)和三个共享文件夹尝试,所有这些都同时链接到project1中,都有自己的缺点,但我计划使用尝试3,因为它对我们来说并不是一个真正的缺点。

顺便说一句,有一个问题对所有三个人来说都是共同的,但也许那是我的 VSCode 表现得很奇怪。如果在 VSCode 中打开根文件夹,则 Vue 文件中的智能感知不理解这三个解决方案中的任何一个导入,而如果在 VSCode 中打开 project1 文件夹,它理解所有三个解决方案的导入。下面对每次尝试的描述假定在 VSCode 中打开项目 1。

要查看的主要文件是:

  • 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共享 1

这是 Terra 答案的打字稿版本。我只在 tsconfig 文件中添加了一个路径和两个包含路径,以使智能感知工作。另请查看 shared1/tsconfig.json,因为我在那里添加了相同的别名 (@s1),因此共享文件之间的引用进展顺利。

优点:无需额外设置,在浏览器中一切正常,控制台中没有警告/错误,您可以在 VSCode 工作区中轻松打开 shared1 作为附加文件夹,因此您可以编辑所有 shared1 文件。

缺点:对node_modules的引用在VSCode中不起作用,并且终端中也为此输出错误。因此,使用项目文件夹中的类时没有智能感知/没有类型安全。最后一部分对我来说是一个很大的骗局。

尝试 2:使用别名 @s2 共享 2

为了尝试修复它,我在共享文件夹中添加了一个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',
],

也许有人有办法正确修复它?

优点:智能感知有效,不再有构建错误。

缺点: 运行时错误,没有工作的应用程序,加上额外的复杂性/风险,因为必须在项目1/shared2之间保持模块的相同版本号,以保持智能感知一致地工作。

尝试 3:使用别名 @s3共享 3

代码方面,尝试 3 与尝试 1 没有太大区别,但使用一个简单的技巧,一切都按照我想要的方式工作。诀窍是使用符号链接,我使用了一个名为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 安装。

**** Update ****

所以这有点地狱。对我来说,这种设置是小团队(1-4)的理想设置。如果已经有一个包含子项目的父存储库(整体式),则不希望处理 npm 打包或创建其他存储库。您希望能够直接在项目中开发和调试组件。比更新、打包、吸进另一个包装要快得多。我终于得到了一切工作,除了使用公共文件夹中组件的项目上的 webpack HMR。以下是最终对我有用的方法:

添加到 webpack.config.js上面的解决方案:

resolveLoader: {
modules: [path.resolve(__dirname, 'node_modules')],
},

在 resolve (webpack.config.js) 中添加 Common 文件夹的别名:

'Common': path.resolve(__dirname, '../Common') <- this is the root of my mono repo

修改我在 webpack.config.js 中的输出(添加了 publicPath):

output: {
path: path.join(__dirname, bundleOutputDir),
filename: '[name].js',
publicPath: 'dist/'
},

到目前为止,这似乎有效。这让我能够坚持直截了当.Vue 组件文件位于一个名为 Common 的文件夹中,它是我所有其他项目文件的同级。所有项目包括主解决方案文件夹中的公共站点,该文件夹是我的 git 存储库的根。

替代方案是使用 NPM 或使用位 (https://bitsrc.io)。所有这些解决方案似乎都比上述解决方案更笨重,更无摩擦。

删除node_modules中的包文件夹,并在node_modules内创建指向真实项目的符号链接。

rm -rf my_project/node_modules/shared_lib
ln -s /path/shared_lib my_project/node_modules/shared_lib

来自 ASP.NET 开发,我们使用类似的设置,这是我们在 JavaScript 开发环境中寻找的项目结构。我们在尝试大量 baseurl/路径/别名组合时遇到了所有相同的问题,所有这些都导致某种失败的 es-linting、打字稿处理、模块加载或其他。

最终对我们有用的解决方案实际上非常简单。

我们使用符号链接在公共项目文件夹中进行映射。要添加符号链接,请以管理员身份运行CMD并执行mklink /D "C:SymbolicLinkTo" "C:ActualCommonDirectory"

完成此操作后,您需要更改 vue.config.js 文件中的一个关键设置。如果没有此设置,依赖项将从其实际位置而不是符号链接位置解析。

configureWebpack: {
resolve: {
symlinks: false // Dependencies must be resolvable from the symlinked location, not the real location
}
}

这应该是你所需要的。

最新更新