Attaching a function to window object in Webpack 5

Viewed 1741

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",
      },
    ],
  };
};
4 Answers

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

node: {
  global: true
}

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.

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",
})

I added

node: {
  global: true
}

but still the function is undefined in window object.

Related