Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use webpack and ES6 with dependencies using a CommonJS module?

I am working on a project with laravel that uses (as it is the default) webpack to bundle its assets. In there, I do have a dependency on a package that in turn has dependencies to lodash and deepdash.

Since deepdash is provided as a mixin for lodash, the usage of it is (as per the docs) like this:

// load Lodash if you need it
const _ = require('lodash');
//mixin all the methods into Lodash object
require('deepdash')(_);

or, if you want to use ES6 syntax (at least that is my understanding), it would translate to:

import _ from 'lodash';
import deepdash from 'deepdash';

deepdash(_);

Having done that, I am trying to use webpack to create a bundle now to be used in the browser. My problem is, that for some reason it appears that webpack replaces the import of lodash with some "__webpack_require__" magic functionality, which leads to lodash not being a function anymore, and the browser says this: enter image description here

To better demonstrate my problem I created a demo github repo with just trying to webpack deepdash and lodash: ArSn/webpack-deepdash Here is the line that the browser complains about: https://github.com/ArSn/webpack-deepdash/blob/master/dist/main.js#L17219

I have played around a lot with adding babel configuration en mass and it felt like my best shot was the plugin babel-plugin-transform-commonjs-es2015-modules. I tried that, the result was still exactly the same.

I feel like either I have a deep misunderstanding of the situation or I am missing just one tiny little thing. I can however for the life of me not figure out which one it is and what.

Side notes:

  • I know there is also a ES6-Version of deepdash, and apparently when using both of those the webpack mechanics work fine (as is stated in the response to the github issue I opened over at deepdash for this), but the dependency I am using is not using those. Also, I do not really see (or understand?) the point of having a dedicated ES6 version there in the first place.
  • The very same code (using deepdash this way with lodash) works just fine when executed on node.js, where it is not bundled with webpack before, obiously. I should mention it is using the require-syntax here though.
like image 875
ArSeN Avatar asked Sep 26 '19 20:09

ArSeN


People also ask

How do I use the CommonJS module in ES6 module?

An ES6 Module can load other ES6 modules using import. An ES6 Module can load CommonJS using import. A CommonJS module can load other CommonJS modules using require. A CommonJS module previously COULD NOT load an ES6 Module, but today it can load an ES6 module using the import() function.

Does webpack support CommonJS?

Webpack supports the following module types natively: ECMAScript modules. CommonJS modules.

What is the difference between ES6 and CommonJS?

While CommonJS and ES6 modules share similar syntax, they work in fundamentally different ways: ES6 modules are pre-parsed in order to resolve further imports before code is executed. CommonJS modules load dependencies on demand while executing the code.


1 Answers

Pointing explicitly to the deepdash main module works for me when running one of the examples from the deepdash website:

import _ from 'lodash';
import deepdash from 'deepdash/deepdash';

deepdash(_);

Webpack uses the browser entry as default:

  "main": "deepdash.js",
  "module": "es/standalone.js",
  "browser": "browser/deepdash.min.js",

This will not work for Webpack and static imports - because there is nothing really "exported".

Also: Commonly these entries do not point to minified builds. These are usually only for CDN use cases and not for bundlers.

On the contrary 'deepdash/deepdash.js' exports the decorator function.

The deepdash-es build basically does the same thing except that it uses es6 exports. Maybe this is the way that treeshaking can work out of the box. Not sure about at that...

In order to circumvent the "browser" issue - the author of deepdash could just simply amend it to use "deepdash.js" or remove it:

https://github.com/defunctzombie/package-browser-field-spec

If your module is pure javascript and can run in both client and server environments, then you do not need a browser field.

like image 141
madflow Avatar answered Oct 06 '22 19:10

madflow