Why is _ undefined when using Miso? - javascript

I'm trying to use Miso (http://misoproject.com/dataset/), and on of the dependencies is underscore.js. I'm using require.js, and keep getting an error in the console: "Uncaught ReferenceError: _ is not defined." Here is my main.js file:
require(["jquery", "underscore", "miso"], function($, _, miso) {
$(function() {
var ds = new Miso.Dataset({
url : "/data/ma_region.csv",
delimiter : " ",
});
});
});
Any ideas? Thanks in advance.

Miso is expecting the _ underscore in the global scope.
In Miso's code:
(function(global, _) {
/* has bunch of stuff using underscore */
}(this, _));
Which means that in this last part (this, _), it doesn't have reference to _ underscore library because it's defined within RequireJS which means it exists in the anonymous function scope.
So you need to load _ underscore when and wrap Miso in a module, eg:
define(['underscore'], function(_) {
/** Miso's code here because Miso is expecting the _ **/
});
You'll need to include this for the other dependencies listed on Miso's website http://misoproject.com/dataset/tutorials/quickstart:
Dependencies
If you chose to include the production version without
built in dependencies, you may need to include them yourself. Dataset
requires the following libraries:
LoDash 0.9.0
Underscore.math.js (unknown version)
Underscore.deferred.js 0.2.0
moment.js 1.7.2 (for 'time' data type)
If you are using IE, you will want to include json2.js:
json2.js 2011-10-19
Alternatively, I recommend using the versions of Miso that already prepackage the dependencies so you don't have to worry about this.

Ensure that your underscore library is named underscore.js and it is in the same same directory as your javascript code. This is the baseURL for require.js.
If this isn't the case, you should configure paths. Refer http://requirejs.org/docs/api.html#config-paths

Related

Require.js define object is somehow being inserted to my code - gulp.js

I'm running a gulp-concat script, which concats jquery, slick-carousel, t.js and my index.js files.
const pack = () => {
return gulp.src(['./node_modules/jquery/**/jquery.js', './node_modules/slick-carousel/**/slick.js', './assets/js/t.js-master/t.js', './js/index.js'])
// .pipe(gulp_babel({
// 'presets': ['#babel/env'],
// 'plugins': ["transform-remove-strict-mode"]
// }))
.pipe(gulp_concat('main.js'))
// .pipe(gulp_uglify())
.pipe(gulp.dest('./build'));
}
As you can see, I removed any pipes that might be causing the issue. The only task running is gulp-concat. (index.js is all in ES5 and I'm running on latest version of firefox, no need for babel atm) When I open my page, however, I get the error
Uncaught ReferenceError: define is not defined
Looking at main.js, I found a define object at the end of the jquery section - but only in the concatinated file, not the jquery in node_modules. I didn't add this, and I'm not using require.js as far as I know:
define( [
"./core",
"./selector",
"./traversing",
"./callbacks",
"./deferred",
"./deferred/exceptionHook",
"./core/ready",
"./data",
"./queue",
"./queue/delay",
"./attributes",
"./event",
"./event/focusin",
"./manipulation",
"./manipulation/_evalUrl",
"./wrap",
"./css",
"./css/hiddenVisibleSelectors",
"./serialize",
"./ajax",
"./ajax/xhr",
"./ajax/script",
"./ajax/jsonp",
"./ajax/load",
"./core/parseXML",
"./core/parseHTML",
"./effects",
"./effects/animatedSelector",
"./offset",
"./dimensions",
"./deprecated",
"./exports/amd",
"./exports/global"
], function( jQuery ) {
"use strict";
return jQuery;
} ); // jQuery seems to end here
How is this extra code being added, and how might I avoid it? I'm also using browserSync, but don't think that's related.
I've just checked the source of jQuery and there is a file:
https://github.com/jquery/jquery/blob/3.5.1/src/jquery.js
So what you need to do is to simply exclude it and it should fix the issue :)

Are RequireJS "shim" needed for Backbone.js?

