Skip to content

Multiple entryModule support #12107

Description

@alexeagle

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

Activity

  1. alexeagle commented on Sep 4, 2018

    @alexeagle
    ContributorAuthor

    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.

  2. alexeagle commented on Sep 4, 2018

    @alexeagle
    ContributorAuthor

    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/core@0.0.0

  3. alexeagle commented on Sep 4, 2018

    @alexeagle
    ContributorAuthor

    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...

  4. alexeagle commented on Sep 4, 2018

    @alexeagle
    ContributorAuthor

    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.

  5. alexeagle commented on Sep 4, 2018

    @alexeagle
    ContributorAuthor

    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.

  6. alexeagle commented on Sep 4, 2018

    @alexeagle
    ContributorAuthor

    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 ?

  7. Rush commented on Nov 8, 2018

    @Rush

    I would love to find a solution as well.

  8. AndreyPoznyak commented on Apr 12, 2019

    @AndreyPoznyak

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

  9. trickeyone commented on Apr 17, 2019

    @trickeyone

    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.

  10. Rush commented on Apr 17, 2019

    @Rush

    @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.

  11. trickeyone commented on Apr 17, 2019

    @trickeyone

    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(?).

  12. jetfontanilla commented on May 30, 2019

    @jetfontanilla

    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"
        ]
    })
    
  13. violetVo commented on Apr 13, 2020

    @violetVo

    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?

  14. added this to the Backlog milestone on May 25, 2020
  15. francisli commented on May 31, 2020

    @francisli

    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...

  16. angular-automatic-lock-bot commented on Dec 6, 2020

    @angular-automatic-lock-bot

    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.

  17. locked and limited conversation to collaborators on Dec 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: @ngtools/webpackfeatureLabel used to distinguish feature request from other issues

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions