I'm providing details below about my specific issue with jvectormap, but I believe this really breaks down to a question of how to import a module that's exporting a factory (not a class or var).
PLEASE NOTE: I cannot use require
but have to use import
!! (We are migrating from Mix to Vite).
The old code that works with require (can't use any longer):
require('jvectormap-next')($);
$.fn.vectorMap('addMap', 'us-merc', require('jvectormap-content/us-merc'));
The code that should work (I definitely could be doing something wrong)??
import jvnext from 'jvectormap-next';
jvnext($);
import US_Merc from 'jvectormap-content/us-merc';
$.fn.vectorMap('addMap', 'us-merc', US_Merc);
This always gives an error of $.fn.vectorMap does not exist.
Module's Export Code Inside the jvectormap-next module are two export pathways:
The first occurrence (line 191):
(function (factory) {
if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports = factory; <--- EXECUTION ALWAYS RUNS HERE
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
...
// This is the function that defines $.fn.vectorMap -- ultimately, how do you call this??
});
The second occurrence (line 249):
(function (factory) {
if ( typeof define === 'function' && define.amd ) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports = factory; <--- EXECUTION ALWAYS RUNS HERE
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
...
//This function DOES NOT define $.fn.vectorMap, but the execution DOES run in here
});
As you can see, execution steps into both of the function(factory)
methods. But when I make the jvnext($);
call above, the code ONLY steps into the SECOND function($)
, and it never enters the first section which is where the jquery method is defined.
Can someone help me understand how to properly convert this from require to import?
Since nobody responded, I'm going to answer this question for anyone else who is interested. (At least, this is how I solved it).
There core issue is that there are two module.exports =
and the second export overwrites the first one
If you dig into the code for jvectormap-next
, it includes a library in the source code, and that library has its own module.exports =
code. When the code is inlined during the build process, the lib is brought in after the original module export.
There is also a difference in how the code runs when it's brought in using require
vs import
:
if ( typeof define === 'function' && define.amd ) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports = factory; <--- Runs when 'import' is used
} else {
// Browser globals
factory(jQuery); <--- Runs when 'require' is used
}
So using require actually executes both of the function($){...}
calls. A call to import, however, simply exports those functions and does not execute them.
My Solution
I created a fork of the jvectormap-next library and made two small changes:
//First export
if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports.jvectormap = factory;
}
///Second export (from the lib)
if (typeof exports === 'object') {
// Node/CommonJS style for Browserify
module.exports.lib = factory;
}
Now when you bring in the code, it looks like this:
import jvectormap from 'my-jvectormap-fork'; //Bring from git repo or whatever
import $ from 'jquery';
jvectormap.jvectormap($); //Initialize the first factory method
jvectormap.lib($); //Initialize the second factory method
//Good to go