0

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

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

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

语境

  • AngularJS 1.7.3
  • 角 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 文档指出可以进行增量迁移:在开始时容忍 TypeScript 错误,以便在不修改的情况下编译 js 代码(并且在修复代码后更严格)。

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

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


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

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

我们在编译或应用程序加载时遇到了一些错误,这些错误与导入 AngularJS 和模块管理有关。实际上TypsScript 模块文档指出:

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 文件中:我们不能使用import from angular,否则我们会得到错误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"] 有什么区别?

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


配置文件

角.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"
    ]
}
4

2 回答 2

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...
],

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

或者,您可以通过将 Angular 导入到导入链中main.ts

import * as angular from 'angular';

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

于 2019-02-28T08:45:47.717 回答
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 已经使用)。

实际上,关于 angular doc 存在一个问题,迁移文档尚未针对 angular-cli 更新(这就是它与 SystemJS 有关的原因)。

于 2019-05-03T08:49:13.673 回答