Windows 10
Node v6.9.1
Npm v3.10.8.
ng-cli beta.30
In brief, I want to bootstap one of my root modules based on an async call to the server. So, my code is like that:
````js
AppPreBootstrap.run(() => {
if (abp.session.userId) {
AppPreBootstrap.bootstrap(AppModule);
} else {
AppPreBootstrap.bootstrap(AccountModule);
}
});
//A workaround to make angular-cli finding the startup module!
var b = false; if (b) { platformBrowserDynamic().bootstrapModule(AppModule); }
````
Given workaround works fine when AOT is disabled. But, when AOT is enabled, it only compiles AppModule and the logic above can not work.
I know AOT statically analysis main.ts and bundles all module files starting from the root module. But I also believe my case is not so unique. I simple want to bootstrap a different module if user has not logged in.
So, isn't that possible or is there a way of doing it? If not, how do you recommend as a best practice? Should I merge 2 modules and implement the logic with routes and route guards?
Thanks.
@hikalkan I think best practice in this case would be to manage this with routes and router guards. You can also lazy load those modules from the router so only the code needed to run would be downloaded.
I will try the lazy load first to see if it's possible. Thank you @deebloo
I suppose there is no way of doing that.
need to be able to select module. Error is thrown with aot on
@hikalkan did you get things working with the router?
No. What I did is to create a new RootModule which lazy loads other modules via router.
But I did not like that solution much :(
@hikalkan ok. that does sound closer to best practice for angular though.
Hey I have followed this documentation : https://www.aspnetzero.com/Documents/Getting-Started-Angular
things went really good as expected. But after successful login I'm unable to see dashboard, it redirects me back to login. I guess it is something related to routing?
I suppose here is not the best place to ask this question :) Can you write to the aspnetzero forum.
How long it will take to get a response on forum against this topic? http://forum.aspnetboilerplate.com/viewtopic.php?f=5&t=5201
@hansl can you have a look?
Can anyone from the Angular team confirm the principle behind AoT not supporting multiple entry points?
Is it a basic principle of Angular 2+ that there must only ever be one root module and everything has to be part of one monolithic SPA application with centralized routing?
This feels like a distinct lack of flexibility that real world applications often require. In my mind AoT needs to just work, regardless of whether or not I have a single monolithic application, multiple sub application or I just want to drop in some components on a static marketing page that is optimized for SEO.
I've patched the AngularCompilerPlugin to allow for multiple entry points. Are you interested in a PR?
Anyway, if somebody needs this feature can see the patch here https://github.com/miiihi/angular-cli/commit/fb75650708c95868cd33a5771d57b905d3b3200e
@filipesilva @hansl What would be your recommendation regarding a workaround for multiple entry point apps at this moment?
Starting from Angular 5, if we want to use AOT compilation for development builds as well, we cannot do it with ngc
and we need to switch to @ngtools/webpack
+ AngularCompilerPlugin
. So far, I couldn't find any way to set it up to work with multiple entry points. The only way might be to hack the plugin as suggested above, but this is not a sustainable approach.
Even if we continue using ngc
for AOT compilation in production builds, starting from Angular 5 the Webpack setup becomes more complex because ngc
now doesn't output TypeScript code anymore...
For a description of our particular use case, see my comment here: https://github.com/angular/angular-cli/issues/7954#issuecomment-341639781
Alternatively, maybe you could suggest how the project should be structured instead of having multiple entry points, so that it would work with @ngtools/webpack
+ AngularCompilerPlugin
.
Having multiple app modules is necessary for us too. We have a very small AppIncognitoModule that checks if localstorage is available since safari incognito (and possibly other small browsers) have this limitation. If localstorage is disabled then we make an API call to retrieve it.
This allows us to readily have the data available once the regular AppModule bootstraps since we have them promise chained together. Any suggestions on how else to do this would be welcome.
I am also interested in something like this. We have several apps (different web landing pages, mobile, desktop, embed, etc.). I don't think it makes much sense to view these as different "routes", we'd really like to have a single build for all the apps (in part so we can avoid compiling shared code multiple times).
Recently I've just landed on the matter of this subject. In my case I do have to manage having Angular working within a JSF project. The project is an old fashioned one and cannot use pretty much the angular goodies like SPA, or having the whole app holding form one angular root node.
In order to use components in such monolithic way I've structured modules per container components. This offers the possibility of locating them where they are needed on the page without relying on a root node. Of course, for this purpose it would be interesting a react or polymer solution but as per client's requirement is not possible.
The shared state can be achieved through a factory provider which uses some global window object. This factory checks if the object property is present in the global scope and return it, in case not just create the new object. The same provider will be set on the modules used in the same page. The object can be any RxJS Subject object or a Mobx instance or whatever you like. Also can be used redux but I think is an overwhelming approach.
To make these modules works on the same page, I've just bootstrap them to the main.ts
. The next snippet works as expected from a JIT compliance.
platform.bootstrapModule(AModule);
platform.bootstrapModule(BModule);
But the main problem resides when deploying within a JSF page. It just don't work. So knowing about two compilations modes, I've tried out the AOT way.
Apart from some peculiarities of AOT strictness everything looked fine until the project testing. The modules were not being mounted. The message error pointed out the first module being mounted was a null instance. After some hours figuring out why this was happening, I removed one of the bootstrap calls. It worked!
I still could not discover how is happening but why. Anyway, this is another subject.
Because the only way to work with AOT was having only one module bundler I had to figure it out how to solve this issue. Well, the solution came reading a post from Maximus Koretskyi about manually bootstrap different components.
This approach allows to place the components wherever we like, not depending on a root node. The only requirement is defining in the markup a div
element (or any block element) where the respective component will be bootstrapped.
The key points are to achieve this manual approach are specified below:
bootstrap
option from the Angular module. There's no need for a main component. Instead the required components would be added in the entryComponents
property. The result can be seen below.@NgModule({
imports: [ BrowserModule ],
declarations: [ AComponent, BComponent ],
entryComponents: [ AComponent, BComponent ]
})
ngDoBootstrap
which receives an ApplicationRef instance. This object is a represents the angular running application. One of the methods contained is bootstrap which does what is expected to do: mounting components. So within ngDoBootstrap
the component or components can be mounted. The whole class module looks like the next example.const components = [AComponent, BComponent];
@NgModule({
imports: [ BrowserModule ],
declarations: [ AComponent, BComponent ],
entryComponents: [ AComponent, BComponent ]
})
export class AppModule {
ngDoBootstrap (app) {
components
.forEach(component => this.bootstrapComponent(app, component));
}
bootstrapComponent (app, component) {
const mountName = component.mountName;
const mountPoint = document.querySelector(`#${mountName}`);
if (isNil(mountPoint)) {
console.error(`${mountPoint} id is not present in DOM`);
return;
}
// Create the mounting point and append into DOM
const componentElement = document.createElement(mountName);
mountPoint.appendChild(componentElement);
// Bootstrap the new component
app.bootstrap(component);
}
}
I've added in the component a static property called mountName
. This name is the value set in the id property in the DOM element container. Because the component keeps the id name is easy to look for the element and bootstrap the component.
And that's pretty much it. Well, of course, don't forget bootstrap the new module. This way allows having several components (think of them as apps) placed wherever you like in the page using an AOT approach.
Please refer to this post for much on this topic. Also check this app demo to see it working.
I hope this approach can help until AOT supports having multiple root modules.
Best Regards.
While this get fixed, I published a npm package with some modifications to handle multiple entry modules: @artonge/webpack
feel free to use it.
You only have to replace @ngtools/webpack
by @artonge/webpack
in your webpack config and change entryModule: "your module"
by entryModules: ["your module A", "your module B"]
Heya, is this still a problem? Can someone provide a repro using the current version of Angular CLI please?
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
Can anyone from the Angular team confirm the principle behind AoT not supporting multiple entry points?
Is it a basic principle of Angular 2+ that there must only ever be one root module and everything has to be part of one monolithic SPA application with centralized routing?
This feels like a distinct lack of flexibility that real world applications often require. In my mind AoT needs to just work, regardless of whether or not I have a single monolithic application, multiple sub application or I just want to drop in some components on a static marketing page that is optimized for SEO.