如何使用Angular创建可嵌入各类网站的JS Widget?
用Angular实现可嵌入第三方网站的JS Widget(无需iframe)
完全可以用Angular实现这类Widget,而且不需要依赖iframe就能实现全局调用(比如MyWidget.show())。下面是具体的实现步骤,帮你生成可直接引入的单JS文件:
1. 准备Angular项目与组件
- 创建一个新的Angular项目(建议用Angular 14+,支持独立组件更方便)
- 编写你的目标Widget组件,比如一个简单的聊天弹窗组件
ChatWidgetComponent - 确保组件的样式做了隔离处理,比如使用
ViewEncapsulation.ShadowDom,或者给所有样式类加专属前缀,避免和宿主网站样式冲突
2. 调整Angular构建配置
修改项目根目录下的angular.json,调整build配置,让Angular打包出单文件UMD格式的产物:
"architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/widget", "index": "src/index.html", "main": "src/main.widget.ts", // 专门的Widget入口文件 "polyfills": ["zone.js"], "tsConfig": "tsconfig.widget.json", "assets": [], "styles": ["src/styles.widget.css"], "scripts": [], "singleBundle": true, // 打包成单个文件 "format": ["umd"], // 输出UMD格式,支持全局引入 "outputHashing": "none" // 关闭哈希,方便文件名固定 } } }
同时创建对应的tsconfig.widget.json,配置编译目标为ES5或ES6,确保兼容性:
{ "extends": "./tsconfig.json", "compilerOptions": { "target": "ES5", "module": "UMD", "declaration": false, "outDir": "./dist/widget" }, "include": ["src/main.widget.ts", "src/app/chat-widget/**/*"] }
3. 编写Widget入口逻辑(暴露全局方法)
创建src/main.widget.ts作为Widget的入口,在这里定义全局可调用的方法,比如MyWidget.show():
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { ChatWidgetComponent } from './app/chat-widget/chat-widget.component'; import { createCustomElement } from '@angular/elements'; platformBrowserDynamic().bootstrapModule(ChatWidgetComponent) .then((moduleRef) => { // 挂载全局对象到window (window as any).MyWidget = { show: () => { // 动态创建组件容器 const container = document.createElement('div'); container.classList.add('chat-widget-container'); document.body.appendChild(container); // 渲染组件到容器 moduleRef.instance.render(container); // 也可以用Angular Elements的方式,直接注册自定义标签 // const ChatWidgetElement = createCustomElement(ChatWidgetComponent, { injector: moduleRef.injector }); // customElements.define('chat-widget', ChatWidgetElement); // document.body.appendChild(document.createElement('chat-widget')); }, hide: () => { // 实现隐藏逻辑 const widget = document.querySelector('chat-widget') || document.querySelector('.chat-widget-container'); widget?.remove(); } }; }) .catch(err => console.error(err));
4. 构建并测试
- 执行构建命令:
ng build --configuration production - 构建完成后,
dist/widget目录下会生成一个main.js(或你配置的文件名),这就是可嵌入的单JS文件 - 在第三方网站中引入该脚本,然后调用
MyWidget.show()即可渲染组件:
<script src="path/to/your/widget/main.js"></script> <button onclick="MyWidget.show()">打开聊天组件</button>
关键注意事项
- 样式隔离:推荐使用
ViewEncapsulation.ShadowDom让组件样式完全隔离,不会影响宿主网站 - 兼容性:如果需要兼容旧浏览器,记得添加必要的polyfill(比如
@webcomponents/webcomponentsjs) - 性能优化:可以开启Tree Shaking,移除Angular的冗余代码,减小打包体积
内容的提问来源于stack exchange,提问作者Gregory Boutte
相关产品推荐
相关产品推荐