It seems that recent versions of Backbone.js and Underscore.js support AMD.
So am I correct in assuming that it is no longer needed to "shim" these libraries in the require.js configuration?
Yes, you are correct, no shim needed. And it's easy to test, here's the simplest setup:
requirejs.config({
/**
* Paths to lib dependencies.
*
* Use non-minified files where possible as they will be minified (and
* optimized via uglify) on release build (r.js)
*/
paths: {
"jquery": "libs/jquery/dist/jquery",
"underscore": "libs/underscore/underscore",
"backbone": "libs/backbone/backbone",
},
deps: ["app"] // starts the app
});
And to make sure it works and it's not the global Underscore that's used:
// I'm using Underscore as to avoid conflicting with the global _
// but you could use _ as the name for the local variable as well.
define(['backbone', 'underscore'], function(Backbone, Underscore) {
console.log("Backbone:", Backbone.VERSION)
console.log("Local Underscore:", Underscore.VERSION);
console.log("Global Underscore:", _.VERSION, _ === Underscore);
});
For Backbone, it's clear in the source that it supports AMD by default:
// Set up Backbone appropriately for the environment. Start with AMD.
if (typeof define === 'function' && define.amd) {
define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
// Export global even in AMD case in case this script is loaded with
// others that may still expect a global Backbone.
root.Backbone = factory(root, exports, _, $);
});
As for Underscore, it is registering itself at the end:
// AMD registration happens at the end for compatibility with AMD loaders
// that may not enforce next-turn semantics on modules. Even though general
// practice for AMD registration is to be anonymous, underscore registers
// as a named module because, like jQuery, it is a base library that is
// popular enough to be bundled in a third party lib, but not be part of
// an AMD load request. Those cases could generate an error when an
// anonymous define() is called outside of a loader request.
if (typeof define === 'function' && define.amd) {
define('underscore', [], function() {
return _;
});
}
Same thing with jQuery:
// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.
// Note that for maximum portability, libraries that are not jQuery should
// declare themselves as anonymous modules, and avoid setting a global if an
// AMD loader is present. jQuery is a special case. For more information, see
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
if ( typeof define === "function" && define.amd ) {
define( "jquery", [], function() {
return jQuery;
} );
}
As #ggozad mentioned:
Well, if underscore is already loaded and available, you do not need
the shim at all. Backbone will happily load. If not, it's probably
because underscore is not actually loaded.
It sounds however wrong to be only partially using require.js, you
might as well AMD-load them all.
I guess that explain why you don't need to load it using require.js

Require module defined in another script

