从项目文件夹外部导入可导入的模块,以供 webpack HMR Vue.js 使用。

11

我的项目结构如下:

.
+-- 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:\Projects\Cb\CommonVue'

我已添加:

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

这似乎解决了在控制台中运行webpack时的路径问题,但在浏览器调试时仍然存在问题。希望有类似项目结构设置经验的人能提供帮助!

5个回答

5
  • Vue-cli: v3.11.0(版本号)
  • webpack: v4.40.2(版本号)
  • babel: 7.6.0(版本号)
  • node: 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']
    }
  }
};

现在,在我的任何一个*项目组件中,我只需要使用以下代码:
import frobinator from 'TTlib/frobinator'

现在,如果我编辑项目或(外部)库文件中的任何一个文件,webpack HMR将会启动并刷新正在运行的' yarn serve '守护进程,并发出我所做的更改。
希望这有所帮助!

4

我之前使用了 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添加以下配置来添加别名:

// vue.config.js
configureWebpack: {
  resolve: {
    alias: {
      '@s3': path.resolve(__dirname, 'shared3'),
    },
  }
},

// tsconfig.json
"compilerOptions": {
  // only needed for auto completion(?)
  "paths": {
    "@s3/*": ["shared3/*"],
  },
},

尽管我更喜欢通过配置来改进shared1,但最终结果对我们这个小团队完美地发挥了作用,我非常满意。
优点:无警告、错误等。所有功能都正常工作,就像代码在项目中一样,而且代码仍然可在其他项目中访问。
缺点:每个开发人员需要手动创建符号链接才能使其代码编译/与Intellisense配合工作。不过,他们也必须运行npm install。

2

**** 更新 ****

这个过程有点麻烦。对我来说,这种设置是小团队(1-4人)的理想设置。如果您已经在父存储库(单块)中拥有子项目,则不需要处理npm打包或创建其他存储库。您希望能够直接在项目中开发和调试组件。比更新、打包、吸入另一个包要快得多。最终,我成功解决了除了从Common文件夹中使用组件的项目之外的所有问题,但webpack HMR仍然存在问题。以下是我最终解决问题的方法:

在webpack.config.js中添加resolve之前:

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 或使用 bit (https://bitsrc.io)。所有这些解决方案似乎比上述解决方案更加笨重和不流畅。

0

我们之前是以ASP.NET开发为主,使用类似的设置。这次在JavaScript开发环境中,我们一直在寻找着合适的项目结构。我们试过多种baseurl/paths/alias组合,但是都导致了各种问题,比如es-linting失败、typescript处理失败、模块加载失败等等。

最终对我们有效的解决方案其实很简单。

我们使用符号链接将共同的项目文件夹映射进来。要添加符号链接,请以管理员身份运行CMD并执行mklink /D "C:\SymbolicLink\To" "C:\Actual\Common\Directory"

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

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

那应该就是你所需要的全部。


0
删除 node_modules 中的包文件夹,并在其中创建一个指向真实项目的符号链接。
rm -rf my_project/node_modules/shared_lib

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接