更新: 链接到 回购
阅读了大量文档和检查示例,但不幸的是我的组合是有史以来最糟糕的。延迟加载、动态导入、带变量的绝对路径:
我有 Angular 15 应用程序,其中有 2 个项目、库和应用程序,它们应该使用绝对路径引用库的组件(因为我需要以与另一个 Angular 应用程序相同的方式使用库)。 库具有独立的组件 - 辅助入口点。其中一个组件很棘手。 它正在根据 REST API 响应在 ViewContainerRef 容器中创建组件。我在存储库中对其进行了简化,因此它可以与提供的示例数据一起使用。
当我尝试相对路径时效果很好
const module = await import(`../../${item.path}/src/${item.path}.component`);
但是我需要一个绝对路径,以便从其他项目中使用。
我尝试了数千种方法来解决它,编辑 tsconfig 以包含项目,编辑包以导出项目。总是有错误。最常见的是:
./projects/mycompany/sdk/dynamic-container/src/dynamic-container.component.ts:21:31-95 - Error: Module not found: Error: Can't resolve '@mycompany/sdk' in 'C:\Users\yekat\apps\new\our-library\projects\mycompany\sdk\dynamic-container\src'
如果您有任何解决办法,请提供帮助。我花了几天几夜都没有答案...
我无法在没有延迟加载的情况下导入所有组件,因为可能有很多或几个组件,而且我不需要加载整个库。
下面的长消息就是我开始的内容。现在我有一个存储库,您可以复制。
提前谢谢您!!!
老问题 我有 2 个 Angular 15 应用程序,我尝试让它们一起工作。 第一个是具有独立组件的库 - 辅助入口点。其中一个组件很棘手。 它正在根据 API 响应在 ViewContainerRef 容器中创建组件。
component.module = await import(`../../../${itemPath}/src/${componentName}.component`);
...
this.componentRef = this.containerRef?.createComponent(component.module[component.moduleName]);
在这个应用程序中,我有一个沙箱,它的模块相对导入我棘手的动态组件。
import { DynamicContainerComponent } from '../../../mycompany/sdk/base-components/dynamic-container/src/dynamic-container.component';
然后它以 html 形式显示。它在图书馆应用程序中运行得非常好。延迟加载按预期工作,构建过程创建文件夹 dist
esm2020/...
fesm2015/...
fesm2020/...
....
服务过程看起来不错,显示了已创建的块:
Initial Chunk Files | Names | Raw Size
vendor.js
.....
| Initial Total | 2.69 MB
.....
Lazy Chunk Files | Names | Raw Size
....
projects_mycompany_sdk_base-components_drop-down-list_src_drop-down-list_component_ts.js | - | 867.52 kB |
....
projects_mycompany_sdk_base-components_plain-html_src_plain-html_component_ts.js | - | 2.26 kB |
它没有我的动态组件,因为它是通过沙箱导入并包含在初始块文件中的。
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"resolveJsonModule": true,
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"strictPropertyInitialization": false,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"typeRoots": [
"node_modules/@types"
],
"paths": {
"@mycompany/sdk/*": [
"projects/mycompany/sdk/*"
],
"@mycompany/sdk": [
"projects/mycompany/sdk"
]
},
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"lib": [
"ES2022",
"dom"
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}
角度.json:
"projects": {
"@mycompany/sdk": {
"projectType": "library",
"root": "projects/mycompany/sdk",
"sourceRoot": "projects/mycompany/sdk",
"prefix": "lib",
"schematics": {
"@schematics/angular:component": {
"standalone": true,
"style": "scss"
},
"@schematics/angular:directive": {
"standalone": true
},
"@schematics/angular:pipe": {
"standalone": true
}
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"project": "projects/mycompany/sdk/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/mycompany/sdk/tsconfig.lib.prod.json"
},
"development": {
"tsConfig": "projects/mycompany/sdk/tsconfig.lib.json"
}
},
"defaultConfiguration": "production"
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"tsConfig": "projects/mycompany/sdk/tsconfig.spec.json",
"polyfills": ["zone.js", "zone.js/testing"]
}
}
}
},
...
我使用 Verdaccio 来发布这个库,效果很好。当我将简单组件从这个库导入另一个应用程序时,它们运行良好。但是当涉及到我的动态容器时,我产生了一个错误。 但让我先介绍一下应用程序 2 是如何工作的。 应用程序组件与应用程序 1 中的沙箱类似,但从包导入:
import { DynamicContainerComponent } from '@mycompany/sdk/base-components/dynamic-container';
(当我导入其他组件时,它们可以工作。但它们没有从相对路径进行这种惰性导入。) 因此 DynamicContainerComponent 的值是来自 API 调用的 Observable 响应。 DynamicContainerComponent 本身决定它应该加载什么组件。
我尝试在 tsconfig 中使用不同的路径:
"paths": {
"../../../base-components/*" : [
"node_modules/@mycompany/sdk/base-components/*"
],
"../../../base-components" : [
"node_modules/@mycompany/sdk/base-components"
],
"base-components": [
"node_modules/@mycompany/sdk/base-components"
],
"@mycompany/sdk/*": [
"node_modules/@mycompany/sdk/*"
],
"./base-components": [
"node_modules/@mycompany/sdk/base-components"
]
}
角度.json:
...
"projects": {
"test-lib": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/test-lib",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
.......
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
....
(很多这些文件,它们确实包含最小化的库组件。) 当服务时我可以看到它也在创建块:
Initial Chunk Files | Names | Raw Size
vendor.js | vendor | 2.40 MB |
....
| Initial Total | 2.96 MB
Lazy Chunk Files | Names | Raw Size
...
node_modules_mycompany_sdk_esm2020_base-components_plain-html_src_plain-html_component_mjs.js | - | 2.83 kB |
...
我想我在 App 2 配置中遗漏了一些东西。
如果建议替换相对路径
../../../${itemPath}/src/${componentName}.component
与
@mycompany/sdk/${itemPath}/src/${componentName}.component
)
我尝试过,在这种情况下,我在服务库时出现错误
./projects/mycompany/sdk/base-components/dynamic-container/src/dynamic-container.component.ts:39:31-105 - Error: Module not found: Error: Can't resolve '@mycompany/sdk' in 'C:\Users\yekat\mw10-front-end-components\projects\mycompany\sdk\base-components\dynamic-container\src'
在App2中
./node_modules/@mycompany/sdk/fesm2020/mycompany-sdk-base-components-dynamic-container.mjs:38:31-105 - Error: Module not found: Error: Can't resolve '@mycompany/sdk' in 'C:\Users\yekat\apps\new\test-lib\node_modules\@mycompany\sdk\fesm2020'
通过在单独的服务中指定所有导入来解决这个问题。在这种情况下,webpack 很高兴并且延迟加载仍然有效。我希望我可以一起使用动态路径和延迟加载,而不需要为所有对象指定导入。但好像不可能