在基于 NgModule 的应用程序中从 Angular 5 迁移到 Angular 19

问题描述 投票:0回答:2

我正在将旧的 Angular 项目从版本 5 迁移到版本 19。我已经识别了所有兼容和依赖的库,并且能够迁移代码。但是我不断收到独立错误。

注意:我已经在组件部分尝试过standalone:false。这没有帮助,得到同样的错误。

该项目基于 NgModule,我想按原样使用,而不需要像现在这样的独立功能。

    ng build 
    √ Browser application bundle generation complete.

    Error: src/app/app.module.ts:7:5 - error NG6008: Component AppComponent is standalone, and cannot be declared in an NgModule. Did you mean to import it instead?

    7     AppComponent // Declare AppComponent here

为了深入研究该问题,我根据实际情况创建了最小的项目并重现了该问题。我在 angular.json 中添加了独立的 false,清除缓存,删除了节点模块,验证了 ts 是否没有独立文件。然而,这对我来说已经成为噩梦,因为从过去两天开始我无法修复它。

angular.json

  {
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "newProjectRoot": "projects",
    "projects": {
      "resource-planning": {
        "projectType": "application",
        "root": "src",
        "sourceRoot": "src",
        "prefix": "app",
        "schematics": {
            "@schematics/angular:component": {
            "standalone": false
          }
        },
        "architect": {
          "build": {
            "builder": "@angular-devkit/build-angular:browser",
            "options": {
              "outputPath": "dist/resource-planning",
              "index": "src/index.html",
              "main": "src/main.ts",
              //"polyfills": "src/polyfills.ts",
              "tsConfig": "tsconfig.app.json",
              "aot": true,
              "assets": [
                "src/assets",
                "src/favicon.ico"
              ],
              "styles": [
                "src/styles.css",
                "node_modules/font-awesome/css/font-awesome.min.css",
                "node_modules/primeng/resources/themes/omega/theme.css",
                "node_modules/primeng/resources/primeng.min.css"
              ],
              "scripts": []
            }
          },
          "serve": {
            "builder": "@angular-devkit/build-angular:dev-server",
            "options": {
              "buildTarget": "resource-planning:build"
            },
            "configurations": {
              "production": {
                "buildTarget": "resource-planning:build:production"
              }
            }
          },
          "test": {
            "builder": "@angular-devkit/build-angular:karma",
            "options": {
              "main": "src/test.ts",
              //"polyfills": "src/polyfills.ts",
              "tsConfig": "tsconfig.spec.json",
              "karmaConfig": "./karma.conf.js",
              "styles": [
                "src/styles.css",
                "node_modules/font-awesome/css/font-awesome.min.css",
                "node_modules/primeng/resources/themes/omega/theme.css",
                "node_modules/primeng/resources/primeng.min.css"
              ],
              "scripts": [],
              "assets": [
                "src/assets",
                "src/favicon.ico"
              ]
            }
          },
          "lint": {
            "builder": "@angular-eslint/builder:lint",
            "options": {
              "lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
            }
          }
        }
      }
    }
  }

package.json

  {
    "name": "resource-planning",
    "version": "0.0.0",
    "license": "MIT",
    "scripts": {
      "ng": "ng",
      "start": "ng serve",
      "build": "ng build --prod",
      "test": "ng test",
      "lint": "ng lint",
      "e2e": "ng e2e"
    },
    "private": true,
    "dependencies": {
      "@angular/animations": "^19.0.5",
      "@angular/common": "^19.0.5",
      "@angular/compiler": "^19.0.5",
      "@angular/core": "^19.0.5",
      "@angular/forms": "^19.0.5",
      "@angular/platform-browser": "^19.0.5",
      "@angular/platform-browser-dynamic": "^19.0.5",
      "@angular/router": "^19.0.5",
      "@fortawesome/fontawesome-free": "^6.5.0",
      "core-js": "^3.32.2",
      "ngx-bootstrap": "^19.0.1",
      "primeicons": "^7.0.0",
      "primeng": "^19.0.1",
      "rxjs": "^7.8.0",
      "xlsx": "^0.18.5",
      "zone.js": "~0.15.0"
    },
    "devDependencies": {
      "@angular-devkit/build-angular": "^19.0.6",
      "@angular/cli": "^19.0.5",
      "@angular/compiler-cli": "^19.0.5",
      "@angular/language-service": "^19.0.5",
      "@eslint/config-array": "^0.19.1",
      "@eslint/object-schema": "^2.0.3",
      "@types/jasmine": "^4.5.0",
      "@types/jasminewd2": "^2.0.10",
      "@types/node": "^20.4.0",
      "angular-eslint": "19.0.2",
      "cypress": "^13.0.0",
      "eslint": "^9.16.0",
      "glob": "^9.0.0",
      "rimraf": "^4.0.0",
      "ts-node": "~10.9.1",
      "typescript": "~5.6.0",
      "typescript-eslint": "8.18.0"
    }
  }

app.module.ts

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { AppComponent } from './app.component';

    @NgModule({
    declarations: [
      AppComponent // Declare AppComponent here
    ],
    imports: [
      BrowserModule
    ],
    providers: [],
    bootstrap: [AppComponent]
    })
    export class AppModule { }

app.component.ts

  import { Component } from '@angular/core';

  @Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
  })
  export class AppComponent {
    title = 'My Angular App';
  }

