Webpack: export default class is not defined on index.html

Viewed 969

I'm new to Webpack.

I have a class that I'm exporting and trying to instantiate on my index.html. (This is an updated version of the original thread)

"use strict";

import {TimelineModule} from "./modules/timeline.module.js";
import {NavigationModule} from './modules/navigation.module.js';
import {FiltersModule} from "./modules/filters.module.js";
import VGLogger from "./modules/logger.module.js";
import {DataSourcesModule} from "./modules/data-sources.module.js";
import {EventsModule} from "./modules/events.module.js";


export default class extends EventsModule {
    constructor(params = null) {
        super();
        this.gridTimeline = null;
        this.gridNavigation = null;
        this.gridFilters = null;
        this.dataSources = new DataSourcesModule();
        this.uniqueID = (((1+Math.random())*0x10000)|0).toString(16).substring(1);

        this.settings.gridSettings = {
            ...this.settings.gridSettings,
            ...params
        };

        VGLogger.log(`New VanillaGrid Instance Created!`, `log`);
    }

    create(gridDOMIdentifier) {
        this.#setWrapper(gridDOMIdentifier);
        this.#renderNavigation();
        this.#renderFilters();
        this.#renderTimeline();
        this.initEvents();
    }

    #renderTimeline() {
        this.gridTimeline = new TimelineModule(this.gridWrapper);
    }

    #renderNavigation() {
        this.gridNavigation = new NavigationModule(this.gridWrapper, this.getSettingValue('navigation'));
    }

    #renderFilters() {
        this.gridFilters = new FiltersModule(this.gridWrapper);
    }

    #setWrapper(wrapper) {
        this.gridWrapper = document.querySelector(wrapper);
        const wrapperClass = this.getSettingValue('wrapperClass');
        this.gridWrapper.classList.add(`${wrapperClass}`);
        this.gridWrapper.classList.add(`vg-${this.uniqueID}`);
    }
}

My library.js file looks like:

const VanillaGrid = require('./index.js').default;
module.exports = VanillaGrid;
// Based on this post -> https://www.seancdavis.com/blog/export-es6-class-globally-webpack/

My config file looks like this:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "bundle.js",
        library: "VanillaGrid",
        libraryTarget: "var"
    },
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        compress: true,
        port: 9000
    },
    entry: {
        main: ['./src/library.js'],
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'sample/index.html'
        }),
    ],
    module: {
        rules: [
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env'],
                        plugins: [
                            '@babel/plugin-proposal-class-properties',
                            '@babel/plugin-syntax-class-properties',
                            '@babel/plugin-proposal-private-methods'
                        ]
                    }
                }
            },
            {
                test: /\.s[ac]ss$/i,
                use: [
                    "style-loader",
                    "css-loader",
                    "sass-loader",
                ],
            },
        ],
    },
};

And .babelrc:

{
"sourceType": "unambiguous",
  "presets": [
    [
      "@babel/preset-env",
      {
        "loose": true
      }
    ]
  ],
  "plugins": [
    "@babel/plugin-proposal-class-properties",
    "@babel/plugin-syntax-class-properties"
  ]
}

My index.html looks like this:

<html>
<head>
  <title>Samples</title>
  <script defer src="bundle.js"></script>
</head>
<body>
</body>
</html>

Thing is that VanillaGrid is undefined on my index.html and can't figure out why. Placed some breakpoints on Webpack's flow, and the class is accessible from within Webpack, but I need to access to it as a global constructor.


UPDATE: So, been analyzing the resuting bundle, and in its final lines have this:

// startup
/******/    // Load entry module and return exports
/******/    // This entry module is referenced by other modules so it can't be inlined
/******/    __webpack_require__("./src/library.js");
/******/    var __webpack_exports__ = __webpack_require__("./node_modules/webpack-dev-server/client/index.js?http://localhost:9000");
/******/    VanillaGrid = __webpack_exports__;

It is assigning this other file that seems to be part of Webpack's dev server to my plugin's global variable. This seems to be webpack-dev-server related.

