best practices for cross commonjs/browser development - javascript

Currently, I use a few defines via the Google Closure Compiler along the lines of IS_CJS and IS_BROWSER, and just have different files that get built (browser.myproject.js, cjs.myproject.js, etc).
Is this the standard way of doing things? If not, what is it and what are the advantages?

I've been using the following preamble in all my projects, for libraries that are loaded by both browser and server code:
if (define === undefined) {
var define = function(f) {
require.paths.unshift('.');
f(require, exports, module);
};
}
define(function(require, exports, module) {
...
// main library here
...
// use require to import dependencies
var v = require(something);
...
// use exports to return library functions
exports.<stuff> = { some stuff };
...
});
This works to load the library with a require(<library>) call running on my node server, as well as with a require(<library>) call with RequireJS. On the browser, nested require calls are pre-fetched by RequireJS prior to library execution, on Node these dependencies are loaded synchronously. Since I'm not using my libraries as stand-alone scripts (via a script tag in the html), and only as dependencies for scripts loaded via the script tag, this works well for me.
However, looking at stand-alone libraries, it looks like the following preamble seems to be the most flexible. (cut and paste from the Q promise library
(function (definition, undefined) {
// This file will function properly as a <script> tag, or a module
// using CommonJS and NodeJS or RequireJS module formats. In
// Common/Node/RequireJS, the module exports the Q API and when
// executed as a simple <script>, it creates a Q global instead.
// The use of "undefined" in the arguments is a
// micro-optmization for compression systems, permitting
// every occurrence of the "undefined" variable to be
// replaced with a single-character.
// RequireJS
if (typeof define === "function") {
define(function (require, exports, module) {
definition(require, exports, module);
});
// CommonJS
} else if (typeof exports === "object") {
definition(require, exports, module);
// <script>
} else {
Q = definition(undefined, {}, {});
}
})(function (serverSideRequire, exports, module, undefined) {
...
main library here
...
/*
* In module systems that support ``module.exports`` assignment or exports
* return, allow the ``ref`` function to be used as the ``Q`` constructor
* exported by the "q" module.
*/
for (var name in exports)
ref[name] = exports[name];
module.exports = ref;
return ref;
});
While wordy, it's impressively flexible, and simply works, no matter what your execution environment is.

You can use uRequire that converts modules written in either AMD or CommonJS to either AMD, CommonJS or UMD through a template system.
Optionally uRequire builds your whole bundle as a combinedFile.js that runs in ALL environments (nodejs, AMD or module-less browser < script/>) thats using rjs optimizer and almond under the hood.
uRequire saves you from having to maintain any boilerplate in each module - just write plain AMD or CommonJS modules (as .js, .coffee, .coco, .ls etc) without gimmicks.
Plus you can declaratively add standard functionality such as exporting a module to global such as window.myModule along with a noConflict() method, or have runtimeInfo (eg __isNode, __isAMD) selectively or replace/remove/inject a dependency while building, automatically minify, manipulate module code and much more.
All of these configuration options can be turned on and off per bundle OR per module, and you can have different build profiles (development, test, production etc) that derive(inherit) from each other.
It works great with grunt through grunt-urequire or standalone and it has a great watch option that rebuilds ONLY changed files.

Have you tried this: https://github.com/medikoo/modules-webmake#modules-webmake ?
It's the approach I'm taking, and it works really well. No boilerplate in a code and you can run same modules on both server and client side

Related

Packaging-up Browser/Server CommonJS modules with dependancies

Lets say I'm writing a module in JavaScript which can be used on both the browser and the server (with Node). Lets call it Module. And lets say that that Module would benefit from methods in another module called Dependancy. Both of these modules have been written to be used by both the browser and the server, à la CommonJS style:
module.js
if (typeof module !== 'undefined' && module.exports)
module.exports = Module; /* server */
else
this.Module = Module; /* browser */
dependancy.js
if (typeof module !== 'undefined' && module.exports)
module.exports = Dependancy; /* server */
else
this.Dependancy = Dependancy; /* browser */
Obviously, Dependancy can be used straight-out-of-the-box in a browser. But if Module contains a var dependancy = require('dependency'); directive in it, it becomes more of a hassle to 'maintain' the module.
I know that I could perform a global check for Dependancy within Module, like this:
var dependancy = this.Dependancy || require('dependancy');
But that means my Module has two added requirements for browser installation:
the user must include the dependency.js file as a <script> in their document
and the user must make sure this script is loaded before module.js
Adding those two requirements throws the idea of an easy-going modular framework like CommonJS.
The other option for me is that I include a second, compiled script in my Module package with the dependency.js bundled using browserify. I then instruct users who are using the script in the browser to include this script, while server-side users use the un-bundled entry script outlined in the package.json. This is preferable to the first way, but it requires a pre-compilation process which I would have to run every time I changed the library (for example, before uploading to GitHub).
Is there any other way of doing this that I haven't thought of?
The two answers currently given are both very useful, and have helped me to arrive at my current solution. But, as per my comments, they don't quite satisfy my particular requirements of both portability vs ease-of-use (both for the client and the module maintainer).
What I found, in the end, was a particular flag in the browserify command line interface that can bundle the modules and expose them as global variables AND be used within RequireJS (if needed). Browserify (and others) call this Universal Module Definition (UMD). Some more about that here.
By passing the --standalone flag in a browserify command, I can set my module up for UMD easily.
So...
Here's the package.js for Module:
{
"name": "module",
"version": "0.0.1",
"description": "My module that requires another module (dependancy)",
"main": "index.js",
"scripts": {
"bundle": "browserify --standalone module index.js > module.js"
},
"author": "shennan",
"devDependencies": {
"dependancy": "*",
"browserify": "*"
}
}
So, when at the root of my module, I can run this in the command line:
$ npm run-script bundle
Which bundles up the dependancies into one file, and exposes them as per the UMD methodology. This means I can bootstrap the module in three different ways:
NodeJS
var Module = require('module');
/* use Module */
Browser Vanilla
<script src="module.js"></script>
<script>
var Module = module;
/* use Module */
</script>
Browser with RequireJS
<script src="require.js"></script>
<script>
requirejs(['module.js'], function (Module) {
/* use Module */
});
</script>
Thanks again for everybody's input. All of the answers are valid and I encourage everyone to try them all as different use-cases will require different solutions.
Of course you could use the same module with dependency on both sides. You just need to specify it better. This is the way I use:
(function (name, definition){
if (typeof define === 'function'){ // AMD
define(definition);
} else if (typeof module !== 'undefined' && module.exports) { // Node.js
module.exports = definition();
} else { // Browser
var theModule = definition(), global = this, old = global[name];
theModule.noConflict = function () {
global[name] = old;
return theModule;
};
global[name] = theModule;
}
})('Dependency', function () {
// return the module's API
return {
'key': 'value'
};
});
This is just a very basic sample - you can return function, instantiate function or do whatever you like. In my case I'm returning an object.
Now let's say this is the Dependency class. Your Module class should look pretty much the same, but it should have a dependency to Dependency like:
function (require, exports, module) {
var dependency = require('Dependency');
}
In RequireJS this is called Simplified CommonJS Wrapper: http://requirejs.org/docs/api.html#cjsmodule
Because there is a require statement at the beginning of your code, it will be matched as a dependency and therefore it will either be lazy loaded or if you optimize it - marked as a dependency early on (it will convert define(definition) to define(['Dependency'], definition) automatically).
The only problem here is to keep the same path to the files. Keep in mind that nested requires (if-else) won't work in Require (read the docs), so I had to do something like:
var dependency;
try {
dependency = require('./Dependency'); // node module in the same folder
} catch(err) { // it's not node
try {
dependency = require('Dependency'); // requirejs
} catch(err) { }
}
This worked perfectly for me. It's a bit tricky with all those paths, but at the end of the day, you get your two separate modules in different files which can be used on both ends without any kind of checks or hacks - they have all their dependencies are work like a charm :)
Take a look at webpack bundler.
You can write module and export it via module exports. Then You can in server use that where you have module.export and for browser build with webpack. Configuration file usage would be the best option
module.exports = {
entry: "./myModule",
output: {
path: "dist",
filename: "myModule.js",
library: "myModule",
libraryTarget: "var"
}
};
This will take myModule and export it to myModule.js file. Inside module will be assigned to var (libraryTarget flag) named myModule (library flag).
It can be exported as commonJS module, war, this, function
Since bundling is node script, this flag values can be grammatically set.
Take a look at externals flag. It is used if you want to have special behavior for some dependencies. For example you are creating react component and in your module you want to require it but not when you are bundling for web because it already is there.
Hope it is what you are looking for.

Using RequireJS and AMD to distribute a project that contains internal dependencies

I have an open-source JavaScript form-validation library that I've created. Recently a contributor helpfully modified my library to support AMD. In the past month or two, I have been refactoring my library to enhance maintainability, modularity, and readability. Essentially I have extracted pieces of logic into self-contained modules. However, these modules all reside inside the main module.
After looking at how AMD does things, I feel that it would be beneficial if I am able to split these internal modules into their own separate files. I come from a Java background, and from that perspective, these individual modules seem like classes to me and I'd like to separate them out. This will also help me manage my dependencies better and also enforce proper modularity. I think in the long run, this will make the code much better.
I know that RequireJS has an "optimize" feature whereby it will combine all dependencies into a single file and minimize it.
My question is this: will this minified file also be AMD compatible? That is, will the file expose itself as an AMD module? The dependencies that the project itself has are all internal and I don't want to expose them separately. However, I would still like developers to be able to import my library as a self-contained module.
will this minified file also be AMD compatible? That is, will the file
expose itself as an AMD module?
Require.js doesn't necessary generate a AMD compatible module. You have to make your library AMD compatible. It should happen in your main file. You can learn it from lowdash how to do it. They created their library compatible with Node and Require.js. They basically looking for global variables to detect Node and Require.
/** Detect free variable `exports` */
var freeExports = typeof exports == 'object' && exports;
/** Detect free variable `module` */
var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;
/** Detect free variable `global` and use it as `window` */
var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal) {
window = freeGlobal;
}
At the end:
// if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// Expose Lo-Dash to the global object even when an AMD loader is present in
// case Lo-Dash was injected by a third-party script and not intended to be
// loaded as a module. The global assignment can be reverted in the Lo-Dash
// module via its `noConflict()` method.
window._ = _;
// define as an anonymous module so, through path mapping, it can be
// referenced as the "underscore" module
define(function() {
return _;
});
}
// check for `exports` after `define` in case a build optimizer adds an `exports` object
else if (freeExports && !freeExports.nodeType) {
// in Node.js or RingoJS v0.8.0+
if (freeModule) {
(freeModule.exports = _)._ = _;
}
// in Narwhal or RingoJS v0.7.0-
else {
freeExports._ = _;
}
}
else {
// in a browser or Rhino
window._ = _;
}

