single-spa / single-spa-angular

Helpers for building single-spa applications which use Angular
Apache License 2.0
198 stars 78 forks source link

Stuck in version 3.0.1, can't figure out why. #175

Closed mbomfim33 closed 4 years ago

mbomfim33 commented 4 years ago

Question

Hello folks, I'm working on upgrading my POC single-spa from version 3.0.1 to 3.1 or latter, but I'm stuck.

I have 7 applications, and a "main" one which is the one that has single-spa. The ONLY application where this happens, is a Angular 7 app, which is running single-spa-angular at version 3.0.1.

When I access my localhost address, I receive the following error message: Screenshot from 2020-04-16 14-20-19

Environment

 "dependencies": {
    "@angular/animations": "7.1.2",
    "@angular/cli": "7.1.2",
    "@angular/common": "7.1.2",
    "@angular/compiler": "7.1.2",
    "@angular/compiler-cli": "7.1.2",
    "@angular/core": "7.1.2",
    "@angular/forms": "7.1.2",
    "@angular/http": "7.1.2",
    "@angular/platform-browser": "7.1.2",
    "@angular/platform-browser-dynamic": "7.1.2",
    "@angular/router": "7.1.2",
    "@ng-select/ng-select": "2.20.0",
    "@ngx-translate/core": "10.0.1",
    "@ngx-translate/http-loader": "3.0.1"
    "angulartics2": "6.1.0",
    "core-js": "2.5.5",
    "crypto-js": "3.1.9-1",
    "file-saver": "1.3.8",
    "gojs": "1.8.38",
    "jsoneditor": "5.13.2",
    "lodash": "4.17.15",
    "marked": "0.7.0",
    "mixpanel": "0.10.2",
    "mixpanel-browser": "2.28.0",
    "moment": "2.24.0",
    "ng2-file-upload": "1.3.0",
    "ngx-infinite-scroll": "6.0.0",
    "ngx-logger": "3.3.13",
    "ngx-mask": "7.3.5",
    "ngx-toastr": "10.0.4",
    "node-sass": "4.9.3",
    "plotly.js": "1.42.5",
    "qrcode": "1.3.3",
    "rxjs": "6.5.2",
    "rxjs-compat": "6.5.3",
    "ts-md5": "1.2.4",
    "tslib": "1.9.0",
    "url": "0.11.0",
    "uuid": "3.3.2",
    "zone.js": "0.8.26"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "0.11.0",
    "@types/crypto-js": "3.1.39",
    "@types/file-saver": "1.3.0",
    "@types/jasmine": "2.8.8",
    "@types/jasminewd2": "2.0.3",
    "@types/jsoneditor": "5.28.1",
    "@types/lodash": "4.14.129",
    "@types/mixpanel-browser": "2.23.1",
    "@types/node": "10.14.6",
    "@types/uuid": "3.4.3",
    "cypress": "3.4.1",
    "cypress-file-upload": "3.1.0",
    "cypress-plugin-retries": "1.2.2",
    "husky": "1.2.1",
    "is-docker": "2.0.0",
    "jasmine-core": "2.99.1",
    "jasmine-spec-reporter": "4.2.1",
    "karma": "4.0.0",
    "karma-chrome-launcher": "2.2.0",
    "karma-coverage-istanbul-reporter": "2.0.1",
    "karma-helpful-reporter": "0.3.4",
    "karma-jasmine": "1.1.2",
    "karma-jasmine-html-reporter": "0.2.2",
    "lint-staged": "8.1.7",
    "single-spa-angular": "3.1.0",
    "ts-node": "6.1.0",
    "tslint": "5.16.0",
    "typescript": "3.1.6"
  }
}

Libs:
- @angular/core version: 7.1.2
- single-spa-angular version: 3.1.0 and newer

Others:

- It seems that on version 3.0.1, when I check my **Network** tab on Chrome, I receive a webpack bundle. **But**, on version 3.1.0 and newer, I receive an **HTML** file for whatever reason.

joeldenning commented 4 years ago

Unexpected token < means that a URL responded with HTML instead of javascript. You can see this if you go to http://localhost:4210/zone.min.b4afa454.js - it will return an HTML file instead of a javascript file.

