Skip to content

[Bug]: NodeJS vm code + 'eval' needlessly included in web bundle (Causing CSP errors) #274

@SunsetFi

Description

@SunsetFi

Describe the bug

We have an in-house microfrontend framework, and we are in the process of adopting @module-federation/vite to deduplicate our shared libraries and reduce the network overhead and browser memory usage.

However, on our trial projects, we are encountering an odd issue: The process of using @module-federation/vite is causing our browser code to gain an eval() statement.

This is specifically called out by rollup in a warning:

node_modules/@module-federation/sdk/dist/index.cjs.js (670:83): Use of eval in "node_modules/@module-federation/sdk/dist/index.cjs.js" is strongly discouraged as it poses security risks and may cause issues with minification.

Even weirder, on further investigation, this eval() statement seems only relevant for NodeJS, and is never touched or invoked by our web project.

A few things stand out here:

Why is rollup consuming the CJS bundle?

@module-federation/sdk has the proper entries in its package.json to specify ESM builds, which are far more tree-shakable. But, vite seems to be consuming the cjs build instead...

Is it really being included in the bundle?

It's hard to tell with minify on, but yes:
{filename,importModuleDynamically:(_vm_constants_USE_MAIN_CONTEXT_DEFAULT_LOADER=(_vm_constants=vm.constants)==null?void 0:_vm_constants.USE_MAIN_CONTEXT_DEFAULT_LOADER)!=null?_vm_constants_USE_MAIN_CONTEXT_DEFAULT_LOADER:importNodeModule});script.runInThisContext()(scriptContext.exports,scriptContext.module,eval("require"),urlDirname,filename);const exportedInterface=scriptContext.module.exports||scriptContext.exports;if(attrs&&exportedInterface&&attrs.globalName){const o=exportedInterface[attrs.globalName]

With a bit of cross-eyed staring, this code is definitely the createScriptNode function that includes our rogue eval statement, and should in theory be totally unnecessary for a web project.

If we force rollup to consume the mjs bundle, does it tree-shake away the NodeJS code?

...No. We tried this using a resolve alias:

resolve: {
    alias: {
      "@module-federation/sdk": import.meta.resolve("@module-federation/sdk"),
    },
  },

Which properly resolves to the esm build, but we still get the same error, only pointing at the esm this time:

node_modules/@module-federation/sdk/dist/index.esm.mjs (668:83): Use of eval in "node_modules/@module-federation/sdk/dist/index.esm.mjs" is strongly discouraged as it poses security risks and may cause issues with minification

And we can still see it in the bundle:
{filename,importModuleDynamically:(_vm_constants_USE_MAIN_CONTEXT_DEFAULT_LOADER=(_vm_constants=vm.constants)==null?void 0:_vm_constants.USE_MAIN_CONTEXT_DEFAULT_LOADER)!=null?_vm_constants_USE_MAIN_CONTEXT_DEFAULT_LOADER:importNodeModule});script.runInThisContext()(scriptContext.exports,scriptContext.module,eval("require"),urlDirname,filename);const exportedInterface=scriptContext.module.exports||scriptContext.exports;if(attrs&&exportedInterface&&attrs.globalName){const s=exportedInte

Here's that reproduction: https://github.com/SunsetFi/vite-module-federation-createScriptNode/tree/with-esm

Will @module-federation/sdk tree-shake when used directly?

Yep!

https://github.com/SunsetFi/vite-module-federation-createScriptNode/tree/direct-usage-tree-shake

When we disable module federation and try importing createScript directly, createScriptNode is nowhere to be found in the source, and as such the eval function disappears from the bundled code.

Two things of note here though:

  • We still get the error about using eval.
  • Vite is properly using the ESM version of the sdk, not the cjs one.

Impact

This is affecting our usage in a few ways:

  • We are getting 'eval' code into our web builds, flagging warnings for our security scanners.

  • This will cause issues for deploying this code to production due to the Content Security Policy we use.

  • We are getting larger builds than we would like, as we are carrying around NodeJS specific code we do not need. Given that this is happening in the runtimeInit chunk that generates for every federated library, this is going to be compounded over the many, many, many microfrontends we are planning on using @module-federation/vite with.

Version

6.2.1

Reproduction

https://github.com/SunsetFi/vite-module-federation-createScriptNode

Relevant log output

node_modules/@module-federation/runtime-core/node_modules/@module-federation/sdk/dist/index.cjs.js (670:83): Use of eval in "node_modules/@module-federation/runtime-core/node_modules/@module-federation/sdk/dist/index.cjs.js" is strongly discouraged as it poses security risks and may cause issues with minification.

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    COMMUNITY: PR is welcomedWe think it's a good feature to have but would love for the community to help with the PR for itbugSomething isn't workinghelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions