Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 动态生成适当的角度元素,而不增加构建大小? 总结:_Javascript_Angular_Sass_Web Component_Angular Elements - Fatal编程技术网

Javascript 动态生成适当的角度元素,而不增加构建大小? 总结:

Javascript 动态生成适当的角度元素,而不增加构建大小? 总结:,javascript,angular,sass,web-component,angular-elements,Javascript,Angular,Sass,Web Component,Angular Elements,当在开关盒内多次调用createCustomElement()时,所有组件都将包含在构建中,而不仅仅是实际使用的组件。这会使用重复的代码增加生成大小 细节 我有一个多站点架构的Angular 11应用程序。每个站点的angular.json中都有一个项目,因此它们可以独立构建,并根据包含“siteCode”的相应environment.ts文件生成自己的dist bundle 对于我网站中的一个大组件——我们称之为myWidget——我还将其导出为通用web组件(也称为“Angular Elem

当在开关盒内多次调用
createCustomElement()
时,所有组件都将包含在构建中,而不仅仅是实际使用的组件。这会使用重复的代码增加生成大小

细节 我有一个多站点架构的Angular 11应用程序。每个站点的
angular.json
中都有一个项目,因此它们可以独立构建,并根据包含“siteCode”的相应
environment.ts
文件生成自己的dist bundle

对于我网站中的一个大组件——我们称之为myWidget——我还将其导出为通用web组件(也称为“Angular Element”,也称为“custom Element”),供其他网站使用。因此,我在主应用程序的一个子项目中有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 bundle analyzer验证)

进一步的背景 这里的三个特定于站点的myWidget组件都继承自一个公共基础组件,其中所有的实际逻辑都是相同的,因此它们几乎是相同的。我这样做是为了能够为该站点加载适当的CSS文件,并将它们作为特定于组件的CSS打包到导出的MyWidget web组件中。它使用shadowDom封装,这样web组件就与插入到其中的父页面完全隔离。因此,所讨论的组件如下所示:

my-widget-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
}

@import '../../../../../../src/app/sites/site1/theme.scss';
@import '../../../../../../src/styles.scss';
@import '../../../../../../src/app/sites/site1/styles.scss';
my-widget-site1.component.scss

@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
}

@import '../../../../../../src/app/sites/site1/theme.scss';
@import '../../../../../../src/styles.scss';
@import '../../../../../../src/app/sites/site1/styles.scss';
结论 我可以想出一些解决这个问题的总体思路:

1)动态加载所需组件的一些技巧,而不是在交换机情况下加载?

我什么也没找到。似乎只要我必须导入组件,它就会包含在构建中

2)避免每个站点都有多个版本的组件?

我很想这样做,但我不知道如何避开CSS问题。特定站点的适当CSS文件需要在构建时绑定到此组件中,以便将它们封装在web组件的影子根中,而不是作为单独的CSS文件构建,并导入到消费页面的全局范围中。这意味着我不能在
angular.json

我试图在SCS上执行动态
@import
语句,但这似乎不可能


您能否以某种方式在构建过程中编写脚本,以便在构建时选择正确的scss文件?我不知道从哪里开始做这样的事情。

我想出了一个有趣的解决方案

通过使用“快捷方式”指向必要的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
  ]
}
因此,现在我可以使用一个始终具有相同导入的组件,但在构建时,它实际上会为正在构建的站点使用正确的文件

有关快捷方式语法的信息:

您是否尝试过使用?