Skip to content

__webpack_require__.l is not a function (follow up #551) #4849

Description

@grgrzybek

Describe the bug

I see this issue closed:

But I'd like to share some findings.

There's something fishy between 3.1.83 and 3.1.85 where you've changed the builder (configuration) used (skip 3.1.84 where the different output wasn't yet reflected in package.json)

I'm just checking the difference between 3.1.83 and 3.1.85 (to narrow the scope).

I use a package with type=module and typescript with ES syntax (import), which means my:

import { importRemote } from '@module-federation/utilities'

brings in node_modules/@module-federation/utilities/dist/index.esm.js in version 3.1.83.

I'm using latest version of webpack bundler, so the above JS file lands in an output chunk in this shape (when output.chunkFormat = 'module'):

export const __webpack_esm_modules__ = {
  "../../node_modules/@module-federation/utilities/dist/index.esm.js"
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
    __webpack_require__.r(__webpack_exports__);
    __webpack_require__.d(__webpack_exports__, {
      ...
      importRemote: () => (/* binding */ importRemote),
      ...
    });

    // ...

    const loadRemote = (url, scope, bustRemoteEntryCache) => new Promise((resolve, reject) => {
      const timestamp = bustRemoteEntryCache ? `?t=${new Date().getTime()}` : '';
      const webpackRequire = __webpack_require__;
      webpackRequire.l(`${url}${timestamp}`, (event) => {
        ...
  }
}

__webpack_require__ is taken from the 3rd argument of "../../node_modules/@module-federation/utilities/dist/index.esm.js" entry function

However in 3.1.85, the chunk contains:

export const __webpack_esm_modules__ = {
  "../../node_modules/@module-federation/utilities/dist/esm/utils/importRemote.mjs"
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
    __webpack_require__.r(__webpack_exports__);
    __webpack_require__.d(__webpack_exports__, {
      // only one
      importRemote: () => (/* binding */ importRemote)
    });

    // ...

    function __nested_webpack_require_187__(moduleId) {
      // Check if module is in cache
      var cachedModule = __webpack_module_cache__[moduleId];
      if (cachedModule !== undefined) {
          return cachedModule.exports;
      }
      // Create a new module (and put it into the cache)
      var module = (__webpack_module_cache__[moduleId] = {
          exports: {}
      });
      // Execute the module function
      __webpack_modules__[moduleId](module, module.exports, __nested_webpack_require_187__);

      // Return the exports of the module
      return module.exports;
    }

    (() => {
    __nested_webpack_require_187__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
    })();

    const loadRemote = (url, scope, bustRemoteEntryCache) => new Promise((resolve, reject) => {
      const timestamp = bustRemoteEntryCache ? `?t=${new Date().getTime()}` : '';
      const webpackRequire = __nested_webpack_require_187__;
      webpackRequire.l(`${url}${timestamp}`, (event)=>{
        ...
  }
}

and while the passed (as 3rd argument) __webpack_require__ contains all necessary helpers:

Image

the __nested_webpack_require_187__ has only the .o one:

Image

See:

The changelog for 3.1.85 mentions:

- 918294f: Add runtime-safe access helpers for webpack require, webpack share-scope globals,
  and ignored dynamic imports, and migrate core/node runtime loaders to use these helpers.
  The helpers are exposed via a standalone `@module-federation/sdk/bundler`
  entrypoint so they can be built and consumed independently from the SDK main index bundle.

The cjs version of importModule.js (cjs/utils/importRemote.js) additionally defines __webpack_require__.r and __webpack_require__.d.

Webpack's CompatibilityPlugin kicks in because both cjs/utils/importRemote.js and esm/utils/importRemote.js actually DEFINE function named __webpack_require__ which triggers the rename (to __nested_webpack_require_187__) because of:

if (
	statement.type === "FunctionDeclaration" &&
	statement.id &&
	statement.id.name === RuntimeGlobals.require
) {

index.cjs.js and index.esm.js in 3.1.83 didn't declare such function - it only used the __webpack_require__ symbol assuming it's there (and it is when you bundle these files using webpack.

Reproduction

not that easy - but try to run importRemote() in 3.1.83 and 3.1.85

Used Package Manager

yarn

System Info

Using Webpack with @module-federation/utilities 3.1.83 and 3.1.85

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions