2

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?

7
  • Your HTML file doesn't appear to load a Webpack bundle? Commented Mar 19, 2021 at 17:37
  • My bad, copied the src version of the file. Updated it to how it actually is once webpack processed it Commented Mar 22, 2021 at 19:00
  • There may be other issues, but at a minimum defer there means that main.js won't run until after new SomeClass(). Commented Mar 22, 2021 at 19:45
  • You may also need to set your Library's name so that you then do new LibName() since it's the library you are importing, and the export of that just happens to be a constructor that was originally named SomeClass. Commented Mar 22, 2021 at 19:48
  • Already did that but it's not working out. Any thoughts? Commented Apr 29, 2021 at 12:30

1 Answer 1

2
+100

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.

Sign up to request clarification or add additional context in comments.

5 Comments

It seems to be dev server related. Checked the bundle, and the resut assigns the library correctly to VanillaGrid global variable. But when I run webpack dev server, is when this happens.
So when you double click on the html file to open it as file:/// it works?
If I run index.html with Webstorm's run function, it works
It works for me with this config: devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, port: 9000 }
@Pablo I just saw you awarded me the bounty. I'm curious did you eventually find out what was wrong?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.