RequireJS doesn't work, not load library? - javascript

It is the first time I use RequireJS and I don't know why it doesn't work...
I have a file example.js inside Folder A.
In the same folder I have 2 other folders that are libraries.
geokdbush
kdbush
In my file I add this code (hoping to add libraries):
require.config({
paths: {
kdbush: 'kdbush',
geokdbush: 'geokdbush'
}
});
And inside function where I should to use libraries I add this:
require(['kdbush', 'geokdbush'], function(kdbush,geokdbush) {
//code
});
But there are two errors: Error: Script error for "kdbush" and Error: Script error for "geokdbush".
I don't know where the problem is in my code. These libraries are used to create K-D tree:
Reverse geocoding with big array is fastest way? - javascript and performance

Related

How to make source maps available with requireJS in Tapestry 5

My goal is to use Bootstrap5 Tooltips with my Tapestry 5.8.1 web application. I try to use requireJS for my JavaScript code as much as possible. So I use the Bootstrap5 JS files in their separated form. That means, I don't use the bundle file but single files like this:
src/main/resources
- META-INF
- modules
- bootstrap5
- alert.js
- alert.js.map
- base-component.js
- base-component.js.map
- ...
- tooltip.js
- tooltip.js.map
In my own JS I activate the tooltips by defining this module:
define(["bootstrap5/tooltip"], function(Tooltip) {
var setuptooltips = function() {
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new Tooltip(tooltipTriggerEl)
})
};
return {
"setuptooltips" : setuptooltips
};
})
and then calling require(...).setuptooltips().
That all works. But.
For each *.js file in my modules/bootstrap5 directory I now get a warning on the JavaScript console about the missing source map files:
Source-Map-Fehler: Error: request failed with status 404
Ressourcen-Adresse: http://localhost:8080/webapp/modules.gz/bootstrap5/tooltip.js
Source-Map-Adresse: tooltip.js.map
And I don't know how to resolve this. Tapestry stores all the modules that are actually used in this modules.gz path. I have to knowledge of the inner workings of this. In the debugger I can browser this path and only the files that have been loaded via require() calls are listed their. Obviously, the source map files are missing. Is there a way to either resolve the issue or at least remove the warnings without the need to edit all the Bootstrap5 JS files? Since it is those JS files that refer to the source map files.
Thanks!

Using D3.JS and the sankey plugin in a require.js module

