-
-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Application not working with webpack externals #204
Comments
Sharing dependencies is not possible in Angular 9. |
Angular 9 with the Ivy Compiler enabled does not support sharing dependencies between separate microfrontends. You can read more about that at https://twitter.com/Joelbdenning/status/1253781652486017024. My understanding is that Angular 10's Ivy compiler may support this. If you'd like to share dependencies with Angular 9, it is possible but only if you turn off the Ivy Compiler and go back to View Engine. |
Why didn't you provide a minimal reproducible example? I can't always spend my time going through steps manually. I'd rather spend this time fixing some bug or helping you to resolve the issue than trying to reproduce it manually 😞
You have to expose dependencies to // apps/host-app/src/polyfills.ts
import * as rxjs from 'rxjs';
import * as compiler from '@angular/compiler';
import * as core from '@angular/core';
import * as common from '@angular/common';
import * as commonHttp from '@angular/common/http';
import * as platformBrowser from '@angular/platform-browser';
import * as platformBrowserDynamic from '@angular/platform-browser-dynamic';
import * as router from '@angular/router';
import * as singleSpaAngular from 'single-spa-angular';
const win = window as any;
win.rxjs = rxjs;
win['ng.compiler'] = compiler;
win['ng.core'] = core;
win['ng.common'] = common;
win['ng.common.http'] = commonHttp;
win['ng.platformBrowser'] = platformBrowser;
win['ng.platformBrowserDynamic'] = platformBrowserDynamic;
win['ng.router'] = router;
win.singleSpaAngular = singleSpaAngular; And this is my module.exports = config => {
config = require('single-spa-angular/lib/webpack').default(config);
config.output.library = 'microApp';
config.externals = {
rxjs: 'rxjs',
'@angular/core': 'ng.core',
'@angular/common': 'ng.common',
'@angular/common/http': 'ng.common.http',
'@angular/platform-browser': 'ng.platformBrowser',
'@angular/platform-browser-dynamic': 'ng.platformBrowserDynamic',
'@angular/compiler': 'ng.compiler',
'@angular/animations': 'ng.animations',
'@angular/router': 'ng.router',
'@angular/forms': 'ng.forms',
'single-spa-angular': 'singleSpaAngular',
};
return config;
}; This is my import { registerApplication, start } from 'single-spa';
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
function loadScript() {
return new Promise(resolve => {
const script = document.createElement('script');
script.src = 'http://localhost:8080/main.js';
script.addEventListener('load', resolve);
document.head.appendChild(script);
});
}
registerApplication({
name: 'microApp',
app: () => loadScript().then(() => window.microApp),
activeWhen: () => true,
});
start();
platformBrowserDynamic().bootstrapModule(AppModule); This is my <div class="micro-app-host"></div> This is my import { enableProdMode, NgZone } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { singleSpaAngular } from 'single-spa-angular';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
const lifecycles = singleSpaAngular({
template: '<micro-app-nx-root />',
bootstrapFunction: () => platformBrowserDynamic().bootstrapModule(AppModule),
NgZone,
domElementGetter: () => document.querySelector('.micro-app-host'),
});
export const bootstrap = lifecycles.bootstrap;
export const mount = lifecycles.mount;
export const unmount = lifecycles.unmount; Result:
|
Thanks for a quick reponse. In my case host application is not an angular app. It's just some html with vendor files that's why i've provided vendors in angular.json. Adding vendor files (UMD version) in angular.json to host-app we gonna have all of them accesable from Having this setup the error is thrown when loading |
@lukszymanski I'm sorry for the delay. You issue is really informative and I've finally found out why it didn't work. The problem was that our package I was able to clone your git repo. Your Webpack config for micro-apps is not correct, you've got such externals: return {
...singleSpaWebpackConfig,
externals: {
rxjs: 'rxjs',
'@angular/core': 'ng.core',
'@angular/common': 'ng.common',
'@angular/common/http': 'ng.common.http',
'@angular/platform-browser': 'ng.platformBrowser',
'@angular/platform-browser-dynamic': 'ng.platformBrowserDynamic',
'@angular/compiler': 'ng.compiler',
'@angular/animations': 'ng.animations',
// '@angular/elements': 'ng.elements',
// '@angular/router': 'ng.router',
// '@angular/forms': 'ng.forms',
'single-spa-angular': 'single-spa-angular',
},
};
console.log(window['ng.core']) It will log module.exports = (angularWebpackConfig, options) => {
const singleSpaWebpackConfig = singleSpaAngularWebpack(
angularWebpackConfig,
options
);
singleSpaWebpackConfig.output.library = 'microApp';
const mappings = {
'@angular/core': 'core',
'@angular/common': 'common',
'@angular/common/http': 'common.http',
'@angular/platform-browser': 'platformBrowser',
'@angular/platform-browser-dynamic': 'platformBrowserDynamic',
'@angular/compiler': 'compiler',
'@angular/animations': 'animations',
};
const angularExternals = Object.keys(mappings).reduce(
(accumulator, mapping) => {
const request = ['ng', mappings[mapping]];
accumulator[mapping] = {
root: request,
commonjs: request,
commonjs2: request,
amd: request,
};
return accumulator;
}
);
return {
...singleSpaWebpackConfig,
externals: {
rxjs: 'rxjs',
...angularExternals,
'single-spa-angular': 'single-spa-angular',
},
};
}; Also, you've added "scripts": [
"node_modules/rxjs/bundles/rxjs.umd.js",
"node_modules/@angular/core/bundles/core.umd.js",
"node_modules/@angular/common/bundles/common.umd.js",
"node_modules/@angular/common/bundles/common-http.umd.js",
"node_modules/@angular/compiler/bundles/compiler.umd.js",
"node_modules/@angular/platform-browser/bundles/platform-browser.umd.js",
"node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js",
"node_modules/@angular/router/bundles/router.umd.js",
"node_modules/@angular/forms/bundles/forms.umd.js",
"node_modules/single-spa-angular/bundles/single-spa-angular-internals.umd.js",
"node_modules/single-spa-angular/bundles/single-spa-angular.umd.js"
] |
cool! thank you for helping out! 💪 |
This is published in https://github.com/single-spa/single-spa-angular/releases/tag/v4.7.0 |
@arturovt are you sure that the code you provided works? I added it to my custom-webpack.js and everything works fine from the application perspective, but the bundle size stays the same. Shouldn't it decrease the bundle size quite immensely? |
Yes, I agree. The size does not change much. |
@tommueller @wudith well, I've decided to check. This is before: This is after: This navbar app is inside this repository, you can clone it and try it out. |
Thanks @arturovt . I can confirm that with the code in the image (webpack.config.ts) it does work for me as well. With the js code from you last post, it does actually not work for me. |
@tommueller I just made a typo and missed |
@arturovt When I now load the application with the externals configured (and the small bundle size) I run into:
|
@tommueller just wondering - did you ever resolve the bare specifier issue above? Running into the same problem myself |
@nmccrack37 no unfortunately not. For us it's luckily such a big issue, because it is only a very small part of our application, so I never took the time to investigate further. |
Is anyone able to get this working with Angular 14? |
Hi there,
i'm trying to use single-spa-angular combined with webpack externals to have a single vendor bundle at host app level that can be shared between all microfrontend apps.
How to reporoduce?
hostapp
->architect
->build
->options
->scripts
add followingThe problem.
All the imports are swpped with the externals from webpack config. However it looks like main.js file is bundled before using original import with internal module references. (snippet below)
Any advaice how to resolve this issue?
The text was updated successfully, but these errors were encountered: