You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Angular Element组件导出为模块,支持多框架ES模块导入

将Angular Element组件导出为ES模块以支持跨框架导入

核心思路

要让组件支持import语法,需要调整项目打包配置输出ES模块格式,同时重构代码暴露可导入的API,而非依赖全局window对象。

步骤1:调整TypeScript与打包配置

首先修改tsconfig.json,确保编译目标和模块格式符合ES标准:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "declaration": true, // 生成类型声明文件,支持TypeScript项目
    "outDir": "./dist",
    "strict": true
  },
  "angularCompilerOptions": {
    "enableIvy": true // 推荐使用Ivy提升打包效率
  }
}

接着修改angular.json的build配置,指定输出ES模块:

"architect": {
  "build": {
    "builder": "@angular-devkit/build-angular:browser",
    "options": {
      "outputPath": "dist/acme-survey-widget",
      "outputType": "module", // 关键:输出ES模块而非IIFE
      "singleBundle": true, // 将组件打包为单个文件
      "index": false, // 不需要生成HTML入口
      "polyfills": "src/polyfills.ts",
      "tsConfig": "tsconfig.json",
      "assets": [],
      "styles": [],
      "scripts": []
    },
    "configurations": {
      "production": {
        "budgets": [],
        "outputHashing": "none"
      }
    }
  }
}

步骤2:重构代码暴露可导入API

不再将方法挂在window上,而是创建一个可导出的模块类,并对外暴露初始化方法。创建src/public-api.ts作为对外API入口:

import { Injector, NgModule } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { SurveyComponent } from './survey/survey.component';

@NgModule({
  declarations: [SurveyComponent],
  imports: [],
  providers: [],
  entryComponents: [SurveyComponent]
})
export class AcmeWidgetModule {
  /**
   * 初始化组件并注册自定义元素
   * @param options 组件配置参数
   * @param injector 可选:外部传入的Angular注入器(用于Angular项目集成)
   */
  static initWidget(options: any, injector?: Injector) {
    console.log('options received', options);
    // 这里可以添加配置参数的处理逻辑

    // 使用传入的注入器或创建新的注入器
    const usedInjector = injector || Injector.create({ providers: [] });
    
    // 避免重复注册自定义元素
    if (!customElements.get('acme-survey')) {
      const surveyElement = createCustomElement(SurveyComponent, { injector: usedInjector });
      customElements.define('acme-survey', surveyElement);
    }
  }
}

// 导出简化的初始化方法,方便直接调用
export const initAcmeWidget = AcmeWidgetModule.initWidget;

步骤3:配置package.json

在项目根目录的package.json中添加模块入口和类型声明配置,确保包管理器能识别ES模块:

{
  "name": "acme-survey-widget",
  "version": "1.0.0",
  "main": "dist/acme-survey-widget/main.js", // CommonJS入口(兼容Node环境)
  "module": "dist/acme-survey-widget/main.js", // ES模块入口
  "types": "dist/acme-survey-widget/public-api.d.ts", // TypeScript类型声明
  "files": [
    "dist/**/*" // 指定发布到npm的文件范围
  ],
  "keywords": ["angular-element", "web-component", "survey"],
  "author": "",
  "license": "MIT"
}

步骤4:打包并在跨框架中使用

执行打包命令:

ng build --configuration production

Angular项目中使用

import { initAcmeWidget } from 'acme-survey-widget';
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

// 在AppModule初始化时调用
initAcmeWidget({ test: "Hello Angular" });

@NgModule({
  schemas: [CUSTOM_ELEMENTS_SCHEMA] // 允许使用自定义元素
})
export class AppModule {}

模板中直接使用:

<acme-survey></acme-survey>

React项目中使用

import { useEffect } from 'react';
import { initAcmeWidget } from 'acme-survey-widget';

function App() {
  useEffect(() => {
    // 组件挂载时初始化
    initAcmeWidget({ test: "Hello React" });
  }, []);

  return (
    <div className="App">
      <acme-survey></acme-survey>
    </div>
  );
}

export default App;

Vue项目中使用

<template>
  <div>
    <acme-survey></acme-survey>
  </div>
</template>

<script setup>
import { onMounted } from 'vue';
import { initAcmeWidget } from 'acme-survey-widget';

onMounted(() => {
  initAcmeWidget({ test: "Hello Vue" });
});
</script>

内容的提问来源于stack exchange,提问作者Vikash Rathee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 23:37:45