Any thoughts?

1 Answers

I've tried this simplified version of your code and it worked perfectly:

"use strict";

export default class {
    constructor(params = null) {
        this.gridTimeline = null;
        this.gridNavigation = null;
        this.gridFilters = null;
        this.uniqueID = (((1+Math.random())*0x10000)|0).toString(16).substring(1);
    }

    create(gridDOMIdentifier) {
        this.#setWrapper(gridDOMIdentifier);
        this.#renderNavigation();
        this.#renderFilters();
        this.#renderTimeline();
        this.initEvents();
    }

    #renderTimeline() {

    }

    #renderNavigation() {

    }

    #renderFilters() {

    }

    #setWrapper(wrapper) {

    }
}

The package.json:

"devDependencies": {
  "@babel/core": "^7.13.16",
  "@babel/plugin-proposal-class-properties": "^7.13.0",
  "@babel/plugin-proposal-private-methods": "^7.13.0",
  "@babel/plugin-syntax-class-properties": "^7.12.13",
  "@babel/preset-env": "^7.13.15",
  "babel-loader": "^8.2.2",
  "css-loader": "^5.2.4",
  "html-webpack-plugin": "^5.3.1",
  "webpack": "^5.35.1",
  "webpack-cli": "^4.6.0"
}

Here is the output with some test code:

// Beginning of webpack output

var VanillaGrid;
(() => {
  var t = {
    352: (t, e, n) => {
      "use strict";
      function i(t, e) {
        for (var n = 0; n < e.length; n++) {
          var i = e[n];
          i.enumerable = i.enumerable || !1,
          i.configurable = !0,
          "value" in i && (i.writable = !0),
          Object.defineProperty(t, i.key, i)
        }
      }
      function r(t, e, n) {
        if (!e.has(t))
          throw new TypeError("attempted to get private field on non-instance");
        return n
      }
      n.d(e, {
        Z: () => u
      });
      var a = new WeakSet,
      o = new WeakSet,
      s = new WeakSet,
      l = new WeakSet,
      u = function () {
        function t() {
          (function (t, e) {
            if (!(t instanceof e))
              throw new TypeError("Cannot call a class as a function")
          })(this, t),
          l.add(this),
          s.add(this),
          o.add(this),
          a.add(this),
          this.gridTimeline = null,
          this.gridNavigation = null,
          this.gridFilters = null,
          this.uniqueID = (65536 * (1 + Math.random()) | 0).toString(16).substring(1)
        }
        var e,
        n;
        return e = t,
        (n = [{
              key: "create",
              value: function (t) {
                r(this, l, d).call(this, t),
                r(this, o, h).call(this),
                r(this, s, f).call(this),
                r(this, a, c).call(this),
                this.initEvents()
              }
            }
          ]) && i(e.prototype, n),
        t
      }
      ();
      function c() {}
      function h() {}
      function f() {}
      function d(t) {}
    },
    509: (t, e, n) => {
      var i = n(352).Z;
      t.exports = i
    }
  },
  e = {};
  function n(i) {
    var r = e[i];
    if (void 0 !== r)
      return r.exports;
    var a = e[i] = {
      exports: {}
    };
    return t[i](a, a.exports, n),
    a.exports
  }
  n.d = (t, e) => {
    for (var i in e)
      n.o(e, i) && !n.o(t, i) && Object.defineProperty(t, i, {
        enumerable: !0,
        get: e[i]
      })
  },
  n.o = (t, e) => Object.prototype.hasOwnProperty.call(t, e);
  var i = n(509);
  VanillaGrid = i
})();

// End of webpack output

// Beginning of the test code

const grid = new VanillaGrid;

console.log(grid.uniqueID);

If your problem is the class not being available immediately in a synchronous script tag, try adding scriptLoading: "blocking" in the HtmlWebpackPlugin configuration in order to remove the defer attribute from the generated script tag.

If that doesn't answer your question, you should add details on the bundle.js output and on how you try to use the generated code.

Related