Generally speaking, zonejs should be loaded once in your single-spa root config's HTML file, and should not be loaded again by each subsequent application. It seems like perhaps your Angular 7 application is trying to load zone js separately from the root config? If so, the solution would be to only load ZoneJS once in the root config and change the Angular 7 app to not try to load it again. More info about this at https://single-spa.js.org/docs/ecosystem-angular#zonejs

mbomfim33 commented 4 years ago

Hey there, @joeldenning. Thanks for the prompt response. I can confirm that the file zone.min.b4afa454.js file in my localhost:4210, is returning a JS file. And, that there is only one zone.js import (latest version as recommended), and is located at localhost:4210's index.html file.

The problem seems to be on my localhost:4201, which is only returning two files: 0.js, and main.js, both are webpack-bundled js files: Screenshot from 2020-04-20 15-02-28

The funny thing, is that if I rollback to version 3.0.1, it returns all the files bundled: Screenshot from 2020-04-20 14-58-34

All of this, is ignoring cache. BTW, in both cases, this is the result of the npm run start:

> selfservice@1.6.1 serve /home/marco.bomfim/Dev/selfservice
> ng serve --disable-host-check --port 4201 --deploy-url http://localhost:4201/ --live-reload false

WARNING: Running a server with --disable-host-check is a security risk. See https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a for more information.
WARNING: --deploy-url and/or --base-href contain unsupported values for ng serve.  Default serve path of '/' used. Use --serve-path to override.
Your single-spa application can be downloaded at http://localhost:4201/main.js
** Angular Live Development Server is listening on localhost:4201, open your browser on http://localhost:4201/ **

Date: 2020-04-20T18:01:56.658Z
Hash: cdfde7db768c8bbb16c3
Time: 14375ms
chunk {0} 0.js, 0.js.map () 79.7 kB  [rendered]
chunk {1} 1.js, 1.js.map () 86.1 kB  [rendered]
chunk {2} 2.js, 2.js.map () 84.3 kB  [rendered]
chunk {main} main.js, main.js.map (main) 6.46 MB [entry] [rendered]
chunk {scripts} scripts.js, scripts.js.map (scripts) 786 kB  [rendered]
ℹ 「wdm」: Compiled successfully.

You can see that there should be more files returned by the application, and I can't pinpoint exactly what is going on. I would love to provide more information, if that would help somehow.

EDIT: You can see on the latest picture, a file called: "legacy.core.core.module", this file returns a webpack bundle that gets rendered (in version 3.0.1), but in version 3.1.0, it returns an HTML file called core.module. As you can see, even the name comes out wrong.

joeldenning commented 4 years ago

It looks like I misread the original error message. it is not zonejs that is failing to download, it's a different file. You need to find what the other file is - it should be red in the Network tab of your devtools. That file will be the one that is returning HTML instead of javascript.

The only change in single-spa-angular@3.1.0 when compared to 3.0.1 is how System.import() is interpreted. In 3.0.1, System.import() was interpreted as a webpack code split. In 3.1.0, it is interpreted as an in-browser module from the import map.

Do you have System.import() in your Angular 7 app? If so, are you intending it to be a webpack code split, or a systemjs in-browser module import? If you want to keep it as a webpack code split, switch from System.import() to import() - the System.import() version of code splits is deprecated by webpack.

mbomfim33 commented 4 years ago

I can't see any System.import() per se, but I can see a call to SystemJS.import(), which is called in a loader(alias) function, that takes the application ie: @platform/myapp, and imports it. Would changing this, perhaps help with this scenario?

Also, which are the libraries that should be loaded in-browser, instead of bundled? Would you happen to know?

joeldenning commented 4 years ago

Did you find the network request that is returning HTML when it should return JS? That is crucial to diagnosing this.

Also, which are the libraries that should be loaded in-browser, instead of bundled? Would you happen to know?

Each of your microfrontends should be an in-browser module. Additionally, you can consider making @angular/core and other angular libs in-browser modules in order to share them between microfrontends. However, if you haven't already set that up it's a fair amount of work so I'd not recommend doing that until after you have fixed the issue in front of you

