Skip to content
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

Error with eager shared modules after update to Angular15 #253

Open
NicoReber opened this issue Nov 18, 2022 · 17 comments
Open

Error with eager shared modules after update to Angular15 #253

NicoReber opened this issue Nov 18, 2022 · 17 comments

Comments

@NicoReber
Copy link

We get the following error message after updating to Angular 15

@angular-architects/module-federation version is 15.0.2

[error] TypeError: Cannot read properties of undefined (reading 'import')
at .\node_modules@angular-architects\module-federation\src\utils\modify-entry-plugin.js:18:120
at mergeEntry (.\node_modules@angular-architects\module-federation\src\utils\modify-entry-plugin.js:11:17)
at cfgOrRemove (.\node_modules@angular-architects\module-federation\src\utils\modify-entry-plugin.js:14:28)
at .\node_modules@angular-architects\module-federation\src\utils\modify-entry-plugin.js:18:75
at Array.forEach ()
at ModifyEntryPlugin.apply (.\node_modules@angular-architects\module-federation\src\utils\modify-entry-plugin.js:17:34)
at createCompiler (.\node_modules\webpack\lib\webpack.js:73:12)
at create (.\node_modules\webpack\lib\webpack.js:134:16)
at webpack (.\node_modules\webpack\lib\webpack.js:158:32)
at Object.f [as webpackFactory] (.\node_modules\webpack\lib\index.js:64:16)

I was also able to reproduce that error message in the tutorial project with the following steps:

  • After cloning the starter kit update the project via ng update
  • Adding module federation via ng add @angular-architects/module-federation to shell and remote
  • add eager: true to shareAll configuration in shell project
  • run ng serve shell

The error only occurs when eager is set to true in shareAll configuration

webpack.config.js shell

const { shareAll, withModuleFederationPlugin } = require('@angular-architects/module-federation/webpack');

module.exports = withModuleFederationPlugin({

  shared: {
    ...shareAll({ singleton: true, eager: true, strictVersion: true, requiredVersion: 'auto' }),
  },

});
@raitisbe
Copy link

The same happens when just one of the definitions contains eager:

