Angular 2+ can't find Angular 1.X to bootstrap

2020-02-05 12:03发布

问题:

I'm trying to bootstrap an Angular 1.X app with Angular 2+ (Angular 4.1.0 at the time of writing this question). I followed the online guide to the T but can't seem to make headway.

I'm using a hybrid of ES2015+ (compiled via Babel) and TypeScript. Everything compiles correctly and I can run both Angular 1 and Angular 2 separately successfully. They get compiled together using Webpack if that makes a difference.

Here's what my Angular 1.X entry file (app.ts) approximately looks like:

import * as angular from 'angular';

export default angular.module('app', [])
  .run(function() { console.log('Angular 1 is running!')})

For simplicity sake, I deleted all dependencies from the main application so that I can be sure it's not the run/config function or one of the dependencies. I have tested with config/run functions to see if any of those run or throw errors but they don't.

I then have an entry file for my Angular 2+ app (that I use as an entry file for Webpack as well) called main.ts which looks like this:

import 'core-js/es7/reflect';
import 'zone.js';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';

import app from '../app/app';

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule).then(platformRef => {
  console.log('angular 2+ bootstrapped');
  const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
  console.log('getting update module');
  console.log('app', app)
  upgrade.bootstrap(document.body, [app.name], { strictDi: true})
   console.log('should be bootstrapped')
})

The process fails after the console.log('app', app) line. The log shows that app is, indeed, an instance of the Angular 1.X app. But the bootstrap process still fails.

Any ideas on what I'm not doing right?

EDIT

Here is my app.module file:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static';

import { AppComponent } from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    UpgradeModule
  ],
  declarations: [
    AppComponent
  ],
  entryComponents: [
    AppComponent
  ]
})
export class AppModule {
  constructor(protected upgrade: UpgradeModule) {}
  ngDoBootstrap() {
  }
};

EDIT2

My hunch is that Angular 2+ depends on AngularJS 1.X to be already on the window object. I'm running AngularJS 1.X from within a module. I'll update as I work on it. I answered a few comments below. Currently, I'm using as simple of an example as possible and for AngularJS 1.X, I'm literally running a barebones app that logs out if it's been bootstrapped via .run

EDIT 3

I posted an answer below. What it boiled down to was the ordering of imports in the main.ts file (the entry file). Simply importing the AngularJS 1.X app before importing zone.js fixed the issue.

回答1:

I hate to answer my own question (and thus not give credit to everyone that helped, thank you!) but here is what fixed it.

I changed the order of imports in main.ts the entry file! :)

Here's what the new version looks like:

import app from '../app/app.temp';

import 'core-js/es7/reflect';
import 'zone.js';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule).then(platformRef => {
  console.log('angular 2+ bootstrapped');
  const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
  console.log('getting update module');
  console.log('app', app)
  upgrade.bootstrap(document.body, [app.name], { strictDi: true})
   console.log('should be bootstrapped')
})

I basically just had to import the AngularJS 1.X app before zone.js. I'm not sure why that is but it worked flawlessly.

EDIT

I filed an issue on Angular's repo and got an "official" answer. It works on 4.1.0-rc.0 and above. There is a method to manually set a reference to AngularJS instead of having the system try to get it from the window object. As it is, AngularJS seems to attach itself to window when it runs even when it's bundled; however, it does so "too late" (which is why my fix works).

So here's what you can do:

import { setAngularLib } from '@angular/upgrade/static';
import * as angular from 'angular';

setAngularLib(angular);
// do your bootstrap here