I'm facing the problem of integrating requirejs with d3 and nvd3, and i found an easy solution using require's shim. Using the shim i can export a variable, and i can also define dependencies:
d3: { exports: 'd3' },
nvd3: {
exports: 'nv',
deps: ['d3']
},
In this way, i simply install d3 and other packages with bower, and include them with require, and it is really quick and clean.
Nonetheless, i faced the following problem: there are probably some clashes between the global d3 variable and the local one (the one injected in the requiring modules). It is a d3 / require / nvd3 integration problem related to transitions and selections. I don't fully understand the problem, but i can already make some considerations.
jquery has the same problem with require, and they provide the noconflict method to fix it
many libraries have this behavior, they export a global symbol, but as far as i know there is no ready fix from requirejs for the general problem
the problem is fixed if i rename all global references to d3 into d3 source to another name. I still have d3 in the injected module, but it is not conflicting anymore
As far as i can see, all d3 functionalities work this way, but one of the nvd3 charts has transitions broken probably because a selection or dispatcher is overwritten. It requires deep understanding of d3 internals to spot precisely the error, but probably a simple yet correct handling of the global symbol will clear the whole tally of similar problems.
Probably, due to the way requirejs handles shim dependencies, the global d3 symbol is exposed to nvd3. The same symbol, anyway, is not available to requiring modules, and will be overwritten somehow if injected (included in the module dependencies).
I tried also to wrap d3 in a module and properly return a local d3 variable, but looks like the problem still persists.
I also asked help about this on this d3 group discussion which hosts some previous posts about d3 and modules.
I added a test case here: https://github.com/danse/requirenvd3
The problem doesn't appear to be your RequireJS configuration but rather the fact that you're using d3.v3 and not d3.v2. I downgraded d3 in your test case, and the transitions worked fine. (The popups are still all off to the side, which I don't think they should be, but that doesn't seem to be what you are presently concerned about.) It's my understanding that nvd3 has a few problems with d3.v3, this probably being one. Also, note the version of d3 in ddotsenko's jsFiddle. That could explain why his solution didn't work when you implemented it using your own d3.v3 library.
First, you can bypass shim You don't need it to return anything for plain-JS. Just use globals.
Loading Angular from CDN via RequireJS is not injected
Second, while shim is semi-useful for declaring dependencies for scripts, you can do them explicitly as well:
require(['path/to/d3.min'], function(){
// nesting to insure d3 loads before nvd3
require(
[
'path/to/mylogic' // <- AMD module
,'path/to/nvd3.min' // <- actually a plain JS file
]
, function(mylogic /*, we ignore what nvd3 returns */){
window.nv // is available for you
}
)
})
Look at what I do in this main.js file (using "depend" requirejs plugin) and then in other files that require something that should be exported to a global variable I do:
define(['d3'], function (d3) {
// Code here ...
});
The depend plugin is really nice and allows you to setup hierarchical loading via depend!plugin[dependancy1, dependancy2] ("plugin" loads after "dependancy1" and "dependancy2" have loaded.
Related
In Webpack 5, module.reasons was removed (see: https://webpack.js.org/blog/2020-10-10-webpack-5-release/). From what I have been able to find, the documentation doesn't list an alternative. Documentation for the module graph is also pretty scarce.
We have build code that currently checks module.reasons inside of the splitChunksPlugin test() function. That code breaks in Webpack 5.
Does anyone know what the replacement for module.reasons is? I've tried looking stuff up in the module graph but I don't think the current module has been added yet because it is always undefined when calling getModule() on the graph.
In my project, there is a custom third-party library (a single build file), which they have created using a couple of non-AMD and AMD files. And most of the properties are exposed directly to window objects. In our project as per the new requirement, we have to load this third-party library in asynchronous mode using requireJS. I tried with shim configuration but am getting an error from third party library saying that globals/window, globals/documents are needed.
How to resolve the above error in the current project without editing a third-party library? is it possible?
How to consume this third party libs properties in the project, since all properties are exposed directly to window Object.
This is the error we are encountering now
Could anyone please help me with this?
Thanks in Advance!
It looks like your 3rd party library is video.js. Video.js was (see below) creating two global objects global/window and global/document which seem to be used for testing video.js on the server where there is no window or document.
You can see their definition here and then the import. If you're willing to edit the file (and stop video.js tests from working server-side) then that's a simple solution.
You said you didn't want to edit the library though, so let's look for other solutions. You could just go ahead and define them like so:
define('global/window', [], () => {
return window;
});
define('global/document', ['global/window'], (window) => {
return window.document;
});
Then load video.js:
require(['video.7.5.0.min.js'], (videojs) => {
window.videojs = videojs;
// any other initialization you want here
});
Also it might be helpful to know which version of video.js you're using. It appears this might have been fixed in 7.11.1 (in this PR) so there's a good chance that just upgrading to that version or later makes the problem go away.
There's a lot more discussion on this problem in this issue, but it appears to be closed due to the previously mentioned PR.
I'm getting this error when try to create a map:
I'm currently using version "datamaps": "^0.5.8", this is directly from my package.json. I also checked the package.json in the actual package to see where main was pointing:
I found a related issue, maybe even the same issue here:
https://github.com/markmarkoh/datamaps/issues/259
Problem is that no one ever said what the answer was, one person mentioned that only a specific country js file was being loaded but I checked and datamaps.all.js is being loaded.
This is to be attributed to the new modularity of D3 v4, which made it necessary to flatten namespaces:
However, there is one unavoidable consequence of adopting ES6 modules: every symbol in D3 4.0 now shares a flat namespace rather than the nested one of D3 3.x.
For your code this means that some references using the d3-geo module are invalid because they refer to properties which are no longer available in v4:
Geographies (d3-geo)
d3.geo.albersUsa ↦ d3.geoAlbersUsa
Because datamaps has defined a dependency on D3 like ^3.5.6 this will include D3 v4. However, because of the above mentioned changes in the namespace you will have to use a D3 v3 instead.
I'm attempting to build a site using a combination of RequireJS and MooTools. It's my first time using both libraries. There is plenty of documentation for using RequireJS with jQuery but less for using it with MooTools. I've found only this really. But I'm having some trouble and much of it probably is a result of ignorance; still, perhaps you all can help.
At the moment, I'm just trying to test out basic functionality and understand how I would go about setting this up. Here is what I have tried:
In my site footer, I have this script tag:
<script src="assets/js/vendor/require.js" data-main="../app.js"></script>
This loads requirejs with the file app.js. Inside app.js I mainly deal with paths:
requirejs.config({
"baseUrl": "assets/js",
"paths": {
"mootools": "//ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed"
}
});
// Load the main app module to start the app
requirejs(["main"]);
Finally, in main.js, I have (so far) the following:
define(["mootools"], function($) {
var a = $$('.menu'); // .menu is a nav menu in the DOM
console.log(a);
var b = $('.menu');
console.log(b);
});
So here, a works, but b causes an error: undefined is not a function. So there are a couple of questions embedded here. First, can someone tell me what the difference in meaning for $ and $$ with mootools? I gather from this tutorial, that both are used in mootools. Also, why is it that mootools is not mapped to $? As I understand it, with jQuery, this is how you would do this, see here for example.
I'm sure there are some basic confusions here, but please have mercy. I'm a newbie to these tools.
MooTools (as is) is not AMD-compliant. David Walsh is cool but he does not like or use RequireJS. The info in his post is well out of date and not practical any more. In fact, I believe none of the MooTools-core team likes AMD or uses it. Anyway, that's beside the point. jQuery now IS based around AMD so using it is easy. MooTools tried it 2 years ago - https://github.com/arian/mootools-core/tree/1.5amd - and gave up. 1.5 is still not out (hopefully next week, still no AMD).
Anyway
You cannot do this quite in that fashion by expecting the script to magically return $ where a module has not been defined.
There is another issue here which is with the fact that you are loading a remote script and that you leave the protocol to be determined automatically - which are sort of quirky things for RequireJS to handle in their own accord.
Two or three ways to handle it.
you can just define a local module, eg your own mootools.js
define([
'http://ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed.js'
], function(){
return window.$;
});
then use by requiring it:
require(['mootools'], function($){
$(document.body).adopt(new Element('div[html=hi]'));
});
eg. http://jsfiddle.net/dimitar/5zYnW/
however, mootools will export all sorts of globals anyway, so it's not really useful. you are better off using the requirejs shim config.
shim example
require.config({
paths: {
mootools: 'https://ajax.googleapis.com/ajax/libs/mootools/1.4.5/mootools-yui-compressed'
},
shim: {
mootools: {
exports: '$'
}
}
});
// some code.
require(['mootools'], function(){
document.id('foo').adopt(new Element('div[html=hi]'));
});
eg: http://jsfiddle.net/dimitar/5zYnW/1/
old school
I find that it's easier to load MooTools before RequireJS and assume it's all global in all modules that I write - it makes more sense as there are too many global exports to catch. eg. Class, Element, Request etc etc.
eg. https://github.com/epitome-mvc/Epitome/blob/master/example/js/model-demo-require.js -s from my MooTools MVC framework Epitome.
Here's example module code via a UMD wrap - https://github.com/epitome-mvc/Epitome/blob/master/src/epitome-model.js - the only code that implicitly requires MooTools is the node.js code.
I'm currently building an app where the frontend is doing a lot of the heavy lifting.
To keep everything neat and organised I'd like to use requirejs. However, to use require.js to its' full extent all the modules I use should be AMD compliant.
Which means that every time a module that I use is updated I need to either wait for an AMD-compliant version to appear or make one myself ( Which I currently don't know how to ).
This is a real turnoff.
Looking at this https://github.com/jrburke/backbone/blob/optamd/backbone.js it seems to me that making a module like Backbone AMD-compliant isn't as straightforward as wrapping the plugin into a generic function.
Is there a more or less straightforward way of making a module AMD-compliant?
Well his version is pretty bullet-proofed so it'll run under a variety of circumstances. Since you know the environment you are running in and what is available/what isn't then you can make some assumptions that will let you do something that is much more straightforward.
Check out this gist where I make bacbkonejs an AMD module assuming jQuery, underscore and define are in the global scope and I don't need commonjs support:
https://gist.github.com/2762813
I just add
define(function() {
var obj = {};
obj._ = window._;
obj.jQuery = window.jQuery;
to the top and
.call(obj);
return obj.Backbone;
});
to the bottom.
Thanks to #SimonSmith for bringing UseJS to my attention. UseJS is an AMD loader plugin that will allow you to load non-amd formatted modules without modifying them. I haven't used use myself yet but it looks promising: https://github.com/tbranyen/use.js/
UPDATE
RequireJS 2.0 now directly supports the functionality you are looking for via shim configs: https://github.com/jrburke/requirejs/wiki/Upgrading-to-RequireJS-2.0#wiki-shim