Skip to content

Multiple entryModule support #12107

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

Closed
alexeagle opened this issue Sep 4, 2018 · 15 comments · Fixed by #19114
Closed

Multiple entryModule support #12107

alexeagle opened this issue Sep 4, 2018 · 15 comments · Fixed by #19114
Labels
area: @ngtools/webpack feature Issue that requests a new feature
Milestone

Comments

@alexeagle
Copy link
Contributor

From @artonge on May 7, 2018 14:51

Bug Report or Feature Request (mark with an x)

- [ ] bug report -> please search issues before submitting
- [x] feature request

Area

- [x] devkit
- [ ] schematics

Versions

node version: v9.4.0
npm version: 5.6.0
Linux (Ubuntu 17.10)

Repro steps

Clone this example: https://github.com/artonge/multiple-entrymodules

The log given by the failure

At execution in the browser I have:
Uncaught Error: No NgModule metadata found for 'AppModule'.
This error only appears for the module that wasn't specified has the entryModule in the webpack config.

Desired functionality

At my company our webpack config has two entry points for two different apps, and generate two bundles for the two apps. The problem is that when using AOT, we can only specify one entryModule, but the two apps have different entryModule. It would be nice to specify two entryModules so the metadata are generated for both of them.

Copied from original issue: angular/devkit#861

@alexeagle alexeagle added state: blocked feature Issue that requests a new feature labels Sep 4, 2018
@alexeagle
Copy link
Contributor Author

From @james-criscuolo on May 7, 2018 20:41

I am also running into this issue while upgrading. I used to be able to use the ngtools/webpack loader without the plugin, which allowed me to get around this issue. I would do this in development, then for production builds I would have the significantly longer build where I sent each entry point individually through webpack. Now I have no choice but to use the plugin in development, so my build process will suffer tremendously once I complete the upgrade.

@alexeagle
Copy link
Contributor Author

From @artonge on May 9, 2018 9:3

Could this feature be backported to version 1.10.2 ? Any ETA ?
Can a maintainer provide some indications to help me to add this feature ? Where should I look ? How to backport it ?

When trying to install @ngtools/webpack dependencies with npm install, I have the following error:
No matching version found for @angular-devkit/[email protected]

@alexeagle
Copy link
Contributor Author

From @artonge on May 15, 2018 9:33

Duplicate of:

@clydin could you help me comming with a solution ? I created a pull request #875 but some tests failed...

@alexeagle
Copy link
Contributor Author

From @filipesilva on May 24, 2018 17:33

This is something we are interested it, but not for 6.x. We will re-evaluate when the Angular Ivy compiler is available as that changes how this feature would work.

@alexeagle
Copy link
Contributor Author

From @sherlock1982 on May 24, 2018 17:54

Could you please provide a kind of a workaround for this? Because I don't quite understand how can I code-split two endpoints in one app. Or for example how a custom element and an app can code-split angular.

@alexeagle
Copy link
Contributor Author

From @artonge on May 25, 2018 9:32

Thanks for the answer @filipesilva ! As @sherlock1982 asked, could you provide some workaround ? Or tell us if my solution in #875 is safe to use ?

@Rush
Copy link

Rush commented Nov 8, 2018

I would love to find a solution as well.

@AndreyPoznyak
Copy link

is it still relevant?
I'm still not able to configure multiple entries using @ngtools/webpack 7.3.8

@trickeyone
Copy link

This is a fairly significant blocker. Our application can't be an SPA due to varying concerns/implementations. We really want to use Angular w/AOT and have implemented a significant amount of our frontend code using Angular 7. Not being able to bootstrap multiple root modules is a huge blocker for us since we don't need a complete page takeover, but multiple modules to only takeover certain parts of the UI since the majority of the UI is generated on the backend.

Having multiple root modules work via JIT, but not AOT, doesn't make a lot of sense and gives a false impression during development that it would work in production w/AOT. I didn't even realize this was a limitation since I didn't see anything about it in the documentation. It took me troubleshooting and looking on stackoverflow/googling for 3 days to find this out. The documentation does give an example of having multiple roots, which is kinda confusing.

Creating multiple projects doesn't seem like a reasonable option, either. As it would lead to having to create an individual project for each part of the UI that needs to be taken over.
If this is something that the Angular team is looking at implementing, as @filipesilva indicated in his post on the original issue:

From @filipesilva on May 24, 2018 17:33

This is something we are interested it, but not for 6.x. We will re-evaluate when the Angular Ivy compiler is available as that changes how this feature would work.

Could we get some feedback on whether there is an approach to workaround this issue, other than sticking with JIT? There were other comments asking for clarity on it that never received a response.

From @artonge on May 25, 2018 9:32

Thanks for the answer @filipesilva ! As @sherlock1982 asked, could you provide some workaround ? Or tell us if my solution in #875 is safe to use ?

If there were a way to have a root module that could then conditionally bootstrap other modules, that would at least provide a work-around.

I attempted this workaround while attempting to utilize lazy-loading. But it doesn't work since the root module doesn't actually attach to the DOM and I was simply attempting to bootstrap the other modules.

No matter my attempt, I consistently received the "Uncaught Error: No NgModule metadata found" exception in the browser for AOT. During the build process, no errors were being generated.

