从现有项目构建angular元素

Build angular element from existing project

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

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

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

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

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

当我使用 ng build.

时,整个应用程序仍应正常构建


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

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

例如我的 Github 存储库

1) 首先是安装@angular/elements

npm i @angular/elements --save

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

1
entryComponents: [MyCustomDatePickerComponent, CustomButtonComponent]

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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 文件夹中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 添加

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

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


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

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

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

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


你需要做很多事情
我建议在这里阅读

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

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

1
2
3
4
5
6
7
8
9
10
    <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">

你应该没事的。


n


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

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

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


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

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

对于浏览器:

编译为包含自执行函数的

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


You can create and publish new libraries to extend Angular functionality. If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.

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

A library typically includes reusable code that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project. A library is packaged into an npm package for publishing and sharing, and this package can also include schematics that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic skeleton app with ng generate component. A schematic that is combined with a library can, for example, provide the Angular CLI with the information it needs to generate a particular component defined in that library.

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