Skip to content

Instantly share code, notes, and snippets.

@pieterv
Last active October 1, 2015 07:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pieterv/1945278 to your computer and use it in GitHub Desktop.
Save pieterv/1945278 to your computer and use it in GitHub Desktop.
Builder plugin for r.js to build Wire.js files
/**
* @license Copyright (c) 2010-2011 Brian Cavalier
* LICENSE: see the LICENSE.txt file. If file is missing, this file is subject
* to the MIT License at: http://www.opensource.org/licenses/mit-license.php.
*/
/**
* Builder plugin for r.js
*/
define([ 'wire/base' ], function() {
var defaultModuleRegex, defaultSpecRegex, fs;
// default dependency regex
defaultModuleRegex = /\.(module|create)$/;
defaultSpecRegex = /\.(wire|spec)$/;
function isStrictlyObject( obj ) {
return obj === Object(obj);
}
function isArray( obj ) {
return Object.prototype.toString.call( obj ) == '[object Array]';
}
// Using special require.nodeRequire, something added by r.js.
fs = require.nodeRequire('fs');
function fetchText(path, callback) {
callback(fs.readFileSync(path, 'utf8'));
}
function analyze(name, req, load, config) {
// Track all modules seen in wire spec, so we only include them once
var modules, seenModules, specs, spec, i, childSpecRegex, moduleRegex;
moduleRegex = defaultModuleRegex;
childSpecRegex = defaultSpecRegex;
// Initalise
seenModules = {};
modules = [];
// Get config values
if(config) {
if(config.moduleRegex) moduleRegex = new RegExp(config.moduleRegex);
if(config.childSpecRegex) childSpecRegex = new RegExp(config.childSpecRegex);
}
function addAbsoluteDep(absoluteId) {
// Only add the moduleId if we haven't already
if (absoluteId in seenModules) return;
seenModules[absoluteId] = 1;
modules.push(absoluteId);
}
function addDependency(moduleId) {
addAbsoluteDep(moduleId);
}
function addChildSpec(specId) {
addAbsoluteDep('wire' + '!' + specId);
}
function scanObj(obj, path) {
// Scan all keys. This might be the spec itself, or any sub-object-literal
// in the spec.
for (var name in obj) {
scanItem(obj[name], path ? ([path, name].join('.')) : name);
}
}
function scanItem(it, path) {
// Determine the kind of thing we're looking at
// 1. If it's a string, and the key is module or create, then assume it
// is a moduleId, and add it as a dependency.
// 2. If it's an object or an array, scan it recursively
if (typeof it === 'string') {
// If it's a regular module, add it as a dependency
// If it's child spec, add it as a wire! dependency
if (isDep(path)) {
addDependency(it);
} else if (isWireDep(path)) {
addChildSpec(it);
}
}
if (isDep(path) && typeof it === 'string') {
// Get module def
addDependency(it);
} else if (isStrictlyObject(it)) {
// Descend into subscope
scanObj(it, path);
} else if (isArray(it)) {
// Descend into array
var arrayPath = path + '[]';
for (var i = 0, len = it.length; i < len; i++) {
scanItem(it[i], arrayPath);
}
}
}
function isWireDep(path) {
return childSpecRegex && childSpecRegex.test(path);
}
function isDep(path) {
return moduleRegex.test(path);
}
// Read in our spec file
fetchText( req.toUrl( name ) + '.js', function( text ) {
// Load our spec to a module from the text
load.fromText( text );
// Grab our spec via require (so we get just the returned value not the file text)
req( [ name ], function( spec_obj ) {
// Scan for dependencies
scanObj( spec_obj );
// Add itself as its last dependency
addDependency( name );
// Require our dependencies, will add to the build system
// This will always have at least one module to call (the spec)
req( modules, function() {} );
// tell r.js that we are finished working
load( spec_obj );
} );
} );
}
return {
load: analyze
};
});
@reduxdj
Copy link

reduxdj commented Apr 9, 2012

Can you provide an example of how to use this please, I most definitely need one.

@pieterv
Copy link
Author

pieterv commented Apr 11, 2012

This example app has the building working in it, https://github.com/pieter-vanderwerff/backbone-require-wire

The key things are:

  • Place this file somewhere in your system, i like to put it under the wire folder.
  • In your build config, specify the path to this build file, paths: { "wire/build/amd/builder": "../../_libs/wire/rjs/builder" }
  • You will need to be using wire.js v0.8.0 for this to work or you will need to add this line // pluginBuilder: './build/amd/builder' to your wire.js file, make sure you leave in the // commenting it out r.js still reads it

This will hopefully be part of wire in the near future

@pieterv
Copy link
Author

pieterv commented Jan 22, 2013

Updated to support requirejs 2.1.3

@lemonskip
Copy link

Hey I can confirm that his builder works. Thanks for the gist #relief

However, I noticed that the actual spec is not included in the compiled file (e.g main.js)

So I have a spec with the following id:
app/spec/main.js

I have a main file which includes the spec:
app/main.js

define(['wire!app/spec/main'], function(){});

app/main.js compiles fine with all the deps for spec intact, but the spec itself.

In your builder I can see that you add the spec as dependency at the end, but r.js seems to not bother include it.

Any clue why this is the case?

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment