如何在本地开发 Angular 7 个相互依赖的库? (npm link 问题)

How can I locally develop Angular 7 libraries that depend on each other? (npm link issues)

我有两个 angular 库 NPM 包:

A-BC 中的某些组件从 A 导入,例如 import { MyThing } from 'A';

A-BC的package.json是:

"peerDependencies": {
   "A": 1.0.0,
   "BC": 4.0.0
},
"devDependencies": {
   "A": 1.0.0,
   "BC": 4.0.0
}

我尝试的开发步骤是:

  1. npm link --only=production 在(内置版本)A
  2. npm link --only=production 在(内置版本)A-BC
  3. my-app, 运行 npm link A
  4. my-app、运行npm link A-BC
  5. 运行 my-app

A-BC 找不到安装在任何地方的 A 时,my-app 的编译失败。它们都作为符号链接文件夹在 node_modules 中正确列出。我已经在 tsconfig.jsonangular.json 中启用了 preserveSymlinks,但没有帮助。

A 可能是 A-BC 的直接依赖项,但是:

目前我的创可贴解决方案是:

  1. A发布为测试版
  2. A-BCmy-app
  3. 中安装测试版
  4. Link A-BC 通过 npm link
  5. my-app
  6. 如果需要进行更改,请发布 A 的新测试版,然后在 my-appA-BC 中再次安装它

可能存在通过 NPM 对本地文件的支持安装 A 的替代工作流程,但我不确定。

我假设您正在谈论的这两个包是使用 ngCli v6 创建的,或者您正在从现有的 ng 工作区中合并它们,无论哪种方式,让我们尝试解决您的问题。

我将假定您具有如下所示的 ng 工作区结构

...
projects >
  A
  B
  host
...

其中 A 是一个库 B 是一个依赖于 A 的库,host 是一个使用 B 的应用程序。

当 working/developing ng 在您的 ng 工作区本地打包时,您应该将它们的别名添加到您的 root tsconfig.json 文件中,例如:

{
 ...
"compilerOptions": {
    ...
    "paths": {
      "a": [
        "dist/a"
      ],
      "a/*": [
        "dist/a/*"
      ],
      "b": [
        "dist/b"
      ],
      "b/*": [
        "dist/b/*"
      ]
    }
  }
}

这是在使用 ng new lib {yourLibName} 命令生成库时在 CLI v7 中自动为您完成的。

确保您拥有此配置后,我建议向您的 package.json 添加一些脚本,以便构建您的库并以更直接的方式为您的开发应用程序提供服务(host 在示例的情况)

"build:a": "ng build A --watch=true",
"build:b": "ng build B --watch=true",
"serve:host": "ng serve host"

之后,通过运行三个脚本相继导入相应的libModules from lib B in your Host App和相应的libModules来自 lib A inside Lib B,您将能够使用 lib B 的组件,这取决于来自 lib A inside Host APP.[=41= 的组件]

请记住,您不能在您的工作区中安装这两个库,因为这会破坏您项目中的导入,而且这些库不应成为您工作区的一部分 package.json

如果您已完成上述步骤但问题仍未解决,请向我们提供 link 到 git 存储库,或分享您的 tsconfig.jsonpackage.json, angular.json 文件,以便我们可以继续调查。

回复子评论

所以如果我得到你的情况,你希望能够开发这些 packages 并将它们安装在一个单独的 ng 工作区中。

如果是这种情况,据我所知,没有直接的方法可以做到这一点,您可能可以通过调整 tsconfig.json 文件。

但在我看来,如果你想在同一个工作区内使用这个 ng packages,你不一定需要推送它们,因为归根结底,它们只是另一组 ngModules 将在您引用它们的应用程序中 "first-class citizens"。因此,在为生产构建时,它们将是 tree-shaken、minimized-optimized 等。在这种情况下,您应该只扩展 package.json 中的部署脚本,这样在您开始构建主应用程序之前,这将取决于那些 npm/ng/packages,您构建那些包。

"deploy": "ng build A && ng build B && ng build MainApp --production"

与此同时,那些 npm/ng/packages 仍然可以 npm 发布,您将能够在其他工作区中使用它们。 请记住,它们不应属于同一(正在开发它们的工作区)工作区的 package.json 依赖项。

我最初尝试做的事情遇到了很多问题,因为场景一开始就错了。

我在这里学到的主要两件事是:

  1. 只在内部 angular 项目中使用的包不应该 发布到 npm
  2. 如果库相互依赖,它们应该直接从您的 typescript/angular 来源导入

如果您试图使我描述的场景有效,它会让您头疼不已,因为它是一种根本上有问题的方法。

现在共享这些库的所有相关项目都在一个 nx monorepo 中。直接导入库后,一切都会自动进行实时重新加载、tree shaking 等,正如其他 answers/comments 此处所建议的那样。迁移不是很麻烦,monorepo 设置的工具非常好。

当设置你的 monorepo 使这个场景工作时,库将通过 tsconfig 路径导入到每个项目,如下所示。这使得 npm 包的旧导入语句能够保持不变,因为您的路径可以只引用以前的 npm 包的名称(如上面问题中的 A 或 A-BC)。

每个项目现在也共享相同的包 json,并且通过将这些工具脚本集中在 monorepo 根中,而不是在每个项目中单独使用工具,用于服务、构建等的 npm 脚本得到了极大的改进回购

@angular/* 的路径修复了库冲突的一些问题。

示例路径来自 /apps/example-project/tsconfig.json

   "paths": {
      "@angular/*": ["../node_modules/@angular/*"],
      "@exampleNPMOrg/A": [
        "../../libs/A/src/index"
      ],
      "@exampleNPMOrg/A-BC": [
        "../../libs/A-BC/src/index"
      ],
    }

示例路径来自 /tsconfig.json

   "paths": {
      "@exampleNPMOrg/A": [
        "libs/A/src/index"
      ],
      "@exampleNPMOrg/A-BC": [
        "libs/A-BC/src/index"
      ],
    }