mbomfim33 commented 4 years ago

I can't see any network requests that are not 200s or 300s. I had a 404, but it was a logger that I typed the wrong path, but that's sorted now.

The issue remains, but I'm completely blind to what I could do next to investigate this. As for the Angular being in-browser, that's the objective in the long term, but for now I'm more worried about this issue here.

joeldenning commented 4 years ago

The network request will have a 200 response, but it will return HTML instead of javascript. The reason is that the server is configured to return the index.html whenever it receives a request that it cannot handle. So it will be a network request to download a js file, but the response will be HTML.

Generally the URL for it is pretty easy to find in the browser console. If not, you can look in the network tab and find the request for a javascript file that is returning HTML

mbomfim33 commented 4 years ago

Hey, @joeldenning! Apologies for the delay on the reply. I can see two files that may be the culprits on the requests (both returning 200).

The first one is the locahost:4201/main.js, which I can't even preview the response body, so I can't say for sure whether it is a JS or HTML file: Screenshot from 2020-04-22 10-22-48

The second, is the core.module (that I've mentioned on my edit in here), which is returning an HTML file: Screenshot from 2020-04-22 10-23-10

Could any of those files pinpoint a direction that I could follow to debug this further? That's the precise point were I'm stuck actually

joeldenning commented 4 years ago

Nice finds. Try going to those URLs in their own browser tabs to diagnose the issue. Until you can get javascript to return from those urls, things won't work. Here are some things to verify:

mbomfim33 commented 4 years ago

Ok, been trying to get some more info on this one, but unfortunately things are still not in the clear. I've verified the above, and can confirm that:

As for the last question... the path to the core-module file is ~/Dev/selfservice/src/app/legacy/core/core.module.ts the script we are using to build this, is:

"serve": "ng serve --disable-host-check --port 4201 --deploy-url http://localhost:4201/ --live-reload false --verbose=true",

It seems that who bundles the app, is ng itself. And, with the verbose flag, I can see that it bundles up a lot of content from .../legacy/core, but, I can't see the core.module.ts getting in the bundle as well.

There is another application that is the one that calls the other apps (micro-frontend architecture), which gets bundled with webpack. core.module is where the body of what I want to show on the screen lives, basically, it is the one that should be rendered, when the main application calls it out, but I'm not able to tell you whether it is a code split or not (as I don't know how ng bundles things up).

EDIT: I think is worth mentioning that the folder is called legacy because this is part of a UI revamp, and the old components (prior to the microfrontend POC), lives in this folder.

mbomfim33 commented 4 years ago

An interesting finding today, is that one of the applications that is being served along with the one that is currently broken, when we stop its execution, the broken application now works without any issues.

The application are a Vue and a Angular (the one shouting the error), and when the Vue gets disabled, the app works again. @joeldenning, do you happen to know if there are any special configuration, or something that would make a Vue application not work along with an Angular one?

I know single-spa should be language agnostic, but I wonder...

EDIT: It seems that what is causing this, is that the Zone.js imported from the Polyfills are not being actually imported with the ng build command. Even though angular.json is configured to import the polyfills from the polyfill.ts file is not actually being included to the bundled app.

The only way to make this work, is by commenting out the Zone.js that is comming from the index.html of the main app, and import zone.js in the main-single-spa.ts file instead.

arturovt commented 4 years ago

Even though angular.json is configured to import the polyfills from the polyfill.ts file is not actually being included to the bundled app

angular.json only specifies the path to polyfills.ts. Our webpack config strips polyfills file since Angular apps have to contain only main.js and lazy-loadable chunks.

The only way to make this work, is by commenting out the Zone.js that is comming from the index.html of the main app, and import zone.js in the main-single-spa.ts file instead.

This shouldn't be done. zone.js library has to be loaded in the root-config that orchestrates all applications.

mbomfim33 commented 4 years ago

@arturovt, that's what I'm trying to do in the past couple of days. Finding a way to set the ZoneJS to be included only inside the root config.

Currently, the app registration is not being made in a Githubissues.

  • Githubissues is a development platform for aggregating issues.