I'm trying to build a requirejs module giving client code the options to render stuff with d3.js. The first plugin I want to use is a sankey diagram.
My module so far:
define(['d3'], function(ignore) {
console.log("bef", d3);
require(['sankey.js']);
console.log("aft", d3);
d3.sankey();
return {
...
d3: d3,
renderSankey: function(options) {
...
}
}
The sankey.js script uses the global d3 variable and adds the function sankey(). (I tried both btw, define(['d3'], function(ignore) and define(['d3'], function(d3), exactly the same result).
The error: TypeError: d3.sankey is not a function, no matter if I try to call it directly as the code shows or like this.d3.sankey() in the renderSankey function.
The console output says (both times, before and after the require(...) call:
sankey: d3.sankey()
No matter what I try, it won't work. I feel like I missed something JS specific about shadowing, but why is there a sankey function, when I console.log the object and a row later, when I try to call I get an error? What am I doing wrong?
info:
I'm using this inside a splunk html dashboard, this is maybe important...
I don't want the client code to import the dependicies (with about 100 plugins to come, this would be a pain)
When I just copy the content of the sankey.js into my module, everything works fine
/edit: Here is the Require configuration (given by the Splunk Dashboard)
require.config({
baseUrl: "{{SPLUNKWEB_URL_PREFIX}}/static/js",
waitSeconds: 0 // Disable require.js load timeout
});
The require call you are using to load sankey is asynchronous. It will launch the loading of sankey but by the time require returns, sankey is not loaded. You should change your code to:
define(['d3', 'sankey'], function (d3) {
d3.sankey();
I take it that d3 also leaks the symbol d3 in the global space but AMD modules should not rely on global symbols unless these are part of the runtime environment (e.g. window, document).
You also need to set your RequireJS configuration to make sankey dependent on d3 because the define above does not by itself ensure that d3 will load before sankey. So you need this in your configuration:
shim: {
sankey: ['d3']
}
This makes sankey dependent on d3. (Note that shim can only be used to affect the loading of files that are not proper AMD module. sankey does not call define to register itself, and thus is not a proper AMD module, and we can use shim for it.)
Also, module names should generally not have .js in them so when you want to load the plugin, load it as sankey, not sankey.js.
Okay, I think #Louis and I just misunderstood each other. This may be caused by my own stupidity, since I wasn't aware that a configuration of require.js can be done anywhere (and not only once in the root file). How ever, to still get the Splunk specific part I post this answer (instead of accepting Louis'):
I added a new app to my splunk environment to (a viz app). I actually configure the dependencies first (in the by other splunk apps loadable d3-viz module):
require.config({
paths: {
'd3': '../app/D3_Viz/d3', // d3.js
'sankey': '../app/D3_Viz/sankey', // sankey.js
'XYZ': 'all the paths go here'
},
shim: {
'sankey': ['d3'],
'XYZ': ['d3'],
// all the dependecies go here
}
});
define(['splunkjs/ready!', 'jquery', 'd3'],
function(mvc, $, ignore) {
var d3Vis = {
...
renderSankey: function(options) {
// load dependencies dynamically
require(['sankey'], function() {
// actually render things
});
},
renderXYZ: function(options) {
require(['XYZ'], function() {
...
});
},
...
}
}
return d3Vis;
All my dependencies can be configured in the viz-app (and not in the client code using the app, this has been my fundamental missunderstanding of require.js); the only thing to do is loading the app/viz as a whole (in this example in a HTML dashboard:
require([
"splunkjs/mvc",
"splunkjs/mvc/utils",
"splunkjs/mvc/tokenutils",
"underscore",
"jquery",
"splunkjs/mvc/simplexml",
"splunkjs/mvc/headerview",
"splunkjs/mvc/footerview",
...
"../app/D3_Viz/viz"
],
function(
mvc,
utils,
TokenUtils,
_,
$,
DashboardController,
HeaderView,
FooterView,
...
d3Viz
){
... splunk specific stuff
// No dependencies have to be configured
// in the client code
d3Viz.renderSankey({...});
}
);

RequireJS not loading modules properly using karma and typescript

I am trying to set up unit testing for a SPA using karma/jasmine
First of all, the following test runs just fine in karma:
/// <reference path="../../definitions/jasmine/jasmine.d.ts" />
/// <reference path="../../src/app/domain/core/Collections.ts"/>
define(["app/domain/core/Collections"], (collections) => {
describe('LinkedList', () => {
it('should be able to store strings for lookup', () => {
var list = new collections.Collections.LinkedList<string>();
list.add("item1");
expect(list.first()).toBe("item1");
});
});
});
However, collections is of type anyso that I can not use it for type declarations, thus I'm missing intellisense and whatnot when I am writing my tests. No good!
The problem arises when I try to re-write the test to a more TypeScript friendly format:
/// <reference path="../../definitions/jasmine/jasmine.d.ts" />
/// <reference path="../../src/app/domain/core/Collections.ts"/>
import c = require("./../../src/app/domain/core/Collections");
describe('LinkedList', () => {
it('should be able to store strings for lookup', () => {
var list: c.Collections.LinkedList<string> = new c.Collections.LinkedList<string>();
list.add("item1");
expect(list.first()).toBe("item1");
});
});
This compiles just fine, I get my type information for handy intellisense etc, but now karma throws an error.
It turns out it is trying to load the module without the .js postfix, indicated by the following error messages:
There is no timestamp for /base/src/app/domain/core/Collections!
Failed to load resource: the server responded with a status of 404 (Not Found)
(http://localhost:9876/base/src/app/domain/core/Collections)
Uncaught Error: Script error for: /base/src/app/domain/core/Collections
I'm gonna stop here for now, but if it will help I am glad to supply my karma config file, test-main and so on. But my hope is that someone has encountered this exact problem before and might be able to point me in the right direction.
My typescript is compiled with the AMD flag.
It is not a TypeScript problem. We encountered the same problem. Turns out that karma "window.__karma__.files" array includes all files included in the test, including the .js extenstion.
Now requireJS does not work when supplying the .js extension. To fix it, in our main-test.js file, we created a variable "tests" by filtering all the *Spec.js files and then we removed the .js from the file name as requireJS needs it to be. More information here: http://karma-runner.github.io/0.8/plus/RequireJS.html
Below is how we did it (based on the info supplied in the link above):
main-test.js
console.log('===========================================')
console.log('=================TEST FILES================')
var tests = Object.keys(window.__karma__.files).filter(function (file) {
return /\Spec\.js$/.test(file);
}).map(function (file) {
console.log(file);
return file.replace(/^\/base\/|\.js$/g, '');
});
console.log('===========================================')
console.log('===========================================')
require.config({
baseUrl:'/base',
paths: {
jquery :["http://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min", "lib/jquery"],
angular : ["https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.14/angular.min", "lib/angular"],
angularMocks: 'app/vendors/bower_components/angular-mocks/angular-mocks',
},
shim: {
'angularMocks': {
deps: ['angular'],
exports: 'angular.mock'
}
},
deps: tests,
callback: window.__karma__.start
});
Also make sure you have supplied the files to be tested in your karma.config.js file, more details here: http://karma-runner.github.io/0.8/plus/RequireJS.html same as the link above.
Hope it helps
It turns out it is trying to load the module without the .js postfix,
That is the perhaps not the actual source of the error. Actually it is looking at /base/src/app/domain/core/Collections and not app/domain/core/Collections (as in your manual type unsafe way). Notice base/src/ that shouldn't be there.

how to optimize project using requireJS if we have defined some maps in config?

I have a require.config in my main like the following.
require.config({
baseUrl:'scripts/',
paths:{
jquery:'shell/lib/jquery/jquery-1.7.1'
// many libraries and modules are aliased here
},
map:{
'*':{
'underscore':'shell/lib/underscore/underscore'
// a few other modules are mapped here
}
}
});
I did this because the files defined in map are using internal dependencies(in their respective folders) using relative paths.
Now when I run optimizer, the modules defined in path are saved as module IDs, like jquery saved as jquery while those in map are getting complete paths, like 'underscore' as 'shell/lib/underscore/underscore' instead of 'underscore'.
This is causing problems as I am using 'underscore' in other modules also and there the optimized file is having 'underscore' instead of 'shell/lib/underscore/underscore'.
Is there some specific way to optimize when we give map configs or something I am missing? Please tell me how to fix it.
Thanks
I'm not sure to understand the issue:
This is causing problems as I am using 'underscore' in other modules also and there the optimized file is having 'underscore' instead of 'shell/lib/underscore/underscore'.
This seems to be the expected behavior, you mapped underscore to that path for all modules. So basically you are telling to r.js: each time that you find the underscore dependency rewrite it to shell/lib/underscore/underscore. If your modules use "internal paths" and you want do do the opposite (make them to reference underscore), you need to do the opposite mapping:
'some/path/underscore': 'underscore'
In that case all the modules will be pointing to the same underscore module. Even those that use some strange path for underscore.
In the extreme case that you need to control how r.js writes modules on disk. You can use the onBuildWrite property (see https://github.com/jrburke/r.js/blob/master/build/example.build.js#L517).
For example:
onBuildWrite: function ( moduleName, path, contents ) {
if ( path === './src/somefile.js' ) {
return contents.replace(/^define\('src\/underscore'/, "define('underscore'");
} else {
return contents;
}
}
This example is a "hack" that tell to r.js: when you process somefile.js, replace src/underscore with underscore (is exactly what you do with map... but is just to show you how you can use onBuildWrite to do nasty things).

Is it possible to stop requireJS from adding the .js file extension automatically?

I'm using requireJS to load scripts. It has this detail in the docs:
The path that is used for a module name should not include the .js
extension, since the path mapping could be for a directory.
In my app, I map all of my script files in a config path, because they're dynamically generated at runtime (my scripts start life as things like order.js but become things like order.min.b25a571965d02d9c54871b7636ca1c5e.js (this is a hash of the file contents, for cachebusting purposes).
In some cases, require will add a second .js extension to the end of these paths. Although I generate the dynamic paths on the server side and then populate the config path, I have to then write some extra javascript code to remove the .js extension from the problematic files.
Reading the requireJS docs, I really don't understand why you'd ever want the path mapping to be used for a directory. Does this mean it's possible to somehow load an entire directory's worth of files in one call? I don't get it.
Does anybody know if it's possible to just force require to stop adding .js to file paths so I don't have to hack around it?
thanks.
UPDATE: added some code samples as requested.
This is inside my HTML file (it's a Scala project so we can't write these variables directly into a .js file):
foo.js.modules = {
order : '#Static("javascripts/order.min.js")',
reqwest : 'http://5.foo.appspot.com/js/libs/reqwest',
bean : 'http://4.foo.appspot.com/js/libs/bean.min',
detect : 'order!http://4.foo.appspot.com/js/detect/detect.js',
images : 'order!http://4.foo.appspot.com/js/detect/images.js',
basicTemplate : '#Static("javascripts/libs/basicTemplate.min.js")',
trailExpander : '#Static("javascripts/libs/trailExpander.min.js")',
fetchDiscussion : '#Static("javascripts/libs/fetchDiscussion.min.js")'
mostPopular : '#Static("javascripts/libs/mostPopular.min.js")'
};
Then inside my main.js:
requirejs.config({
paths: foo.js.modules
});
require([foo.js.modules.detect, foo.js.modules.images, "bean"],
function(detect, images, bean) {
// do stuff
});
In the example above, I have to use the string "bean" (which refers to the require path) rather than my direct object (like the others use foo.js.modules.bar) otherwise I get the extra .js appended.
Hope this makes sense.
If you don't feel like adding a dependency on noext, you can also just append a dummy query string to the path to prevent the .js extension from being appended, as in:
require.config({
paths: {
'signalr-hubs': '/signalr/hubs?noext'
}
});
This is what the noext plugin does.
requirejs' noext plugin:
Load scripts without appending ".js" extension, useful for dynamic scripts...
Documentation
check the examples folder. All the info you probably need will be inside comments or on the example code itself.
Basic usage
Put the plugins inside the baseUrl folder (usually same folder as the main.js file) or create an alias to the plugin location:
require.config({
paths : {
//create alias to plugins (not needed if plugins are on the baseUrl)
async: 'lib/require/async',
font: 'lib/require/font',
goog: 'lib/require/goog',
image: 'lib/require/image',
json: 'lib/require/json',
noext: 'lib/require/noext',
mdown: 'lib/require/mdown',
propertyParser : 'lib/require/propertyParser',
markdownConverter : 'lib/Markdown.Converter'
}
});
//use plugins as if they were at baseUrl
define([
'image!awsum.jpg',
'json!data/foo.json',
'noext!js/bar.php',
'mdown!data/lorem_ipsum.md',
'async!http://maps.google.com/maps/api/js?sensor=false',
'goog!visualization,1,packages:[corechart,geochart]',
'goog!search,1',
'font!google,families:[Tangerine,Cantarell]'
], function(awsum, foo, bar, loremIpsum){
//all dependencies are loaded (including gmaps and other google apis)
}
);
I am using requirejs server side with node.js. The noext plugin does not work for me. I suspect this is because it tries to add ?noext to a url and we have filenames instead of urls serverside.
I need to name my files .njs or .model to separate them from static .js files. Hopefully the author will update requirejs to not force automatic .js file extension conventions on the users.
Meanwhile here is a quick patch to disable this behavior.
To apply this patch (against version 2.1.15 of node_modules/requirejs/bin/r.js) :
Save in a file called disableAutoExt.diff or whatever and open a terminal
cd path/to/node_modules/
patch -p1 < path/to/disableAutoExt.diff
add disableAutoExt: true, to your requirejs.config: requirejs.config({disableAutoExt: true,});
Now we can do require(["test/index.njs", ...] ... and get back to work.
Save this patch in disableAutoExt.diff :
--- mod/node_modules/requirejs/bin/r.js 2014-09-07 20:54:07.000000000 -0400
+++ node_modules/requirejs/bin/r.js 2014-12-11 09:33:21.000000000 -0500
## -1884,6 +1884,10 ##
//Delegates to req.load. Broken out as a separate function to
//allow overriding in the optimizer.
load: function (id, url) {
+ if (config.disableAutoExt && url.match(/\..*\.js$/)) {
+ url = url.replace(/\.js$/, '');
+ }
+
req.load(context, id, url);
},
The patch simply adds the following around line 1887 to node_modules/requirejs/bin/r.js:
if (config.disableAutoExt && url.match(/\..*\.js$/)) {
url = url.replace(/\.js$/, '');
}
UPDATE: Improved patch by moving url change deeper in the code so it no longer causes a hang after calling undef on a module. Needed undef because:
To disable caching of modules when developing with node.js add this to your main app file:
requirejs.onResourceLoad = function(context, map)
{
requirejs.undef(map.name);
};

Categories