javascript - 动态生成适当的 Angular Element 而不会膨胀构建大小?
问题描述
概括:
在createCustomElement()
switch case 中多次调用时,所有组件都将包含在构建中,而不仅仅是实际使用的组件。这会增加重复代码的构建大小。
细节
我有一个具有多站点架构的 Angular 11 应用程序。每个站点都有一个项目,因此它们可以独立构建并基于包含“siteCode”angular.json
的相应文件生成自己的dist包。environment.ts
对于我网站中的一个大型组件——我们称之为myWidget——我还将它导出为通用 Web 组件(又名“Angular 元素”,又名“自定义元素”)以供其他网站使用。所以我在主应用程序的子项目中有myWidget,它也有自己的项目列在angular.json
. 这意味着我可以运行一个只包含给定站点的myWidget的构建(显然还有核心 Angular 框架)。
myWidget 子项目的app.module.ts(简体):
import { MyWidgetSite1Component } from './my-widget/site-widgets/my-widget-site1.component';
import { MyWidgetSite2Component } from './my-widget/site-widgets/my-widget-site2.component';
import { MyWidgetSite3Component } from './my-widget/site-widgets/my-widget-site3.component';
@NgModule({
declarations: [AppComponent],
imports: [MyWidgetModule]
})
export class AppModule {
constructor(private injector: Injector) {
//Create generic web component version of myWidget. Use correct child version per site.
switch (environment.siteCode) {
case "site1": {
const myWidgetCustomElement = createCustomElement(MyWidgetSite1Component , { injector: this.injector });
customElements.define('site1-myWidget', myWidgetCustomElement);
break;
}
case "site2": {
const myWidgetCustomElement = createCustomElement(MyWidgetSite2Component , { injector: this.injector });
customElements.define('site2-myWidget', myWidgetCustomElement);
break;
}
case "site3": {
const myWidgetCustomElement = createCustomElement(MyWidgetSite3Component , { injector: this.injector });
customElements.define('site3-myWidget', myWidgetCustomElement);
break;
}
}
}
}
问题:它在构建中包含所有这三个组件,而不仅仅是将用于该站点的一个(使用 webpack 包分析器验证)。
更多背景
这里的三个特定于站点的 myWidget 组件都继承自一个公共基础组件,所有真正的逻辑都在这个基础组件中,因此它们几乎相同。我这样做是为了可以为该站点加载适当的 CSS 文件,并将它们作为特定于组件的 CSS 捆绑在导出的 MyWidget Web 组件中。它使用 shadowDom 封装,这样 Web 组件与它插入的父页面完全隔离。所以有问题的组件看起来像这样:
我的小部件-site1.component.ts
@Component({
selector: 'my-widget-site1',
templateUrl: '../my-widget/my-widget.component.html', //Shares base myWidget template
//First file does nothing but import appropriate site's stylesheets from main project. It would
//have been better to directly include them here, but that resulted in odd build errors.
styleUrls: [
'./my-widget-site1.component.scss',
'../my-widget/my-widget.component.scss'],
encapsulation: ViewEncapsulation.ShadowDom
})
export class MyWidgetSite1Component extends MyWidgetComponent implements OnInit {
//Do not add any code here
}
我的小部件-site1.component.scss
@import '../../../../../../src/app/sites/site1/theme.scss';
@import '../../../../../../src/styles.scss';
@import '../../../../../../src/app/sites/site1/styles.scss';
结论
我可以想出一些一般的想法来解决这个问题:
1) 一些技巧来动态加载所需的组件,而不是在 switch case 中?
我什么都没找到。看来只要我有import
这个组件,它就会被包含在构建中。
2) 完全避免每个站点拥有多个版本的组件?
我很想这样做,但我不知道如何解决 CSS 问题。给定站点的适当 CSS 文件需要在构建时捆绑到此组件中,因此它们被封装在 Web 组件的 shadow-root 中,而不是构建为单独的 CSS 文件,导入到消费页面的全局范围内. 这意味着我不能只在项目构建的“样式”部分中列出它们angular.json
我试图@import
在 scss 上做一个动态声明,但这似乎是不可能的。
您能否以某种方式在构建过程中编写脚本以在构建时选择正确的 scss 文件?我不知道从哪里开始这样的事情。
解决方案
我想出了一个有趣的解决方案。
我可以摆脱对多个组件文件的需求,并@import
通过使用“快捷方式”指向必要的 scss 文件而不是完整路径来有效地实现动态:
@import "theme";
@import "styles";
@import "site-styles";
您可以通过以下方式配置它将在其中找到指定文件的文件夹angular.json
:
"stylePreprocessorOptions": {
"includePaths": [
"src/app/sites/site1/", //theme.scss and site-styles.scss are here
"src/" //styles.scss is here
]
}
所以现在我可以使用一个始终具有相同导入的组件,但在构建时它实际上会为正在构建的站点使用正确的文件。
有关快捷方式语法的信息:https ://www.digitalocean.com/community/tutorials/angular-shortcut-to-importing-styles-files-in-components
推荐阅读
- reactjs - 如何在自定义验证器中使用 PropType 内置函数?
- javascript - 如何在 JavaScript 中的嵌入式 HTML 中创建 if 语句以显示 CSS 类
- api - 在 Flutter 中使用 Multi Image Picker 选择图像后如何获取图像路径?
- sql - 如何将 varchar 转换为 int - SQL 错误:'=' 不能应用于 varchar、bigint
- python - 查找大小为 K 且总和可被 M 整除的子数组的数量?
- cmd - 有没有办法用命令显示 wim 文件的索引?
- node.js - 找不到本地安装的 NPM 模块命令
- django - 如何使 unique_together 双向?
- azure - Azure B2C Twitter ID 提供程序不起作用
- python - Pandas:获取按其他列分组后不为空的元素数量的百分比