Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronous require in Webpack

I'm using webpack and I'm using require to pull in some packages. I have two packages: package1.js and package2.js. package1.js simply creates an object with some properties called pkg1. package2 is a javascript file that contains a self executing function that extends package1. E.g.

package2.js:

!function () {
    pkg1.prototype.newFunction = function {return "foo"};
}()

I'm trying to require both of these into a new script in the following manner:

require('package1')
require('package2')

When I do this, I get an error:

Uncaught TypeError: pkg1.newFunction is not a function

I think this is because of Javascripts asynchronous loading: require(package2) executes before require('package1'). My evidence for this is that when I do the following I don't get an error:

require('package1')
!function () {
    pkg1.prototype.newFunction = function {return "foo"};
}()

However, this is very messy, and I would like to use require. How would I go about making this work?

Edit: Specific Examples

The leaflet-d3 plugin begins with:

(function() {
    L.HexbinLayer = L.Class.extend({
    ...
 })()

Hence, at least to my understanding, putting in a require(leaflet-d3-plugin) should cause this script to execute and extend L which is brought in by require('leaflet')

Similarly, d3-hexbin-v0 starts with:

!function(){d3.hexbin=function(){
    ...
}}()

Again, the way I read this is that this script simply adds a .hexbin method to d3.

Now if I were just writing html, I would just put these different things in various script tags and this just works:

<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/d3.hexbin.v0.min.js"></script>

or

<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
<script src="static/leaflet-d3.min.js" charset="utf-8"></script>

But since I'm using webpack, I should just be able to require and/or import these libraries after I have installed them with npm or if I just copy the .js in these scripts into some directory and then require them from that location. Unfortunately, this does not seem to work unless I copy the .js in these modules directly into whatever script I am writing. This is what I am trying to avoid.

E.g.

import * as d3 from 'd3'; \\I'm using d3 v4 here.
require('/resources/d3-hexbin.min.js')

results in:

Uncaught TypeError: d3.hexbin is not a function
like image 825
Logister Avatar asked Sep 13 '16 01:09

Logister


People also ask

What are 4 core concept of webpack?

There are four basic concepts in webpack: entry , output , modules and plug-ins . These configurations are added in webpack.

Does webpack automatically minify?

Webpack v4+ will minify your code by default in production mode .

Does webpack require node?

Webpack runs on Node. js, a JavaScript runtime that can be used in computers and servers outside a browser environment.

Is import better than require?

The major difference between require and import , is that require will automatically scan node_modules to find modules, but import , which comes from ES6, won't. Most people use babel to compile import and export , which makes import act the same as require .


1 Answers

Webpack loades it synchronously but each file have its own scope.

That's why in your statement

import * as d3 from 'd3'; \\I'm using d3 v4 here.
require('/resources/d3-hexbin.min.js')

your second doesn't find d3 variable.

You can solve it by using ProvidePlugin:

webpack.config.js

plugins: [
  new webpack.ProvidePlugin({
    d3: 'd3'
  }),
  ... //other plugins

This way d3 will be available throughout the application.

Alternative way to achieve it is to use the following:

import * as d3 from 'd3';
window.d3 = d3;
require('./d3.hexbin.v0.min.js')

Hope it helps you!

like image 98
yurzui Avatar answered Sep 20 '22 10:09

yurzui