How to write an AMD module for use in pages without RequireJS?

I need to re-structure an existing AMD module to make it both usable by pages with/without RequireJS presented. How should I do it, and is there any example code? Preferably, it would be a way without polluting the global namespace, though not a strict requirement.
This is not a bad idea at all, quite often JS libs are required to support a AMD/non AMD environment. Here is one variation of the solution:
!function (name, definition) {
if (typeof module != 'undefined') module.exports = definition()
else if (typeof define == 'function' && define.amd) define(name, definition)
else this[name] = definition()
}('reqwest', function () {
// Module here
});
The only downside is you can't request other dependencies, so this would only be useful in stand alone libraries, like the ones below
Dustin Diaz's Reqwest
Mustache
I recently wrote a gist regarding this topic so I have copied the relevant bits for you below; however, feel free to check out the original Gist for more info.
The following boilerplate allows you to write your module once and have it work in a CJS/NodeJs, AMD, or Browser Global environment.
Best Used When...
You are migrating from namespaced (err, globals) code to either AMD or CJS modules or both.
You can't yet factor out browser globals but also need to test your code via NodeJS (e.g. Mocha)
Benefits & Trade-offs
A single module format allowing you to target AMD, CJS/NodeJS, and legacy browser globals like window.*.
Allows multiple dependencies to be defined.
Run unit tests via CLI/NodeJS runner (e.g. Mocha).
Less pain while incrementally migrating to CJS/NodeJS or AMD modules.
You give up the Java-like namespaces (e.g. com.company.package.module) -- meh, they are a mess anyway.
This (UMD) isn't a standard; to be fair, neither is AMD (it's a convention with a well-defined spec).
Non-trivial amount of boilerplate (and Ugly).
Example
/**
* Creates a an "AppWidget" module that imports a "SingleDependency" constructor and exposes an "AppWidget" constructor.
*
* Allows you to access AppWidget as a CJS/AMD module (i.e. NodeJS or RequireJs):
*
* #example
* var AppWidget = require('app-widget')
*
* Allows you to access AppWidget as a legacy browser global:
*
* #example
* var AppWidget = window.AppWidget
*/
!(function (name, context, definition) {
if (typeof exports === 'object') { module.exports = definition(require); } else if (typeof define === 'function' && define.amd) { define(definition); } else { context[name] = definition(); }
}).call(this, 'AppWidget', this, function (require) {
'use strict'
// imports
var SingleDependency = (typeof require === 'function') ? require('./single-dependency') : window.SingleDependency;
var singleDependency = new SingleDependency();
function AppWidget() {}
AppWidget.prototype.start = function () {};
// exports
return AppWidget;
});
Check out UMD. You should find a pattern suitable for your purposes there. The templates are somewhat ugly but work.
I think that this is quite a bad idea.
Your possible steps that you have to take to make sure that it works:
ensure that all module's dependencies are loaded on that page (jQuery, Backbone and others)
include your module(s) on the page in the order you know they should be executed
ensure that any module that is a dependency of another module creates a global variable
with the same name the "importing" module expects and refers to in its code
ensure that your module refers to the dependencies (including other modules) by the same name
override/create a global method define that executes your module's factory function
And that is only a part of what you'd have to do. What about 3rd parties that you need to be AMD-compliant for your RequireJS pages (or at least be in its shim configuration), but also should be global for your non-RequireJS pages?
Simply put, IMO, it'd be easier to rework existing code into AMD version, that to make your modules non-AMD
Based on Simon Smiths answer I dealed with module dependencies:
(function (root, factory) {
if (typeof exports === "object") {
module.exports = factory();
} else if (typeof define === "function" && define.amd) {
define(['jquery', 'ol'], factory);
} else {
root.module_name = factory();
}
}(this, function (_$, _ol) {
return new function () {
// supposed that window.ol and window.$ are defined
var ol = goog.isDef(_ol) ? _ol : window.ol;
var $ = goog.isDef(_$) ? _$ : window.$;
}
}));
Where goog.isDef is Google Closure function:
goog.isDef = function(val) {
return val !== void 0;
};
Hope it will help someone.
Check out Browserify, which will create single, standalone .js file with all dependencies embedded from your AMD/JS code.
You could then ship 2 versions of your code, one for AMD users and one for "oldschool" js users.

RequireJS Optimizer and VS 2010 Itegration

I was wondering if there were any VS 2010 extensions out there for triggering the requirejs optimization similar to how squishit works:
When in debug mode, module files stay separate
When in release mode, modules files get minified and combined
Edit: We use VS2012, but the general principle should work
While this isn't a direct answer to your question, this is the work around that we came up with:
Create a module for the files that you want to have minimized and bundled. For the sake of discussion, call it base_module.
Create a script in your _layout.cshtml
function requireBaseModulesDebug(func) {
// In debug mode, just execute the call back directly.
// Do not load any base modules, require each module to fully state any dependencies.
func();
}
function requireBaseModulesRelease(func) {
require(["js_modules/base_module"], func);
}
// Views are always in DEBUG mode, so we have to this this work-around.
#if (HttpContext.Current.IsDebuggingEnabled)
{
<text>requireBaseModules = requireBaseModulesDebug;</text>
}
else
{
<text>requireBaseModules = requireBaseModulesRelease;</text>
}
With that script created, you then have to wrap anything that would use a module like this:
// If you are in DEBUG mode, requireBaseModules won't do anything
// But, if you are in a release mode, then requireBaseModules will load your
// bundled module and have them primed. Any modules required but NOT in your
// base bundle will be loaded normally.
requireBaseModules(function () {
require(['jQuery'], function ($) {
// Do Stuff
});
});

