2

I recently updated to Webpack 5 from Webpack 4, earlier I had a function on window object in index.js such that it looked something like

index.js

window.someFunction = function (...arguments) {
    // function body
}

when this index.js gets bundled I can find this same function in common.bundle.js file.

and my index.html looks something like this

index.html

<head>
    // rest of the head stuff
    <script src="./dist/common.bundle.js"></script>
</head>
<body>
    <script type="text/javascript">
        someFunction(); // calling someFunction from the window object
        // Also tried using window.someFunction() still doesn't work    
    </script>
</body>

In console I get ReferenceError: someFunction is not defined and I am not able to print the function defination in chrome console when I type window.someFunction which was working in Webpack 4 as expected.

How do I attach my functions to window object in Webpack 5, and how do I go about accessing it?

webpack.config.js

const path = require("path");
const webpack = require("webpack");

module.exports = (env) => {
  return {
    mode: "development",
    devtool: "source-map",
    entry: {
      common: "./index.js",
    },
    output: {
      pathinfo: true,
      path: path.join(__dirname, "dist"),
      filename: "[name].bundle.js",
    },
    plugins: [
      new webpack.DefinePlugin({
        "process.env.NODE_ENV": JSON.stringify("development"),
      }),
    ],
    module: {
      rules: [
        {
          test: /\.(js|jsx)$/,
          exclude: /(node_modules|bower_components)/,
          use: {
            loader: "babel-loader",
            options: {
              cacheDirectory: true,
              babelrc: false,
              presets: [
                [
                  "@babel/env",
                  {
                    modules: false,
                    loose: true,
                    targets: {
                      browsers: [">0.25%", "not ie 11", "not op_mini all"],
                    },
                  },
                ],
                "@babel/react",
              ],
              plugins: [
                [
                  "@babel/plugin-proposal-class-properties",

                  {
                    loose: true,
                  },
                ],
                ["@babel/plugin-transform-runtime"],
              ],
            },
          },
        },
        {
          test: /\.css$/,
          include: /node_modules/,
          use: [{ loader: "style-loader" }, { loader: "css-loader" }],
        },
      ],
    },
    resolve: {
      extensions: [".js", ".jsx"],
      modules: [path.resolve(__dirname, "node_modules")],
      fallback: {
        buffer: false,
        fs: false,
        tls: false,
        net: false,
        path: false,
        zlib: false,
        http: false,
        https: false,
        stream: false,
        crypto: false,
      },
    },
    optimization: {
      // namedModules: true,
      // namedChunks: true,
      minimize: false,
      // minimizer: [new TerserPlugin()],
      runtimeChunk: "single",
      moduleIds: "deterministic",
      chunkIds: "deterministic",
      nodeEnv: "development",
      flagIncludedChunks: false,
      concatenateModules: false,
      splitChunks: {
        hidePathInfo: false,
        minSize: 20000,
        maxAsyncRequests: Infinity,
        maxInitialRequests: Infinity,
        chunks: "all",
        // maxSize: 0,
        minChunks: 1,
        automaticNameDelimiter: "~",
        cacheGroups: {
          commons: {
            test: /[\\/]node_modules[\\/]/,
            name: "other.bundle",
            chunks: "all",
            minChunks: 2,
          },
          defaultVendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10,
          },
          default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true,
          },
        },
      },
      emitOnErrors: true,
      checkWasmTypes: false,
      removeAvailableModules: false,
    },
    performance: {
      hints: "warning",
    },
    stats: {
      all: false,
      assets: true,
      builtAt: true,
      cachedAssets: false,
      cachedModules: true,
      chunkGroups: true,
      colors: true,
      env: true,
      errors: true,
      hash: true,
      logging: "info",
      timings: true,
      modules: true,
      outputPath: true,
      performance: true,
      errorsCount: true,
      warnings: false,
      warningsCount: true,
      publicPath: true,
      reasons: true,
      ids: true,
      version: true,
    },
    cache: {
      type: "filesystem",
      version: "1.0.0",
      store: "pack",
      name: "AppBuildCache",
      maxMemoryGenerations: 1,
      idleTimeout: 60000,
      idleTimeoutAfterLargeChanges: 1000,
      idleTimeoutForInitialStore: 0,
      hashAlgorithm: "md4",
      cacheLocation: path.resolve(__dirname, ".cache"),
    },
    externals: [
      {
        react: "React",
        "react-dom": "ReactDOM",
        jquery: "jQuery",
      },
    ],
  };
};
Miraaj Kadam
  • 59
  • 2
  • 4
  • 1
    How did you generate the `index.html`? Do you use `html-webpack-plugin`? – Lin Du Aug 24 '21 at 10:23
  • @slideshowp2 no the index.html isn't generated, The `index.html` resides in the root with the `script` with src pointing to the generated `common.bundle.js`. – Miraaj Kadam Aug 24 '21 at 11:29
  • Can't reproduce the issue. Can you create a minimal, reproducible example? – Lin Du Aug 24 '21 at 11:32
  • I have added the steps to reproduce, however, I am not able to reproduce the issue that I am encountering in the real project in the example files, everything seems to be working fine. Will check again and update. – Miraaj Kadam Aug 24 '21 at 13:03

4 Answers4

1

Try to add node.global: true to your config:

node: {
  global: true
}
DoneDeal0
  • 5,273
  • 13
  • 55
  • 114
1

DoneDel0's comment was the correct solution for me.

node: {
  global: true
}

The reasoning behind this is webpack 5 does no longer include a polyfills for node modules, so you have to manually set each.

https://webpack.js.org/configuration/node/#nodeglobal

However its good to note that the docs does suggest using ProvidePlugin instead of global.

James Dinnes
  • 131
  • 2
  • 3
0

Thank you for the answers, the issue turned out exactly to be due to missing polyfills for node core modules.

In my case the I had to provide polyfill for process using ProvidePlugin.

I did the same by adding below to my config

new webpack.ProvidePlugin({
    process: "process/browser",
})
Miraaj Kadam
  • 59
  • 2
  • 4
  • I'm running into a similar issue as you were. I added a fallback for `process` in `resolve.fallbacks`, but it did not help. What was the reason that you needed to polyfill `process`? Was it for env var? Were there any specific errors that it helped resolve? – jfoo Aug 30 '23 at 18:03
-1

I added

node: {
  global: true
}

but still the function is undefined in window object.

Keshav Dhawan
  • 29
  • 1
  • 6