【问题标题】:Upgrading to an Angular/AngularJS hybrid application: getting typescript errors / AngularJS import errors升级到 Angular/AngularJS 混合应用程序:获取 typescript 错误/AngularJS 导入错误
【发布时间】:2019-07-15 09:30:45
【问题描述】:

我们正在使用增量方法将 AngularJS 应用程序升级到 Angular:我们希望能够在 Angular 中创建新组件并逐个升级现有的 AngularJS 组件,所有这些在过程。

我们使用official documentation 以及几篇关于现实世界应用程序中混合 Angular/AngularJS 应用程序的文章。

这是我们的尝试和我们得到的错误。

上下文

  • AngularJS 1.7.3
  • Angular 6.1.7
  • 打字稿 2.7.2
  • 角度-cli

第一步

  • 升级到 AngularJS 1.7
  • 移除 Grunt 并使用 angular-cli
  • 使用 ngUpgrade(app.module.ts 和 app.module.ajs.ts)

迁移到 Typscript:处理错误

这是官方流程:将.js文件重命名为.ts。

然后我们从 Node require() 转移到 TypeScript 模块加载 (var ... = require --> import ... = require)

理想情况下,我们应该纠正由于使用 TypeScript 编译器而导致的所有打字错误。

TypeScript doc 声明可以进行增量迁移:在开始时容忍 TypeScript 错误,以便在不修改的情况下编译 js 代码(在修复代码)。

为了实现这一点,我们使用 awesome-typescript-loader 而不是 tsc 来获取这些选项:transpileOnlyerrorsAsWarnings(这需要angular-builders/custom-webpack)的使用。

选项允许通过编译,但似乎编译完成了两次:第一次没有错误(警告与否),但第二次有错误......所以构建失败。我们怎样才能只运行第一次编译?


替代尝试:保留 .js 文件,导入和引导时出错

我们还尝试了一种非官方且不寻常的方式来增量迁移 js 代码,即将原始 .js 文件与新的 .ts 文件一起保留。

我们在编译或应用程序加载时遇到了一些错误,这些错误与导入 AngularJS 和模块管理有关。事实上,TypsScript module documentation 声明:

Some libraries are designed to be used in many module loaders, or with no module loading (global variables). These are known as UMD modules. These libraries can be accessed through either an import or a global variable. ... can be used as a global variable, but only inside of a script. (A script is a file with no imports or exports.)

我们注意到了什么:

  • 在 .js 文件中:访问 AngularJS 全局 angular(如果我们删除 require("angular")) - 脚本模式

  • 在 .ts 文件中:我们不能使用 import from angular,否则我们会收到错误 angular.module is undefined - module mode

考虑到这一点,我们使应用程序在浏览器中编译和加载没有错误,但最后:

this.upgrade.bootstrap(document.body, [App])

在 AngularJS 引导时产生错误:

Angular 1.x not loaded !

如何解决这个问题?可能是因为我们没有以TypeScript模块的方式导入AngularJS来避免之前的错误?

官方文档提到angular.IAngularStatic(还是报错)?

我们也可以试试 setAngularJSGlobal()Used when AngularJS is loaded lazily, and not available on window

顺便问一下,调用 bootstrap() 时使用 [App] 或 ["App"] 有什么区别?

...由于我们是这个升级过程的新手,我们可能会做完全错误的事情。感谢您分享您的经验!


配置文件