module.exports = withModuleFederationPlugin({
  name: 'x',
  shared: {
    '@angular/core': {
      singleton: true,
      strictVersion: false,
      requiredVersion: 'auto',
    },
    '@ngx-translate/core': { singleton: true, strictVersion: false },
    '@angular/localize/init': {
      singleton: true,
      eager: true,
    },

@NicoReber
Copy link
Author

I think I've found the source of the problem.
As soon as 1 package gets shared with the eager or pinned option, the ModifyEntryPlugin gets added to the webpack plugins definition.

if (hasPinned || hasEager) {
modifyEntryPlugin = new ModifyEntryPlugin(modifyEntryConfig);
}

Now in the ModifyEntryPlugin the entry points for styles/polyfills/main get changed. But here compiler.options.entry is expected to be an object but in reality it is a function.

image

This worked fine in Angular14 because I guess compiler.options.entry always was an object.
But changes in this commit that got released with Angular15 broke this behaviour because Angular now handles entry points for the styles with a webpack plugin and change the compiler entries option from an object to a function.

before StylesWebpackPlugin gets executed.
image

after StylesWebpackPlugin gets executed.
image

I think to fix the problem the ModifyEntryPlugin would need to be able to handle the case that the entries in the compiler options are already defined as a function.

Hope this info helps with finding a solution.

@kaplan81
Copy link

I investigated this issue yesterday.

Support for eager and pinned was provided in June.

Unfortunately, as @NicoReber has pointed out, this changes are not compatible with Angular 15 due to the new implementations for Webpack compilation in the CLI project.

Screenshot 2023-01-18 at 19 09 58

The ModifyEntryPlugin is expecting compiler.options.entry['styles'] to be defined but it is not anymore:

Screenshot 2023-01-17 at 13 55 40

We should also notice that we are now referencing polyfills as "polyfills": ["zone.js"], in the angular.json.

So basically this code would not be useful in libs/mf/src/utils/with-mf-plugin.ts:

if (hasEager) {
    modifyEntryConfig['styles'] = { dependOn: ['main'] };
    modifyEntryConfig['polyfills'] = { dependOn: ['main'] };
  }

So in the end I have provided a workaround in my project to avoid using this plugin:

// @ts-check
const {
  share,
  withModuleFederationPlugin,
  SharedMappings,
} = require('@angular-architects/module-federation/webpack');
const {
  ModifyEntryPlugin,
} = require('@angular-architects/module-federation/src/utils/modify-entry-plugin');
const path = require('path');
const sharedMappings = new SharedMappings();
sharedMappings.register(path.join(__dirname, '../../tsconfig.json'), [
  /* mapped paths to share */
]);
const remotes = require('./remotes.json');
const webpackConfig = {
  ...withModuleFederationPlugin({
    remotes,
    shared: share({
      '@angular/core': {
        singleton: true,
        strictVersion: true,
        requiredVersion: 'auto',
        eager: true,
      },
      '@angular/common': {
        singleton: true,
        strictVersion: true,
        requiredVersion: 'auto',
        eager: true,
      },
      ...sharedMappings.getDescriptors(),
    }),
  }),
};
const plugins = webpackConfig.plugins.filter((plugin) => !(plugin instanceof ModifyEntryPlugin));

// // Uncomment for debugging.
// console.log('webpackConfig:::', webpackConfig);
// console.log('plugins:::', plugins);

module.exports = {
  ...webpackConfig,
  plugins,
};

I hope this helps.

@ssams
Copy link

ssams commented Jan 19, 2023

also just spent some time with this error after running into it during the update of a project to Angular 15.

Part of the cause seems to be how the ModifyEntryPlugin is implemented. According to the Webpack docs, a plugin usually taps into event hooks within its apply method. The plugin part here however directly expected the entries to be present and started patching as soon as the apply is executed. This apparently worked with the old Angular builder, but now that Angular itself is using a plugin to add the styles (which only registers hooks to be executed at a later point in the latest version), the order of execution got mixed up. So now the ModifyEntryPlugin is trying to perform its changes too early in the lifecycle, before the styles entry even got added.

The issue of entries being a function after the styles plugin execution as pointed out by @NicoReber (thanks for the initial analysis and the link to the respective change in Angular, which was very helpful) then also comes into play of course, and the plugin probably should be able to handle both function and object entries to work independently from the implementation of other plugins. Note that at the time @NicoReber linked the Angular change, the styles plugin was not yet using the hook but also made the changes directly in its apply method. By now this has been updated, so in total the two issues of (a) execution order via hooks and (b) entries potentially being a function have to be fixed.

For the change to polyfills pointed out by @kaplan81 it's basically the same story, when run at the right lifecycle stage the changes should be possible to apply again.

Looking at the StylesWebpackPlugin in Angular, it currently makes it changes in the environment hook. Based on that I'd assume that the immediately following afterEnvironment hook should be the right stage for performing the changes in the ModifyEntryPlugin. At least that's the earliest stage where the changes from Angular are visible already, without delaying the execution further. In theory with more detailed understanding of the Webpack lifecycle it may be possible to move it back even further to keep it reliable in case the Angular plugin implementation changes, but as the ModifyEntryPlugin may also perform quite generic other changes in its current version I wouldn't want to move it back too far (risking that the changes are made too late in the overall packing process).

Created a working patch with my colleague which fixes the functionality of the ModifyEntryPlugin as described without the need to skip or disable anything, pull request with the changes should be available shortly.

@ssams
Copy link

ssams commented Feb 1, 2023

@manfredsteyer any idea if/when this could be reviewed and merged? got the patch running locally, but having to keep copies of it in several projects becomes cumbersome ;-)

let me know if we can assist or speedup the process somehow, would be great to see a new release with some of the recent contributions which currently only exist as PRs.

@ktsangop
Copy link

Sorry to bump this, but we are facing the same problem.
This is also reproducible using the share function also (not only shareAll)
For example the following config is broken too:

  shared: share({
    ...
    "zone.js": { singleton: true, strictVersion: true, requiredVersion: "auto" , eager: true },
    ....
})

Unfortunately for us, removing eager: true will not work, as it results in the following error at runtime :
Shared module is not available for eager consumption

Is there any chance this will be addressed?
Thank you!

@nthaidang
Copy link

Sorry, I have to bring up this issue again.

Some shared libs have eager: true, which means we have to ignore the ModifyEntryPlugin for the build to work in the shell, but this results in large initial chunk files, where polyfills.js is a copy of our vendor.js.

Screenshot 2023-03-06 at 15 53 15

With the fix provided in #278, everything works perfectly, and our chunk files return to their normal size.

Screenshot 2023-03-07 at 09 53 35

Hope that this issue will be addressed soon.

@brilyanhalodoc
Copy link

Bump this ^, we are also facing the same issue on angular 15.

can we merge this fix #273 soon?
or do you guys have any idea when the fix could be merged?

Thanks!

@warnerjc
Copy link

Adding a friendly bump to this as well. Our CI/CD pipeline failed due to increased bundle size of polyfills.ts after applying the temporary fix by @kaplan81. Hoping that #278 will be merged soon enough, as our team plans to migrate to Angular 15.2.x soon and would also look to update Module Federation at the same time.

@hardikpatel043
Copy link

eagerly (ha..ha..) waiting for the fix.

@ross-moug
Copy link

I've also encountered this while investigating Module Federation for usage within our codebase, any chance that #278 could get progressed? Any timescale on when this could be merged?

@jacogreyling
Copy link

Ditto on the merge. @manfredsteyer can we get a 15.0.4 build please?

@stefanocke
Copy link

On more "please" from us...

@Ketec
Copy link

Ketec commented Aug 4, 2023

And the same, end up on this very issue halfway through the upgrade.

Is it fixed for 16? (not that I can upgrade it yet - too many libraries are broken because of ViewEngine removal).

@mchlbrnd
Copy link

Eagerly waiting for PR. merge....

@out-dev
Copy link

out-dev commented Apr 26, 2024

Hi all,
I'm a little confused why there is no progress because PR seems ready to be merged?
#278

@frazzaglia
Copy link

Like suggested here #418
I've overrided the node_modules/@angular-architects/module-federation/src/utils/modify-entry-plugin.js with a postinstall command.
Hope to see a merge closed as soon as possible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests