在 angular 项目中使用多个 angular 元素作为 Web 组件
Using multiple angular elements as web components within an angular project
给定三个@angular 项目都使用 v6.1.9:host
、alpha
和 beta
alpha
和 beta
使用 @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
}
alpha
和 beta
是使用 ng build --prod --output-hashing none
构建的,然后 post 构建脚本 运行 按以下顺序连接生成的文件:scripts.js, styles.js, runtime.js, main.js
。
polyfills.js 被跳过,因为 main.ts
将检查在加载库时是否已经定义了使用的 polyfill(例如避免尝试重新定义 zones.js)。
生成的包是 alpha-component.bundle.js
和 beta-component.bundle.js
。
host
使用 <script defer>
标签在 index.html
的 <head>
中引用上述捆绑包。
如果按 alpha
然后 beta
的顺序引用包,我将看到 alpha
尝试 bootstrap 两次;以相反的顺序,我会看到 beta
尝试 bootstrap 两次。
由于第一个引用的 bundle 尝试 bootstrap 两次,它尝试为 bundle 定义 web 组件两次,导致错误,并且从未注册第二个引用的 bundle 的 web 组件。
目标是能够使用@angular 创建许多 Web 组件,然后在其他@angular 或 insert framework here
技术中使用它们。
不幸的是,捆绑包的连接在这里不起作用,b/c webpack 使用全局变量。 alpha 包创建的变量将被 beta 包的变量覆盖。
您可以在捆绑包中重命名此变量,或者您可以使用 [1],它是 --single-bundle 开关。
开始之前,忘记自述文件中关于外部的内容。这是进一步的优化技术,主机、alpha 和 beta 可以共享相同的库。这会阻止您多次加载 Angular。
也许,我的 blog series about Angular Elements 对你来说也很有趣 [2]。
最良好的祝愿,
曼弗雷德
我使用 建议并且它有效,所以我将通过提供更详细的工作示例来开发他的答案(基于我的案例 - Angular 8,我在 MacOs 上做):
在您的 alpha
网络组件上(它是单独的 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
I add/edit 键:
"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>
两者应该同时工作
我使用 angular 自定义构建器导出构建的 angular 捆绑包,并使用 angular 构建器的自定义 webpack 配置导出具有唯一命名空间的捆绑包。
安装@angular-builders/custom-webpack包
创建自定义 webpack 配置文件。例如。 额外-webpack.config.js.
module.exports = {
output: {
chunkLoadingGlobal: 'webpackChunkModuleName',
library: 'ModuleName'
}
为 chunkLoadingGlobal 和库提供您的应用程序名称或任何唯一名称。
注意:这些属性根据 angular 12+ 中使用的 webpack 5。旧版本的 webpack 请参考 webpack 文档。
- 使用 @angular-builders/custom-webpack 作为构建器代替 @angular-devkit/build-angular 并添加 [=23= angular.json.
中的 ]customWebpackConfig 对象
"builder": "@angular-builders/custom-webpack:browser",
.....
"customWebpackConfig": {
"path": "extra-webpack.config.js",
"mergeStrategies": {
"externals": "prepend"
}
}
- 现在,当您 运行 ng 构建时,您的应用程序将使用自定义构建器和自定义 webpack 配置来构建。导出为 Web 组件的其他应用程序的类似配置和多个 Web 组件可以在同一个容器应用程序中使用,没有任何错误或命名空间 collisions/contamination.
给定三个@angular 项目都使用 v6.1.9:host
、alpha
和 beta
alpha
和 beta
使用 @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
}
alpha
和 beta
是使用 ng build --prod --output-hashing none
构建的,然后 post 构建脚本 运行 按以下顺序连接生成的文件:scripts.js, styles.js, runtime.js, main.js
。
polyfills.js 被跳过,因为 main.ts
将检查在加载库时是否已经定义了使用的 polyfill(例如避免尝试重新定义 zones.js)。
生成的包是 alpha-component.bundle.js
和 beta-component.bundle.js
。
host
使用 <script defer>
标签在 index.html
的 <head>
中引用上述捆绑包。
如果按 alpha
然后 beta
的顺序引用包,我将看到 alpha
尝试 bootstrap 两次;以相反的顺序,我会看到 beta
尝试 bootstrap 两次。
由于第一个引用的 bundle 尝试 bootstrap 两次,它尝试为 bundle 定义 web 组件两次,导致错误,并且从未注册第二个引用的 bundle 的 web 组件。
目标是能够使用@angular 创建许多 Web 组件,然后在其他@angular 或 insert framework here
技术中使用它们。
不幸的是,捆绑包的连接在这里不起作用,b/c webpack 使用全局变量。 alpha 包创建的变量将被 beta 包的变量覆盖。
您可以在捆绑包中重命名此变量,或者您可以使用 [1],它是 --single-bundle 开关。
开始之前,忘记自述文件中关于外部的内容。这是进一步的优化技术,主机、alpha 和 beta 可以共享相同的库。这会阻止您多次加载 Angular。
也许,我的 blog series about Angular Elements 对你来说也很有趣 [2]。
最良好的祝愿, 曼弗雷德
我使用
在您的 alpha
网络组件上(它是单独的 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
I add/edit 键:
"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>
两者应该同时工作
我使用 angular 自定义构建器导出构建的 angular 捆绑包,并使用 angular 构建器的自定义 webpack 配置导出具有唯一命名空间的捆绑包。
安装@angular-builders/custom-webpack包
创建自定义 webpack 配置文件。例如。 额外-webpack.config.js.
module.exports = { output: { chunkLoadingGlobal: 'webpackChunkModuleName', library: 'ModuleName' }
为 chunkLoadingGlobal 和库提供您的应用程序名称或任何唯一名称。
注意:这些属性根据 angular 12+ 中使用的 webpack 5。旧版本的 webpack 请参考 webpack 文档。
- 使用 @angular-builders/custom-webpack 作为构建器代替 @angular-devkit/build-angular 并添加 [=23= angular.json. 中的 ]customWebpackConfig 对象
"builder": "@angular-builders/custom-webpack:browser", ..... "customWebpackConfig": { "path": "extra-webpack.config.js", "mergeStrategies": { "externals": "prepend" } }
- 现在,当您 运行 ng 构建时,您的应用程序将使用自定义构建器和自定义 webpack 配置来构建。导出为 Web 组件的其他应用程序的类似配置和多个 Web 组件可以在同一个容器应用程序中使用,没有任何错误或命名空间 collisions/contamination.