'TypeError: arguments[i].apply is not a function' error when working with Webpack

When working with Webpack you might come across the following error:

TypeError: arguments[i].apply is not a function

So what are you doing wrong exactly?

Webpack

Webpack is a powerful module bundler. Using Webpack you can combine the different assets that belong together and improve the performance of your JavaScript solution. Webpack is highly configurable and there are plenty of plugins available for processing all kinds of assets and applying different optimizations to the generated bundles - all making Webpack a versatile solution for improving the performance of your solution.

In most cases Webpack is configured through a webpack.config.js file located in the root of your project. That file describes what bundles you want Webpack to generate and how it should do it.

Webpack configuration error

When working with Webpack you might encounter the following error:

TypeError: arguments[i].apply is not a function

Most likely it is caused by invalid configuration of Webpack plugins.

When configuring Webpack, you might be tempted to use the serialized representation of the configuration, of which the plugins section would resemble:

{
  "plugins": [
    {
      "opts": {
        "filename": "spfx-hello-world.stats.json",
        "fields": null
      }
    },
    {
      "opts": {
        "filename": "spfx-hello-world.stats.html"
      }
    },
    {
      "definitions": {
        "DEBUG": true,
        "UNIT_TEST": false
      }
    },
    {
      "chunkNames": [
        "hello-world.bundle",
        "vendor.bundle"
      ],
      "ident": "/Users/clippy/dev/spfx-hello-world/node_modules/webpack/lib/optimize/CommonsChunkPlugin.js0"
    }
  ]
}

You might want to use this representation of Webpack configuration particularly when working with the recently announced SharePoint Framework where all of the configuration is expressed using JSON format.

While this configuration seems valid, it isn't. Here is why.

Anatomy of Webpack plugins

Webpack plugins system is built upon the Tapable package. When loading plugins listed in Webpack's configuration, Webpack is trying to call the apply() function on each plugin which through Tapable would be routed to the apply() function of that particular plugin in order to execute it. Unfortunately, the serialized objects specified in JSON are not instances of Webpack plugins and have no apply() function which causes the aforementioned error.

If you want to configure Webpack plugins, you should always use a .js file and pass to the plugins array the instances of the plugins you want to use:

var webpack = require('webpack');

module.exports = {  
  // omitted for brevity
  plugins: [
    new StatsPlugin.StatsWriterPlugin({
      fields: null,
      filename: lastDirName + ".stats.json"
    }),
    new VisualizerPlugin({
      filename: lastDirName + ".stats.html"
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: [ 'hello-world.bundle', 'vendor.bundle' ]
    })
  ]
};

Summary

Webpack is a powerful module bundler. Using its rich configuration and collection of plugins you can improve the performance of your JavaScript solution. While the majority of Webpack's configuration could be expressed through JSON, the plugins section must contain references to instances of plugins, rather than their serialized representation, for Webpack to work correctly.

Comments

comments powered by Disqus