【问题标题】:Build angular element from existing project从现有项目构建角度元素
【发布时间】:2023-04-02 08:03:01
【问题描述】:

我们有一个现有的 Angular 8 项目,其中包括一堆通用组件(如自定义 datepickers, numeric inputs, ...)。该项目本身是一个标准的 Angular 应用程序。

我们希望将其中一些组件提取为 Angular 元素,以便它们可以在其他 Angular 应用程序甚至其他与 Angular 无关的项目中使用。

是否可以在生成的 JavaScript 文件中只包含特定于单个 Angular 元素的代码来构建项目?

我需要的是这样的: ng build --element myDatePicker

这应该为 myDatePicker-Element 生成所有 JavaScript 文件,仅包含所有需要的依赖项,但不包含项目中的任何其他代码(如其他 components, modules, ...)。

当我使用ng build 时,整个应用程序仍应正常构建。

【问题讨论】:

    标签: angular angular-cli angular-elements


    【解决方案1】:

    我写过一篇文章:https://micklawitzke.medium.com/build-web-components-out-of-an-existing-angular-app-with-angular-elements-7dacf84b2fb3

    基本上,您需要为要在 Angular 项目中提取的每个 Web 组件使用另一个应用程序。首先向您的项目添加一个新应用:

    ng generate application MyWebComponent --routing=false --skipInstall=true
    

    现在您在新生成的projects 文件夹中有了第二个应用程序。这个新应用程序将是 Web 组件/Angular 元素。在那里你可以从你的基础应用中导入你想要的一切。

    然后您可以像往常一样使用ng startng build --prod 构建您的基础应用程序,因为它在 angular.json 中定义为默认项目,并通过引用其名称对每个 Web 组件应用程序执行相同操作,在此例如:ng start MyWebComponentng build MyWebComponent --prod

    【讨论】:

      【解决方案2】:

      我建议你看看Angular Elements,更具体地说是createCustomElement。这将帮助您准确地实现您所需要的。

      我可以给你一个简短的指南,告诉你你可以做什么。

      My Github Repo for example

      1) 首先是安装@angular/elements

      npm i @angular/elements --save

      2) 此步骤包括修改您的app.module.ts。如果您只想构建一组选定的组件(自定义日期选择器、数字输入等),您将不得不暂时删除 bootstrap: [ ] 并将其替换为 @ 987654327@。在 entryComponents 中,您将放置您想要构建的自定义组件。

      entryComponents: [MyCustomDatePickerComponent, CustomButtonComponent]
      

      3) 现在是时候告诉 Angular 引导您的自定义组件了。您还必须为自定义组件定义选择器。您将在注入它们的任何其他应用程序中使用该选择器调用它们。例如:<my-button-element></my-button-element>

      export class AppModule {
      
        constructor(private injector: Injector) {}
      
        ngDoBootstrap() {
          const el = createCustomElement(CustomButtonComponent,
            { injector: this.injector });
          customElements.define('my-button-element', el);
          const el2 = createCustomElement(MyCustomDatePickerComponent,
            { injector: this.injector });
          customElements.define('custom-date-picker', el2);
        }
      }
      

      4) 构建组件 - 如果您运行ng build --prod,您将获得多个文件。我们希望将这些文件合并为一个,以便更轻松地使用和注入我们构建的自定义元素。有两个软件包可以帮助我们做到这一点。 npm install --save-dev concat fs-extra

      在您的应用程序的root 中创建一个elements-build.js 并粘贴它。 (它会将构建输出合并到一个.js.css 文件中,并将它们放在root/elements 文件夹中。

      const concat = require('concat');
      const fs = require('fs-extra');
      
      (async function build() {
        // Instead of /CustomElements/ put your project name - just check a dist folder to see how its formatted and make it that way
        const files = [
          './dist/CustomElements/runtime-es2015.js',
          './dist/CustomElements/polyfills-es2015.js',
          './dist/CustomElements/main-es2015.js'
        ];
      
        await fs.ensureDir('elements');
        await concat(files, 'elements/myCustomElements.js');
        await fs.copyFile(
          './dist/CustomElements/styles.css',
          'elements/styles.css'
        );
      })();
      

      5) 在你的 package.json 添加

      "build:elements": "ng build --prod --output-hashing none && node elements-build.js",
      

      6) 就是这样。您已经构建了自定义元素,并且可以在其他 Angular 应用程序甚至非 Angular 应用程序中的任何地方重用它们。您唯一需要做的就是导入您刚刚创建的.js.css。您甚至可以像往常一样使用 Input() 和 Output()。

      <custom-date-picker dateTitle="My Date Title"></custom-date-picker>

      注意: 如果您决定将它导入另一个 Angular 应用程序,您可能会遇到zone.js 的问题,因为它将被导入两次。解决方案是只导入一次(无论是从核心应用程序还是自定义元素)。

      【讨论】:

      • 这并不能真正解决我的问题。我知道如何创建一个角度元素。我的问题是我想以这个自定义组件为起点进行构建。这将导致一个仅包含元素和所需依赖项的包。目前我能看到的唯一方法是为每个组件创建一个自己的 Angular-Library。
      • 首先我不知道你为什么将多个组件捆绑到一个文件中,这不是被问到的。此外,我认为答案不能回答问题,因为它显示了如何创建自定义元素,但没有显示如何保留应用程序并具有单独的自定义元素构建命令。我对你的回答投了反对票。
      【解决方案3】:

      为了组件的可重用性,您可以将组件提取到“通用”npm 依赖项中。 Angular 文档可在此处找到:https://angular.io/guide/creating-libraries

      请记住,您必须构建您的库项目,然后将包发布到 npm 注册表(公共注册表或私有注册表)上以用作依赖项。

      要在 Angular 之外使用您的 Angular 组件,您可以使用 Angular Elements 将您的组件转换为标准 WebComponents (https://angular.io/guide/elements)。

      请记住,您仍然需要某种构建管道来将 Angular 代码转换为 JS。

      【讨论】:

      • 我真的很想听听可重用性和 Angular Elements 部分是如何协同工作的,以及这种“某种构建管道”。不幸的是,这个答案太高级了,对我没有任何帮助。
      • @KevinBeal 一个 gitlab CI/Jenkins 管道/一个执行 ng build 的人,cd 进入构建的文件夹,npm publish 你的包。这将生成可用的 html/js/css 文件。
      【解决方案4】:

      将 angular 组件添加到非 Angular 应用程序有点棘手,并且有一些缺点。您甚至可能想考虑在没有 Angular 的情况下创建某些组件,然后将它们导入到 Angular 项目中,而不是反过来。

      我有一个 Angular 项目(项目 A)和一个 jquery 项目(项目 B),我想在两者之间共享一个组件。我可以通过创建一个简单的框架(没有路由器,没有额外的依赖项)项目(项目 C)并将组件从项目 A 迁移到 C 来做到这一点。项目 A 从 C 中使用组件相对简单,因为它们都是有角度的.这是在 Angular 6 之前。现在在 Angular 6 左右,他们甚至创建了一个 ng generate library command in the CLI。另请查看此答案here 了解更多信息。

      Angular 有一些要求,当您构建应用程序时,它会在 dist 文件夹中为 shim、Angular 框架、供应商包和您的共享组件代码创建一些文件。如果您的共享组件被您的非 Angular 应用程序使用,您将需要引用这些文件,因为您的组件是用 Angular 编写的,因此需要 Angular 的存在才能运行。此时,您不妨将 Angular 添加到您的非 Angular 应用程序中。我从我的 jQuery 应用程序中执行此操作,然后结合使用发送 custom events 和通过 Rxjs 在 Angular 中接收事件。

      【讨论】:

      • 那是如何共享组件的一种方式,但不是被问到的。他想将他现有的组件构建为可用于任何 Web 项目的 Web 组件。
      【解决方案5】:

      你需要做很多事情 我建议阅读此here

      我还建议为您要导出的那些共享组件创建一个新项目。

      然后在您现有的项目中使用它们作为元素。 (您需要为组件引用 javascript、css 文件和 html 标记)。比如这样

          <link rel="stylesheet" href="https://xybot-v1-dev.web.app/dist/dlx-styles-1.0.css">
      
          <dlx-chat-fab 
            bot-name="Condo Bot" 
            popup-text="Hi I am your virtual concierge." 
            theme="blue_deep-orange" 
            agent="condo-dev">
          </dlx-chat-fab>
      
           <script type="text/javascript" src="https://xybot-v1-dev.web.app/dist/dlx-chatbot-1.0.js"></script>
      
      

      你应该没事的。

      【讨论】:

        【解决方案6】:

        您正在寻找用于 JavaScript 的模块捆绑器,它可以将小段代码编译成更大更复杂的东西,例如库或应用程序。 试试 RollupJSrollup.js guide

        这些命令假定您的应用程序的入口点名为 main.js,并且您希望将所有导入编译到一个名为 bundle.js 的文件中。

        对于浏览器:

        编译成一个包含自执行函数的

        $ rollup main.js --file bundle.js --format iife

        【讨论】:

        • 其实没有,hw 想构建一个他现有的组件作为一个 web 组件。不捆绑任何东西。
        【解决方案7】:

        您可以创建和发布新库来扩展 Angular 功能。如果您发现需要在多个应用程序中解决相同的问题(或希望与其他开发人员共享您的解决方案),那么您可以使用库。

        生成库的命令是ng generate library my-lib

        库通常包含可重用的代码,这些代码定义了您只需导入到项目中的组件、服务和其他 Angular 工件(管道、指令等)。一个库被打包到一个 npm 包中用于发布和共享,这个包还可以包含原理图,提供直接在项目中生成或转换代码的说明,就像 CLI 使用 ng generate 组件创建通用骨架应用程序一样。例如,与库结合的原理图可以为 Angular CLI 提供生成该库中定义的特定组件所需的信息。

        来源:https://angular.io/guide/creating-libraries

        【讨论】:

        • 他不想创建库。他想将他现有的组件构建为 Web 组件。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-26
        • 2020-03-07
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 2014-04-27
        • 1970-01-01
        相关资源
        最近更新 更多