aProgger
aProgger

Reputation: 871

Webpack imported module is an empty object

I want to use the "virtual-select-plugin" library in my webpack/typescript project. It has no type definitions. The library was installed via npm. In the browser I get the error:

TypeError: virtual_select_plugin__WEBPACK_IMPORTED_MODULE_13___default(...).init is not a function

Typescript and webpack does not complain.

Webpack generates the required thingies, as it does for bootstrap, flickity and others which work well:

...

/* harmony import */ var flickity__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flickity */ "./node_modules/flickity/js/index.js");
/* harmony import */ var flickity__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flickity__WEBPACK_IMPORTED_MODULE_2__);

...

/* harmony import */ var virtual_select_plugin__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! virtual-select-plugin */ "./node_modules/virtual-select-plugin/dist/virtual-select.min.js");
/* harmony import */ var virtual_select_plugin__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(virtual_select_plugin__WEBPACK_IMPORTED_MODULE_13__);

...

I noticed the var flickity__WEBPACK_IMPORTED_MODULE_2__ contains an object with propertys, functions and so on but var virtual_select_plugin__WEBPACK_IMPORTED_MODULE_13__ is just an empty object. The code from the virtual-select-plugin is imported later in the bundle and is the content of the "./node_modules/virtual-select-plugin/dist/virtual-select.min.js" file.

I added a typedef in decs.d.ts:

declare module 'virtual-select-plugin'

I import the plugin with:

import VirtualSelect from 'virtual-select-plugin';

and want to call the init function later:

// Browser says no...
VirtualSelect.init({
  ele:     ...,
  options: ...,
});

I have added an alias in the webpack config:

...

  resolve: {
    alias:      {
      'virtual-select-plugin': 'virtual-select-plugin/dist/virtual-select.min',
    },
    extensions: [
      '.js',
      '.jsx',
      '.ts',
      '.tsx',
    ],
  },

...

I searched for 6h now and I don't find a solution to get this work. Can someone help me please?

Upvotes: 0

Views: 937

Answers (1)

aProgger
aProgger

Reputation: 871

I ended up including the minified js via the dom and copy the needed files from node_modules to dist via webpack.

I found an indirect "solution". I am not happy with because it will get tedious with larger libraries. But maybe it helps others with small ones.

tldr: Basically I import the library's src files and compile them by myself.

  1. Installed the dependencies popover-plugin and popper-plugin (browser told me this... see below)
  2. Changed/added resolve aliases in webpack config
  resolve: {
    alias:      {
      'virtual-select-plugin': 'virtual-select-plugin/src/virtual-select',
      'PopoverComponent':      'popover-plugin/src/popover',
      'PopperComponent':       'popper-plugin/src/popper',
    },
  ...
  }
  1. required them in the code (note the braces around VirtualSelect)
import {VirtualSelect} from 'virtual-select-plugin';

require('PopoverComponent');
require('PopperComponent');

There is no need to add the two additional libraries in the declaration because typescript does not use them.

How I came to this

I somewhere got a hint that a library imported by webpack must have an export (Not sure about that). The minified js of "virtual-select-plugin" does not have one. But the src file (src/virtual-select.js) export "VirtualSelect".

I pointed webpack to that file by changing the alias of 'virtual-select-plugin' like above. Because there is no default export, I had to add braces around VirtualSelect import {VirtualSelect} ...

After hitting F5, browser complained about "missing undefined PopoverComponent". I looked in the code and noticed a usage of that component. Because it was not defined somewhere, I checked the package.json of the library and found it there. I installed the package as dev and added the alias to this lib and a require in the code of my project (see above stept 2 and 3).

Hitting f5 again, browser said "missing PopperComponent". Did the same again as with the PopoverComponent. Everything runs fine now.

Im pretty sure every small library can be included by that way. But there must be a better way. But maybe webpack isn't able to import a plain javascript?

Upvotes: 1

Related Questions