@Rush
Copy link

Rush commented Apr 17, 2019

@trickeyone For AOT you may want to try my fork of @ngtools/webpack (which is forked from @artonge). Install @rush/webpack (https://github.com/Rush/angular-cli)

And use it like so:

const AotPlugin = require('@rush/webpack').AngularCompilerPlugin;

const aotPlugins = USE_AOT ? [
  new AotPlugin({
    tsConfigPath: IS_PRODUCTION ? 'tsconfig.prod.json' : 'tsconfig.dev.json',
    entryModules: [
      path.join(__dirname, 'src/js/app/app.module#AppModule'),
      path.join(__dirname, 'src/js/app/landing.module#LandingModule'),
    ],
    skipCodeGeneration: !IS_PRODUCTION,
  })
] : [];

If there were a way to have a root module that could then conditionally bootstrap other modules, that would at least provide a work-around.

Kind of :-)

// unfortunately for AOT compiler to work, these components need to be defined twice
// (AOT will throw)
const declarations = [
    LandingComponent,
    GetNotifiedComponent,
    TypedComponent,
    StickyBarComponent,
    ImageGalleryComponent,
    RequestDemoFormComponent,
    PricingPlansComponent,
    SalesRequestFormComponent,
    DetailedPricingPlansComponent,
];

const landingComponents = {
    'landing-root': LandingComponent,
    'get-notified': GetNotifiedComponent,
    'typed-component': TypedComponent,
    'sticky-bar': StickyBarComponent,
    'image-gallery': ImageGalleryComponent,
    'request-demo-form': RequestDemoFormComponent,
    'pricing-plans': PricingPlansComponent,
    'detailed-pricing-plans': DetailedPricingPlansComponent,
    'standalone-help-manual': StandaloneHelpManualComponent,
};

function hasKey<O>(obj: O, key: string | number | symbol): key is (keyof O) {
    return key in obj;
}

// tslint:disable-next-line:max-classes-per-file
@NgModule({
    declarations,
    entryComponents: [...declarations, StandaloneHelpManualComponent],
    imports: [
        BrowserModule,
        CommonModule,
        ClarityModule,
        LightboxModule,
        HttpClientModule,
        FormsModule,
        BrowserAnimationsModule,
        HelpModule,
    ],
    providers: [
        WaitlistedService,
        PricingService,
    ],
})
export class LandingModule {
    ngDoBootstrap(applicationRef: ApplicationRef) {
        for (const tagName in landingComponents) {
            if (hasKey(landingComponents, tagName)) {
                const component = landingComponents[tagName];
                if (document.getElementsByTagName(tagName).length) {
                    applicationRef.bootstrap(component as any);
                }
            }
        }
    }
}

As you can see I am using both methods. I have one app which is a plain old regular Angular app and a LandingModule which is using the above trick to get different components bootstrapped on different landing pages.

@trickeyone
Copy link

After doing some research into @angular/elements, I have been able to, so far, successfully implement partial takeovers. It's taken some reworking of a number of components, to allow for them to be used as regular Angular components and then to also be used as custom elements.

I do really like the @angular/elements setup, but I would suggest possibly allowing for components to be included as custom elements without having to do the createCustomElement(...) and customElements.define(...) routine. While it's not necessarily a large amount of overhead for the developer (i.e. me) to do, it does seem to be a significant amount of extra work for this feature to work. I would suggest possibly allowing this to be implemented using the @Component metadata and possibly a new @NgModule section to include custom elements.

i.e.

@Component({
    selector: 'my-component',
    templateUrl: '...'
})
class MyComponent {
}

@NgModule({
...
    customElements: [MyElementComponent]
})
class AppModule {}

This seems like it would a much easier implementation. If @angular/elements is not present and customElements is defined, then an exception could be thrown(?).

@jetfontanilla
Copy link

if you need an option for multiple paths instead of multiple entry modules, I've forked @Rush (based from @artonge) and added this feature
https://github.com/jetlogs/angular-cli

npm install @jetlogs/webpack

import { AngularCompilerPlugin } from "@jetlogs/webpack";


new AngularCompilerPlugin({
    tsConfigPath: "tsconfig.json",
    paths: [
      "/path/to/entry1.ts",
      "/path/to/entry2.ts"
    ]
})

@violetVo
Copy link

Any news on this feature? Do you have an ETA for the multi entryModule support? It's a blocker for us.
It looks like this commit by @Rush implements it:
Rush@d439496

Is it possible to add this commit to webpack repository?

@francisli
Copy link

I'm glad to see some activity on this issue! For what it's worth, I have my own branches in which I've rebased the work by @Rush and @artonge onto the v9.1.7 release of angular-cli:

https://github.com/francisli/angular-cli/tree/v9.1.7-multiple-entry-modules

And I've built the package for direct reference in package.json files here (instead of publishing yet another variation of the package to npm):

https://github.com/francisli/ngtools-webpack-builds/tree/9.1.x-multiple-entry-modules

Hope this helps anyone else landing here, looking for this support with the latest release of Angular and TypeScript...

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Dec 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: @ngtools/webpack feature Issue that requests a new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants