I'm having trouble rewriting this to work in 'strict' mode. Since 'this' is not defined explicitly I'm getting jshint errors on compile. I'm thinking my brain is just not thinking abstractly enough to find a creative solution. Any help would be appreciated. Code adapted from the Universal Module Definition Github repo: https://github.com/umdjs/umd/blob/master/returnExports.js
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD Module
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node Module
module.exports = factory();
} else {
// Browser Global
root.returnExports = factory();
}
}(this, function () {
return {};
}));
Looking at your code, I see that root is only actually used in the case that you are in a browser, which simplifies things.
That means that we can replace this with the following expression:
typeof window !== "undefined" ? window : undefined
This is valid in strict mode (I tried it in Node, it returns undefined, no errors), and JSHint.com allowed it.
If you need the global object in other cases as well, you can chain the ternary expressions.
Related
Running a script via NodeJS which imports from a library is failing because the library references the window variable. Even though in the library, it looks like this:
{
baseUrl: (typeof window !== undefined ? window.location.origin : '') + "/blah",
}
This line still results in the following error when running the script via NodeJS:
ReferenceError: window is not defined
I thought it was enough to add the typeof window !== undefined check but clearly that is not the case. What am I missing here? (FWIW the imported module is a UMD module.)
typeof gives you a string so you need to be comparing to "undefined", not undefined. Change your code to this:
{
baseUrl: (typeof window !== "undefined" ? window.location.origin : '') + "/blah",
}
I got a doozie here. In Electron's main process, I require in the function below to setup event handlers with ipcMain. This keeps the main.js file a little more streamlined. All went swimmingly until I wrote some validation code to ensure that the user passes in an object. I use typeof all the time for this purpose, and never have I had an issue. But in Electron I am getting:
A JavaScript error occurred in the main process - TypeError: Cannot
assign to read only property 'exports' of object '# '
The code:
const {ipcMain} = require('electron');
function ipcSetup() {
ipcMain.on('123', function(event, arg) {
// this blows chunks...
if(arg && typeof arg === 'object') {
console.log(`All good....`);
}
// and if you comment that out, this use of "typeof" does the same thing
console.log(typeof arg);
// and to eliminate 'arg' as the issue...
let a = 1;
console.log(typeof a); // expect 'number', get Exception
});
}
module.exports = ipcSetup;
I didn't know if Electron is using Object.defineProperty to make arg read only, but typeof is not making an assignment here anyway, and I eliminated arg so this error makes no sense. Environment is Electron 1.8.4 on Node 8.2.1 using electron-vue
If you're importing that module in another module that uses ES6 import/export syntax, using typeof apparently causes this. I think this is because webpack doesn't support mixing the two syntaxes. But it is quite funny that it would work fine if you didn't use the typeof operator...
We are working on templating library with helpers (Dust.js), the helper library has below design pattern inside the codebase.
(function(root, factory) {
if (typeof define === 'function' && define.amd && define.amd.dust === true) {
define(['dust-linkedin'], factory);
} else if (typeof exports === 'object') {
module.exports = factory(require('dust-linkedin'));
// module.exports = factory; // <<--- This is working on v8
} else {
factory(root.dust);
}
}(this, function (dust) {
...
});
In node v6, exporting factory(require('dust-linkedin')) is working fine, but after switching to node v8 (v8.9.3) and we see helpers are not getting executed, changing factory(require('dust-linkedin')) to factory inside the helper library, things starts working.
In node v8, when require('dust-linkedin') does it create a new context/object because of which we are losing all our helpers? Is there any change in commonjs require behavior?
The solution was fixed in the PR https://github.com/krakenjs/festucam/pull/4
I thought I'd be able to expose my JS library to Require.js, and make it dependent on jQuery, Backbone, and Underscore, with the following code:
} else if (typeof define === 'function' && define.amd) {
define(['backbone', 'jquery', 'underscore'], function(Backbone, $, _) {
return factory(root, Backbone, $, _);
});
where factory is a function that returns my library. That seems ok, except that the module name "backbone" appears to be hard-coded to the filesystem path "{Require root}/backbone". Even if I define a path in my Require config before requiring the library:
'backbone': '/some/other/path/backbone'
my browser still gives me an error:
GET http://localhost:8000/js/backbone.js 404 (NOT FOUND)
Can anyone explain how I can define "this library depends on Backbone" without saying "this library requires exactly {root}/backbone.js"?
That is exactly what Backbone does so I'm not sure why you're having problems. Can you post the code of how you're requiring this library and where you're defining your require config?
if (typeof define === 'function' && define.amd) {
define(['underscore', 'jquery', 'exports'], function(_, $, exports) {
Suppose I have a JS-library, neatly wrapped in a define('myModule', function(myModule) { return myModule.someObject; });
How could I bind the myModule.someObject to global scope (please don't ask why, I know modular programming has a lot of benefits over putting stuff on the global scope), without using requirejs or any other module handling framework?
The thing is: while developing, I'd like to use requirejs. The library that we build should be able to be included by somebody using requirejs (AMD, CommonJS, whatever), but should also be available as window.SomeObject for the people that don't want to use require just for the sake of being able to use our SomeObject. After the development phase, all code will be minified and obfuscated to a single JS file.
I think I'm just googling with the wrong search terms, because all I can find is an answer to the question how to include code that isn't wrapped in a requirejs friendly define function.
Any ideas on this would greatly be appreciated. Thanks!
--- EDIT ---
My file (before it all started) looked like:
(function(define, global) {
define([a,b,c],function(theA, theB, theC) {
return theA + theB + theC; // or something, it doesn't matter
});
})(define, this);
I'm thinking of something like this:
(function(define, global) {
// same as above
})(typeof define === 'function'
? define
: function(factory /* need more args? */) { /* solution here */ }, this);
But I'm not sure how to implement it properly...
I guess you need to wrap your modules so that they could be accessed without requirejs:
if ( typeof define === "function" && define.amd ) {
define( "mymodule", [], function () {
// do your logic
return mystuff;
} );
} else {
// do your logic
window.mystuff = mystuff;
}
Look at jQuery as an example.
I would refrain from giving your module an id if you can help it, it makes it less portable. jQuery is incredibly annoying that it forces you to set a jquery path option, but they did it for compatibility reasons. Always prefer anonymous modules if you can.
From the jQuery source
// 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.
James Burke goes into a little more detail here also.
I would instead use a more common example from the umdjs repository:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], factory);
} else {
// Browser globals
root.amdWeb = factory(root.b);
}
}(this, function (b) {
//use b in some fashion.
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {};
}));
For another example that also supports CommonJS, check out the reqwest library:
!function (name, context, definition) {
if (typeof module != 'undefined' && module.exports) module.exports = definition()
else if (typeof define == 'function' && define.amd) define(definition)
else context[name] = definition()
}('reqwest', this, function () {
return {};
});
How can I provide a library to others that does not depend on RequireJS?
This allows you to ship code that does not ship with all of RequireJS, and allows you to export any kind of API that works on a plain web page without an AMD loader.
You need to make a build config file which uses wrap and almond.
It all feels pretty dirty, but I've had it working (by following the almond ReadMe) with exactly what you're describing.