如何将Angular 17 Elements组件集成到ASP.NET WebForms应用中?
问题:ASP.NET WebForms集成Angular 17 Elements时出现模块语法错误
我有一个运行.NET 4.5的ASP.NET WebForms应用,参照教程构建了包含Angular Elements和Angular Material Table的Angular 17应用。构建后将生成的JS和样式文件引入WebForms页面,浏览器控制台报错:
Uncaught SyntaxError: Unexpected token 'export' chunk-HH4V2P6H.js:7 Uncaught SyntaxError: Cannot use import statement outside a module chunk-OH42BLK4.js:1 Uncaught SyntaxError: Cannot use import statement outside a module main.js:1
相关配置文件如下:
angular.json 配置
{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "MatTableElements": { "projectType": "application", "schematics": { "@schematics/angular:component": { "style": "scss", "standalone": false }, "@schematics/angular:directive": { "standalone": false }, "@schematics/angular:pipe": { "standalone": false } }, "root": "projects/mat-table-elements", "sourceRoot": "projects/mat-table-elements/src", "prefix": "app", "architect": { "build": { "builder": "@angular-devkit/build-angular:application", "options": { "outputPath": "dist/mat-table-elements", "index": "projects/mat-table-elements/src/index.html", "browser": "projects/mat-table-elements/src/main.ts", "polyfills": [ "zone.js" ], "tsConfig": "projects/mat-table-elements/tsconfig.app.json", "inlineStyleLanguage": "scss", "assets": [ "projects/mat-table-elements/src/favicon.ico", "projects/mat-table-elements/src/assets" ], "styles": [ "@angular/material/prebuilt-themes/indigo-pink.css", "projects/mat-table-elements/src/styles.scss" ], "scripts": [] }, "configurations": { "production": { "budgets": [ { "type": "initial", "maximumWarning": "1500kb", "maximumError": "1mb" }, { "type": "anyComponentStyle", "maximumWarning": "2kb", "maximumError": "4kb" } ], "outputHashing": "none", "optimization": { "scripts": true, "styles": { "minify": true, "inlineCritical": false }, "fonts": true } }, "development": { "optimization": false, "extractLicenses": false, "sourceMap": true } }, "defaultConfiguration": "production" }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", "configurations": { "production": { "buildTarget": "MatTableElements:build:production" }, "development": { "buildTarget": "MatTableElements:build:development" } }, "defaultConfiguration": "development" }, "extract-i18n": { "builder": "@angular-devkit/build-angular:extract-i18n", "options": { "buildTarget": "MatTableElements:build" } }, "test": { "builder": "@angular-devkit/build-angular:karma", "options": { "polyfills": [ "zone.js", "zone.js/testing" ], "tsConfig": "projects/mat-table-elements/tsconfig.spec.json", "inlineStyleLanguage": "scss", "assets": [ "projects/mat-table-elements/src/favicon.ico", "projects/mat-table-elements/src/assets" ], "styles": [ "@angular/material/prebuilt-themes/indigo-pink.css", "projects/mat-table-elements/src/styles.scss" ], "scripts": [] } } } } } }
app.module.ts(非独立组件版本)
import { NgModule, DoBootstrap, Injector, ApplicationRef } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { createCustomElement } from "@angular/elements"; import { ItemAssignmentsComponent } from './item-assignments/item-assignments.component'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { MatTableModule } from '@angular/material/table'; import { MatPaginatorModule } from '@angular/material/paginator'; @NgModule({ declarations: [ ItemAssignmentsComponent ], imports: [ BrowserModule, MatTableModule, MatPaginatorModule ], providers: [ provideAnimationsAsync() ] // entryComponents: [ItemAssignmentsComponent] }) export class AppModule implements DoBootstrap { constructor(private injector: Injector) { const el = createCustomElement(ItemAssignmentsComponent, {injector}); customElements.define('item-assignment', el); } ngDoBootstrap(appRef: ApplicationRef): void { } }
WebForms页面引入代码
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="Server"> <link rel="stylesheet" type="text/css" href="assets/css/moog-default.css" /> <link rel="stylesheet" type="text/css" href="assets/css/moog-layout.css" /> <link rel="stylesheet" type="text/css" href="assets/js/item-data-report/styles.css" /> <script type="text/javascript" src="assets/js/item-data-report/chunk-HH4V2P6H.js"></script> <script type="text/javascript" src="assets/js/item-data-report/chunk-OH42BLK4.js"></script> <script type="text/javascript" src="assets/js/item-data-report/main.js"></script> <script type="text/javascript" src="assets/js/item-data-report/polyfills.js"></script> <item-assignment></item-assignment> </asp:Content>
tsconfig.json
/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "compileOnSave": false, "compilerOptions": { "outDir": "./dist/out-tsc", "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "skipLibCheck": true, "esModuleInterop": true, "sourceMap": true, "declaration": false, "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, "target": "ES2022", "module": "ES2022", "useDefineForClassFields": false, "lib": [ "ES2022", "dom" ] }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, "strictInputAccessModifiers": true, "strictTemplates": true } }
更新:已重构为独立组件,但错误依旧。
解决方案
错误核心原因:Angular 17默认输出ES模块格式,但ASP.NET WebForms的传统脚本引入方式不支持import/export语法。以下两种方案可解决问题:
方案1:修改Angular构建配置,输出兼容传统脚本的IIFE格式
- 打开
angular.json,在projects.MatTableElements.architect.build.options中添加format配置,指定输出格式为iife:
"options": { // 保留原有所有配置 "format": ["iife"] }
- 在
production构建配置中添加singleBundle选项,将所有代码合并为单个文件:
"configurations": { "production": { // 保留原有所有配置 "singleBundle": true } }
- 重新执行生产构建:
ng build --configuration production - 此时
dist目录会生成main.iife.js,只需在WebForms页面引入这一个文件即可,无需引入其他chunk:
<script type="text/javascript" src="assets/js/item-data-report/main.iife.js"></script>
方案2:在WebForms页面声明脚本为ES模块
若不想修改Angular构建配置,可将脚本的type改为module,同时调整加载顺序(polyfills需优先加载):
<script type="module" src="assets/js/item-data-report/polyfills.js"></script> <script type="module" src="assets/js/item-data-report/chunk-HH4V2P6H.js"></script> <script type="module" src="assets/js/item-data-report/chunk-OH42BLK4.js"></script> <script type="module" src="assets/js/item-data-report/main.js"></script>
注意:该方式要求浏览器支持ES模块,若需兼容旧版IE浏览器,优先选择方案1。
额外检查项
- 若需兼容旧浏览器(如IE11),需将
tsconfig.json中的target改为ES5,并添加core-js等必要polyfills。 - 独立组件版本需确保
createCustomElement使用正确:
import { createCustomElement, Injector } from '@angular/elements'; import { ItemAssignmentsComponent } from './item-assignments/item-assignments.component'; import { bootstrapApplication, inject } from '@angular/platform-browser'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; bootstrapApplication(ItemAssignmentsComponent, { providers: [provideAnimationsAsync()] }).then(() => { const el = createCustomElement(ItemAssignmentsComponent, { injector: inject(Injector) }); customElements.define('item-assignment', el); });
内容的提问来源于stack exchange,提问作者ben.kansas
相关产品推荐
相关产品推荐

