【问题标题】:Using multiple angular elements as web components within an angular project在 Angular 项目中使用多个 Angular 元素作为 Web 组件
【发布时间】:2018-10-23 10:51:36
【问题描述】:

给定三个使用 v6.1.9 的 @angular 项目:hostalphabeta

alphabeta 分别使用 @angular/elements 创建和定义一个 Web 组件:

constructor(private injector: Injector) {}

ngDoBootstrap() {
  const config: NgElementConfig = { injector: this.injector };
  const component= createCustomElement(component, config);
  customElements.define("alpha-component", component); // beta-component respectively
}

alphabeta 使用 ng build --prod --output-hashing none 构建,然后运行构建后脚本以按以下顺序连接生成的文件:scripts.js, styles.js, runtime.js, main.js

polyfills.js 被跳过,因为main.ts 将检查在加载库时是否已经定义了所使用的 polyfill(例如,避免尝试重新定义 zone.js)。

生成的包是alpha-component.bundle.jsbeta-component.bundle.js

host 使用<script defer> 标签在index.html<head> 中引用上述捆绑包。

如果捆绑包的引用顺序是alpha 然后beta,我会看到alpha 尝试引导两次;以相反的顺序,我会看到beta 尝试引导两次。

由于第一个引用的包尝试引导两次,它尝试为该包定义 Web 组件两次,导致错误,并且从未注册第二个引用的包的 Web 组件。

目标是能够使用 @angular 创建许多 Web 组件,然后在其他 @angular 或 insert framework here 技术中使用它们。

【问题讨论】:

标签: angular web-component angular-elements


【解决方案1】:
  1. 安装 @angular-builders/custom-webpack

  2. 创建自定义 webpack 配置文件。例如。 extra-webpack.config.js.

    module.exports = {
    output: {
        chunkLoadingGlobal: 'webpackChunkModuleName',
        library: 'ModuleName'
    }
    

为 chunkLoadingGlobal & 库提供您的应用程序名称或任何唯一名称。

注意:这些属性是根据 webpack 5 在 angular 12+ 中使用的。请参阅 webpack 文档以了解旧版本的 webpack。

  1. 使用 @angular-builders/custom-webpack 作为构建器来代替 @angular-devkit/build-angular 并添加 customWebpackConfig angular.json 中的对象。
"builder": "@angular-builders/custom-webpack:browser",
    .....
    "customWebpackConfig": {
       "path": "extra-webpack.config.js",
        "mergeStrategies": {
           "externals": "prepend"
         }
     }
  1. 现在,当您运行 ng build 时,您的应用程序将使用带有自定义 webpack 配置的自定义构建器来构建。导出为 Web 组件和多个 Web 组件的其他应用程序的类似配置可以在同一个容器应用程序中使用,而不会出现任何错误或命名空间冲突/污染。

【讨论】:

    【解决方案2】:

    不幸的是,捆绑包的连接在这里不起作用,b/c webpack 正在使用全局变量。由 alpha-bundle 创建的变量将被 beta-bundle 的变量覆盖。

    您可以在包中重命名此变量,也可以使用 [1] 并使用 --single-bundle 开关。

    要开始使用,请忘记自述文件中关于外部的内容。这是进一步的优化技术,主机、alpha 和 beta 可以共享相同的库。这可以防止您多次加载 Angular。

    也许,我的blog series about Angular Elements 对你来说也很有趣 [2]。

    最好的祝愿, 曼弗雷德

    [1]https://github.com/manfredsteyer/ngx-build-plus

    [2]https://www.softwarearchitekt.at/post/2018/07/13/angular-elements-part-i-a-dynamic-dashboard-in-four-steps-with-web-components.aspx

    【讨论】:

    • 我不确定 --single-bundle 开关存在于哪里,它是用于角度还是 webpack 功能?谷歌搜索没有产生任何相关结果。至于 webpack 变量,我假设它是在 github.com/angular/angular/issues/23732 中引用的 webpackJsonp 变量。我刚刚放置了构建后脚本,以将每个包中的这个变量重命名为“唯一”名称,并且我能够在一个 Angular 项目中托管两个单独构建和捆绑的 Angular Web 组件。我会看看你的博客文章系列!我希望在 v7 中我们能有一种正式的方式来做到这一点。
    • 发布后,我意识到--single-bundle开关存在于ngx-build-plus lib中。
    • 这节省了我很多时间,因为我正在研究一些非常奇怪的解决方案(请参阅github.com/angular/angular/issues/35429)。我所要做的就是添加 ngx-build-plus 并使用 --single-bundle 选项能够在同一页面上运行 2 个不同的外部 Angular 元素(v 10.1.2)。非常感谢曼弗雷德,我简直不敢相信让这个工作变得如此容易:)
    【解决方案3】:

    我使用Manfred Steyer 建议并且它有效,所以我将在这里通过提供更详细的工作示例来开发他的答案(基于我的案例 - Angular 8,我在 MacOs 上做):

    在您的 alpha web-commponent(这是单独的 Angular 项目 <alpha>)上运行以下命令

    npm install ngx-build-plus -S
    ng update ngx-build-plus --force
    ng add ngx-build-plus
    ng g ngx-build-plus:wc-polyfill
    ng g ngx-build-plus:externals
    

    (这将在您的主项目目录中创建文件 webpack.externals.js)然后在 package.json 上的键 scripts 我添加/编辑键:

    "build:alpha:externals": "ng build --output-hashing none --extra-webpack-config webpack.externals.js --prod --single-bundle true --project alpha && cat dist/alpha/polyfill-webcomp-es5.js dist/alpha/polyfills-es5.js dist/alpha/scripts.js dist/alpha/main-es5.js > dist/alpha.js"
    

    现在我通过以下方式构建 Web 组件:

    npm run build:alpha:externals
    

    这将创建文件 dist/alpha.js - 与构建 beta.js 的方式相同(在 beta 项目中) - 在您的 host 中,您可以将两者都添加到您的 index.html 通过

    <head>
    ...
      <script src="./assets/web-components/alpha.js" type="text/javascript"></script>
      <script src="./assets/web-components/beta.js" type="text/javascript"></script>
    ...
    </head>
    

    两者应该同时工作

    【讨论】:

      猜你喜欢
      • 2020-04-08
      • 1970-01-01
      • 2018-11-10
      • 2019-07-19
      • 1970-01-01
      • 2019-05-19
      • 2016-05-07
      • 2020-03-12
      • 2022-01-23
      相关资源
      最近更新 更多