升级到Angular / AngularJS混合应用程序:获取typescript错误/ AngularJS导入错误

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

我们正在使用增量方法将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)

转到Typescript:处理错误

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

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

理想情况下,我们应该更正因使用TypeScript编译器而导致的所有输入错误。

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

为了实现这一点,我们使用awesome-typescript-loader而不是tsc来获取这些选项:transpileOnly,errorsAsWarnings(这需要使用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全局角度(如果我们删除require(“angular”)) - 脚本模式
  • 在.ts文件中:我们不能使用从角度导入,否则我们得到错误angular.module is undefined - 模块模式

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

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 hybrid
2个回答
0
投票

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

$ npm install --save [email protected] \
      @types/angular

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

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

Here是一个升级类似于你拥有的应用程序的例子。

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

import * as angular from 'angular';

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


0
投票

我确认答案有效,我们已经能够以混合模式运行我们的应用程序。实际上,在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有关)。

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