angular.json

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "newProjectRoot": "acd-banner-multicanal",
    "projects": {
        "acd-banner-multicanal": {
            "root": "",
            "sourceRoot": "src",
            "projectType": "application",
            "architect": {
                "build": {
                    "builder": "@angular-devkit/build-angular:browser",
                    "options": {
                        "outputPath": "target",
                        "index": "src/index.html",
                        "main": "src/main.ts",
                        "tsConfig": "./tsconfig.json",
                        "assets": [
                            "src/i18n",
                            "src/conf/conf.txt",
                            "src/conf/conf_DEFAULT.txt",
                            "src/systemjs.config.js",
                            { "glob": "font-banner*", "input": "./node_modules/elq-font-icon/build/", "output": "/assets/fonts" },
                            "src/assets/images",
                            { "glob": "system.js*", "input": "./node_modules/systemjs/dist/", "output": "/assets" },
                            "src/assets/images",
                            { "glob": "**/*", "input": "./node_modules/tinymce/plugins", "output": "/assets/tinymce/plugins" },
                            { "glob": "**/*", "input": "./node_modules/tinymce/skins", "output": "/assets/tinymce/skins" }

                        ],
                        "styles": [
                            "src/assets/styles/style.less"
                        ],
                        "scripts": [
                            "./node_modules/jquery/dist/jquery.js",
                            "./node_modules/jquery-ui-dist/jquery-ui.js"
                        ]
                    },
                    "configurations": {
                        "production": {
                            "fileReplacements": [
                                {
                                    "replace": "src/environments/environment.ts",
                                    "with": "src/environments/environment.prod.ts"
                                }
                            ],
                            "optimization": true,
                            "aot": true,
                            "buildOptimizer": true
                        }
                    }
                },
                "test": {
                    "builder": "@angular-devkit/build-angular:karma",
                    "options": {
                        "main": "src/test.ts",
                        "polyfills": "src/polyfills.ts",
                        "tsConfig": "src/tsconfig.spec.json",
                        "karmaConfig": "./karma.conf.js",
                        "scripts": [],
                        "styles": [
                            "src/assets/main.less"
                        ],
                        "assets": [
                            "src/i18n",
                            "src/favicon.ico"
                        ]
                    }
                },
                "lint": {
                    "builder": "@angular-devkit/build-angular:tslint",
                    "options": {
                        "tsConfig": [
                            "tsconfig.json",
                            "src/tsconfig.spec.json"
                        ],
                        "exclude": [
                            "**/node_modules/**"
                        ]
                    }
                }
            }
        },
        "acd-ihm-angular-e2e": {
            "root": "e2e/",
            "sourceRoot": "e2e",
            "projectType": "application",
        }
    },
    "defaultProject": "acd-banner-multicanal",
    "schematics": {
        "@schematics/angular:component": {
            "styleext": "less",
            "lintFix": true
        }
    }
}

tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "commonjs",
        "moduleResolution": "node",
        "outDir": "./target",
        "sourceMap": true,
        "experimentalDecorators": true,
        "allowJs": true,
        "baseUrl": "./",
        "lib": [
            "es2017",
            "dom"
        ],
        "noImplicitAny": true,
        "suppressImplicitAnyIndexErrors": true,
        "paths": {
            "angular": ["node_modules/angular/angular"]
        }
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
                "src/**/*.spec.ts"
    ]
}

【问题讨论】:

    标签: angularjs angular typescript upgrade angular-hybrid


    【解决方案1】:

    至于angular 1.x not loaded错误; 你在新应用中安装了 angularJS 吗?

    $ npm install --save angular@1.7.3 \
          @types/angular
    

    angular.json 文件中,您需要包含脚本:

    "scripts": [
        "../node_modules/angular/angular.js",
        //etc...
    ],
    

    Here 是一个升级与您所拥有的应用程序相似的应用程序的示例。

    或者,您可以通过在 main.ts 中导入 Angular 来将其引入导入链;

    import * as angular from 'angular';
    

    这可能是一个更好的选择,因为它使 angular cli / webpack 能够识别 angularJS,并且可以防止在某些其他组件(例如混合路由器导入 angular)时可能出现的诸如“WARNING: Tried to Load Angular More Than Once”之类的错误。

    【讨论】:

    • 确实,将angular.js 添加到angular.json 可以更正angular undefinedAngular 1.x not loaded 错误。我会继续这个过程,谢谢。
    【解决方案2】:

    我确认答案有效,我们已经能够在混合模式下运行我们的应用程序。事实上,在 AngularJs 中,我们使用了 grunt 和 browserify,并且我们已经使用 package.json browser 字段打包了一些库。为此,我们必须在angular.js / build.options.scripts声明要在浏览器中加载的库:

    "scripts": [
        "./node_modules/jquery/dist/jquery.js",
        "./node_modules/jquery-ui-dist/jquery-ui.js",
        "./node_modules/moment/moment.js",
        "./node_modules/bootstrap/dist/js/bootstrap.js",
        "./node_modules/eonasdan-bootstrap-datetimepicker/src/js/bootstrap- datetimepicker.js",
        "./node_modules/bootstrap-tour/build/js/bootstrap-tour.js",
        "./node_modules/angular/angular.js",
        "./node_modules/ng-table/bundles/ng-table.js"`
    ]
    

    非常感谢。

    添加到 Angular 文档中可能有用吗?事实上,https://angular.io/guide/upgrade#bootstrapping-hybrid-applications 中给出的示例是基于 SystemJS,而我们只是使用 Webpack(Angular 已经使用)。

    确实,有一个 issue about the angular doc,迁移文档尚未针对 angular-cli 更新(这就是它与 SystemJS 相关的原因)。

    【讨论】:

      猜你喜欢
      • 2019-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-30
      • 2018-06-10
      • 1970-01-01
      • 2018-09-02
      • 2021-02-04
      相关资源
      最近更新 更多