JavaScript require() on client side

Is it possible to use require() (or something similar) on client side?
Example
var myClass = require('./js/myclass.js');
You should look into require.js or head.js for this.
I've been using browserify for that. It also lets me integrate Node.js modules into my client-side code.
I blogged about it here: Add node.js/CommonJS style require() to client-side JavaScript with browserify
If you want to have Node.js style require you can use something like this:
var require = (function () {
var cache = {};
function loadScript(url) {
var xhr = new XMLHttpRequest(),
fnBody;
xhr.open('get', url, false);
xhr.send();
if (xhr.status === 200 && xhr.getResponseHeader('Content-Type') === 'application/x-javascript') {
fnBody = 'var exports = {};\n' + xhr.responseText + '\nreturn exports;';
cache[url] = (new Function(fnBody)).call({});
}
}
function resolve(module) {
//TODO resolve urls
return module;
}
function require(module) {
var url = resolve(module);
if (!Object.prototype.hasOwnProperty.call(cache, url)) {
loadScript(url);
}
return cache[url];
}
require.cache = cache;
require.resolve = resolve;
return require;
}());
Beware: this code works but is incomplete (especially url resolving) and does not implement all Node.js features (I just put this together last night).
YOU SHOULD NOT USE THIS CODE in real apps but it gives you a starting point. I tested it with this simple module and it works:
function hello() {
console.log('Hello world!');
}
exports.hello = hello;
I asked myself the very same questions. When I looked into it I found the choices overwhelming.
Fortunately I found this excellent spreadsheet that helps you choice the best loader based on your requirements:
https://spreadsheets.google.com/lv?key=tDdcrv9wNQRCNCRCflWxhYQ
Take a look at requirejs project.
I have found that in general it is recommended to preprocess scripts at compile time and bundle them in one (or very few) packages with the require being rewritten to some "lightweight shim" also at compile time.
I've Googled out following "new" tools that should be able to do it
http://mixu.net/gluejs/
https://github.com/jrburke/almond
https://github.com/component/builder2.js
And the already mentioned browserify should also fit quite well - http://esa-matti.suuronen.org/blog/2013/04/15/asynchronous-module-loading-with-browserify/
What are the module systems all about?
Older Stack Overflow explanation - Relation between CommonJS, AMD and RequireJS?
Detailed discussion of various module frameworks and the require() they need is in Addy Osmani - Writing Modular JavaScript With AMD, CommonJS & ES Harmony
You can create elements to the DOM, which loads items.
Like such:
var myScript = document.createElement('script'); // Create new script element
myScript.type = 'text/javascript'; // Set appropriate type
myScript.src = './js/myclass.js'; // Load javascript file
Simply use Browserify, what is something like a compiler that process your files before it go into production and packs the file in bundles.
Think you have a main.js file that require the files of your project, when you run browserify in it, it simply process all and creates a bundle with all your files, allowing the use of the require calls synchronously in the browser without HTTP requests and with very little overhead for the performance and for the size of the bundle, for example.
See the link for more info: http://browserify.org/
Some answers already - but I would like to point you to YUI3 and its on-demand module loading. It works on both server (node.js) and client, too - I have a demo website using the exact same JS code running on either client or server to build the pages, but that's another topic.
YUI3: http://developer.yahoo.com/yui/3/
Videos: http://developer.yahoo.com/yui/theater/
Example:
(precondition: the basic YUI3 functions in 7k yui.js have been loaded)
YUI({
//configuration for the loader
}).use('node','io','own-app-module1', function (Y) {
//sandboxed application code
//...
//If you already have a "Y" instance you can use that instead
//of creating a new (sandbox) Y:
// Y.use('moduleX','moduleY', function (Y) {
// });
//difference to YUI().use(): uses the existing "Y"-sandbox
}
This code loads the YUI3 modules "node" and "io", and the module "own-app-module1", and then the callback function is run. A new sandbox "Y" with all the YUI3 and own-app-module1 functions is created. Nothing appears in the global namespace. The loading of the modules (.js files) is handled by the YUI3 loader. It also uses (optional, not show here) configuration to select a -debug or -min(ified) version of the modules to load.
Here's a solution that takes a very different approach: package up all the modules into a JSON object and require modules by reading and executing the file content without additional requests.
https://github.com/STRd6/require/blob/master/main.coffee.md
STRd6/require depends on having a JSON package available at runtime. The require function is generated for that package. The package contains all the files your app could require. No further http requests are made because the package bundles all dependencies. This is as close as one can get to the Node.js style require on the client.
The structure of the package is as follows:
entryPoint: "main"
distribution:
main:
content: "alert(\"It worked!\")"
...
dependencies:
<name>: <a package>
Unlike Node a package doesn't know it's external name. It is up to the pacakge including the dependency to name it. This provides complete encapsulation.
Given all that setup here's a function that loads a file from within a package:
loadModule = (pkg, path) ->
unless (file = pkg.distribution[path])
throw "Could not find file at #{path} in #{pkg.name}"
program = file.content
dirname = path.split(fileSeparator)[0...-1].join(fileSeparator)
module =
path: dirname
exports: {}
context =
require: generateRequireFn(pkg, module)
global: global
module: module
exports: module.exports
PACKAGE: pkg
__filename: path
__dirname: dirname
args = Object.keys(context)
values = args.map (name) -> context[name]
Function(args..., program).apply(module, values)
return module
This external context provides some variable that modules have access to.
A require function is exposed to modules so they may require other modules.
Additional properties such as a reference to the global object and some metadata
are also exposed.
Finally we execute the program within the module and given context.
This answer will be most helpful to those who wish to have a synchronous node.js style require statement in the browser and are not interested in remote script loading solutions.
I find the component project giving a much more streamlined workflow than other solutions (including require.js), so I'd advise checking out https://github.com/component/component . I know this is a bit late answer but may be useful to someone.
Here's a light weight way to use require and exports in your web client. It's a simple wrapper that creates a "namespace" global variable, and you wrap your CommonJS compatible code in a "define" function like this:
namespace.lookup('org.mydomain.mymodule').define(function (exports, require) {
var extern = require('org.other.module');
exports.foo = function foo() { ... };
});
More docs here:
https://github.com/mckoss/namespace
The clientside-require library provides an asynchronous load() function that can be used to load any JS file or NPM module (which uses module.exports), any .css file, any .json, any .html, any any other file as text.
e.g.,
npm install clientside-require --save
<script src = '/node_modules/clientside-require/dist/bundle.js'></script>
<script>
load('color-name') // an npm module
.then(color_name=>{
console.log(color_name.blue); // outputs [0, 0, 255]
})
</script>
A really cool part of this project is that inside of any load()ed script, you can use the synchronous require() function the same way you would expect in node.js!
e.g.,
load('/path/to/functionality.js')
and inside /path/to/functionality.js:
var query_string = require("qs") // an npm module
module.exports = function(name){
return qs.stringify({
name:name,
time:new Date()
}
}
That last part, implementing the synchronous require() method, is what enables it to utilize NPM packages built to run on the server.
This module was designed to implement the require functionality as closely as possible in the browser. Disclaimer: I have written this module.
Yes it is very easy to use, but you need to load javascript file in browser by script tag
<script src="module.js"></script>
and then user in js file like
var moduel = require('./module');
I am making a app using electron and it works as expected.

Categories

Resources