app-routing.module.ts

    import { Routes,RouterModule } from '@angular/router';
    import { NgModule } from '@angular/core';

    @NgModule({
        imports: [
            
        ],
        exports: [RouterModule]
    })
    export class AppRoutingModule {}

main.ts

  import { enableProdMode } from '@angular/core';
  import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

  import { AppModule } from './app/app.module';
  import { environment } from './environments/environment';

  if (environment.production) {
    enableProdMode();
  }

  /*platformBrowserDynamic().bootstrapModule(AppModule)
    .catch(err => console.log(err));
  */

  console.log('App bootstrapping...');
  platformBrowserDynamic().bootstrapModule(AppModule)
    .catch(err => console.error('Error bootstrapping module:', err));
angular ng-modules angular-standalone-components
2个回答
1
投票

尚未准备好独立使用,只是希望我的代码使用非独立组件方法进行编译:

如果您还没有准备好使用独立组件,您所需要做的就是将

standalone: false
添加到所有组件中。这可以使用
vsCode
查找和替换功能轻松实现,因为我们只需添加一个额外的属性:

enter image description here


问题:

在 Angular 19 中,所有组件都是默认的

standalone: true
。如果一个组件是独立的,它必须有自己的导入,并且可以单独工作而不依赖于应用程序的其他部分。我们可以将它们添加到导入数组中来使用它们。


代码修复来解决问题,有两种方法:


如果您想使用独立组件,那么您应该查看以下链接:

将现有的 Angular 项目迁移到独立项目

ng g @angular/core:standalone

帮助您迁移到独立组件的迁移代码。


这里有两个可能的修复方法。

迁移到 Angular 独立方法(推荐):

在这种方法中,您将组件保留为独立组件,并在

main.ts
上进行更改,其中我们使用
bootstrapApplication
来引导组件(默认为独立组件),除此之外,我们还使用
ApplicationConfig
对象来添加提供商:

  • provideHttpClient
    -> 需要 http 客户端在依赖注入中可用。

  • provideAnimations
    -> 需要角度动画才能工作。

    import { bootstrapApplication } from '@angular/platform-browser';
    import { enableProdMode } from '@angular/core';
    import { AppComponent } from './app/app.component';
    import { environment } from './environments/environment';
    import { provideHttpClient } from '@angular/common/http';
    import { provideAnimations } from '@angular/platform-browser/animations';
    
    if (environment.production) {
      enableProdMode();
    }
    
    bootstrapApplication(AppComponent, {
      providers: [
        provideHttpClient(), // <- required for http client to work
        provideAnimations(), // <- required for animations to work
      ]
    })
      .catch(err => console.error('Error bootstrapping module:', err));
    

继续使用模块化方法:

这种方法需要较少的编码工作,我们可以简单地将

AppComponent
设置为
standalone: false
,通过这样做,我们可以使用 appModule 引导它并且它会工作,但是代码的其他部分应该尝试在任何地方使用独立方法需要。通过手动将
standalone
设置为
false
,Angular 会将其视为非独立组件,并使用模块进行引导。

  import { Component } from '@angular/core';

  @Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    standalone: false,
  })
  export class AppComponent {
    title = 'My Angular App';
  }

0
投票

您可以尝试这篇Medium文章中提到的步骤:

  • angular.json
    中的原理图下,添加以下行:

    "schematics": {
        "@schematics/angular: component": {
            "standalone": false
        },
        "@schematics/angular:directive": {
            "standalone": false
    ·   },
        "@schematics/angular: pipe" : {
            "standalone": false
        },
     }
    
  • 删除

    app.config.ts
    app.config.server.ts
    app.routes.ts

  • 添加

    app.routing.module.ts
    并复制
    app.routes.ts
    中的所有路线 前往
    app.routing.module.ts
    的路线。

  • main.ts
    中,替换:

    bootstrapApplication(AppComponent, appConfig).catch((err) =>console.error(err));

    至:

    platformBrowserDynamic().bootstrapModule(AppModule).catch(err =>console.error(err));

    并在此处添加所需的导入。

  • 删除

    main.server.ts
    中的所有内容并粘贴以下行:

    export { AppServerModule as default } from ‘./app/app.module.server’;
    
  • app.module.ts
    @NgModule
    下,providers 数组内,添加 下面一行并导入所需的包:

    provideClientHydration()
    

    在引导数组内,添加以下行并导入所需的包:

    AppComponent
    

    在导入数组中,删除

    CommonModule
    RouterOutlet
    ,然后添加到此行下方并导入所需的包:

    BrowserModule,AppRoutingModule
    
  • 创建一个名为

    app.module.server.ts
    的新文件,其中包含以下行:

     import { NgModule } from '@angular/core';
     import { ServerModule } from '@angular/platform-server';
    
     import { AppModule } from './app.module';
     import { AppComponent } from '../app.component';
    
     @NgModule({
       imports: [
         AppModule,
         ServerModule,
       ],
       bootstrap: [AppComponent],
     })
     export class AppServerModule {}
    
  • 最后在各自的组件文件中,将独立更改为

    false
    并 删除导入数组。

完成后,您可以构建项目然后运行它。

希望这个回答对你有帮助!

请注意,这些步骤是为 Angular 17 量身定制的,但它们应该在很大程度上适用于 Angular 19。因此,您可能需要根据需要针对任何特定于版本的差异进行调整。

© www.soinside.com 2019 - 2024. All rights reserved.