Angular1.6与Angular5共存迁移咨询:无需改旧代码且可独立运行
Hey there, great question! Running AngularJS 1.6 and Angular 5 side-by-side without modifying your legacy code is totally feasible using Angular's official UpgradeModule. Let me break down a complete implementation for you, including project structure, Grunt build setup, and how to run both apps independently.
We'll leverage Angular's UpgradeModule to bootstrap both AngularJS 1.6 and Angular 5 in the same page. The legacy AngularJS code stays 100% untouched, while the new Angular 5 app can coexist or even interact with it (if needed). We'll also set up separate entry points to run each app independently.
Here's a clean, maintainable structure that keeps legacy and new code completely separated:
angular-hybrid-project/ ├── legacy/ # Your unmodified AngularJS 1.6 codebase │ ├── app/ │ │ ├── controllers/ │ │ ├── directives/ │ │ ├── services/ │ │ └── app.js # Original AngularJS entry module │ ├── index.html # Pure AngularJS standalone entry │ └── assets/ # CSS, images, etc. for legacy app ├── ng5-app/ # Angular 5 application code │ ├── src/ │ │ ├── app/ │ │ │ ├── app.module.ts │ │ │ ├── app.component.ts │ │ │ └── upgrade/ # Upgrade bridge code │ │ │ └── upgrade.module.ts │ │ ├── index.html # Hybrid app entry (both frameworks) │ │ └── main.ts # Angular 5 bootstrap entry │ └── tsconfig.json ├── Gruntfile.js # Unified build configuration ├── package.json └── .gitignore
1. Unmodified AngularJS 1.6 Code
Your legacy app.js stays exactly as-is:
// legacy/app/app.js angular.module('legacyApp', []) .controller('LegacyController', function($scope) { $scope.legacyMessage = "Hello from AngularJS 1.6!"; });
2. Angular 5 Upgrade Bridge
Create an upgrade module to bootstrap both frameworks:
// ng5-app/src/app/upgrade/upgrade.module.ts import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { UpgradeModule } from '@angular/upgrade/static'; import { AppComponent } from '../app.component'; // Declare global AngularJS variable for TypeScript declare var angular: any; @NgModule({ imports: [ BrowserModule, UpgradeModule ], declarations: [AppComponent], bootstrap: [AppComponent] }) export class UpgradeAppModule { constructor(private upgrade: UpgradeModule) {} ngDoBootstrap() { // Bootstrap the legacy AngularJS app alongside Angular 5 this.upgrade.bootstrap(document.body, ['legacyApp'], { strictDi: true }); } }
3. Angular 5 Entry Point
Update main.ts to use the upgrade module:
// ng5-app/src/main.ts import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { UpgradeAppModule } from './app/upgrade/upgrade.module'; import 'core-js/es6'; import 'core-js/es7/reflect'; import 'zone.js/dist/zone'; platformBrowserDynamic().bootstrapModule(UpgradeAppModule);
4. Entry HTML Files
Pure AngularJS Entry (legacy/index.html)
Keep your original legacy entry:
<!DOCTYPE html> <html ng-app="legacyApp"> <head> <meta charset="UTF-8"> <title>Pure AngularJS 1.6 App</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script> <script src="app/app.js"></script> </head> <body ng-controller="LegacyController"> <h1>{{ legacyMessage }}</h1> </body> </html>
Hybrid Entry (ng5-app/src/index.html)
Load AngularJS first, then bootstrap Angular 5:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hybrid AngularJS + Angular 5 App</title> <!-- Load AngularJS dependencies --> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script> <!-- Load unmodified legacy code --> <script src="../../legacy/app/app.js"></script> <!-- Load Angular 5 polyfills --> <script src="assets/shim.min.js"></script> <script src="assets/zone.js"></script> </head> <body> <!-- Angular 5 component --> <app-root></app-root> <!-- Unmodified AngularJS component --> <div ng-controller="LegacyController"> <h2>{{ legacyMessage }}</h2> </div> </body> </html>
1. Package Dependencies
Add these to your package.json:
{ "name": "angular-hybrid-app", "version": "1.0.0", "devDependencies": { "grunt": "^1.0.4", "grunt-contrib-copy": "^1.0.0", "grunt-contrib-connect": "^3.0.0", "grunt-contrib-watch": "^1.1.0", "grunt-ts": "^6.0.0-beta.22", "typescript": "^2.9.2" }, "dependencies": { "@angular/common": "^5.2.11", "@angular/compiler": "^5.2.11", "@angular/core": "^5.2.11", "@angular/platform-browser": "^5.2.11", "@angular/platform-browser-dynamic": "^5.2.11", "@angular/upgrade": "^5.2.11", "core-js": "^2.5.7", "rxjs": "^5.5.12", "zone.js": "^0.8.29" } }
2. Gruntfile.js Setup
Configure tasks for building, running the pure legacy app, and running the hybrid app:
module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), // Compile TypeScript for Angular 5 ts: { default: { tsconfig: './ng5-app/tsconfig.json' } }, // Copy static assets to dist folder copy: { ng5Assets: { files: [ { expand: true, cwd: 'ng5-app/src', src: ['index.html'], dest: 'dist/ng5' }, { expand: true, cwd: 'node_modules/core-js/client', src: ['shim.min.js'], dest: 'dist/ng5/assets' }, { expand: true, cwd: 'node_modules/zone.js/dist', src: ['zone.js'], dest: 'dist/ng5/assets' }, { expand: true, cwd: 'node_modules/@angular', src: ['**/*.umd.min.js'], dest: 'dist/ng5/assets/angular' } ] }, legacyAssets: { files: [ { expand: true, cwd: 'legacy', src: ['**/*'], dest: 'dist/legacy' } ] } }, // Development servers connect: { legacy: { options: { port: 8080, base: 'dist/legacy', livereload: true } }, hybrid: { options: { port: 8081, base: 'dist/ng5', livereload: true } } }, // Watch for file changes watch: { ts: { files: ['ng5-app/src/**/*.ts'], tasks: ['ts', 'copy:ng5Assets'], options: { livereload: true } }, legacy: { files: ['legacy/**/*'], tasks: ['copy:legacyAssets'], options: { livereload: true } } } }); // Load plugins grunt.loadNpmTasks('grunt-ts'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.loadNpmTasks('grunt-contrib-watch'); // Custom tasks grunt.registerTask('build', ['ts', 'copy']); grunt.registerTask('run-legacy', ['build', 'connect:legacy', 'watch:legacy']); grunt.registerTask('run-hybrid', ['build', 'connect:hybrid', 'watch:ts']); };
- Install dependencies: Run
npm install - Run pure AngularJS app: Execute
grunt run-legacy, then visithttp://localhost:8080 - Run hybrid app: Execute
grunt run-hybrid, then visithttp://localhost:8081
Both apps run independently, and your legacy AngularJS code remains completely unmodified.
- Ensure your AngularJS module name matches what's referenced in the
UpgradeAppModule - TypeScript's
tsconfig.jsonshould target ES5 and use CommonJS modules for Angular 5 compatibility - If you don't need interaction between the two frameworks, they'll run entirely independently in the same page
内容的提问来源于stack exchange,提问作者Satzz