Script A
;(function(g){
define('hotness', [], function() {
function f() {;
console.log('gotem');
}
return f;
});
define('otherModule', [], function() {});
})(this);
Script B
define([
'ScriptA',
], function() {
var hotness = require('hotness')
});
Error: Module name "hotness" has not been loaded yet for context: _
What is the recommended way to require in a definition from ScriptA in ScriptB?
I've also tried:
Script B Alt
define([
'require',
'ScriptA',
'hotness'
], function(require) {
var hotness = require('hotness')
});
Which gives me
Error loading resource ... /hotness.js: No such file or directory
Error: Script error for: hotness
EDIT:
It's important to note that ScriptA stands as is and will not be modified. The question is how can I get at the named module in ScriptA from ScriptB.
EDIT2:
I have no control over the HTML or any other aspect of the page. I must do everything within ScriptB.
EDIT3:
I have an example of something that works but it looks like a horrible antipattern work-around so I didn't even want to mention it:
define(['require'], function(require) {
// why use window? IDK.
// this is just verbatim what is "working" for someone else
window.require(['scriptA'], function(sA) {
//sA never actually used
window.require([
'otherModule'
], function(oM) {
var hotness = require('hotness'),
You should use a bundles configuration. Given what you've described works, you should use:
bundles: {
'scriptA': ['hotness', 'otherModule']
}
This essentially tells RequireJS "when you want to find hotness or otherModule then load scriptA because they are defined there". I use this every now and then to load modules from bundles that have been generated with r.js.
Other than this Joseph the Dreamer is correct that you should not in the same module mix the AMD and CommonJS methods of getting dependencies.
Your ScriptA uses named modules. They must be loaded after RequireJS but prior to any of the dependents. RequireJS does not recommend named modules unless you know what you're doing (like load a library like a regular script, and register it as a module at the same time).
Error: Module name "hotness" has not been loaded yet for context: _
This is a generic RequireJS error, when the module is loaded from the server, but somehow RequireJS can't provide it to the dependent. Usually happens when the module has syntax errors or when there's a circular dependency, among others.
ScriptB also has problems. It's trying to use both AMD style (array dependencies) and CommonJS style (explicit require). Just use one of the two syntaxes. Note that in the CommonJS format, it needs the module to have a first argument named require to trigger CommonJS format of writing.
define(['hotness'], function(hotness) {
// use hotness
});
// or
define(function(require){
var hotness = require('hotness');
// use hotness
});
Error loading resource ... /hotness.js: No such file or directory
Be sure to set a base url. It can be implicit (based on the data-main location) or explicit (using require.config). Module names are usually paths + filenames relative to the base url.
It is advised that you use one file per module, containing a module definition that has no name (the file name becomes the name of the module) and resides somewhere under the set baseUrl.

JavaScript Faux Pas - Let me put global libraries on the window?

I'm using RequireJS. I absolutely hate the double variable syntax of defining a dependency and passing it in as a variable in a callback function. I am therefore attempting the implement the 'Sugar' syntax available in RequireJS.
However, I only want to 'import' global libraries like Backbone, jQuery, Underscore and Marionette once. jQuery and Backbone obviously assign themselves to the Window object but Underscore and Marionette do not.
This is my main.js file:
require.config({
paths: {
"jquery" : "vendor/jquery.min",
"underscore": "vendor/underscore-min",
"backbone" : "vendor/backbone-min",
"marionette" : "vendor/marionette",
"app" : "app/app"
}
});
define(function(require, exports, module) {
// Make these libraries available globally
var jquery = require('jquery');
window.underscore = require('underscore');
var Backbone = require('backbone');
window.marionette = require('marionette');
// Require and start our own app
var app = require('app');
app.start();
});
This obviously stops me from having to import/require each of these core libraries into every subsequent module/component for my application. Taking my code from potentially this (app.js file):
define(function (require, exports, module) {
var jquery = require('jquery'),
underscore = require('underscore'),
Backbone = require('backbone'),
Marionette = require('marionette'),
// module specific libs
mymodule = require('../js/app/module'),
logger = require('../js/app/logger');
return {
start: function () {
var testview = new mymodule();
logger.logme();
}
}
});
To this (better app.js):
define(function (require, exports, module) {
var mymodule = require('../js/app/module'),
logger = require('../js/app/logger');
return {
start: function () {
var testview = new mymodule();
logger.logme();
}
}
});
Much cleaner IMO.
So thoughts? Criticisms? Are these going to play well together? (two already do it themselves - why not for the other two if they are core to the app).
In my head I don't think it will be a problem as long as I don't start hammering every module/component/library onto the global scope but I'm interested for someone more experienced to weigh in.
If I'm doing it wrong or there is a better way let me know!
Thanks
EDIT: After reading your comments, I realized your question has two components. One component is purely syntactical - and my original answer addresses a possible solution to that component. However, to the extent that your solution also incorporates an application design component, whereby dependencies of individual modules are defined at the application level, my answer is that is "bad practice." Dependencies should be defined at the module level (or lower) so that every element of your application is decouplable. This will be an enormous benefit in writing code that is (1) reusable, (2) testable, (3) refactorable. By defining your dependencies at the application level, you force yourself into loading the entire application simply to access a single module, for example, to run a test - and you inhibit rearranging modules or reuse of the same modules in other projects. If you do this, in the long run... you're gonna have a bad time.
Now, to the extent that your question is syntactical...
ORIGINAL ANSWER: I agree that require.js syntax is ugly as hell, annoying to use, and a potential source of difficult to debug errors. My own approach was to implement the following wrapping function (pardon the coffeescript).
# Takes dependencies in the form of a hash of arguments with the format
# { path: "name"}
# Assigns each dependency to a wrapper variable (by default "deps"),
# without the need to list each dependency as an argument of the function.
PrettyRequire = (argHash, callback) ->
deps = new Array()
args = new Array()
#loops through the passed argument, sorts into two arrays.
for propt of argHash
deps.push(propt)
args.push(argHash[propt])
#calls define using the 'dependency' array
define(deps, ()->
deps = new Array()
# assigns the resulting dependencies to properties of the deps object
for arg, i in args
deps[arg] = arguments[i]
# runs callback, passing in 'deps' object
return callback(deps)
)
This code is a simple rewrite which (1) preserves scope and (2) prettifies the syntax. I simply include the function as a part of a internal library that I maintain, and include that library at the outset of any project.
Define can then be called with the following (imho) prettier syntax:
PrettyRequire({
'backbone': 'Backbone'
'vendor/marionette': 'Marionette'
'../js/app/module': 'myModule'
}, (deps)->
Backbone.Model.extend(...) # for dependencies that assign themselves to global
deps.myModule(...) # for all dependencies (including globals)
)
That's my approach, to the extent that it's responsive to your question. It's worth noting also that your apps will take a (small) performance hit as a result of the increased overhead, but as long as you're not calling too many sub modules, it shouldn't be too much of an issue, and to me, it's worth it not to have to deal with the double syntax you describe.

Explicit vs. implicit dependency handling in require.js

I'll use what I'm actually doing as an example. I have a knockout custom binding that depends on a jquery plugin that itself depends on jQuery UI that of course depends on jQuery. There is another file that depends on another plugin, and another file that depends on jQuery UI, etc. In require.config.js I have:
shim: {
"jquery-ui": {exports: "$", deps: ["jquery"]},
"jquery-plugin1": {exports: "$", deps: ["jquery-ui"]},
"jquery-plugin2": {exports: "$", deps: ["jquery-ui"]}
}
This works, and then in corresponding files I may do:
define(["jquery-plugin1"], function ($) {
However, I could also do:
define(["jquery", "jquery-ui", "jquery-plugin1"], function ($) {
There is also the case where a file may depend on both plugins:
// which one?
define(["jquery-plugin1", "jquery-plugin2"], function ($) {
define(["jquery", "jquery-ui", "jquery-plugin1", "jquery-plugin2"], function ($){
There may also be other dependencies such as knockout custom bindings (which don't need to export anything) so I may end up with:
define(["jquery-plugin1", "model1", "model2",
"ko-custom1", "ko-custom2", "ko-custom3",
"jquery-plugin2"],
function ($, m1, m2) {
This file may also depend on jQuery UI (which depends on jQuery), but those are both loaded implicitly via the plugins.
My question is is it better to be explicit about all requirements (i.e. include jQuery and jQuery-UI in define) and possibly leave off the exports, or is the less-verbose nested dependency handling preferred?
This is a great question and becomes very relevant when using something like AngularJS dependency injection as those dependencies need to exist before the module is registered. So this won't work:
define(['angular'],function (angular) {
return angular.module('myModule', ['mySubmodule']);
});
// Error: [$injector:nomod] Module 'mySubmodule' is not available!
You need to define the AMD dependency as well:
define(['angular','./mySubmodule'],function (angular) {
return angular.module('myModule', ['mySubmodule']);
});
It might be subjective but I find it easier to reason about it by having each module define it's own dependencies explicitly and letting requireJS resolve them instead of leaving it up to faith that an out-of-scope module has already defined them which breaks modularity.
By doing this you also know that your AMD modules can be tested independently without rewiring the missing dependency.

Categories

Resources