From ca1d944dd30eb62797b41b4da042c744713c88b1 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Thu, 6 Nov 2014 23:02:54 +0100
Subject: [PATCH 01/59] expose server in API
using it for CLI building of resources
---
lib/websocket/transports/engineio/index.js | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/websocket/transports/engineio/index.js b/lib/websocket/transports/engineio/index.js
index 6b76c29d..cfb3501a 100644
--- a/lib/websocket/transports/engineio/index.js
+++ b/lib/websocket/transports/engineio/index.js
@@ -38,6 +38,9 @@ module.exports = function(ss, messageEmitter, httpServer, config){
// Tell the SocketStream client to use this transport, passing any client-side config along to the wrapper
ss.client.send('code', 'transport', "require('socketstream').assignTransport(" + JSON.stringify(config.client) + ");");
+ // don't set up server for CLI and test
+ if (httpServer == null) return;
+
// Create a new Engine.IO server and bind to /ws
ws = engine.attach(httpServer, config.server);
// ws.installHandlers(httpServer, {prefix: '/ws'});
From ac1a788c8493ad0bacc246b2c3c91125e32cf453 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Tue, 18 Nov 2014 23:49:27 +0100
Subject: [PATCH 02/59] pass client name in dev
---
lib/client/serve/dev.js | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index d00d0876..56ff4e5c 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -28,12 +28,15 @@ module.exports = function (ss, router, options) {
params = qs.parse(thisUrl.query);
path = utils.parseUrl(request.url);
return asset.js(path, {
+ client: params.client,
+ clientId: params.ts,
pathPrefix: params.pathPrefix
}, function(output) {
return utils.serve.js(output, response);
});
});
router.on('/_serveDev/start?*', function(request, response) {
+ //TODO initCode for a client with ts=..
return utils.serve.js(system.serve.initCode(), response);
});
@@ -42,8 +45,12 @@ module.exports = function (ss, router, options) {
// Listen for requests for CSS files
return router.on('/_serveDev/css?*', function(request, response) {
var path;
+ params = qs.parse(thisUrl.query);
path = utils.parseUrl(request.url);
- return asset.css(path, {}, function(output) {
+ return asset.css(path, {
+ client: params.client,
+ clientId: params.ts
+ }, function(output) {
return utils.serve.css(output, response);
});
});
From 06dc8c3553abb8f146b03150599064c05aae9a75 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Tue, 18 Nov 2014 23:51:27 +0100
Subject: [PATCH 03/59] bundler will handle the asset combining
Allow changing the include logic for html/css/code
---
lib/client/bundler/index.js | 56 ++++++++++++++++++++++++++++++
lib/client/bundler/pack.js | 68 +++++++++++++++++++++++++++++++++++++
2 files changed, 124 insertions(+)
create mode 100644 lib/client/bundler/index.js
create mode 100644 lib/client/bundler/pack.js
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
new file mode 100644
index 00000000..4967025d
--- /dev/null
+++ b/lib/client/bundler/index.js
@@ -0,0 +1,56 @@
+function includeFlags(overrides) {
+ var includes = {
+ css: true,
+ html: true,
+ system: true,
+ initCode: true
+ };
+ if (overrides) {
+ for(var n in overrides) { includes[n] = overrides[n]; }
+ }
+ return includes;
+}
+
+
+module.exports = function bundler(ss,options){
+ var pack = require('./pack')(ss,options);
+
+ return {
+
+ define: function define(client, paths) {
+
+ if (typeof paths.view !== 'string') {
+ throw new Error('You may only define one HTML view per single-page client. Please pass a filename as a string, not an Array');
+ }
+ if (paths.view.indexOf('.') === -1) {
+ throw new Error('The \'' + paths.view + '\' view must have a valid HTML extension (such as .html or .jade)');
+ }
+
+ // Alias 'templates' to 'tmpl'
+ if (paths.templates) {
+ paths.tmpl = paths.templates;
+ }
+
+ // Force each into an array
+ ['css', 'code', 'tmpl'].forEach(function(assetType) {
+ if (!(paths[assetType] instanceof Array)) {
+ paths[assetType] = [paths[assetType]];
+ return paths[assetType];
+ }
+ });
+
+ // Define new client object
+ client.paths = paths;
+ client.includes = includeFlags(paths.includes);
+
+ return client;
+ },
+
+ packCSS: pack.css,
+ packJS: pack.js,
+
+ load: function load() {
+ //TODO something
+ }
+ };
+};
\ No newline at end of file
diff --git a/lib/client/bundler/pack.js b/lib/client/bundler/pack.js
new file mode 100644
index 00000000..02c49b23
--- /dev/null
+++ b/lib/client/bundler/pack.js
@@ -0,0 +1,68 @@
+//TODO ss.root.lenth, ss.root
+// clientDir
+
+module.exports = function(ss, options) {
+
+function packAssetSet(assetType, dir, client, postProcess) {
+ var filePaths, prefix,
+ paths = client.paths[assetType],
+ description = ss.client.describeAssets(client.name);
+
+ function writeFile(fileContents) {
+ var fileName = description.paths[assetType];
+ fs.writeFileSync(fileName, postProcess(fileContents));
+ return log.info('✓'.green, 'Packed ' + filePaths.length + ' files into ' + fileName.substr(ss.root.length));
+ }
+
+ function processFiles(fileContents, i) {
+ var file, path, _ref;
+ if (!fileContents) {
+ fileContents = [];
+ }
+ if (!i) {
+ i = 0;
+ }
+ _ref = filePaths[i], path = _ref.path, file = _ref.file;
+ return asset[assetType](file, {
+ pathPrefix: path,
+ compress: true
+ }, function(output) {
+ fileContents.push(output);
+ if (filePaths[++i]) {
+ return processFiles(fileContents, i);
+ } else {
+ return writeFile(fileContents);
+ }
+ });
+ }
+
+ // Expand any dirs into real files
+ if (paths && paths.length > 0) {
+ filePaths = [];
+ prefix = pathlib.join(ss.root, dir);
+ paths.forEach(function(path) {
+ return magicPath.files(prefix, path).forEach(function(file) {
+ return filePaths.push({
+ path: path,
+ file: file
+ });
+ });
+ });
+ return processFiles();
+ }
+}
+
+
+ return {
+
+ js: function(client, postProcess) {
+ packAssetSet('js', options.dirs.code, client, postProcess);
+ },
+
+ css: function(client, postProcess) {
+ packAssetSet('css', options.dirs.css, client, postProcess);
+ }
+
+ };
+};
+
From ba030e25cb2bd2372164a7df16f740d1afe81200 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Tue, 18 Nov 2014 23:53:41 +0100
Subject: [PATCH 04/59] missing var
---
lib/client/serve/dev.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index 56ff4e5c..e41ca798 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -44,7 +44,8 @@ module.exports = function (ss, router, options) {
// Listen for requests for CSS files
return router.on('/_serveDev/css?*', function(request, response) {
- var path;
+ var params, path, thisUrl;
+ thisUrl = url.parse(request.url);
params = qs.parse(thisUrl.query);
path = utils.parseUrl(request.url);
return asset.css(path, {
From c1423497384a640140f25ceffb8931027e51accb Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Wed, 19 Nov 2014 19:06:23 +0100
Subject: [PATCH 05/59] reworked bundler
client bundler with the current asset combination
---
lib/client/{ => bundler}/asset.js | 20 ++++----
lib/client/bundler/default.js | 58 +++++++++++++++++++++++
lib/client/bundler/index.js | 77 +++++++++++++------------------
lib/client/index.js | 1 +
lib/client/serve/ondemand.js | 2 +
lib/client/view.js | 7 ++-
6 files changed, 103 insertions(+), 62 deletions(-)
rename lib/client/{ => bundler}/asset.js (93%)
create mode 100644 lib/client/bundler/default.js
diff --git a/lib/client/asset.js b/lib/client/bundler/asset.js
similarity index 93%
rename from lib/client/asset.js
rename to lib/client/bundler/asset.js
index 5f2e7d45..a9c93079 100644
--- a/lib/client/asset.js
+++ b/lib/client/bundler/asset.js
@@ -1,6 +1,3 @@
-// Client Asset File
-// -----------------
-// An asset is a Code (JS or CoffeeScript), CSS or HTML file
'use strict';
var formatKb, formatters, fs, jsp, log, minifyJSFile, pathlib, pro, uglifyjs, wrap, wrapCode,
@@ -12,11 +9,11 @@ pathlib = require('path');
uglifyjs = require('uglify-js');
-formatters = require('./formatters');
+formatters = require('../formatters');
-log = require('../utils/log');
+log = require('../../utils/log');
-wrap = require('./wrap');
+wrap = require('../wrap');
jsp = uglifyjs.parser;
@@ -25,8 +22,8 @@ pro = uglifyjs.uglify;
// Load, compile and minify the following assets
module.exports = function(ss, options) {
- var loadFile;
- loadFile = function(dir, fileName, type, options, cb) {
+
+ function loadFile(dir, fileName, type, options, cb) {
var extension, formatter, path;
dir = pathlib.join(ss.root, dir);
path = pathlib.join(dir, fileName);
@@ -43,11 +40,10 @@ module.exports = function(ss, options) {
throw new Error('Unable to render \'' + fileName + '\' as this appears to be a ' + (formatter.assetType.toUpperCase()) + ' file. Expecting some type of ' + (type.toUpperCase()) + ' file in ' + (dir.substr(ss.root.length)) + ' instead');
}
return formatter.compile(path.replace(/\\/g, '/'), options, cb);
- };
- return {
-
- // Public
+ }
+
+ return {
js: function(path, opts, cb) {
return loadFile(options.dirs.code, path, 'js', opts, function(output) {
output = wrapCode(output, path, opts.pathPrefix, options);
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
new file mode 100644
index 00000000..fb14d2c5
--- /dev/null
+++ b/lib/client/bundler/default.js
@@ -0,0 +1,58 @@
+// Default bundler implementation
+
+function includeFlags(overrides) {
+ var includes = {
+ css: true,
+ html: true,
+ system: true,
+ initCode: true
+ };
+ if (overrides) {
+ for(var n in overrides) { includes[n] = overrides[n]; }
+ }
+ return includes;
+}
+
+
+module.exports = function bundler(ss,options){
+ var pack = require('./pack')(ss,options);
+ var asset = require('./asset')(ss,options);
+
+ return {
+ asset: asset,
+
+ define: function define(client, paths) {
+
+ if (typeof paths.view !== 'string') {
+ throw new Error('You may only define one HTML view per single-page client. Please pass a filename as a string, not an Array');
+ }
+ if (paths.view.indexOf('.') === -1) {
+ throw new Error('The \'' + paths.view + '\' view must have a valid HTML extension (such as .html or .jade)');
+ }
+
+ // Alias 'templates' to 'tmpl'
+ if (paths.templates) {
+ paths.tmpl = paths.templates;
+ }
+
+ // Force each into an array
+ ['css', 'code', 'tmpl'].forEach(function(assetType) {
+ if (!(paths[assetType] instanceof Array)) {
+ paths[assetType] = [paths[assetType]];
+ return paths[assetType];
+ }
+ });
+
+ // Define new client object
+ client.paths = paths;
+ client.includes = includeFlags(paths.includes);
+
+ return client;
+ },
+
+ packCSS: pack.css,
+ packJS: pack.js,
+
+ loadFile: asset.loadFile
+ };
+};
\ No newline at end of file
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 4967025d..23a83d0e 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -1,56 +1,41 @@
-function includeFlags(overrides) {
- var includes = {
- css: true,
- html: true,
- system: true,
- initCode: true
- };
- if (overrides) {
- for(var n in overrides) { includes[n] = overrides[n]; }
- }
- return includes;
-}
-
-
-module.exports = function bundler(ss,options){
- var pack = require('./pack')(ss,options);
- return {
+var defaultBundler,
+ bundlers = {}; // get bundler by client name
- define: function define(client, paths) {
+/**
+ * Define the bundler for a client
+ * @param client object to store the definition in
+ * @param args arguments passed to define
+ */
+exports.define = function bundler(ss,client,args,options) {
- if (typeof paths.view !== 'string') {
- throw new Error('You may only define one HTML view per single-page client. Please pass a filename as a string, not an Array');
- }
- if (paths.view.indexOf('.') === -1) {
- throw new Error('The \'' + paths.view + '\' view must have a valid HTML extension (such as .html or .jade)');
- }
+ var name = args[0],
+ pathsOrFunc = args[1];
- // Alias 'templates' to 'tmpl'
- if (paths.templates) {
- paths.tmpl = paths.templates;
- }
+ defaultBundler = defaultBundler || require('./default')(ss,options);
- // Force each into an array
- ['css', 'code', 'tmpl'].forEach(function(assetType) {
- if (!(paths[assetType] instanceof Array)) {
- paths[assetType] = [paths[assetType]];
- return paths[assetType];
- }
- });
+ if (typeof pathsOrFunc === "function") {
+ bundlers[name] = pathsOrFunc(ss,options);
+ bundlers[name].define(client, args[2], args[3], args[4], args[5]);
+ } else {
+ defaultBundler.define(client, args[1]);
+ }
+};
- // Define new client object
- client.paths = paths;
- client.includes = includeFlags(paths.includes);
+/**
+ * Determine the bundler for a client
+ * @param client Query params with client=name or an actual client object
+ */
+exports.get = function bundler(ss,client,options){
- return client;
- },
+ if (client.bundler) return client.bundler;
- packCSS: pack.css,
- packJS: pack.js,
+ if (typeof client.client === "string") {
+ return bundlers[client.client] || defaultBundler;
+ }
+ if (typeof client.name === "string") {
+ return bundlers[client.name] || defaultBundler;
+ }
- load: function load() {
- //TODO something
- }
- };
+ return defaultBundler;
};
\ No newline at end of file
diff --git a/lib/client/index.js b/lib/client/index.js
index baf68d24..397ea897 100644
--- a/lib/client/index.js
+++ b/lib/client/index.js
@@ -21,6 +21,7 @@ var options = {
packedAssets: packAssets || false,
liveReload: ['code', 'css', 'static', 'templates', 'views'],
dirs: {
+ client: '/client',
code: '/client/code',
css: '/client/css',
static: '/client/static',
diff --git a/lib/client/serve/ondemand.js b/lib/client/serve/ondemand.js
index 1a09de97..2b1eb5bc 100644
--- a/lib/client/serve/ondemand.js
+++ b/lib/client/serve/ondemand.js
@@ -44,9 +44,11 @@ module.exports = function(ss, router, options) {
output = [];
dir = pathlib.join(ss.root, options.dirs.code);
files = magicPath.files(dir, [path]);
+ //TODO determine client and get bundler
return files.forEach(function(file) {
var description;
try {
+ //TODO return bundler.js()
return asset.js(file, {
pathPrefix: options.globalModules? null : path,
compress: options.packAssets
diff --git a/lib/client/view.js b/lib/client/view.js
index a9dffd85..113d50a7 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -8,9 +8,8 @@ var pathlib = require('path'),
wrap = require('./wrap');
module.exports = function(ss, client, options, cb) {
- var templateEngine = require('./template_engine')(ss);
-
- var asset = require('./asset')(ss, options);
+ var templateEngine = require('./template_engine')(ss),
+ bundler = require('./bundler/index').get(ss, client, options);
// Add links to CSS and JS files
var includes = headers().concat(templates());
@@ -21,7 +20,7 @@ module.exports = function(ss, client, options, cb) {
compress: options.packedAssets,
filename: client.paths.view
};
- return asset.html(client.paths.view, htmlOptions, cb);
+ return bundler.asset.html(client.paths.client, htmlOptions, cb);
// When packing assets the default path to the CSS or JS file can be overridden
// either with a string or a function, typically pointing to an resource on a CDN
From a8d55747343718a4b68ccc4defc42417c848933f Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Thu, 20 Nov 2014 18:00:01 +0100
Subject: [PATCH 06/59] no asset ref
---
lib/client/serve/ondemand.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/client/serve/ondemand.js b/lib/client/serve/ondemand.js
index 2b1eb5bc..51e26106 100644
--- a/lib/client/serve/ondemand.js
+++ b/lib/client/serve/ondemand.js
@@ -21,8 +21,8 @@ utils = require('./utils');
queryCache = {};
module.exports = function(ss, router, options) {
- var asset, code, serve, worker;
- asset = require('../asset')(ss, options);
+ var code, serve, worker;
+
serve = function(processor) {
return function(request, response) {
var path;
From e9bed65937d769eef52d8632a730b94bfc4113bb Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Thu, 20 Nov 2014 18:01:29 +0100
Subject: [PATCH 07/59] pack with bundler
---
lib/client/bundler/default.js | 116 ++++++++++++++++++++++++----------
lib/client/bundler/index.js | 79 +++++++++++++++++++----
lib/client/bundler/pack.js | 94 +++++++++++++--------------
3 files changed, 200 insertions(+), 89 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index fb14d2c5..6d680d39 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -1,5 +1,10 @@
// Default bundler implementation
+var fs = require('fs'),
+ path = require('path'),
+ log = require('../../utils/log');
+
+
function includeFlags(overrides) {
var includes = {
css: true,
@@ -13,46 +18,93 @@ function includeFlags(overrides) {
return includes;
}
+function deleteOldFiles(clientDir) {
+ var filesDeleted, numFilesDeleted;
+ numFilesDeleted = 0;
+ filesDeleted = fs.readdirSync(clientDir).map(function(fileName) {
+ return fs.unlinkSync(path.join(clientDir, fileName));
+ });
+ return filesDeleted.length > 1 && log('✓'.green, '' + filesDeleted.length + ' previous packaged files deleted');
+}
-module.exports = function bundler(ss,options){
- var pack = require('./pack')(ss,options);
- var asset = require('./asset')(ss,options);
+function mkdir(dir) {
+ if (!fs.existsSync(dir)) {
+ return fs.mkdirSync(dir);
+ }
+}
- return {
- asset: asset,
- define: function define(client, paths) {
+module.exports = function bundler(ss,client,options){
+ var bundler = {
+ define: define,
+ load: load,
+ ensureAssetFolder: ensureAssetFolder
+ };
- if (typeof paths.view !== 'string') {
- throw new Error('You may only define one HTML view per single-page client. Please pass a filename as a string, not an Array');
- }
- if (paths.view.indexOf('.') === -1) {
- throw new Error('The \'' + paths.view + '\' view must have a valid HTML extension (such as .html or .jade)');
- }
+ bundler.pack = require('./pack')(ss,client,bundler,options);
+ bundler.asset = require('./asset')(ss,options);
+
+ return bundler;
- // Alias 'templates' to 'tmpl'
- if (paths.templates) {
- paths.tmpl = paths.templates;
+ function define(paths) {
+
+ if (typeof paths.view !== 'string') {
+ throw new Error('You may only define one HTML view per single-page client. Please pass a filename as a string, not an Array');
+ }
+ if (paths.view.indexOf('.') === -1) {
+ throw new Error('The \'' + paths.view + '\' view must have a valid HTML extension (such as .html or .jade)');
+ }
+
+ // Alias 'templates' to 'tmpl'
+ if (paths.templates) {
+ paths.tmpl = paths.templates;
+ }
+
+ // Force each into an array
+ ['css', 'code', 'tmpl'].forEach(function(assetType) {
+ if (!(paths[assetType] instanceof Array)) {
+ paths[assetType] = [paths[assetType]];
+ return paths[assetType];
}
+ });
- // Force each into an array
- ['css', 'code', 'tmpl'].forEach(function(assetType) {
- if (!(paths[assetType] instanceof Array)) {
- paths[assetType] = [paths[assetType]];
- return paths[assetType];
- }
- });
+ // Define new client object
+ client.paths = paths;
+ client.includes = includeFlags(paths.includes);
- // Define new client object
- client.paths = paths;
- client.includes = includeFlags(paths.includes);
+ return client;
+ }
- return client;
- },
+ function load() {
+ var containerDir = path.join(ss.root, options.dirs.assets);
+ var clientDir = path.join(containerDir, client.name);
- packCSS: pack.css,
- packJS: pack.js,
+ this.description = {
+
+ //TODO perhaps mixin the abs versions by SS
+ paths: {
+ html: path.join(clientDir, client.id + '.html'),
+ js: path.join(clientDir, client.id + '.js'),
+ css: path.join(clientDir, client.id + '.css')
+ },
+ relPaths: {
+ html: path.join(options.dirs.assets, client.name, client.id + '.html'),
+ js: path.join(options.dirs.assets, client.name, client.id + '.js'),
+ css: path.join(options.dirs.assets, client.name, client.id + '.css')
+ },
+ dir: clientDir,
+ containerDir: containerDir
+ };
+ }
+
+ function ensureAssetFolder() {
+
+ // Prepare folder
+ mkdir(this.description.containerDir);
+ mkdir(this.description.dir);
+ if (!(options.packedAssets && options.packedAssets.keepOldFiles)) {
+ deleteOldFiles(this.description.dir);
+ }
+ }
+};
- loadFile: asset.loadFile
- };
-};
\ No newline at end of file
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 23a83d0e..439bb5ca 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -1,24 +1,27 @@
+var fs = require('fs'),
+ log = require('../../utils/log'),
+ cleanCSS = require('clean-css'),
+ system = require('../system'),
+ view = require('../view');
-var defaultBundler,
- bundlers = {}; // get bundler by client name
+var bundlers = {}; // get bundler by client name
/**
* Define the bundler for a client
* @param client object to store the definition in
* @param args arguments passed to define
*/
-exports.define = function bundler(ss,client,args,options) {
+exports.define = function defineBundler(ss,client,args,options) {
var name = args[0],
pathsOrFunc = args[1];
- defaultBundler = defaultBundler || require('./default')(ss,options);
-
if (typeof pathsOrFunc === "function") {
bundlers[name] = pathsOrFunc(ss,options);
bundlers[name].define(client, args[2], args[3], args[4], args[5]);
} else {
- defaultBundler.define(client, args[1]);
+ bundlers[name] = require('./default')(ss,client,options);
+ bundlers[name].define(args[1]);
}
};
@@ -26,16 +29,70 @@ exports.define = function bundler(ss,client,args,options) {
* Determine the bundler for a client
* @param client Query params with client=name or an actual client object
*/
-exports.get = function bundler(ss,client,options){
+function getBundler(ss,client,options){
if (client.bundler) return client.bundler;
if (typeof client.client === "string") {
- return bundlers[client.client] || defaultBundler;
+ return bundlers[client.client];
}
if (typeof client.name === "string") {
- return bundlers[client.name] || defaultBundler;
+ return bundlers[client.name];
}
- return defaultBundler;
-};
\ No newline at end of file
+ throw new Error('Unknow client '+(client.name || client.client) );
+}
+
+exports.get = getBundler;
+
+exports.load = function() {
+ for(var n in bundlers) bundlers[n].load();
+};
+
+exports.pack = function pack(ss, client, options) {
+ client.pack = true;
+
+ // the concrete bundler for the client
+ var bundler = getBundler(ss, client, options);
+
+ /* PACKER */
+
+ log(('Pre-packing and minifying the \'' + client.name + '\' client...').yellow);
+
+ bundler.ensureAssetFolder();
+
+ // Output CSS
+ bundler.pack.css(client, function(files) {
+ var minified, original;
+ original = files.join('\n');
+ minified = cleanCSS.process(original);
+ log.info((' Minified CSS from ' + (formatKb(original.length)) + ' to ' + (formatKb(minified.length))).grey);
+ return minified;
+ });
+
+ // Output JS
+ bundler.pack.js(client, function(files) {
+ var parts = [];
+ if (client.includes.system) {
+ parts.push( system.serve.js({ compress:true }) );
+ }
+ parts = parts.concat(files);
+ if (client.includes.initCode) {
+ parts.push( system.serve.initCode() );
+ }
+
+ return parts.join(";");
+ });
+
+ // Output HTML view
+ return view(ss, client, options, function(html) {
+ fs.writeFileSync(bundler.description.paths.html, html);
+ return log.info('✓'.green, 'Created and cached HTML file ' + bundler.description.relPaths.html);
+ });
+};
+
+// PRIVATE
+
+function formatKb(size) {
+ return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
+}
diff --git a/lib/client/bundler/pack.js b/lib/client/bundler/pack.js
index 02c49b23..843b2b8c 100644
--- a/lib/client/bundler/pack.js
+++ b/lib/client/bundler/pack.js
@@ -1,65 +1,67 @@
-//TODO ss.root.lenth, ss.root
-// clientDir
+var fs = require('fs'),
+ path = require('path'),
+ magicPath = require('../magic_path'),
+ view = require('../view');
-module.exports = function(ss, options) {
+module.exports = function(ss, client, bundler, options) {
-function packAssetSet(assetType, dir, client, postProcess) {
- var filePaths, prefix,
- paths = client.paths[assetType],
- description = ss.client.describeAssets(client.name);
+ function packAssetSet(assetType, dir, client, postProcess) {
+ var filePaths, prefix,
+ paths = client.paths[assetType],
+ description = bundler.description;
- function writeFile(fileContents) {
- var fileName = description.paths[assetType];
- fs.writeFileSync(fileName, postProcess(fileContents));
- return log.info('✓'.green, 'Packed ' + filePaths.length + ' files into ' + fileName.substr(ss.root.length));
- }
-
- function processFiles(fileContents, i) {
- var file, path, _ref;
- if (!fileContents) {
- fileContents = [];
- }
- if (!i) {
- i = 0;
+ function writeFile(fileContents) {
+ var fileName = description.paths[assetType];
+ fs.writeFileSync(fileName, postProcess(fileContents));
+ return log.info('✓'.green, 'Packed ' + filePaths.length + ' files into ' + fileName.substr(ss.root.length));
}
- _ref = filePaths[i], path = _ref.path, file = _ref.file;
- return asset[assetType](file, {
- pathPrefix: path,
- compress: true
- }, function(output) {
- fileContents.push(output);
- if (filePaths[++i]) {
- return processFiles(fileContents, i);
- } else {
- return writeFile(fileContents);
+
+ function processFiles(fileContents, i) {
+ var file, path, _ref;
+ if (!fileContents) {
+ fileContents = [];
}
- });
- }
+ if (!i) {
+ i = 0;
+ }
+ _ref = filePaths[i], path = _ref.path, file = _ref.file;
+ return bundler.asset[assetType](file, {
+ pathPrefix: path,
+ compress: true
+ }, function(output) {
+ fileContents.push(output);
+ if (filePaths[++i]) {
+ return processFiles(fileContents, i);
+ } else {
+ return writeFile(fileContents);
+ }
+ });
+ }
- // Expand any dirs into real files
- if (paths && paths.length > 0) {
- filePaths = [];
- prefix = pathlib.join(ss.root, dir);
- paths.forEach(function(path) {
- return magicPath.files(prefix, path).forEach(function(file) {
- return filePaths.push({
- path: path,
- file: file
+ // Expand any dirs into real files
+ if (paths && paths.length > 0) {
+ filePaths = [];
+ prefix = path.join(ss.root, dir);
+ paths.forEach(function(path) {
+ return magicPath.files(prefix, path).forEach(function(file) {
+ return filePaths.push({
+ path: path,
+ file: file
+ });
});
});
- });
- return processFiles();
+ return processFiles();
+ }
}
-}
return {
- js: function(client, postProcess) {
+ js: function(postProcess) {
packAssetSet('js', options.dirs.code, client, postProcess);
},
- css: function(client, postProcess) {
+ css: function(postProcess) {
packAssetSet('css', options.dirs.css, client, postProcess);
}
From 5c629daa4f53ee75f11f1b4bb74e68d9813f3214 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Thu, 20 Nov 2014 23:51:15 +0100
Subject: [PATCH 08/59] pack fix
log include
pack param
---
lib/client/bundler/index.js | 4 ++--
lib/client/bundler/pack.js | 11 ++++++-----
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 439bb5ca..d4e9a7cf 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -62,7 +62,7 @@ exports.pack = function pack(ss, client, options) {
bundler.ensureAssetFolder();
// Output CSS
- bundler.pack.css(client, function(files) {
+ bundler.pack.css(function(files) {
var minified, original;
original = files.join('\n');
minified = cleanCSS.process(original);
@@ -71,7 +71,7 @@ exports.pack = function pack(ss, client, options) {
});
// Output JS
- bundler.pack.js(client, function(files) {
+ bundler.pack.js(function(files) {
var parts = [];
if (client.includes.system) {
parts.push( system.serve.js({ compress:true }) );
diff --git a/lib/client/bundler/pack.js b/lib/client/bundler/pack.js
index 843b2b8c..447c78c0 100644
--- a/lib/client/bundler/pack.js
+++ b/lib/client/bundler/pack.js
@@ -1,19 +1,20 @@
var fs = require('fs'),
path = require('path'),
+ log = require('../../utils/log'),
magicPath = require('../magic_path'),
view = require('../view');
module.exports = function(ss, client, bundler, options) {
function packAssetSet(assetType, dir, client, postProcess) {
- var filePaths, prefix,
- paths = client.paths[assetType],
- description = bundler.description;
+ var filePaths,
+ prefix,
+ paths = client.paths[assetType];
function writeFile(fileContents) {
- var fileName = description.paths[assetType];
+ var fileName = bundler.description.paths[assetType];
fs.writeFileSync(fileName, postProcess(fileContents));
- return log.info('✓'.green, 'Packed ' + filePaths.length + ' files into ' + fileName.substr(ss.root.length));
+ return log.info('✓'.green, 'Packed', filePaths.length, 'files into', bundler.description.relPaths[assetType]);
}
function processFiles(fileContents, i) {
From 52795b6dd61302cd907b782ab2b5daf626009a3d Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Thu, 4 Dec 2014 08:41:42 +0100
Subject: [PATCH 09/59] TODO
---
lib/client/wrap.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/client/wrap.js b/lib/client/wrap.js
index 508bbd03..c91e2046 100644
--- a/lib/client/wrap.js
+++ b/lib/client/wrap.js
@@ -1,6 +1,8 @@
// Simple wrapper for modules
'use strict';
+//TODO review if this should be isolated in bundler API
+
exports.module = function(modPath, code) {
return 'require.define("' + modPath + '", function (require, module, exports, __dirname, __filename){\n' + code + '\n});';
};
From 17fc4270770f8c88e1a8d0dbb8c4b213cb4b1586 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Fri, 30 Jan 2015 20:17:35 +0100
Subject: [PATCH 10/59] asset is in bundler
---
lib/client/serve/dev.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index e41ca798..3c26307f 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -12,7 +12,7 @@ var url = require('url'),
//
module.exports = function (ss, router, options) {
var asset;
- asset = require('../asset')(ss, options);
+ asset = require('../bundler/asset')(ss, options);
// JAVASCRIPT
From 0d8cdbf72639b60d4d4da750bbb46f1076bacd53 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sat, 31 Jan 2015 17:47:54 +0100
Subject: [PATCH 11/59] doc(bundler): How to write a custom bundler
---
docs/js/docs-setup.js | 9 +++
.../tutorials/client_side_xbundler.html | 54 ++++++++++++++
lib/client/bundler/default.js | 1 +
lib/client/bundler/index.js | 6 +-
lib/client/bundler/pack.js | 6 +-
.../tutorials/en/client_side_xbundler.ngdoc | 71 +++++++++++++++++++
6 files changed, 144 insertions(+), 3 deletions(-)
create mode 100644 docs/partials/tutorials/client_side_xbundler.html
create mode 100644 src/docs/tutorials/en/client_side_xbundler.ngdoc
diff --git a/docs/js/docs-setup.js b/docs/js/docs-setup.js
index 9d9a5710..46f31cfd 100644
--- a/docs/js/docs-setup.js
+++ b/docs/js/docs-setup.js
@@ -41,6 +41,15 @@ NG_DOCS={
"shortDescription": "Client-Side Templates",
"keywords": "accessible alice allowing allows angular apart app append argument astronomy bad bandwidth biology bob browser building built-in bundled called client client-side clients code coffeekup compiled construct convert correct create css data default define directories directory display div don dramatically easy ember engine engines enter example exiting extension external favorite file find flexibility folder format formatter functions generate github good happy html including inline iphone jade jquery js languages larger layoutless length lib library libs limit live ll logic main major manually match md mix mixing mobile model model-person module modules mustache npm number optional organizing out-of-the-box outputs overview pass passing people perfect person practice prefer prefix project raw ready recommended reduces refactoring refresh render required requires scale scope second send serve server serving simple simply single-page small socketstream solution source ss ss-hogan string student studies styl subdirectory suitable supported supports tag template templateengine templates templating time tmpl tmpl- tutorials types var view ways websocket wrappers wraps"
},
+ {
+ "section": "tutorials",
+ "id": "client_side_xbundler",
+ "shortName": "Client-Side Bundler",
+ "type": "overview",
+ "moduleName": "Client-Side Bundler",
+ "shortDescription": "Client-Side Bundler",
+ "keywords": "action additional arguments asset assets aware based browserify bulk bundle bundler bundlers bundling callback called cb changes client client-side code complete completely config contents create css current custom default define definition described development directory discuss dropped early ensureassetfolder experimental features file files function future html implement implementation implemented implementing individual jade js jspm lacks load method methods minification move named newer next_arg object objective optimisations options opts overview pack pass passed production referenced responsibilities return saved scss separate served server ss starting step supported templates text tmpl tutorials types var view views webpack webpackbundler worker"
+ },
{
"section": "tutorials",
"id": "defining_multiple_clients",
diff --git a/docs/partials/tutorials/client_side_xbundler.html b/docs/partials/tutorials/client_side_xbundler.html
new file mode 100644
index 00000000..388b9773
--- /dev/null
+++ b/docs/partials/tutorials/client_side_xbundler.html
@@ -0,0 +1,54 @@
+
+
+
+
+
Client-Side Bundler
+
Each view is served with a separate bundle of assets. A HTML, JS and CSS file makes up the view.
+The default bundler will create the bundle based on the client definition as described in Client-Side Code and Client-Side Templates.
+
You can implement your own bundler and use it for a client definition. The bundlers are named and referenced by name.
+
Be aware the API is experimental. The current bundler is based on an early Browserify implementation, so it lacks some
+features. The objective is to be able to move to bundling based on newer ones such as WebPack or JSPM. It should be possible
+to implement a bundler that completely changes how the client is implemented. Hence there will be additional responsibilities
+for bundlers in the future.
+
Custom Bundler
+
You can define a custom bundler by implementing a bundler function that will be called for each client it is used on.
The define method of the bundler will be called to complete ss.client.define.
+
Bundler Define define(client,config,..)
+
The define method will be called with a client object containing id, name,
+If you pass additional arguments to define they will be passed to bundler.define. This may be dropped in the future.
+
Bundler Load load()
+
The load method is called as the first step to load the client views. This is done as a bulk action as part of starting
+the server.
+
Bundler asset methods
+
For each of the asset types supported individual files can be served during development.
+A callback function is passed, and must be called with the text contents.
+
Bundler pack methods
+
Files are saved in the assets directory for production use. The HTML file is the same as the one used during development,
+so the asset.html method will be called. For JS and CSS the pack methods are called to do additional minification and
+other optimisations.
+
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index 6d680d39..52b2e830 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -97,6 +97,7 @@ module.exports = function bundler(ss,client,options){
};
}
+ //TODO move to index.js
function ensureAssetFolder() {
// Prepare folder
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index d4e9a7cf..68e2b190 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -4,7 +4,11 @@ var fs = require('fs'),
system = require('../system'),
view = require('../view');
-var bundlers = {}; // get bundler by client name
+/**
+ * Bundler by client name
+ * @type {{}}
+ */
+var bundlers = {};
/**
* Define the bundler for a client
diff --git a/lib/client/bundler/pack.js b/lib/client/bundler/pack.js
index 447c78c0..8d9a233a 100644
--- a/lib/client/bundler/pack.js
+++ b/lib/client/bundler/pack.js
@@ -1,3 +1,5 @@
+'use strict';
+
var fs = require('fs'),
path = require('path'),
log = require('../../utils/log'),
@@ -7,8 +9,8 @@ var fs = require('fs'),
module.exports = function(ss, client, bundler, options) {
function packAssetSet(assetType, dir, client, postProcess) {
- var filePaths,
- prefix,
+ var filePaths,
+ prefix,
paths = client.paths[assetType];
function writeFile(fileContents) {
diff --git a/src/docs/tutorials/en/client_side_xbundler.ngdoc b/src/docs/tutorials/en/client_side_xbundler.ngdoc
new file mode 100644
index 00000000..5a60e1aa
--- /dev/null
+++ b/src/docs/tutorials/en/client_side_xbundler.ngdoc
@@ -0,0 +1,71 @@
+@ngdoc overview
+@name Client-Side Bundler
+
+@description
+# Client-Side Bundler
+
+Each view is served with a separate bundle of assets. A HTML, JS and CSS file makes up the view.
+The default bundler will create the bundle based on the client definition as described in Client-Side Code and Client-Side Templates.
+
+You can implement your own bundler and use it for a client definition. The bundlers are named and referenced by name.
+
+Be aware the *API is experimental*. The current bundler is based on an early Browserify implementation, so it lacks some
+features. The objective is to be able to move to bundling based on newer ones such as WebPack or JSPM. It should be possible
+to implement a bundler that completely changes how the client is implemented. Hence there will be additional responsibilities
+for bundlers in the future.
+
+#### Custom Bundler
+
+You can define a custom bundler by implementing a bundler function that will be called for each client it is used on.
+
+ function webpackBundler(ss, options) {
+ var bundler = {};
+ bundler.define = function(client,config,next_arg...) {};
+ bundler.load = function() {};
+ bundler.ensureAssetFolder = function() {}; // likely to be dropped
+ bundler.asset = {
+ html: function(path, opts, cb) { cb(output) },
+ css: function(path, opts, cb) { cb(output) },
+ js: function(path, opts, cb) { cb(output) },
+ worker: function(path, opts, cb) { cb(output) }
+ };
+ bundler.pack = {
+ css: function(cb) { cb(output); },
+ js: function(cb) { cb(output); }
+ };
+
+ return bundler;
+ }
+
+You can use a custom bundler by for a client view by specifying it in the definition.
+
+ ss.client.define('discuss', webpackBundler, {
+ view: './views/discuss.jade',
+ css: './css/discuss.scss',
+ code: './code/discuss',
+ tmpl: './templates/discuss'
+ });
+
+The define method of the bundler will be called to complete `ss.client.define`.
+
+#### Bundler Define `define(client,config,..)`
+
+The define method will be called with a client object containing `id`, `name`,
+If you pass additional arguments to define they will be passed to `bundler.define`. This may be dropped in the future.
+
+#### Bundler Load `load()`
+
+The load method is called as the first step to load the client views. This is done as a bulk action as part of starting
+the server.
+
+#### Bundler asset methods
+
+For each of the asset types supported individual files can be served during development.
+A callback function is passed, and must be called with the text contents.
+
+
+#### Bundler pack methods
+
+Files are saved in the assets directory for production use. The HTML file is the same as the one used during development,
+so the `asset.html` method will be called. For JS and CSS the pack methods are called to do additional minification and
+other optimisations.
From cc1dfa7f1b2c2e46c4841521e5a084242309a67f Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sat, 31 Jan 2015 17:50:01 +0100
Subject: [PATCH 12/59] chore(linting): use strict
---
lib/client/bundler/default.js | 4 ++--
lib/client/bundler/index.js | 11 ++++++++---
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index 52b2e830..a20623ca 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -1,10 +1,10 @@
// Default bundler implementation
+'use strict';
-var fs = require('fs'),
+var fs = require('fs'),
path = require('path'),
log = require('../../utils/log');
-
function includeFlags(overrides) {
var includes = {
css: true,
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 68e2b190..f4297bf8 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -1,3 +1,6 @@
+// Client-Side Bundler of assets in development and production
+'use strict';
+
var fs = require('fs'),
log = require('../../utils/log'),
cleanCSS = require('clean-css'),
@@ -17,7 +20,7 @@ var bundlers = {};
*/
exports.define = function defineBundler(ss,client,args,options) {
- var name = args[0],
+ var name = args[0],
pathsOrFunc = args[1];
if (typeof pathsOrFunc === "function") {
@@ -35,7 +38,7 @@ exports.define = function defineBundler(ss,client,args,options) {
*/
function getBundler(ss,client,options){
- if (client.bundler) return client.bundler;
+ if (client.bundler) { return client.bundler; }
if (typeof client.client === "string") {
return bundlers[client.client];
@@ -50,7 +53,9 @@ function getBundler(ss,client,options){
exports.get = getBundler;
exports.load = function() {
- for(var n in bundlers) bundlers[n].load();
+ for(var n in bundlers) {
+ bundlers[n].load();
+ }
};
exports.pack = function pack(ss, client, options) {
From cf7641c4ca62a1d34dc2bc8c1d143746f204ab3c Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sat, 31 Jan 2015 17:54:44 +0100
Subject: [PATCH 13/59] feat(bundler): Use default bundler in the client
---
lib/client/index.js | 60 +++++++-----------------------------
lib/client/pack.js | 68 ++++++-----------------------------------
lib/client/serve/dev.js | 6 ++--
lib/client/view.js | 6 ++--
4 files changed, 26 insertions(+), 114 deletions(-)
diff --git a/lib/client/index.js b/lib/client/index.js
index 397ea897..b9500c7b 100644
--- a/lib/client/index.js
+++ b/lib/client/index.js
@@ -11,7 +11,9 @@ require('colors');
var fs = require('fs'),
path = require('path'),
log = require('../utils/log'),
- systemAssets = require('./system');
+ systemAssets = require('./system'),
+
+ bundler = require('./bundler/index');
// Determine if assets should be (re)packed on startup
var packAssets = process.env['SS_PACK'];
@@ -35,23 +37,6 @@ var options = {
// Store each client as an object
var clients = {};
-function includeFlags(overrides) {
- var includes = {
- css: true,
- html: true,
- system: true,
- initCode: true
- }, n;
- if (overrides) {
- for (n in overrides) {
- if (overrides.hasOwnProperty(n)) {
- includes[n] = overrides[n];
- }
- }
- }
- return includes;
-}
-
module.exports = function(ss, router) {
// Require sub modules
@@ -148,40 +133,19 @@ module.exports = function(ss, router) {
if (clients[name]) {
throw new Error('Client name \'' + name + '\' has already been defined');
}
- if (typeof paths.view !== 'string') {
- throw new Error('You may only define one HTML view per single-page client. Please pass a filename as a string, not an Array');
- }
- if (paths.view.indexOf('.') === -1) {
- throw new Error('The \'' + paths.view + '\' view must have a valid HTML extension (such as .html or .jade)');
- }
-
- // Alias 'templates' to 'tmpl'
- if (paths.templates) {
- paths.tmpl = paths.templates;
- }
-
- // Force each into an array
- ['css', 'code', 'tmpl'].forEach(function(assetType) {
- if (!(paths[assetType] instanceof Array)) {
- paths[assetType] = [paths[assetType]];
- return paths[assetType];
- }
- });
-
- // Define new client object
- clients[name] = {
- id: Number(Date.now()),
- name: name,
- paths: paths,
- includes: includeFlags(paths.includes)
- };
- return clients[name];
+ // if a function is used construct a bundler with it otherwise use default bundler
+ var client = clients[name] = { name: name };
+ client.id = Number(Date.now());
+ bundler.define(ss,client,arguments,options);
+ return client;
},
// Listen and serve incoming asset requests
load: function() {
var client, id, name, pack, entryInit;
+ bundler.load();
+
// Cache instances of code formatters and template engines here
// This may change in the future as I don't like hanging system objects
// on the 'ss' internal API object, but for now it solves a problem
@@ -221,11 +185,9 @@ module.exports = function(ss, router) {
// Pack Assets
if (packAssets) {
- pack = require('./pack');
for (name in clients) {
if (clients.hasOwnProperty(name)) {
- client = clients[name];
- pack(ss, client, options);
+ bundler.pack(ss, clients[name], options);
}
}
}
diff --git a/lib/client/pack.js b/lib/client/pack.js
index 1d793a4c..18f9e107 100644
--- a/lib/client/pack.js
+++ b/lib/client/pack.js
@@ -15,81 +15,33 @@ var fs = require('fs'),
log = require('../utils/log');
module.exports = function(ss, client, options) {
- var asset, clientDir, containerDir, packAssetSet;
- asset = require('./asset')(ss, options);
+ var bundler = require('./bundler/index').get(ss, client, options);
+ var clientDir, containerDir; //TODO
client.pack = true;
- containerDir = pathlib.join(ss.root, options.dirs.assets);
- clientDir = pathlib.join(containerDir, client.name);
- packAssetSet = function(assetType, paths, dir, postProcess) {
- var filePaths, prefix, processFiles, writeFile;
- writeFile = function(fileContents) {
- var fileName;
- fileName = clientDir + '/' + client.id + '.' + assetType;
- fs.writeFileSync(fileName, postProcess(fileContents));
- return log.info('✓'.green, 'Packed ' + filePaths.length + ' files into ' + fileName.substr(ss.root.length));
- };
- processFiles = function(fileContents, i) {
- var file, path, _ref;
- if (!fileContents) {
- fileContents = [];
- }
- if (!i) {
- i = 0;
- }
- _ref = filePaths[i];
- path = _ref.path;
- file = _ref.file;
- return asset[assetType](file, {
- pathPrefix: path,
- compress: true
- }, function(output) {
- fileContents.push(output);
- if (filePaths[++i]) {
- return processFiles(fileContents, i);
- } else {
- return writeFile(fileContents);
- }
- });
- };
-
- // Expand any dirs into real files
- if (paths && paths.length > 0) {
- filePaths = [];
- prefix = pathlib.join(ss.root, dir);
- paths.forEach(function(path) {
- return magicPath.files(prefix, path).forEach(function(file) {
- return filePaths.push({
- path: path,
- file: file
- });
- });
- });
- return processFiles();
- }
- };
/* PACKER */
log(('Pre-packing and minifying the \'' + client.name + '\' client...').yellow);
-
+
+ var description = ss.client.describeAssets(client.name);
+
// Prepare folder
- mkdir(containerDir);
- mkdir(clientDir);
+ description.ensureDirs();
if (!(options.packedAssets && options.packedAssets.keepOldFiles)) {
- deleteOldFiles(clientDir);
+ deleteOldFiles(description.dir);
}
// Output CSS
- packAssetSet('css', client.paths.css, options.dirs.css, function(files) {
+ bundler.packCSS(client, function(files) {
var minified, original;
original = files.join('\n');
- minified = cleanCSS().minify(original);
+ minified = cleanCSS.process(original);
log.info((' Minified CSS from ' + (formatKb(original.length)) + ' to ' + (formatKb(minified.length))).grey);
return minified;
});
// Output JS
- packAssetSet('js', client.paths.code, options.dirs.code, function(files) {
+ bundler.packJS(client, function(files) {
var parts = [];
if (client.includes.system) {
parts.push( system.serve.js({ compress:true }) );
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index 3c26307f..84d8ba57 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -11,8 +11,6 @@ var url = require('url'),
// Expose asset server as the public API
//
module.exports = function (ss, router, options) {
- var asset;
- asset = require('../bundler/asset')(ss, options);
// JAVASCRIPT
@@ -27,7 +25,7 @@ module.exports = function (ss, router, options) {
thisUrl = url.parse(request.url);
params = qs.parse(thisUrl.query);
path = utils.parseUrl(request.url);
- return asset.js(path, {
+ return bundler.get(ss,params,options).asset.js(path, {
client: params.client,
clientId: params.ts,
pathPrefix: params.pathPrefix
@@ -48,7 +46,7 @@ module.exports = function (ss, router, options) {
thisUrl = url.parse(request.url);
params = qs.parse(thisUrl.query);
path = utils.parseUrl(request.url);
- return asset.css(path, {
+ return bundler.get(ss,params,options).asset.css(path, {
client: params.client,
clientId: params.ts
}, function(output) {
diff --git a/lib/client/view.js b/lib/client/view.js
index 113d50a7..e389856f 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -87,7 +87,7 @@ module.exports = function(ss, client, options, cb) {
if (client.includes.css) {
client.paths.css.forEach(function(path) {
return magicPath.files(pathlib.join(ss.root, options.dirs.css), path).forEach(function(file) {
- return output.push(wrap.htmlTag.css('/_serveDev/css/' + file + '?ts=' + client.id));
+ return output.push(wrap.htmlTag.css('/_serveDev/css/' + file + '?ts=' + client.id + '&client=' + client.name));
});
});
}
@@ -95,8 +95,8 @@ module.exports = function(ss, client, options, cb) {
// Send Application Code
client.paths.code.forEach(function(path) {
return magicPath.files(pathlib.join(ss.root, options.dirs.code), path).forEach(function(file) {
- var url = '/_serveDev/code/' + file + '?ts=' + client.id;
- if (! options.globalModules) { url += '&pathPrefix=' + path; }
+ var url = '/_serveDev/code/' + file + '?ts=' + client.id + '&client=' + client.name;
+ if (! options.globalModules) url += '&pathPrefix=' + path;
return output.push(wrap.htmlTag.js(url));
});
});
From 03c1b04ff704624ee51ab6fa60aae3a289a002bb Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sat, 31 Jan 2015 18:09:32 +0100
Subject: [PATCH 14/59] perf(array): Use map over forEach
---
lib/client/view.js | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/client/view.js b/lib/client/view.js
index e389856f..52aa790f 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -44,9 +44,8 @@ module.exports = function(ss, client, options, cb) {
} else {
return defaultPath;
}
- }
-
- function templates() {
+ };
+ templates = function() {
var dir, files, output;
dir = pathlib.join(ss.root, options.dirs.templates);
output = [];
From aea18d25e8365532ef48680ba4ef5d5d4879f5af Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sat, 31 Jan 2015 23:53:45 +0100
Subject: [PATCH 15/59] feat(bundler): Bundlers have common implementation
methods
ss.bundler provides common functionality
---
lib/client/bundler/asset.js | 133 ----------------------------
lib/client/bundler/default.js | 69 ++++++++++-----
lib/client/bundler/index.js | 160 ++++++++++++++++++++++++++++++++--
lib/client/bundler/pack.js | 61 +------------
lib/client/index.js | 3 +
5 files changed, 205 insertions(+), 221 deletions(-)
delete mode 100644 lib/client/bundler/asset.js
diff --git a/lib/client/bundler/asset.js b/lib/client/bundler/asset.js
deleted file mode 100644
index a9c93079..00000000
--- a/lib/client/bundler/asset.js
+++ /dev/null
@@ -1,133 +0,0 @@
-'use strict';
-
-var formatKb, formatters, fs, jsp, log, minifyJSFile, pathlib, pro, uglifyjs, wrap, wrapCode,
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) {return i; }} return -1; };
-
-fs = require('fs');
-
-pathlib = require('path');
-
-uglifyjs = require('uglify-js');
-
-formatters = require('../formatters');
-
-log = require('../../utils/log');
-
-wrap = require('../wrap');
-
-jsp = uglifyjs.parser;
-
-pro = uglifyjs.uglify;
-
-// Load, compile and minify the following assets
-
-module.exports = function(ss, options) {
-
- function loadFile(dir, fileName, type, options, cb) {
- var extension, formatter, path;
- dir = pathlib.join(ss.root, dir);
- path = pathlib.join(dir, fileName);
- extension = pathlib.extname(path);
- extension = extension && extension.substring(1); // argh!
- formatter = ss.client.formatters[extension];
- if (path.substr(0, dir.length) !== dir) {
- throw new Error('Invalid path. Request for ' + path + ' must not live outside ' + dir);
- }
- if (!formatter) {
- throw new Error('Unsupported file extension \'.' + extension + '\' when we were expecting some type of ' + (type.toUpperCase()) + ' file. Please provide a formatter for ' + (path.substring(ss.root.length)) + ' or move it to /client/static');
- }
- if (formatter.assetType !== type) {
- throw new Error('Unable to render \'' + fileName + '\' as this appears to be a ' + (formatter.assetType.toUpperCase()) + ' file. Expecting some type of ' + (type.toUpperCase()) + ' file in ' + (dir.substr(ss.root.length)) + ' instead');
- }
- return formatter.compile(path.replace(/\\/g, '/'), options, cb);
- }
-
-
- return {
- js: function(path, opts, cb) {
- return loadFile(options.dirs.code, path, 'js', opts, function(output) {
- output = wrapCode(output, path, opts.pathPrefix, options);
- if (opts.compress && path.indexOf('.min') === -1) {
- output = minifyJSFile(output, path);
- }
- return cb(output);
- });
- },
- worker: function(path, opts, cb) {
- return loadFile(options.dirs.workers, path, 'js', opts, function(output) {
- if (opts.compress) {
- output = minifyJSFile(output, path);
- }
- return cb(output);
- });
- },
- css: function(path, opts, cb) {
- return loadFile(options.dirs.css, path, 'css', opts, cb);
- },
- html: function(path, opts, cb) {
- return loadFile(options.dirs.views, path, 'html', opts, cb);
- }
- };
-};
-
-// PRIVATE
-
-formatKb = function(size) {
- return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
-};
-
-minifyJSFile = function(originalCode, fileName) {
- var ast, minifiedCode;
- ast = jsp.parse(originalCode);
- ast = pro.ast_mangle(ast);
- ast = pro.ast_squeeze(ast);
- minifiedCode = pro.gen_code(ast);
- log.info((' Minified ' + fileName + ' from ' + (formatKb(originalCode.length)) + ' to ' + (formatKb(minifiedCode.length))).grey);
- return minifiedCode;
-};
-
-// Before client-side code is sent to the browser any file which is NOT a library (e.g. /client/code/libs)
-// is wrapped in a module wrapper (to keep vars local and allow you to require() one file in another).
-// The 'system' directory is a special case - any module placed in this dir will not have a leading slash
-wrapCode = function(code, path, pathPrefix, options) {
- var modPath, pathAry, sp, i;
- pathAry = path.split('/');
-
- // Don't touch the code if it's in a 'libs' directory
- if (__indexOf.call(pathAry, 'libs') >= 0) {
- return code;
- }
-
- if (__indexOf.call(pathAry, 'entry.js') === -1 && options && options.browserifyExcludePaths) {
- for(i in options.browserifyExcludePaths) {
- if (options.browserifyExcludePaths.hasOwnProperty(i)) {
- if ( path.split( options.browserifyExcludePaths[i] )[0] === '' ) {
- return code;
- }
- }
- }
- }
-
- // Don't add a leading slash if this is a 'system' module
- if (__indexOf.call(pathAry, 'system') >= 0) {
- modPath = pathAry[pathAry.length - 1];
- return wrap.module(modPath, code);
- } else {
-
- // Otherwise treat as a regular module
- modPath = options.globalModules? pathAry.join("/") : pathAry.slice(1).join('/');
-
- // Work out namespace for module
- if (pathPrefix) {
-
- // Ignore any filenames in the path
- if (pathPrefix.indexOf('.') > 0) {
- sp = pathPrefix.split('/');
- sp.pop();
- pathPrefix = sp.join('/');
- }
- modPath = path.substr(pathPrefix.length + 1);
- }
- return wrap.module('/' + modPath, code);
- }
-};
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index a20623ca..ff58afd3 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -34,16 +34,23 @@ function mkdir(dir) {
}
-module.exports = function bundler(ss,client,options){
+module.exports = function(ss,client,options){
var bundler = {
define: define,
load: load,
+ asset: {
+ js: assetJS,
+ worker: assetWorker,
+ css: assetCSS,
+ html: assetHTML
+ },
+ pack: {
+ js: packJS,
+ css: packCSS
+ },
ensureAssetFolder: ensureAssetFolder
};
- bundler.pack = require('./pack')(ss,client,bundler,options);
- bundler.asset = require('./asset')(ss,options);
-
return bundler;
function define(paths) {
@@ -76,25 +83,41 @@ module.exports = function bundler(ss,client,options){
}
function load() {
- var containerDir = path.join(ss.root, options.dirs.assets);
- var clientDir = path.join(containerDir, client.name);
-
- this.description = {
-
- //TODO perhaps mixin the abs versions by SS
- paths: {
- html: path.join(clientDir, client.id + '.html'),
- js: path.join(clientDir, client.id + '.js'),
- css: path.join(clientDir, client.id + '.css')
- },
- relPaths: {
- html: path.join(options.dirs.assets, client.name, client.id + '.html'),
- js: path.join(options.dirs.assets, client.name, client.id + '.js'),
- css: path.join(options.dirs.assets, client.name, client.id + '.css')
- },
- dir: clientDir,
- containerDir: containerDir
- };
+ this.description = ss.bundler.descriptionFor(ss,client,options);
+ }
+
+ function assetJS(path, opts, cb) {
+ return ss.bundler.loadFile(ss, options.dirs.code, path, 'js', opts, function(output) {
+ output = ss.bundler.wrapCode(output, path, opts.pathPrefix, options);
+ if (opts.compress && path.indexOf('.min') === -1) {
+ output = ss.bundler.minifyJSFile(output, path);
+ }
+ return cb(output);
+ });
+ }
+ function assetWorker(path, opts, cb) {
+ return ss.bundler.loadFile(ss, options.dirs.workers, path, 'js', opts, function(output) {
+ if (opts.compress) {
+ output = ss.bundler.minifyJSFile(output, path);
+ }
+ return cb(output);
+ });
+ }
+
+ function assetCSS(path, opts, cb) {
+ return ss.bundler.loadFile(ss, options.dirs.css, path, 'css', opts, cb);
+ }
+
+ function assetHTML(path, opts, cb) {
+ return ss.bundler.loadFile(ss, options.dirs.views, path, 'html', opts, cb);
+ }
+
+ function packJS(postProcess) {
+ ss.bundler.packAssetSet('js', options.dirs.code, client, bundler, postProcess);
+ }
+
+ function packCSS(postProcess) {
+ ss.bundler.packAssetSet('css', options.dirs.css, client, bundler, postProcess);
}
//TODO move to index.js
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index f4297bf8..4809c996 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -2,10 +2,15 @@
'use strict';
var fs = require('fs'),
+ path = require('path'),
log = require('../../utils/log'),
cleanCSS = require('clean-css'),
system = require('../system'),
- view = require('../view');
+ view = require('../view'),
+ wrap = require('../wrap'),
+ uglifyjs = require('uglify-js'),
+ jsp = uglifyjs.parser,
+ pro = uglifyjs.uglify;
/**
* Bundler by client name
@@ -75,7 +80,7 @@ exports.pack = function pack(ss, client, options) {
var minified, original;
original = files.join('\n');
minified = cleanCSS.process(original);
- log.info((' Minified CSS from ' + (formatKb(original.length)) + ' to ' + (formatKb(minified.length))).grey);
+ log.info((' Minified CSS from ' + (exports.formatKb(original.length)) + ' to ' + (exports.formatKb(minified.length))).grey);
return minified;
});
@@ -100,8 +105,153 @@ exports.pack = function pack(ss, client, options) {
});
};
-// PRIVATE
+// API for implementing bundlers
-function formatKb(size) {
- return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
+exports.loadFile = function loadFile(ss, dir, fileName, type, options, cb) {
+ dir = path.join(ss.root, dir);
+ var p = path.join(dir, fileName);
+ var extension = path.extname(p);
+ extension = extension && extension.substring(1); // argh!
+ var formatter = ss.client.formatters[extension];
+ if (p.substr(0, dir.length) !== dir) {
+ throw new Error('Invalid path. Request for ' + p + ' must not live outside ' + dir);
+ }
+ if (!formatter) {
+ throw new Error('Unsupported file extension \'.' + extension + '\' when we were expecting some type of ' + (type.toUpperCase()) + ' file. Please provide a formatter for ' + (p.substring(ss.root.length)) + ' or move it to /client/static');
+ }
+ if (formatter.assetType !== type) {
+ throw new Error('Unable to render \'' + fileName + '\' as this appears to be a ' + (formatter.assetType.toUpperCase()) + ' file. Expecting some type of ' + (type.toUpperCase()) + ' file in ' + (dir.substr(ss.root.length)) + ' instead');
+ }
+ return formatter.compile(p.replace(/\\/g, '/'), options, cb);
+};
+
+exports.minifyJSFile = function minifyJSFile(originalCode, fileName) {
+ var ast = jsp.parse(originalCode);
+ ast = pro.ast_mangle(ast);
+ ast = pro.ast_squeeze(ast);
+ var minifiedCode = pro.gen_code(ast);
+ log.info((' Minified ' + fileName + ' from ' + (exports.formatKb(originalCode.length)) + ' to ' + (exports.formatKb(minifiedCode.length))).grey);
+ return minifiedCode;
+};
+
+exports.descriptionFor = function(ss,client,options) {
+ var containerDir = path.join(ss.root, options.dirs.assets);
+ var clientDir = path.join(containerDir, client.name);
+
+ return {
+
+ //TODO perhaps mixin the abs versions by SS
+ paths: {
+ html: path.join(clientDir, client.id + '.html'),
+ js: path.join(clientDir, client.id + '.js'),
+ css: path.join(clientDir, client.id + '.css')
+ },
+ relPaths: {
+ html: path.join(options.dirs.assets, client.name, client.id + '.html'),
+ js: path.join(options.dirs.assets, client.name, client.id + '.js'),
+ css: path.join(options.dirs.assets, client.name, client.id + '.css')
+ },
+ dir: clientDir,
+ containerDir: containerDir
+ };
+}
+
+exports.packAssetSet = function packAssetSet(assetType, dir, client, bundler, postProcess) {
+ var filePaths,
+ prefix,
+ paths = client.paths[assetType];
+
+ function writeFile(fileContents) {
+ var fileName = bundler.description.paths[assetType];
+ fs.writeFileSync(fileName, postProcess(fileContents));
+ return log.info('✓'.green, 'Packed', filePaths.length, 'files into', bundler.description.relPaths[assetType]);
+ }
+
+ function processFiles(fileContents, i) {
+ var file, path, _ref;
+ if (!fileContents) {
+ fileContents = [];
+ }
+ if (!i) {
+ i = 0;
+ }
+ _ref = filePaths[i], path = _ref.path, file = _ref.file;
+ return bundler.asset[assetType](file, {
+ pathPrefix: path,
+ compress: true
+ }, function(output) {
+ fileContents.push(output);
+ if (filePaths[++i]) {
+ return processFiles(fileContents, i);
+ } else {
+ return writeFile(fileContents);
+ }
+ });
+ }
+
+ // Expand any dirs into real files
+ if (paths && paths.length > 0) {
+ filePaths = [];
+ prefix = path.join(ss.root, dir);
+ paths.forEach(function(path) {
+ return magicPath.files(prefix, path).forEach(function(file) {
+ return filePaths.push({
+ path: path,
+ file: file
+ });
+ });
+ });
+ return processFiles();
+ }
}
+
+
+exports.formatKb = function formatKb(size) {
+ return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
+};
+
+// Before client-side code is sent to the browser any file which is NOT a library (e.g. /client/code/libs)
+// is wrapped in a module wrapper (to keep vars local and allow you to require() one file in another).
+// The 'system' directory is a special case - any module placed in this dir will not have a leading slash
+exports.wrapCode = function wrapCode(code, path, pathPrefix, options) {
+ var modPath, sp, i;
+ var pathAry = path.split('/');
+
+ // Don't touch the code if it's in a 'libs' directory
+ if (pathAry.indexOf('libs') >= 0) {
+ return code;
+ }
+
+ if (pathAry.indexOf('entry.js') === -1 && options && options.browserifyExcludePaths) {
+ for(i in options.browserifyExcludePaths) {
+ if (options.browserifyExcludePaths.hasOwnProperty(i)) {
+ if ( path.split( options.browserifyExcludePaths[i] )[0] === '' ) {
+ return code;
+ }
+ }
+ }
+ }
+
+ // Don't add a leading slash if this is a 'system' module
+ if (pathAry.indexOf('system') >= 0) {
+ modPath = pathAry[pathAry.length - 1];
+ return wrap.module(modPath, code);
+ } else {
+
+ // Otherwise treat as a regular module
+ modPath = options.globalModules? pathAry.join("/") : pathAry.slice(1).join('/');
+
+ // Work out namespace for module
+ if (pathPrefix) {
+
+ // Ignore any filenames in the path
+ if (pathPrefix.indexOf('.') > 0) {
+ sp = pathPrefix.split('/');
+ sp.pop();
+ pathPrefix = sp.join('/');
+ }
+ modPath = path.substr(pathPrefix.length + 1);
+ }
+ return wrap.module('/' + modPath, code);
+ }
+};
diff --git a/lib/client/bundler/pack.js b/lib/client/bundler/pack.js
index 8d9a233a..2cfbf1cb 100644
--- a/lib/client/bundler/pack.js
+++ b/lib/client/bundler/pack.js
@@ -8,66 +8,7 @@ var fs = require('fs'),
module.exports = function(ss, client, bundler, options) {
- function packAssetSet(assetType, dir, client, postProcess) {
- var filePaths,
- prefix,
- paths = client.paths[assetType];
- function writeFile(fileContents) {
- var fileName = bundler.description.paths[assetType];
- fs.writeFileSync(fileName, postProcess(fileContents));
- return log.info('✓'.green, 'Packed', filePaths.length, 'files into', bundler.description.relPaths[assetType]);
- }
-
- function processFiles(fileContents, i) {
- var file, path, _ref;
- if (!fileContents) {
- fileContents = [];
- }
- if (!i) {
- i = 0;
- }
- _ref = filePaths[i], path = _ref.path, file = _ref.file;
- return bundler.asset[assetType](file, {
- pathPrefix: path,
- compress: true
- }, function(output) {
- fileContents.push(output);
- if (filePaths[++i]) {
- return processFiles(fileContents, i);
- } else {
- return writeFile(fileContents);
- }
- });
- }
-
- // Expand any dirs into real files
- if (paths && paths.length > 0) {
- filePaths = [];
- prefix = path.join(ss.root, dir);
- paths.forEach(function(path) {
- return magicPath.files(prefix, path).forEach(function(file) {
- return filePaths.push({
- path: path,
- file: file
- });
- });
- });
- return processFiles();
- }
- }
-
-
- return {
-
- js: function(postProcess) {
- packAssetSet('js', options.dirs.code, client, postProcess);
- },
-
- css: function(postProcess) {
- packAssetSet('css', options.dirs.css, client, postProcess);
- }
-
- };
+ return ;
};
diff --git a/lib/client/index.js b/lib/client/index.js
index b9500c7b..4ca1b709 100644
--- a/lib/client/index.js
+++ b/lib/client/index.js
@@ -39,6 +39,9 @@ var clients = {};
module.exports = function(ss, router) {
+ // make bundler methods available for default and other implementations
+ ss.bundler = bundler;
+
// Require sub modules
var templateEngine = require('./template_engine')(ss),
formatters = require('./formatters')(ss),
From ef97274b250afd610807d087e6dbf6700afe2ced Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sat, 31 Jan 2015 23:56:19 +0100
Subject: [PATCH 16/59] perf(array): indexOf direct call
No need to support Node JS without Array.indexOf
---
lib/client/live_reload.js | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/client/live_reload.js b/lib/client/live_reload.js
index f57fcdb9..f0b64998 100644
--- a/lib/client/live_reload.js
+++ b/lib/client/live_reload.js
@@ -3,8 +3,7 @@
// Detects changes in client files and sends an event to connected browsers instructing them to refresh the page
'use strict';
-var chokidar, consoleMessage, cssExtensions, lastRun, pathlib, log,
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) {return i;}} return -1; };
+var chokidar, consoleMessage, cssExtensions, lastRun, pathlib, log;
require('colors');
@@ -60,7 +59,7 @@ module.exports = function(ss, options) {
//
onChange = function (path) {
var action, _ref;
- action = (_ref = pathlib.extname(path), __indexOf.call(cssExtensions, _ref) >= 0) ? 'updateCSS' : 'reload';
+ action = (_ref = pathlib.extname(path), cssExtensions.indexOf(_ref) >= 0) ? 'updateCSS' : 'reload';
if ((Date.now() - lastRun[action]) > 1000) { // Reload browser max once per second
log.info('✎'.green, consoleMessage[action].grey);
ss.publish.all('__ss:' + action);
From ca55b5daa4a5ca98718d6ce4df0119af29dc4478 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 1 Feb 2015 01:02:30 +0100
Subject: [PATCH 17/59] feat(bundler): Manage saved asset files
bundler.define returns the destination paths so pack can manage the output files.
---
docs/js/docs-setup.js | 2 +-
.../tutorials/client_side_xbundler.html | 6 ++-
lib/client/bundler/default.js | 34 ++----------
lib/client/bundler/index.js | 52 +++++++++++++------
lib/client/bundler/pack.js | 14 -----
.../tutorials/en/client_side_xbundler.ngdoc | 6 ++-
6 files changed, 48 insertions(+), 66 deletions(-)
delete mode 100644 lib/client/bundler/pack.js
diff --git a/docs/js/docs-setup.js b/docs/js/docs-setup.js
index 46f31cfd..cef19541 100644
--- a/docs/js/docs-setup.js
+++ b/docs/js/docs-setup.js
@@ -48,7 +48,7 @@ NG_DOCS={
"type": "overview",
"moduleName": "Client-Side Bundler",
"shortDescription": "Client-Side Bundler",
- "keywords": "action additional arguments asset assets aware based browserify bulk bundle bundler bundlers bundling callback called cb changes client client-side code complete completely config contents create css current custom default define definition described development directory discuss dropped early ensureassetfolder experimental features file files function future html implement implementation implemented implementing individual jade js jspm lacks load method methods minification move named newer next_arg object objective optimisations options opts overview pack pass passed production referenced responsibilities return saved scss separate served server ss starting step supported templates text tmpl tutorials types var view views webpack webpackbundler worker"
+ "keywords": "action additional arguments asset assets aware based browserify bulk bundle bundler bundlers bundling callback called cb changes client client-side code complete completely config contents create css current custom default define definition described destsfor development directory discuss dropped early experimental features file files function future html implement implementation implemented implementing individual jade js jspm lacks load method methods minification move named newer next_arg object objective optimisations options opts overview pack pass passed production referenced responsibilities return saved scss separate served server ss starting step supported templates text tmpl tutorials types var view views webpack webpackbundler worker"
},
{
"section": "tutorials",
diff --git a/docs/partials/tutorials/client_side_xbundler.html b/docs/partials/tutorials/client_side_xbundler.html
index 388b9773..2dda8b38 100644
--- a/docs/partials/tutorials/client_side_xbundler.html
+++ b/docs/partials/tutorials/client_side_xbundler.html
@@ -14,9 +14,11 @@
Custom Bundler
You can define a custom bundler by implementing a bundler function that will be called for each client it is used on.
function webpackBundler(ss, options) {
var bundler = {};
- bundler.define = function(client,config,next_arg...) {};
+ bundler.define = function(client,config,next_arg...) {
+ // ...
+ return ss.bundler.destsFor(ss,client,options);
+ };
bundler.load = function() {};
- bundler.ensureAssetFolder = function() {}; // likely to be dropped
bundler.asset = {
html: function(path, opts, cb) { cb(output) },
css: function(path, opts, cb) { cb(output) },
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index ff58afd3..3eec6918 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -18,22 +18,6 @@ function includeFlags(overrides) {
return includes;
}
-function deleteOldFiles(clientDir) {
- var filesDeleted, numFilesDeleted;
- numFilesDeleted = 0;
- filesDeleted = fs.readdirSync(clientDir).map(function(fileName) {
- return fs.unlinkSync(path.join(clientDir, fileName));
- });
- return filesDeleted.length > 1 && log('✓'.green, '' + filesDeleted.length + ' previous packaged files deleted');
-}
-
-function mkdir(dir) {
- if (!fs.existsSync(dir)) {
- return fs.mkdirSync(dir);
- }
-}
-
-
module.exports = function(ss,client,options){
var bundler = {
define: define,
@@ -47,8 +31,7 @@ module.exports = function(ss,client,options){
pack: {
js: packJS,
css: packCSS
- },
- ensureAssetFolder: ensureAssetFolder
+ }
};
return bundler;
@@ -79,11 +62,11 @@ module.exports = function(ss,client,options){
client.paths = paths;
client.includes = includeFlags(paths.includes);
- return client;
+ return ss.bundler.destsFor(ss,client,options);
}
function load() {
- this.description = ss.bundler.descriptionFor(ss,client,options);
+
}
function assetJS(path, opts, cb) {
@@ -119,16 +102,5 @@ module.exports = function(ss,client,options){
function packCSS(postProcess) {
ss.bundler.packAssetSet('css', options.dirs.css, client, bundler, postProcess);
}
-
- //TODO move to index.js
- function ensureAssetFolder() {
-
- // Prepare folder
- mkdir(this.description.containerDir);
- mkdir(this.description.dir);
- if (!(options.packedAssets && options.packedAssets.keepOldFiles)) {
- deleteOldFiles(this.description.dir);
- }
- }
};
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 4809c996..279905be 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -8,6 +8,7 @@ var fs = require('fs'),
system = require('../system'),
view = require('../view'),
wrap = require('../wrap'),
+ magicPath = require('../magic_path'),
uglifyjs = require('uglify-js'),
jsp = uglifyjs.parser,
pro = uglifyjs.uglify;
@@ -30,10 +31,10 @@ exports.define = function defineBundler(ss,client,args,options) {
if (typeof pathsOrFunc === "function") {
bundlers[name] = pathsOrFunc(ss,options);
- bundlers[name].define(client, args[2], args[3], args[4], args[5]);
+ bundlers[name].dests = bundlers[name].define(client, args[2], args[3], args[4], args[5]);
} else {
bundlers[name] = require('./default')(ss,client,options);
- bundlers[name].define(args[1]);
+ bundlers[name].dests = bundlers[name].define(args[1]);
}
};
@@ -73,7 +74,12 @@ exports.pack = function pack(ss, client, options) {
log(('Pre-packing and minifying the \'' + client.name + '\' client...').yellow);
- bundler.ensureAssetFolder();
+ // Prepare folder
+ mkdir(bundler.dests.containerDir);
+ mkdir(bundler.dests.dir);
+ if (!(options.packedAssets && options.packedAssets.keepOldFiles)) {
+ deleteOldFiles(bundler.dests.dir);
+ }
// Output CSS
bundler.pack.css(function(files) {
@@ -100,11 +106,26 @@ exports.pack = function pack(ss, client, options) {
// Output HTML view
return view(ss, client, options, function(html) {
- fs.writeFileSync(bundler.description.paths.html, html);
- return log.info('✓'.green, 'Created and cached HTML file ' + bundler.description.relPaths.html);
+ fs.writeFileSync(bundler.dests.paths.html, html);
+ return log.info('✓'.green, 'Created and cached HTML file ' + bundler.dests.relPaths.html);
});
};
+
+function deleteOldFiles(clientDir) {
+ var numFilesDeleted = 0,
+ filesDeleted = fs.readdirSync(clientDir).map(function(fileName) {
+ return fs.unlinkSync(path.join(clientDir, fileName));
+ });
+ return filesDeleted.length > 1 && log('✓'.green, '' + filesDeleted.length + ' previous packaged files deleted');
+}
+
+function mkdir(dir) {
+ if (!fs.existsSync(dir)) {
+ return fs.mkdirSync(dir);
+ }
+}
+
// API for implementing bundlers
exports.loadFile = function loadFile(ss, dir, fileName, type, options, cb) {
@@ -134,7 +155,7 @@ exports.minifyJSFile = function minifyJSFile(originalCode, fileName) {
return minifiedCode;
};
-exports.descriptionFor = function(ss,client,options) {
+exports.destsFor = function(ss,client,options) {
var containerDir = path.join(ss.root, options.dirs.assets);
var clientDir = path.join(containerDir, client.name);
@@ -162,9 +183,9 @@ exports.packAssetSet = function packAssetSet(assetType, dir, client, bundler, po
paths = client.paths[assetType];
function writeFile(fileContents) {
- var fileName = bundler.description.paths[assetType];
+ var fileName = bundler.dests.paths[assetType];
fs.writeFileSync(fileName, postProcess(fileContents));
- return log.info('✓'.green, 'Packed', filePaths.length, 'files into', bundler.description.relPaths[assetType]);
+ return log.info('✓'.green, 'Packed', filePaths.length, 'files into', bundler.dests.relPaths[assetType]);
}
function processFiles(fileContents, i) {
@@ -214,7 +235,6 @@ exports.formatKb = function formatKb(size) {
// is wrapped in a module wrapper (to keep vars local and allow you to require() one file in another).
// The 'system' directory is a special case - any module placed in this dir will not have a leading slash
exports.wrapCode = function wrapCode(code, path, pathPrefix, options) {
- var modPath, sp, i;
var pathAry = path.split('/');
// Don't touch the code if it's in a 'libs' directory
@@ -223,9 +243,10 @@ exports.wrapCode = function wrapCode(code, path, pathPrefix, options) {
}
if (pathAry.indexOf('entry.js') === -1 && options && options.browserifyExcludePaths) {
- for(i in options.browserifyExcludePaths) {
- if (options.browserifyExcludePaths.hasOwnProperty(i)) {
- if ( path.split( options.browserifyExcludePaths[i] )[0] === '' ) {
+ //TODO is this an array? should be revised
+ for(var p in options.browserifyExcludePaths) {
+ if (options.browserifyExcludePaths.hasOwnProperty(p)) {
+ if ( path.split( options.browserifyExcludePaths[p] )[0] === '' ) {
return code;
}
}
@@ -234,19 +255,18 @@ exports.wrapCode = function wrapCode(code, path, pathPrefix, options) {
// Don't add a leading slash if this is a 'system' module
if (pathAry.indexOf('system') >= 0) {
- modPath = pathAry[pathAry.length - 1];
- return wrap.module(modPath, code);
+ return wrap.module(pathAry[pathAry.length - 1], code);
} else {
// Otherwise treat as a regular module
- modPath = options.globalModules? pathAry.join("/") : pathAry.slice(1).join('/');
+ var modPath = options.globalModules? pathAry.join("/") : pathAry.slice(1).join('/');
// Work out namespace for module
if (pathPrefix) {
// Ignore any filenames in the path
if (pathPrefix.indexOf('.') > 0) {
- sp = pathPrefix.split('/');
+ var sp = pathPrefix.split('/');
sp.pop();
pathPrefix = sp.join('/');
}
diff --git a/lib/client/bundler/pack.js b/lib/client/bundler/pack.js
deleted file mode 100644
index 2cfbf1cb..00000000
--- a/lib/client/bundler/pack.js
+++ /dev/null
@@ -1,14 +0,0 @@
-'use strict';
-
-var fs = require('fs'),
- path = require('path'),
- log = require('../../utils/log'),
- magicPath = require('../magic_path'),
- view = require('../view');
-
-module.exports = function(ss, client, bundler, options) {
-
-
- return ;
-};
-
diff --git a/src/docs/tutorials/en/client_side_xbundler.ngdoc b/src/docs/tutorials/en/client_side_xbundler.ngdoc
index 5a60e1aa..20bcae87 100644
--- a/src/docs/tutorials/en/client_side_xbundler.ngdoc
+++ b/src/docs/tutorials/en/client_side_xbundler.ngdoc
@@ -20,9 +20,11 @@ You can define a custom bundler by implementing a bundler function that will be
function webpackBundler(ss, options) {
var bundler = {};
- bundler.define = function(client,config,next_arg...) {};
+ bundler.define = function(client,config,next_arg...) {
+ // ...
+ return ss.bundler.destsFor(ss,client,options);
+ };
bundler.load = function() {};
- bundler.ensureAssetFolder = function() {}; // likely to be dropped
bundler.asset = {
html: function(path, opts, cb) { cb(output) },
css: function(path, opts, cb) { cb(output) },
From f99eb5fead9d4e49dc61f7f532932d5c1542d0db Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 1 Feb 2015 01:12:45 +0100
Subject: [PATCH 18/59] feat(bundler): Alternate bundler
webpack bundler for trying out
---
lib/client/bundler/webpack.js | 92 +++++++++++++++++++++++++++++++++++
1 file changed, 92 insertions(+)
create mode 100644 lib/client/bundler/webpack.js
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
new file mode 100644
index 00000000..2a9f7ab5
--- /dev/null
+++ b/lib/client/bundler/webpack.js
@@ -0,0 +1,92 @@
+// Webpack bundler implementation
+'use strict';
+
+var fs = require('fs'),
+ path = require('path'),
+ log = require('../../utils/log');
+
+module.exports = function(webpack) {
+ return function(ss,options){
+ var bundler = {
+ define: define,
+ load: load,
+ pack: {
+ js: packJS,
+ css: packCSS
+ },
+ asset: {
+ html: assetHTML,
+ js: assetJS,
+ worker: assetWorker,
+ css: assetCSS
+ }
+ };
+ return bundler;
+
+ function define(client, paths) {
+
+ if (typeof paths.view !== 'string') {
+ throw new Error('You may only define one HTML view per single-page client. Please pass a filename as a string, not an Array');
+ }
+ if (paths.view.indexOf('.') === -1) {
+ throw new Error('The \'' + paths.view + '\' view must have a valid HTML extension (such as .html or .jade)');
+ }
+
+ bundler.client = client;
+
+ // Alias 'templates' to 'tmpl'
+ if (paths.templates) {
+ paths.tmpl = paths.templates;
+ }
+
+ // Force each into an array
+ ['css', 'code', 'tmpl'].forEach(function(assetType) {
+ if (!(paths[assetType] instanceof Array)) {
+ paths[assetType] = [paths[assetType]];
+ return paths[assetType];
+ }
+ });
+
+ // Define new client object
+ client.paths = paths;
+
+ return ss.bundler.destsFor(ss,client,options);
+ }
+
+ function load() {
+
+ }
+
+ function assetCSS(path, opts, cb) {
+ return ss.bundler.loadFile(ss, options.dirs.css, path, 'css', opts, cb);
+ }
+
+ function assetHTML(path, opts, cb) {
+ return ss.bundler.loadFile(ss, options.dirs.views, path, 'html', opts, cb);
+ }
+
+ function assetJS(path, opts, cb) {
+ webpack({}, function() {
+ cb('//');
+ });
+
+ }
+
+ function assetWorker(path, opts, cb) {
+ webpack({}, function() {
+ cb('//');
+ });
+
+ }
+
+ function packCSS(postProcess) {
+ ss.bundler.packAssetSet('css', options.dirs.css, client, bundler, postProcess);
+ }
+
+ function packJS() {
+
+ }
+ };
+
+};
+
From 5c37be20317e24d1b23417d489183581e575172b Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 1 Feb 2015 15:28:22 +0100
Subject: [PATCH 19/59] doc(bundler): Bundling in development
---
docs/js/docs-setup.js | 11 +++++++-
.../tutorials/client_side_development.html | 15 ++++++++++
.../tutorials/client_side_xbundler.html | 25 +++++++++++++----
.../en/client_side_development.ngdoc | 17 +++++++++++
.../tutorials/en/client_side_xbundler.ngdoc | 28 +++++++++++++++----
5 files changed, 84 insertions(+), 12 deletions(-)
create mode 100644 docs/partials/tutorials/client_side_development.html
create mode 100644 src/docs/tutorials/en/client_side_development.ngdoc
diff --git a/docs/js/docs-setup.js b/docs/js/docs-setup.js
index cef19541..8d556272 100644
--- a/docs/js/docs-setup.js
+++ b/docs/js/docs-setup.js
@@ -32,6 +32,15 @@ NG_DOCS={
"shortDescription": "Client-Side Code",
"keywords": "ability absolutely access accessed add allowing allows alphanumerically amd amount app apply approaches as-is automatically aware awesome backbone background bear better blank boiler-plate brought browser browserify browserifyexcludepaths cache called calls case cases catch change chaos choice clean client client-code client-side code coffee coming command common components connection console copy create created critical critically default define demand depend dependencies depends developer developers difference directores directory disable distinction doesn don easily ensure entry entrymodulename error established exactly example exceptions exclude excluded excluding execuring execute executed exist expect experience explicitly export file files folder forget form full functions future globalmodules goal going great handle head history hopes https inbuilt info instantly internally javascript jquery js killing leading legacy libraries library libs lightweight list live lives ll load loading long magic major making manage managing manually md mess mind modification modify module modules namespacing node null onus options order org overview packaging path paths performs point position problem problems project querystring reconnecting reference regular relative require required requires send serve served server server-side set share sharing side single slash small socketstream solution solutions solves special ss stack statement string structure subdirectories substack syntax system top track treated tricky true tutorials type typically underscore unique unstructured url values variable view views wade wanted web websocket window work works write writing"
},
+ {
+ "section": "tutorials",
+ "id": "client_side_development",
+ "shortName": "Client-Side Development",
+ "type": "overview",
+ "moduleName": "Client-Side Development",
+ "shortDescription": "Client-Side Development",
+ "keywords": "asset assets break browser bundle bundler caching client client-side css determine development directory entry file fly html http injected js overview path pattern relative separate separately served timestamp tutorials type url view"
+ },
{
"section": "tutorials",
"id": "client_side_templates",
@@ -48,7 +57,7 @@ NG_DOCS={
"type": "overview",
"moduleName": "Client-Side Bundler",
"shortDescription": "Client-Side Bundler",
- "keywords": "action additional arguments asset assets aware based browserify bulk bundle bundler bundlers bundling callback called cb changes client client-side code complete completely config contents create css current custom default define definition described destsfor development directory discuss dropped early experimental features file files function future html implement implementation implemented implementing individual jade js jspm lacks load method methods minification move named newer next_arg object objective optimisations options opts overview pack pass passed production referenced responsibilities return saved scss separate served server ss starting step supported templates text tmpl tutorials types var view views webpack webpackbundler worker"
+ "keywords": "action additional arguments array asset assets aware based behaviour browserify built-in bulk bundle bundler bundlers bundling callback called cb changes client client-side code complete completely config considered contents create css current custom default define definition described destsfor development directory dirs discuss dropped early entries existing experimental features file files forced function functionality future html implement implementation implemented implementing individual jade js jspm lacks load lot method methods minification move named newer next_arg object objective optimisations options opts overview pack pass passed path paths production referenced relative responsibilities return returns revised saved scss separate served server set shorthand shouldn sourcepaths ss starting starts step supported templates text tmpl tutorials types var view views webpack webpackbundler worker write"
},
{
"section": "tutorials",
diff --git a/docs/partials/tutorials/client_side_development.html b/docs/partials/tutorials/client_side_development.html
new file mode 100644
index 00000000..dc64043b
--- /dev/null
+++ b/docs/partials/tutorials/client_side_development.html
@@ -0,0 +1,15 @@
+
+
+
+
+
Client-Side Development
+
Each view is served with a separate bundle of assets. A HTML, JS and CSS file makes up the view.
+
Each entry is served separately to the browser injected in the HTML on the fly.
+
+
A relative path is given in the URL, relative to the "/client" directory.
+
The client is given in the URL to determine the bundler.
+
The asset type is specified in the URL to determine the bundler.
+
A timestamp is given in the URL to break any caching.
+
+
The URL pattern is http:///_serveDev/<type>/<relative path>?ts=<id>&client=<client>.
features. The objective is to be able to move to bundling based on newer ones such as WebPack or JSPM. It should be possible
to implement a bundler that completely changes how the client is implemented. Hence there will be additional responsibilities
for bundlers in the future.
-
Custom Bundler
+
Custom Bundler
You can define a custom bundler by implementing a bundler function that will be called for each client it is used on.
function webpackBundler(ss, options) {
var bundler = {};
@@ -40,17 +40,30 @@
Custom Bundler
tmpl: './templates/discuss'
});
The define method of the bundler will be called to complete ss.client.define.
-
Bundler Define define(client,config,..)
+
Bundler Define define(client,config,..)
The define method will be called with a client object containing id, name,
If you pass additional arguments to define they will be passed to bundler.define. This may be dropped in the future.
-
Bundler Load load()
+
Bundler Load load()
The load method is called as the first step to load the client views. This is done as a bulk action as part of starting
the server.
-
Bundler asset methods
+
Bundler asset methods
For each of the asset types supported individual files can be served during development.
A callback function is passed, and must be called with the text contents.
-
Bundler pack methods
+
Bundler pack methods
Files are saved in the assets directory for production use. The HTML file is the same as the one used during development,
so the asset.html method will be called. For JS and CSS the pack methods are called to do additional minification and
other optimisations.
-
+
Bundler shorthand
+
A lot of functionality is built-in. When you write your own bundler you shouldn't have to do it all over again. So most
+of the existing behaviour can be called through ss.bundler.
+
ss.bundler.sourcePaths(ss,paths,options)
+
This returns a revised paths object. Paths should contain entries code, css, tmpl. They will be forced into an array.
+If a path starts with "./", it is considered relative to "/client". Otherwise it is considered relative to "/client/code",
+"/client/css", "/client/templates". These directory options can be set using ss.client.set.
diff --git a/src/docs/tutorials/en/client_side_development.ngdoc b/src/docs/tutorials/en/client_side_development.ngdoc
new file mode 100644
index 00000000..6eeac654
--- /dev/null
+++ b/src/docs/tutorials/en/client_side_development.ngdoc
@@ -0,0 +1,17 @@
+@ngdoc overview
+@name Client-Side Development
+
+@description
+# Client-Side Development
+
+Each view is served with a separate bundle of assets. A HTML, JS and CSS file makes up the view.
+
+Each entry is served separately to the browser injected in the HTML on the fly.
+
+* A relative path is given in the URL, relative to the "/client" directory.
+* The client is given in the URL to determine the bundler.
+* The asset type is specified in the URL to determine the bundler.
+* A timestamp is given in the URL to break any caching.
+
+The URL pattern is `http:///_serveDev//?ts=&client=`.
+
diff --git a/src/docs/tutorials/en/client_side_xbundler.ngdoc b/src/docs/tutorials/en/client_side_xbundler.ngdoc
index 20bcae87..78336444 100644
--- a/src/docs/tutorials/en/client_side_xbundler.ngdoc
+++ b/src/docs/tutorials/en/client_side_xbundler.ngdoc
@@ -14,7 +14,7 @@ features. The objective is to be able to move to bundling based on newer ones su
to implement a bundler that completely changes how the client is implemented. Hence there will be additional responsibilities
for bundlers in the future.
-#### Custom Bundler
+### Custom Bundler
You can define a custom bundler by implementing a bundler function that will be called for each client it is used on.
@@ -50,24 +50,42 @@ You can use a custom bundler by for a client view by specifying it in the defini
The define method of the bundler will be called to complete `ss.client.define`.
-#### Bundler Define `define(client,config,..)`
+### Bundler Define `define(client,config,..)`
The define method will be called with a client object containing `id`, `name`,
If you pass additional arguments to define they will be passed to `bundler.define`. This may be dropped in the future.
-#### Bundler Load `load()`
+### Bundler Load `load()`
The load method is called as the first step to load the client views. This is done as a bulk action as part of starting
the server.
-#### Bundler asset methods
+### Bundler asset methods
For each of the asset types supported individual files can be served during development.
A callback function is passed, and must be called with the text contents.
-#### Bundler pack methods
+### Bundler pack methods
Files are saved in the assets directory for production use. The HTML file is the same as the one used during development,
so the `asset.html` method will be called. For JS and CSS the pack methods are called to do additional minification and
other optimisations.
+
+### Bundler shorthand
+
+A lot of functionality is built-in. When you write your own bundler you shouldn't have to do it all over again. So most
+of the existing behaviour can be called through `ss.bundler`.
+
+##### `ss.bundler.sourcePaths(ss,paths,options)`
+
+This returns a revised paths object. Paths should contain entries `code`, `css`, `tmpl`. They will be forced into an array.
+If a path starts with "./", it is considered relative to "/client". Otherwise it is considered relative to "/client/code",
+"/client/css", "/client/templates". These directory options can be set using `ss.client.set`.
+
+ ss.client.set({
+ dirs: {
+ client: '/client',
+ code: '/client/code'
+ }
+ });
From 0643377160faa3748d1ebf0040e55f407a63bee8 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 1 Feb 2015 15:31:30 +0100
Subject: [PATCH 20/59] feat(bundler): Assets relative to /client
sourcePaths common logic notes paths relative to /client rather than type specific.
---
lib/client/bundler/default.js | 27 +++++++--------------------
lib/client/bundler/index.js | 25 +++++++++++++++++++++++++
lib/client/bundler/webpack.js | 21 ++++-----------------
lib/client/serve/ondemand.js | 26 ++++++++++++--------------
lib/client/view.js | 6 +++---
5 files changed, 51 insertions(+), 54 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index 3eec6918..b3c78feb 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -45,21 +45,8 @@ module.exports = function(ss,client,options){
throw new Error('The \'' + paths.view + '\' view must have a valid HTML extension (such as .html or .jade)');
}
- // Alias 'templates' to 'tmpl'
- if (paths.templates) {
- paths.tmpl = paths.templates;
- }
-
- // Force each into an array
- ['css', 'code', 'tmpl'].forEach(function(assetType) {
- if (!(paths[assetType] instanceof Array)) {
- paths[assetType] = [paths[assetType]];
- return paths[assetType];
- }
- });
-
// Define new client object
- client.paths = paths;
+ client.paths = ss.bundler.sourcePaths(ss,paths,options);
client.includes = includeFlags(paths.includes);
return ss.bundler.destsFor(ss,client,options);
@@ -70,7 +57,7 @@ module.exports = function(ss,client,options){
}
function assetJS(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.code, path, 'js', opts, function(output) {
+ return ss.bundler.loadFile(ss, options.dirs.client, path, 'js', opts, function(output) {
output = ss.bundler.wrapCode(output, path, opts.pathPrefix, options);
if (opts.compress && path.indexOf('.min') === -1) {
output = ss.bundler.minifyJSFile(output, path);
@@ -79,7 +66,7 @@ module.exports = function(ss,client,options){
});
}
function assetWorker(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.workers, path, 'js', opts, function(output) {
+ return ss.bundler.loadFile(ss, options.dirs.client, path, 'js', opts, function(output) {
if (opts.compress) {
output = ss.bundler.minifyJSFile(output, path);
}
@@ -88,19 +75,19 @@ module.exports = function(ss,client,options){
}
function assetCSS(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.css, path, 'css', opts, cb);
+ return ss.bundler.loadFile(ss, options.dirs.client, path, 'css', opts, cb);
}
function assetHTML(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.views, path, 'html', opts, cb);
+ return ss.bundler.loadFile(ss, options.dirs.client, path, 'html', opts, cb);
}
function packJS(postProcess) {
- ss.bundler.packAssetSet('js', options.dirs.code, client, bundler, postProcess);
+ ss.bundler.packAssetSet('js', options.dirs.client, client, bundler, postProcess);
}
function packCSS(postProcess) {
- ss.bundler.packAssetSet('css', options.dirs.css, client, bundler, postProcess);
+ ss.bundler.packAssetSet('css', options.dirs.client, client, bundler, postProcess);
}
};
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 279905be..bcb7f972 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -155,6 +155,31 @@ exports.minifyJSFile = function minifyJSFile(originalCode, fileName) {
return minifiedCode;
};
+// input is decorated and returned
+exports.sourcePaths = function(ss,paths,options) {
+
+ function entries(from, dirType) {
+ if (from == null) {
+ return [];
+ }
+ var list = (from instanceof Array)? from : [from];
+
+ return list.map(function(value) {
+ var relClient = './' + path.relative(options.dirs.client, options.dirs[dirType]);
+ return value.substring(0,2) === './'? value : path.join(relClient, value);
+ });
+ }
+
+ paths.css = entries(paths.css, 'css');
+ paths.code = entries(paths.code, 'code');
+ paths.tmpl = entries(paths.tmpl || paths.templates, 'templates');
+
+ var relClient = './' + path.relative(options.dirs.client, options.dirs['views']);
+ paths.view = paths.view.substring(0,2) === './'? paths.view : path.join(relClient, paths.view);
+
+ return paths;
+};
+
exports.destsFor = function(ss,client,options) {
var containerDir = path.join(ss.root, options.dirs.assets);
var clientDir = path.join(containerDir, client.name);
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 2a9f7ab5..375eff7b 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -34,21 +34,8 @@ module.exports = function(webpack) {
bundler.client = client;
- // Alias 'templates' to 'tmpl'
- if (paths.templates) {
- paths.tmpl = paths.templates;
- }
-
- // Force each into an array
- ['css', 'code', 'tmpl'].forEach(function(assetType) {
- if (!(paths[assetType] instanceof Array)) {
- paths[assetType] = [paths[assetType]];
- return paths[assetType];
- }
- });
-
// Define new client object
- client.paths = paths;
+ client.paths = ss.bundler.sourcePaths(ss,paths,options);
return ss.bundler.destsFor(ss,client,options);
}
@@ -58,11 +45,11 @@ module.exports = function(webpack) {
}
function assetCSS(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.css, path, 'css', opts, cb);
+ return ss.bundler.loadFile(ss, options.dirs.client, path, 'css', opts, cb);
}
function assetHTML(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.views, path, 'html', opts, cb);
+ return ss.bundler.loadFile(ss, options.dirs.client, path, 'html', opts, cb);
}
function assetJS(path, opts, cb) {
@@ -80,7 +67,7 @@ module.exports = function(webpack) {
}
function packCSS(postProcess) {
- ss.bundler.packAssetSet('css', options.dirs.css, client, bundler, postProcess);
+ ss.bundler.packAssetSet('css', options.dirs.client, client, bundler, postProcess);
}
function packJS() {
diff --git a/lib/client/serve/ondemand.js b/lib/client/serve/ondemand.js
index 51e26106..074f6ee1 100644
--- a/lib/client/serve/ondemand.js
+++ b/lib/client/serve/ondemand.js
@@ -21,12 +21,9 @@ utils = require('./utils');
queryCache = {};
module.exports = function(ss, router, options) {
- var code, serve, worker;
-
- serve = function(processor) {
+ function serve(processor) {
return function(request, response) {
- var path;
- path = utils.parseUrl(request.url);
+ var path = utils.parseUrl(request.url);
if (options.packAssets && queryCache[path]) {
return utils.serve.js(queryCache[path], response);
} else {
@@ -36,14 +33,14 @@ module.exports = function(ss, router, options) {
});
}
};
- };
+ }
// Async Code Loading
- code = function(request, response, path, cb) {
- var dir, files, output;
- output = [];
- dir = pathlib.join(ss.root, options.dirs.code);
- files = magicPath.files(dir, [path]);
+ function code(request, response, path, cb) {
+ var output = [],
+ dir = pathlib.join(ss.root, options.dirs.client),
+ files = magicPath.files(dir, [path]);
+
//TODO determine client and get bundler
return files.forEach(function(file) {
var description;
@@ -63,14 +60,15 @@ module.exports = function(ss, router, options) {
return log.error(('! Unable to load ' + file + ' on demand:').red, description);
}
});
- };
+ }
// Web Workers
- worker = function(request, response, path, cb) {
+ function worker(request, response, path, cb) {
+ //TODO return bundler.js()
return asset.worker(path, {
compress: options.packAssets
}, cb);
- };
+ }
// Bind to routes
router.on('/_serve/code?*', serve(code));
diff --git a/lib/client/view.js b/lib/client/view.js
index 52aa790f..6246e4a7 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -29,7 +29,7 @@ module.exports = function(ss, client, options, cb) {
defaultPath = '/assets/' + client.name + '/' + client.id + '.' + type;
if (link = (_ref = options.packedAssets) !== undefined ? (_ref1 = _ref.cdn) !== undefined ? _ref1[type] : void 0 : void 0) {
if (typeof link === 'function') {
- file = {
+ var file = {
id: client.id,
name: client.name,
extension: type,
@@ -85,7 +85,7 @@ module.exports = function(ss, client, options, cb) {
// Send all CSS
if (client.includes.css) {
client.paths.css.forEach(function(path) {
- return magicPath.files(pathlib.join(ss.root, options.dirs.css), path).forEach(function(file) {
+ return magicPath.files(pathlib.join(ss.root, options.dirs.client), path).forEach(function(file) {
return output.push(wrap.htmlTag.css('/_serveDev/css/' + file + '?ts=' + client.id + '&client=' + client.name));
});
});
@@ -93,7 +93,7 @@ module.exports = function(ss, client, options, cb) {
// Send Application Code
client.paths.code.forEach(function(path) {
- return magicPath.files(pathlib.join(ss.root, options.dirs.code), path).forEach(function(file) {
+ return magicPath.files(pathlib.join(ss.root, options.dirs.client), path).forEach(function(file) {
var url = '/_serveDev/code/' + file + '?ts=' + client.id + '&client=' + client.name;
if (! options.globalModules) url += '&pathPrefix=' + path;
return output.push(wrap.htmlTag.js(url));
From a08f775352b021de3f04842735e098c06f43da0e Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 1 Feb 2015 17:10:30 +0100
Subject: [PATCH 21/59] bug(merge): Fixed merge errors
---
lib/client/index.js | 1 -
lib/client/serve/dev.js | 3 ++-
lib/client/view.js | 7 ++++---
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/lib/client/index.js b/lib/client/index.js
index 4ca1b709..a0d56a74 100644
--- a/lib/client/index.js
+++ b/lib/client/index.js
@@ -12,7 +12,6 @@ var fs = require('fs'),
path = require('path'),
log = require('../utils/log'),
systemAssets = require('./system'),
-
bundler = require('./bundler/index');
// Determine if assets should be (re)packed on startup
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index 84d8ba57..464c1b0d 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -6,7 +6,8 @@
var url = require('url'),
qs = require('querystring'),
system = require('../system'),
- utils = require('./utils');
+ utils = require('./utils'),
+ bundler = require('../bundler/index');
// Expose asset server as the public API
//
diff --git a/lib/client/view.js b/lib/client/view.js
index 6246e4a7..671b27bf 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -20,7 +20,7 @@ module.exports = function(ss, client, options, cb) {
compress: options.packedAssets,
filename: client.paths.view
};
- return bundler.asset.html(client.paths.client, htmlOptions, cb);
+ return bundler.asset.html(client.paths.view, htmlOptions, cb);
// When packing assets the default path to the CSS or JS file can be overridden
// either with a string or a function, typically pointing to an resource on a CDN
@@ -44,8 +44,9 @@ module.exports = function(ss, client, options, cb) {
} else {
return defaultPath;
}
- };
- templates = function() {
+ }
+
+ function templates() {
var dir, files, output;
dir = pathlib.join(ss.root, options.dirs.templates);
output = [];
From 8788aeec9aa422b5dc8b620489d8d4ce4c323a94 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 1 Feb 2015 20:23:17 +0100
Subject: [PATCH 22/59] feat(bundler): tmpl: '*'
Templates are in '/client/templates' by default, but can be outside using paths starting with './'
---
lib/client/view.js | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/lib/client/view.js b/lib/client/view.js
index 671b27bf..d5f4e7b7 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -47,13 +47,18 @@ module.exports = function(ss, client, options, cb) {
}
function templates() {
- var dir, files, output;
- dir = pathlib.join(ss.root, options.dirs.templates);
- output = [];
+ var dir = pathlib.join(ss.root, options.dirs.client);
+ var output = [];
if (client.paths.tmpl) {
- files = [];
+ var files = [];
client.paths.tmpl.forEach(function(tmpl) {
- files = files.concat(magicPath.files(dir, tmpl));
+ if (tmpl.substring(tmpl.length-2) == '/*') {
+ var matching = magicPath.files(pathlib.join(dir,tmpl.substring(0,tmpl.length-2)), '*');
+ files = files.concat(matching.map(function(p) { return pathlib.join(tmpl.substring(0,tmpl.length-2),p); }));
+ }
+ else {
+ files = files.concat(magicPath.files(dir, tmpl));
+ }
});
templateEngine.generate(dir, files, function(templateHTML) {
return output.push(templateHTML);
From bb3133eb61c27e453389a065c36e89548be2b475 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 1 Feb 2015 20:23:48 +0100
Subject: [PATCH 23/59] bug(ondemand): Call bundler
---
lib/client/serve/ondemand.js | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/lib/client/serve/ondemand.js b/lib/client/serve/ondemand.js
index 074f6ee1..ab1ad832 100644
--- a/lib/client/serve/ondemand.js
+++ b/lib/client/serve/ondemand.js
@@ -4,21 +4,18 @@
// ----------------------
// Serves assets to browsers on demand, caching responses in production mode
-var magicPath, pathlib, queryCache, utils, log;
-
require('colors');
-pathlib = require('path');
-
-magicPath = require('../magic_path');
-
-log = require('../../utils/log');
-
-utils = require('./utils');
+var url = require('url'),
+ qs = require('querystring'),
+ pathlib = require('path'),
+ magicPath = require('../magic_path'),
+ log = require('../../utils/log'),
+ utils = require('./utils');
// When packing assets, cache responses to each query in RAM to avoid
// having to re-compile and minify assets. TODO: Add limits/purging
-queryCache = {};
+var queryCache = {};
module.exports = function(ss, router, options) {
function serve(processor) {
@@ -38,15 +35,17 @@ module.exports = function(ss, router, options) {
// Async Code Loading
function code(request, response, path, cb) {
var output = [],
+ thisUrl = url.parse(request.url),
+ params = qs.parse(thisUrl.query),
dir = pathlib.join(ss.root, options.dirs.client),
files = magicPath.files(dir, [path]);
- //TODO determine client and get bundler
return files.forEach(function(file) {
var description;
try {
- //TODO return bundler.js()
- return asset.js(file, {
+ return bundler.get(ss,params,options).asset.js(file, {
+ client: params.client,
+ clientId: params.ts,
pathPrefix: options.globalModules? null : path,
compress: options.packAssets
}, function(js) {
@@ -64,8 +63,10 @@ module.exports = function(ss, router, options) {
// Web Workers
function worker(request, response, path, cb) {
- //TODO return bundler.js()
- return asset.worker(path, {
+ var thisUrl = url.parse(request.url),
+ params = qs.parse(thisUrl.query);
+
+ return bundler.get(ss,params,options).asset.worker(path, {
compress: options.packAssets
}, cb);
}
@@ -74,3 +75,4 @@ module.exports = function(ss, router, options) {
router.on('/_serve/code?*', serve(code));
return router.on('/_serve/worker?*', serve(worker));
};
+
From 94b86e7b4750c4d92b62f250b593dbbef5eb74f0 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 1 Feb 2015 20:24:36 +0100
Subject: [PATCH 24/59] feat(bundler): client.includes needed for now
---
lib/client/bundler/webpack.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 375eff7b..617a2562 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -36,6 +36,7 @@ module.exports = function(webpack) {
// Define new client object
client.paths = ss.bundler.sourcePaths(ss,paths,options);
+ client.includes = {}; //TODO post-define default?
return ss.bundler.destsFor(ss,client,options);
}
From e6cb07b9ef511adeed39f39a5f1a8752f97669c2 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Tue, 3 Feb 2015 20:37:46 +0100
Subject: [PATCH 25/59] feat(bundler): ss.bundler.asset.launch
---
lib/client/bundler/default.js | 6 ++++++
lib/client/bundler/index.js | 7 +++++++
lib/client/bundler/webpack.js | 6 ++++++
lib/client/index.js | 4 ++++
lib/client/serve/dev.js | 17 +++++++++++------
5 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index b3c78feb..e55a7ace 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -25,6 +25,7 @@ module.exports = function(ss,client,options){
asset: {
js: assetJS,
worker: assetWorker,
+ launch: assetLaunch,
css: assetCSS,
html: assetHTML
},
@@ -74,6 +75,11 @@ module.exports = function(ss,client,options){
});
}
+ function assetLaunch(cb) {
+ var output = ss.bundler.launchCode(ss, client);
+ return cb(output);
+ }
+
function assetCSS(path, opts, cb) {
return ss.bundler.loadFile(ss, options.dirs.client, path, 'css', opts, cb);
}
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index bcb7f972..5b2b080a 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -202,6 +202,13 @@ exports.destsFor = function(ss,client,options) {
};
}
+exports.launchCode = function(ss, client) {
+ var initCode = system.serve.initCode(),
+ entryInit = 'require("/entry");';
+ initCode = initCode.replace(entryInit, 'require(' + client.entryInitPath + ');')
+ return initCode;
+};
+
exports.packAssetSet = function packAssetSet(assetType, dir, client, bundler, postProcess) {
var filePaths,
prefix,
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 617a2562..8c612d24 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -18,6 +18,7 @@ module.exports = function(webpack) {
html: assetHTML,
js: assetJS,
worker: assetWorker,
+ launch: assetLaunch,
css: assetCSS
}
};
@@ -60,6 +61,11 @@ module.exports = function(webpack) {
}
+ function assetLaunch(cb) {
+ var output = ss.bundler.launchCode(ss, client);
+ return cb(output);
+ }
+
function assetWorker(path, opts, cb) {
webpack({}, function() {
cb('//');
diff --git a/lib/client/index.js b/lib/client/index.js
index a0d56a74..6f27b43c 100644
--- a/lib/client/index.js
+++ b/lib/client/index.js
@@ -139,6 +139,10 @@ module.exports = function(ss, router) {
var client = clients[name] = { name: name };
client.id = Number(Date.now());
bundler.define(ss,client,arguments,options);
+
+ //TODO reconsider relative paths of all these
+ client.entryInitPath = '/code/' + client.name + '/entry';
+
return client;
},
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index 464c1b0d..a295e74d 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -22,10 +22,10 @@ module.exports = function (ss, router, options) {
// Listen for requests for application client code
router.on('/_serveDev/code?*', function(request, response) {
- var params, path, thisUrl;
- thisUrl = url.parse(request.url);
- params = qs.parse(thisUrl.query);
- path = utils.parseUrl(request.url);
+ var thisUrl = url.parse(request.url),
+ params = qs.parse(thisUrl.query),
+ path = utils.parseUrl(request.url);
+
return bundler.get(ss,params,options).asset.js(path, {
client: params.client,
clientId: params.ts,
@@ -35,8 +35,13 @@ module.exports = function (ss, router, options) {
});
});
router.on('/_serveDev/start?*', function(request, response) {
- //TODO initCode for a client with ts=..
- return utils.serve.js(system.serve.initCode(), response);
+ var thisUrl = url.parse(request.url),
+ params = qs.parse(thisUrl.query);
+
+ bundler.get(ss,params,options).asset.launch(function(output) {
+ return utils.serve.js(output, response);
+ });
+
});
// CSS
From d3dcc2df06c2b7b7d10a736807e30ad4b2176d72 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Tue, 3 Feb 2015 20:38:25 +0100
Subject: [PATCH 26/59] chore(declare): var and function declarations updated
---
lib/client/system/index.js | 24 ++++++++++--------------
1 file changed, 10 insertions(+), 14 deletions(-)
diff --git a/lib/client/system/index.js b/lib/client/system/index.js
index e7ba376b..8a32b171 100644
--- a/lib/client/system/index.js
+++ b/lib/client/system/index.js
@@ -4,20 +4,15 @@
// -------------
// Loads system libraries and modules for the client. Also exposes an internal API
// which other modules can use to send system assets to the client
-var assets, fs, fsUtils, minifyJS, pathlib, send, uglifyjs, wrap;
-fs = require('fs');
-
-pathlib = require('path');
-
-uglifyjs = require('uglify-js');
-
-wrap = require('../wrap');
-
-fsUtils = require('../../utils/file');
+var fs = require('fs'),
+ pathlib = require('path'),
+ uglifyjs = require('uglify-js'),
+ wrap = require('../wrap'),
+ fsUtils = require('../../utils/file');
// Allow internal modules to deliver assets to the browser
-assets = {
+var assets = {
shims: [],
libs: [],
modules: {},
@@ -35,10 +30,11 @@ function pushUniqueAsset(listName,asset) {
}
// API to add new System Library or Module
-exports.send = send = function (type, name, content, options) {
+var send = exports.send = function (type, name, content, options) {
if (options === null || options === undefined) {
options = {};
}
+
switch (type) {
case 'code':
return assets.initCode.push(content);
@@ -165,7 +161,7 @@ exports.serve = {
};
// Private
-minifyJS = function(originalCode) {
+function minifyJS(originalCode) {
var ast, jsp, pro;
jsp = uglifyjs.parser;
pro = uglifyjs.uglify;
@@ -173,4 +169,4 @@ minifyJS = function(originalCode) {
ast = pro.ast_mangle(ast);
ast = pro.ast_squeeze(ast);
return pro.gen_code(ast) + ';';
-};
+}
From 4c4313e66f0a500b16baa25d8964cd45ff0dc529 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Tue, 3 Feb 2015 21:58:06 +0100
Subject: [PATCH 27/59] feat(bundler): Improved bundler api
---
lib/client/bundler/default.js | 16 +-
lib/client/bundler/index.js | 479 +++++++++++++++++-----------------
lib/client/bundler/webpack.js | 12 +-
lib/client/index.js | 9 +-
lib/client/pack.js | 2 +-
lib/client/serve/dev.js | 11 +-
lib/client/serve/ondemand.js | 7 +-
lib/client/view.js | 2 +-
8 files changed, 276 insertions(+), 262 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index e55a7ace..8247b31c 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -47,10 +47,10 @@ module.exports = function(ss,client,options){
}
// Define new client object
- client.paths = ss.bundler.sourcePaths(ss,paths,options);
+ client.paths = ss.bundler.sourcePaths(paths);
client.includes = includeFlags(paths.includes);
- return ss.bundler.destsFor(ss,client,options);
+ return ss.bundler.destsFor(client);
}
function load() {
@@ -58,8 +58,8 @@ module.exports = function(ss,client,options){
}
function assetJS(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.client, path, 'js', opts, function(output) {
- output = ss.bundler.wrapCode(output, path, opts.pathPrefix, options);
+ return ss.bundler.loadFile(options.dirs.client, path, 'js', opts, function(output) {
+ output = ss.bundler.wrapCode(output, path, opts.pathPrefix);
if (opts.compress && path.indexOf('.min') === -1) {
output = ss.bundler.minifyJSFile(output, path);
}
@@ -67,7 +67,7 @@ module.exports = function(ss,client,options){
});
}
function assetWorker(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.client, path, 'js', opts, function(output) {
+ return ss.bundler.loadFile(options.dirs.client, path, 'js', opts, function(output) {
if (opts.compress) {
output = ss.bundler.minifyJSFile(output, path);
}
@@ -76,16 +76,16 @@ module.exports = function(ss,client,options){
}
function assetLaunch(cb) {
- var output = ss.bundler.launchCode(ss, client);
+ var output = ss.bundler.launchCode(client);
return cb(output);
}
function assetCSS(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.client, path, 'css', opts, cb);
+ return ss.bundler.loadFile(options.dirs.client, path, 'css', opts, cb);
}
function assetHTML(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.client, path, 'html', opts, cb);
+ return ss.bundler.loadFile(options.dirs.client, path, 'html', opts, cb);
}
function packJS(postProcess) {
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 5b2b080a..85398d01 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -19,291 +19,302 @@ var fs = require('fs'),
*/
var bundlers = {};
-/**
- * Define the bundler for a client
- * @param client object to store the definition in
- * @param args arguments passed to define
- */
-exports.define = function defineBundler(ss,client,args,options) {
+module.exports = function(ss,options) {
- var name = args[0],
- pathsOrFunc = args[1];
+ function getBundler(client){
- if (typeof pathsOrFunc === "function") {
- bundlers[name] = pathsOrFunc(ss,options);
- bundlers[name].dests = bundlers[name].define(client, args[2], args[3], args[4], args[5]);
- } else {
- bundlers[name] = require('./default')(ss,client,options);
- bundlers[name].dests = bundlers[name].define(args[1]);
- }
-};
-
-/**
- * Determine the bundler for a client
- * @param client Query params with client=name or an actual client object
- */
-function getBundler(ss,client,options){
+ if (client.bundler) { return client.bundler; }
- if (client.bundler) { return client.bundler; }
+ if (typeof client.client === "string") {
+ return bundlers[client.client];
+ }
+ if (typeof client.name === "string") {
+ return bundlers[client.name];
+ }
- if (typeof client.client === "string") {
- return bundlers[client.client];
- }
- if (typeof client.name === "string") {
- return bundlers[client.name];
+ throw new Error('Unknow client '+(client.name || client.client) );
}
- throw new Error('Unknow client '+(client.name || client.client) );
-}
-exports.get = getBundler;
+ return {
-exports.load = function() {
- for(var n in bundlers) {
- bundlers[n].load();
- }
-};
+ /**
+ * Define the bundler for a client
+ * @param client object to store the definition in
+ * @param args arguments passed to define
+ */
+ define: function defineBundler(client,args) {
-exports.pack = function pack(ss, client, options) {
- client.pack = true;
+ var name = args[0],
+ pathsOrFunc = args[1];
- // the concrete bundler for the client
- var bundler = getBundler(ss, client, options);
+ if (typeof pathsOrFunc === "function") {
+ bundlers[name] = pathsOrFunc(ss,options);
+ bundlers[name].dests = bundlers[name].define(client, args[2], args[3], args[4], args[5]);
+ } else {
+ bundlers[name] = require('./default')(ss,client,options);
+ bundlers[name].dests = bundlers[name].define(args[1]);
+ }
- /* PACKER */
+ //console.warn('client defined',name,client,bundlers[name].dests);
+ },
- log(('Pre-packing and minifying the \'' + client.name + '\' client...').yellow);
-
- // Prepare folder
- mkdir(bundler.dests.containerDir);
- mkdir(bundler.dests.dir);
- if (!(options.packedAssets && options.packedAssets.keepOldFiles)) {
- deleteOldFiles(bundler.dests.dir);
- }
+ /**
+ * Determine the bundler for a client
+ * @param client Query params with client=name or an actual client object
+ */
+ get: getBundler,
- // Output CSS
- bundler.pack.css(function(files) {
- var minified, original;
- original = files.join('\n');
- minified = cleanCSS.process(original);
- log.info((' Minified CSS from ' + (exports.formatKb(original.length)) + ' to ' + (exports.formatKb(minified.length))).grey);
- return minified;
- });
-
- // Output JS
- bundler.pack.js(function(files) {
- var parts = [];
- if (client.includes.system) {
- parts.push( system.serve.js({ compress:true }) );
- }
- parts = parts.concat(files);
- if (client.includes.initCode) {
- parts.push( system.serve.initCode() );
- }
+ load: function() {
+ for(var n in bundlers) {
+ bundlers[n].load();
+ }
+ },
- return parts.join(";");
- });
+ pack: function pack(client) {
+ client.pack = true;
- // Output HTML view
- return view(ss, client, options, function(html) {
- fs.writeFileSync(bundler.dests.paths.html, html);
- return log.info('✓'.green, 'Created and cached HTML file ' + bundler.dests.relPaths.html);
- });
-};
+ // the concrete bundler for the client
+ var bundler = getBundler(client);
+ /* PACKER */
-function deleteOldFiles(clientDir) {
- var numFilesDeleted = 0,
- filesDeleted = fs.readdirSync(clientDir).map(function(fileName) {
- return fs.unlinkSync(path.join(clientDir, fileName));
+ log(('Pre-packing and minifying the \'' + client.name + '\' client...').yellow);
+
+ // Prepare folder
+ mkdir(bundler.dests.containerDir);
+ mkdir(bundler.dests.dir);
+ if (!(options.packedAssets && options.packedAssets.keepOldFiles)) {
+ deleteOldFiles(bundler.dests.dir);
+ }
+
+ // Output CSS
+ bundler.pack.css(function(files) {
+ var minified, original;
+ original = files.join('\n');
+ minified = cleanCSS.process(original);
+ log.info((' Minified CSS from ' + (exports.formatKb(original.length)) + ' to ' + (exports.formatKb(minified.length))).grey);
+ return minified;
});
- return filesDeleted.length > 1 && log('✓'.green, '' + filesDeleted.length + ' previous packaged files deleted');
-}
-function mkdir(dir) {
- if (!fs.existsSync(dir)) {
- return fs.mkdirSync(dir);
- }
-}
+ // Output JS
+ bundler.pack.js(function(files) {
+ var parts = [];
+ if (client.includes.system) {
+ parts.push( system.serve.js({ compress:true }) );
+ }
+ parts = parts.concat(files);
+ if (client.includes.initCode) {
+ parts.push( system.serve.initCode() );
+ }
-// API for implementing bundlers
+ return parts.join(";");
+ });
-exports.loadFile = function loadFile(ss, dir, fileName, type, options, cb) {
- dir = path.join(ss.root, dir);
- var p = path.join(dir, fileName);
- var extension = path.extname(p);
- extension = extension && extension.substring(1); // argh!
- var formatter = ss.client.formatters[extension];
- if (p.substr(0, dir.length) !== dir) {
- throw new Error('Invalid path. Request for ' + p + ' must not live outside ' + dir);
- }
- if (!formatter) {
- throw new Error('Unsupported file extension \'.' + extension + '\' when we were expecting some type of ' + (type.toUpperCase()) + ' file. Please provide a formatter for ' + (p.substring(ss.root.length)) + ' or move it to /client/static');
- }
- if (formatter.assetType !== type) {
- throw new Error('Unable to render \'' + fileName + '\' as this appears to be a ' + (formatter.assetType.toUpperCase()) + ' file. Expecting some type of ' + (type.toUpperCase()) + ' file in ' + (dir.substr(ss.root.length)) + ' instead');
- }
- return formatter.compile(p.replace(/\\/g, '/'), options, cb);
-};
+ // Output HTML view
+ return view(ss, client, options, function(html) {
+ fs.writeFileSync(bundler.dests.paths.html, html);
+ return log.info('✓'.green, 'Created and cached HTML file ' + bundler.dests.relPaths.html);
+ });
+ },
-exports.minifyJSFile = function minifyJSFile(originalCode, fileName) {
- var ast = jsp.parse(originalCode);
- ast = pro.ast_mangle(ast);
- ast = pro.ast_squeeze(ast);
- var minifiedCode = pro.gen_code(ast);
- log.info((' Minified ' + fileName + ' from ' + (exports.formatKb(originalCode.length)) + ' to ' + (exports.formatKb(minifiedCode.length))).grey);
- return minifiedCode;
-};
-// input is decorated and returned
-exports.sourcePaths = function(ss,paths,options) {
+ // API for implementing bundlers
- function entries(from, dirType) {
- if (from == null) {
- return [];
- }
- var list = (from instanceof Array)? from : [from];
+ loadFile: function loadFile(dir, fileName, type, options, cb) {
+ dir = path.join(ss.root, dir);
+ var p = path.join(dir, fileName);
+ var extension = path.extname(p);
+ extension = extension && extension.substring(1); // argh!
+ var formatter = ss.client.formatters[extension];
+ if (p.substr(0, dir.length) !== dir) {
+ throw new Error('Invalid path. Request for ' + p + ' must not live outside ' + dir);
+ }
+ if (!formatter) {
+ throw new Error('Unsupported file extension \'.' + extension + '\' when we were expecting some type of ' + (type.toUpperCase()) + ' file. Please provide a formatter for ' + (p.substring(ss.root.length)) + ' or move it to /client/static');
+ }
+ if (formatter.assetType !== type) {
+ throw new Error('Unable to render \'' + fileName + '\' as this appears to be a ' + (formatter.assetType.toUpperCase()) + ' file. Expecting some type of ' + (type.toUpperCase()) + ' file in ' + (dir.substr(ss.root.length)) + ' instead');
+ }
+ return formatter.compile(p.replace(/\\/g, '/'), options, cb);
+ },
- return list.map(function(value) {
- var relClient = './' + path.relative(options.dirs.client, options.dirs[dirType]);
- return value.substring(0,2) === './'? value : path.join(relClient, value);
- });
- }
+ minifyJSFile: function minifyJSFile(originalCode, fileName) {
+ var ast = jsp.parse(originalCode);
+ ast = pro.ast_mangle(ast);
+ ast = pro.ast_squeeze(ast);
+ var minifiedCode = pro.gen_code(ast);
+ log.info((' Minified ' + fileName + ' from ' + (exports.formatKb(originalCode.length)) + ' to ' + (exports.formatKb(minifiedCode.length))).grey);
+ return minifiedCode;
+ },
- paths.css = entries(paths.css, 'css');
- paths.code = entries(paths.code, 'code');
- paths.tmpl = entries(paths.tmpl || paths.templates, 'templates');
+ // input is decorated and returned
+ sourcePaths: function(paths) {
- var relClient = './' + path.relative(options.dirs.client, options.dirs['views']);
- paths.view = paths.view.substring(0,2) === './'? paths.view : path.join(relClient, paths.view);
+ function entries(from, dirType) {
+ if (from == null) {
+ return [];
+ }
+ var list = (from instanceof Array)? from : [from];
- return paths;
-};
+ return list.map(function(value) {
+ var relClient = './' + path.relative(options.dirs.client, options.dirs[dirType]);
+ return value.substring(0,2) === './'? value : path.join(relClient, value);
+ });
+ }
-exports.destsFor = function(ss,client,options) {
- var containerDir = path.join(ss.root, options.dirs.assets);
- var clientDir = path.join(containerDir, client.name);
+ paths.css = entries(paths.css, 'css');
+ paths.code = entries(paths.code, 'code');
+ paths.tmpl = entries(paths.tmpl || paths.templates, 'templates');
- return {
+ var relClient = './' + path.relative(options.dirs.client, options.dirs['views']);
+ paths.view = paths.view.substring(0,2) === './'? paths.view : path.join(relClient, paths.view);
- //TODO perhaps mixin the abs versions by SS
- paths: {
- html: path.join(clientDir, client.id + '.html'),
- js: path.join(clientDir, client.id + '.js'),
- css: path.join(clientDir, client.id + '.css')
+ return paths;
},
- relPaths: {
- html: path.join(options.dirs.assets, client.name, client.id + '.html'),
- js: path.join(options.dirs.assets, client.name, client.id + '.js'),
- css: path.join(options.dirs.assets, client.name, client.id + '.css')
+
+ destsFor: function(client) {
+ var containerDir = path.join(ss.root, options.dirs.assets);
+ var clientDir = path.join(containerDir, client.name);
+
+ return {
+
+ //TODO perhaps mixin the abs versions by SS
+ paths: {
+ html: path.join(clientDir, client.id + '.html'),
+ js: path.join(clientDir, client.id + '.js'),
+ css: path.join(clientDir, client.id + '.css')
+ },
+ relPaths: {
+ html: path.join(options.dirs.assets, client.name, client.id + '.html'),
+ js: path.join(options.dirs.assets, client.name, client.id + '.js'),
+ css: path.join(options.dirs.assets, client.name, client.id + '.css')
+ },
+ dir: clientDir,
+ containerDir: containerDir
+ };
},
- dir: clientDir,
- containerDir: containerDir
- };
-}
-exports.launchCode = function(ss, client) {
- var initCode = system.serve.initCode(),
- entryInit = 'require("/entry");';
- initCode = initCode.replace(entryInit, 'require(' + client.entryInitPath + ');')
- return initCode;
-};
+ launchCode: function(client) {
+ var initCode = system.serve.initCode(),
+ entryInit = 'require("/entry");';
+ initCode = initCode.replace(entryInit, 'require(' + client.entryInitPath + ');')
+ return initCode;
+ },
-exports.packAssetSet = function packAssetSet(assetType, dir, client, bundler, postProcess) {
- var filePaths,
- prefix,
- paths = client.paths[assetType];
+ packAssetSet: function packAssetSet(assetType, dir, client, bundler, postProcess) {
+ var filePaths,
+ prefix,
+ paths = client.paths[assetType];
- function writeFile(fileContents) {
- var fileName = bundler.dests.paths[assetType];
- fs.writeFileSync(fileName, postProcess(fileContents));
- return log.info('✓'.green, 'Packed', filePaths.length, 'files into', bundler.dests.relPaths[assetType]);
- }
+ function writeFile(fileContents) {
+ var fileName = bundler.dests.paths[assetType];
+ fs.writeFileSync(fileName, postProcess(fileContents));
+ return log.info('✓'.green, 'Packed', filePaths.length, 'files into', bundler.dests.relPaths[assetType]);
+ }
- function processFiles(fileContents, i) {
- var file, path, _ref;
- if (!fileContents) {
- fileContents = [];
- }
- if (!i) {
- i = 0;
- }
- _ref = filePaths[i], path = _ref.path, file = _ref.file;
- return bundler.asset[assetType](file, {
- pathPrefix: path,
- compress: true
- }, function(output) {
- fileContents.push(output);
- if (filePaths[++i]) {
- return processFiles(fileContents, i);
- } else {
- return writeFile(fileContents);
+ function processFiles(fileContents, i) {
+ var file, path, _ref;
+ if (!fileContents) {
+ fileContents = [];
+ }
+ if (!i) {
+ i = 0;
+ }
+ _ref = filePaths[i], path = _ref.path, file = _ref.file;
+ return bundler.asset[assetType](file, {
+ pathPrefix: path,
+ compress: true
+ }, function(output) {
+ fileContents.push(output);
+ if (filePaths[++i]) {
+ return processFiles(fileContents, i);
+ } else {
+ return writeFile(fileContents);
+ }
+ });
}
- });
- }
- // Expand any dirs into real files
- if (paths && paths.length > 0) {
- filePaths = [];
- prefix = path.join(ss.root, dir);
- paths.forEach(function(path) {
- return magicPath.files(prefix, path).forEach(function(file) {
- return filePaths.push({
- path: path,
- file: file
+ // Expand any dirs into real files
+ if (paths && paths.length > 0) {
+ filePaths = [];
+ prefix = path.join(ss.root, dir);
+ paths.forEach(function(path) {
+ return magicPath.files(prefix, path).forEach(function(file) {
+ return filePaths.push({
+ path: path,
+ file: file
+ });
+ });
});
- });
- });
- return processFiles();
- }
-}
+ return processFiles();
+ }
+ },
-exports.formatKb = function formatKb(size) {
- return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
-};
+ formatKb: function formatKb(size) {
+ return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
+ },
-// Before client-side code is sent to the browser any file which is NOT a library (e.g. /client/code/libs)
-// is wrapped in a module wrapper (to keep vars local and allow you to require() one file in another).
-// The 'system' directory is a special case - any module placed in this dir will not have a leading slash
-exports.wrapCode = function wrapCode(code, path, pathPrefix, options) {
- var pathAry = path.split('/');
+ // Before client-side code is sent to the browser any file which is NOT a library (e.g. /client/code/libs)
+ // is wrapped in a module wrapper (to keep vars local and allow you to require() one file in another).
+ // The 'system' directory is a special case - any module placed in this dir will not have a leading slash
+ wrapCode: function wrapCode(code, path, pathPrefix) {
+ var pathAry = path.split('/');
- // Don't touch the code if it's in a 'libs' directory
- if (pathAry.indexOf('libs') >= 0) {
- return code;
- }
+ // Don't touch the code if it's in a 'libs' directory
+ if (pathAry.indexOf('libs') >= 0) {
+ return code;
+ }
- if (pathAry.indexOf('entry.js') === -1 && options && options.browserifyExcludePaths) {
- //TODO is this an array? should be revised
- for(var p in options.browserifyExcludePaths) {
- if (options.browserifyExcludePaths.hasOwnProperty(p)) {
- if ( path.split( options.browserifyExcludePaths[p] )[0] === '' ) {
- return code;
+ if (pathAry.indexOf('entry.js') === -1 && options && options.browserifyExcludePaths) {
+ //TODO is this an array? should be revised
+ for(var p in options.browserifyExcludePaths) {
+ if (options.browserifyExcludePaths.hasOwnProperty(p)) {
+ if ( path.split( options.browserifyExcludePaths[p] )[0] === '' ) {
+ return code;
+ }
+ }
}
}
- }
- }
- // Don't add a leading slash if this is a 'system' module
- if (pathAry.indexOf('system') >= 0) {
- return wrap.module(pathAry[pathAry.length - 1], code);
- } else {
+ // Don't add a leading slash if this is a 'system' module
+ if (pathAry.indexOf('system') >= 0) {
+ return wrap.module(pathAry[pathAry.length - 1], code);
+ } else {
- // Otherwise treat as a regular module
- var modPath = options.globalModules? pathAry.join("/") : pathAry.slice(1).join('/');
+ // Otherwise treat as a regular module
+ var modPath = options.globalModules? pathAry.join("/") : pathAry.slice(1).join('/');
- // Work out namespace for module
- if (pathPrefix) {
+ // Work out namespace for module
+ if (pathPrefix) {
- // Ignore any filenames in the path
- if (pathPrefix.indexOf('.') > 0) {
- var sp = pathPrefix.split('/');
- sp.pop();
- pathPrefix = sp.join('/');
+ // Ignore any filenames in the path
+ if (pathPrefix.indexOf('.') > 0) {
+ var sp = pathPrefix.split('/');
+ sp.pop();
+ pathPrefix = sp.join('/');
+ }
+ modPath = path.substr(pathPrefix.length + 1);
+ }
+ return wrap.module('/' + modPath, code);
}
- modPath = path.substr(pathPrefix.length + 1);
}
- return wrap.module('/' + modPath, code);
- }
+
+ };
};
+
+function deleteOldFiles(clientDir) {
+ var numFilesDeleted = 0,
+ filesDeleted = fs.readdirSync(clientDir).map(function(fileName) {
+ return fs.unlinkSync(path.join(clientDir, fileName));
+ });
+ return filesDeleted.length > 1 && log('✓'.green, '' + filesDeleted.length + ' previous packaged files deleted');
+}
+
+function mkdir(dir) {
+ if (!fs.existsSync(dir)) {
+ return fs.mkdirSync(dir);
+ }
+}
+
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 8c612d24..261a8bfc 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -36,10 +36,10 @@ module.exports = function(webpack) {
bundler.client = client;
// Define new client object
- client.paths = ss.bundler.sourcePaths(ss,paths,options);
+ client.paths = ss.bundler.sourcePaths(paths);
client.includes = {}; //TODO post-define default?
- return ss.bundler.destsFor(ss,client,options);
+ return ss.bundler.destsFor(client);
}
function load() {
@@ -47,11 +47,11 @@ module.exports = function(webpack) {
}
function assetCSS(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.client, path, 'css', opts, cb);
+ return ss.bundler.loadFile(options.dirs.client, path, 'css', opts, cb);
}
function assetHTML(path, opts, cb) {
- return ss.bundler.loadFile(ss, options.dirs.client, path, 'html', opts, cb);
+ return ss.bundler.loadFile(options.dirs.client, path, 'html', opts, cb);
}
function assetJS(path, opts, cb) {
@@ -62,7 +62,7 @@ module.exports = function(webpack) {
}
function assetLaunch(cb) {
- var output = ss.bundler.launchCode(ss, client);
+ var output = ss.bundler.launchCode(client);
return cb(output);
}
@@ -74,7 +74,7 @@ module.exports = function(webpack) {
}
function packCSS(postProcess) {
- ss.bundler.packAssetSet('css', options.dirs.client, client, bundler, postProcess);
+ ss.bundler.packAssetSet('css', options.dirs.client, bundler.client, bundler, postProcess);
}
function packJS() {
diff --git a/lib/client/index.js b/lib/client/index.js
index 6f27b43c..e94fee42 100644
--- a/lib/client/index.js
+++ b/lib/client/index.js
@@ -11,8 +11,7 @@ require('colors');
var fs = require('fs'),
path = require('path'),
log = require('../utils/log'),
- systemAssets = require('./system'),
- bundler = require('./bundler/index');
+ systemAssets = require('./system');
// Determine if assets should be (re)packed on startup
var packAssets = process.env['SS_PACK'];
@@ -39,7 +38,7 @@ var clients = {};
module.exports = function(ss, router) {
// make bundler methods available for default and other implementations
- ss.bundler = bundler;
+ var bundler = ss.bundler = require('./bundler/index')(ss,options);
// Require sub modules
var templateEngine = require('./template_engine')(ss),
@@ -138,7 +137,7 @@ module.exports = function(ss, router) {
// if a function is used construct a bundler with it otherwise use default bundler
var client = clients[name] = { name: name };
client.id = Number(Date.now());
- bundler.define(ss,client,arguments,options);
+ bundler.define(client,arguments);
//TODO reconsider relative paths of all these
client.entryInitPath = '/code/' + client.name + '/entry';
@@ -193,7 +192,7 @@ module.exports = function(ss, router) {
if (packAssets) {
for (name in clients) {
if (clients.hasOwnProperty(name)) {
- bundler.pack(ss, clients[name], options);
+ bundler.pack(clients[name]);
}
}
}
diff --git a/lib/client/pack.js b/lib/client/pack.js
index 18f9e107..83d8b471 100644
--- a/lib/client/pack.js
+++ b/lib/client/pack.js
@@ -15,7 +15,7 @@ var fs = require('fs'),
log = require('../utils/log');
module.exports = function(ss, client, options) {
- var bundler = require('./bundler/index').get(ss, client, options);
+ var bundler = ss.bundler.get(client);
var clientDir, containerDir; //TODO
client.pack = true;
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index a295e74d..92699f42 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -6,13 +6,14 @@
var url = require('url'),
qs = require('querystring'),
system = require('../system'),
- utils = require('./utils'),
- bundler = require('../bundler/index');
+ utils = require('./utils');
// Expose asset server as the public API
//
module.exports = function (ss, router, options) {
+ var bundler = require('../bundler/index')(ss,options);
+
// JAVASCRIPT
// Serve system libraries and modules
@@ -26,7 +27,7 @@ module.exports = function (ss, router, options) {
params = qs.parse(thisUrl.query),
path = utils.parseUrl(request.url);
- return bundler.get(ss,params,options).asset.js(path, {
+ return bundler.get(params).asset.js(path, {
client: params.client,
clientId: params.ts,
pathPrefix: params.pathPrefix
@@ -38,7 +39,7 @@ module.exports = function (ss, router, options) {
var thisUrl = url.parse(request.url),
params = qs.parse(thisUrl.query);
- bundler.get(ss,params,options).asset.launch(function(output) {
+ bundler.get(params).asset.launch(function(output) {
return utils.serve.js(output, response);
});
@@ -52,7 +53,7 @@ module.exports = function (ss, router, options) {
thisUrl = url.parse(request.url);
params = qs.parse(thisUrl.query);
path = utils.parseUrl(request.url);
- return bundler.get(ss,params,options).asset.css(path, {
+ return bundler.get(params).asset.css(path, {
client: params.client,
clientId: params.ts
}, function(output) {
diff --git a/lib/client/serve/ondemand.js b/lib/client/serve/ondemand.js
index ab1ad832..21a8fc29 100644
--- a/lib/client/serve/ondemand.js
+++ b/lib/client/serve/ondemand.js
@@ -18,6 +18,9 @@ var url = require('url'),
var queryCache = {};
module.exports = function(ss, router, options) {
+
+ var bundler = require('../bundler/index')(ss,options);
+
function serve(processor) {
return function(request, response) {
var path = utils.parseUrl(request.url);
@@ -43,7 +46,7 @@ module.exports = function(ss, router, options) {
return files.forEach(function(file) {
var description;
try {
- return bundler.get(ss,params,options).asset.js(file, {
+ return bundler.get(params).asset.js(file, {
client: params.client,
clientId: params.ts,
pathPrefix: options.globalModules? null : path,
@@ -66,7 +69,7 @@ module.exports = function(ss, router, options) {
var thisUrl = url.parse(request.url),
params = qs.parse(thisUrl.query);
- return bundler.get(ss,params,options).asset.worker(path, {
+ return bundler.get(params).asset.worker(path, {
compress: options.packAssets
}, cb);
}
diff --git a/lib/client/view.js b/lib/client/view.js
index d5f4e7b7..d40502ae 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -9,7 +9,7 @@ var pathlib = require('path'),
module.exports = function(ss, client, options, cb) {
var templateEngine = require('./template_engine')(ss),
- bundler = require('./bundler/index').get(ss, client, options);
+ bundler = ss.bundler.get(client);
// Add links to CSS and JS files
var includes = headers().concat(templates());
From 6f0b391bd288363a74915a125ce57e6c2881b910 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Thu, 5 Feb 2015 18:10:26 +0100
Subject: [PATCH 28/59] feat(bundler): Dropping global-require
Require path starting with ./ is relative to /client, this must also be passed in the dev time URL.
---
docs/js/docs-setup.js | 2 +-
docs/partials/tutorials/client_side_code.html | 4 ----
lib/client/serve/ondemand.js | 2 +-
src/docs/tutorials/en/client_side_code.ngdoc | 4 ----
4 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/docs/js/docs-setup.js b/docs/js/docs-setup.js
index 8d556272..0b168bf7 100644
--- a/docs/js/docs-setup.js
+++ b/docs/js/docs-setup.js
@@ -30,7 +30,7 @@ NG_DOCS={
"type": "overview",
"moduleName": "Client-Side Code",
"shortDescription": "Client-Side Code",
- "keywords": "ability absolutely access accessed add allowing allows alphanumerically amd amount app apply approaches as-is automatically aware awesome backbone background bear better blank boiler-plate brought browser browserify browserifyexcludepaths cache called calls case cases catch change chaos choice clean client client-code client-side code coffee coming command common components connection console copy create created critical critically default define demand depend dependencies depends developer developers difference directores directory disable distinction doesn don easily ensure entry entrymodulename error established exactly example exceptions exclude excluded excluding execuring execute executed exist expect experience explicitly export file files folder forget form full functions future globalmodules goal going great handle head history hopes https inbuilt info instantly internally javascript jquery js killing leading legacy libraries library libs lightweight list live lives ll load loading long magic major making manage managing manually md mess mind modification modify module modules namespacing node null onus options order org overview packaging path paths performs point position problem problems project querystring reconnecting reference regular relative require required requires send serve served server server-side set share sharing side single slash small socketstream solution solutions solves special ss stack statement string structure subdirectories substack syntax system top track treated tricky true tutorials type typically underscore unique unstructured url values variable view views wade wanted web websocket window work works write writing"
+ "keywords": "ability absolutely access accessed add allowing allows alphanumerically amd amount app apply approaches as-is automatically aware awesome backbone background bear better blank boiler-plate brought browser browserify browserifyexcludepaths cache called calls case cases catch change chaos choice clean client client-code client-side code coffee coming command common components connection console copy create created critical critically default define demand depend dependencies depends developer developers difference directores directory disable distinction doesn don easily ensure entry entrymodulename error established exactly example exceptions exclude excluded excluding execuring execute executed exist expect experience explicitly export file files folder forget form functions future goal going great handle head history hopes https inbuilt info instantly internally javascript jquery js killing leading legacy libraries library libs lightweight list live lives ll load loading long magic major making manage managing manually md mess mind modification modify module modules namespacing node null onus options order org overview packaging path paths performs point position problem problems project querystring reconnecting reference regular relative require required requires send serve served server server-side set share sharing side single slash small socketstream solution solutions solves special ss stack statement string structure subdirectories substack syntax system top track treated tricky tutorials type typically underscore unique unstructured url values variable view views wade wanted web websocket window work works write writing"
},
{
"section": "tutorials",
diff --git a/docs/partials/tutorials/client_side_code.html b/docs/partials/tutorials/client_side_code.html
index 49a94c7d..acdb8c20 100644
--- a/docs/partials/tutorials/client_side_code.html
+++ b/docs/partials/tutorials/client_side_code.html
@@ -38,10 +38,6 @@
Options
ss.client.set({ entryModuleName: null });
-
globalModules {boolean} - set true to load client side modules using their full path relative to client/code. If for example your app is my the entry module can be accessed with require('/my/entry').
-
-ss.client.set({ globalModules: true });
-
Note, that paths for excluding should be relative to client/code/ and that file client/code/app/entry.js could not be excluded in any cases.
If you need to exclude from automatically packaging certain file, just specify the file's relative path:
diff --git a/lib/client/serve/ondemand.js b/lib/client/serve/ondemand.js
index 21a8fc29..0ada457e 100644
--- a/lib/client/serve/ondemand.js
+++ b/lib/client/serve/ondemand.js
@@ -49,7 +49,7 @@ module.exports = function(ss, router, options) {
return bundler.get(params).asset.js(file, {
client: params.client,
clientId: params.ts,
- pathPrefix: options.globalModules? null : path,
+ //pathPrefix: options.globalModules? null : path,
compress: options.packAssets
}, function(js) {
output.push(js);
diff --git a/src/docs/tutorials/en/client_side_code.ngdoc b/src/docs/tutorials/en/client_side_code.ngdoc
index 811abf02..40b7773e 100644
--- a/src/docs/tutorials/en/client_side_code.ngdoc
+++ b/src/docs/tutorials/en/client_side_code.ngdoc
@@ -70,10 +70,6 @@ code for the entry module. If null or a blank string is given no entry module is
ss.client.set({ entryModuleName: null });
-- **globalModules {boolean} ** - set true to load client side modules using their full path relative to `client/code`. If for example your app is `my` the entry module can be accessed with `require('/my/entry')`.
-
-ss.client.set({ globalModules: true });
-
**Note**, that paths for excluding should be relative to `client/code/` and that file `client/code/app/entry.js` could not be excluded in any cases.
From bd7ab276c0a94884304a42656bae62083a5b0c7e Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Thu, 5 Feb 2015 18:11:07 +0100
Subject: [PATCH 29/59] feat(shim): Dropping JSON shim
#485
---
lib/client/system/shims/json.min.js | 18 ------------------
1 file changed, 18 deletions(-)
delete mode 100644 lib/client/system/shims/json.min.js
diff --git a/lib/client/system/shims/json.min.js b/lib/client/system/shims/json.min.js
deleted file mode 100644
index 73be3910..00000000
--- a/lib/client/system/shims/json.min.js
+++ /dev/null
@@ -1,18 +0,0 @@
-if(!this.JSON){JSON=function(){function f(n){return n<10?'0'+n:n;}
-Date.prototype.toJSON=function(){return this.getUTCFullYear()+'-'+
-f(this.getUTCMonth()+1)+'-'+
-f(this.getUTCDate())+'T'+
-f(this.getUTCHours())+':'+
-f(this.getUTCMinutes())+':'+
-f(this.getUTCSeconds())+'Z';};var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};function stringify(value,whitelist){var a,i,k,l,r=/["\\\x00-\x1f\x7f-\x9f]/g,v;switch(typeof value){case'string':return r.test(value)?'"'+value.replace(r,function(a){var c=m[a];if(c){return c;}
-c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+
-(c%16).toString(16);})+'"':'"'+value+'"';case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
-if(typeof value.toJSON==='function'){return stringify(value.toJSON());}
-a=[];if(typeof value.length==='number'&&!(value.propertyIsEnumerable('length'))){l=value.length;for(i=0;i
Date: Sun, 8 Feb 2015 02:01:23 +0100
Subject: [PATCH 30/59] feat(bundler): Pack & System Assets serving in bundler
---
lib/client/bundler/default.js | 70 ++++++++++++++----
lib/client/bundler/index.js | 132 +++++++++++++++++++++-------------
lib/client/bundler/webpack.js | 45 +++++++++---
lib/client/index.js | 35 ++++-----
lib/client/pack.js | 85 ----------------------
lib/client/serve/dev.js | 8 ++-
lib/client/system/index.js | 82 ++-------------------
lib/client/view.js | 29 +++-----
lib/client/wrap.js | 17 -----
9 files changed, 214 insertions(+), 289 deletions(-)
delete mode 100644 lib/client/pack.js
delete mode 100644 lib/client/wrap.js
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index 8247b31c..a5f3e263 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -3,7 +3,8 @@
var fs = require('fs'),
path = require('path'),
- log = require('../../utils/log');
+ log = require('../../utils/log'),
+ systemAssets = require('../system').assets;
function includeFlags(overrides) {
var includes = {
@@ -22,16 +23,17 @@ module.exports = function(ss,client,options){
var bundler = {
define: define,
load: load,
+ toMinifiedCSS: toMinifiedCSS,
+ toMinifiedJS: toMinifiedJS,
asset: {
+ includeSystemLib: includeSystemLib,
+ includeSystemModule: includeSystemModule,
+ entries: entries,
js: assetJS,
worker: assetWorker,
launch: assetLaunch,
css: assetCSS,
html: assetHTML
- },
- pack: {
- js: packJS,
- css: packCSS
}
};
@@ -57,8 +59,29 @@ module.exports = function(ss,client,options){
}
+ function includeSystemLib(name,content,options) {
+ switch(name) {
+ case "browserify":
+ }
+ return true;
+ }
+
+ function includeSystemModule(name,content,options) {
+ switch(name) {
+ case "eventemitter2":
+ case "socketstream":
+ }
+ return true;
+ }
+
+ // list of entries for an asset type relative to the client directory
+ function entries(assetType) {
+ return ss.bundler.entries(client, assetType);
+ }
+
function assetJS(path, opts, cb) {
return ss.bundler.loadFile(options.dirs.client, path, 'js', opts, function(output) {
+ //TODO with options compress saved to avoid double compression
output = ss.bundler.wrapCode(output, path, opts.pathPrefix);
if (opts.compress && path.indexOf('.min') === -1) {
output = ss.bundler.minifyJSFile(output, path);
@@ -75,9 +98,8 @@ module.exports = function(ss,client,options){
});
}
- function assetLaunch(cb) {
- var output = ss.bundler.launchCode(client);
- return cb(output);
+ function assetLaunch() {
+ return ss.bundler.launchCode(client);
}
function assetCSS(path, opts, cb) {
@@ -88,12 +110,36 @@ module.exports = function(ss,client,options){
return ss.bundler.loadFile(options.dirs.client, path, 'html', opts, cb);
}
- function packJS(postProcess) {
- ss.bundler.packAssetSet('js', options.dirs.client, client, bundler, postProcess);
+ function toMinifiedCSS(files) {
+ return ss.bundler.minifyCSS(files);
}
- function packCSS(postProcess) {
- ss.bundler.packAssetSet('css', options.dirs.client, client, bundler, postProcess);
+ function toMinifiedJS(files) {
+ // Libs
+ var libs = systemAssets.libs.map(function(lib) {
+ return bundler.asset.includeSystemLib(lib.name, lib.content, lib.options)? lib : null;
+ }).filter(function(content) {
+ return !!content;
+ });
+
+ // Modules
+ var mods = [],
+ _ref = systemAssets.modules;
+ for (var name in _ref) {
+ if (_ref.hasOwnProperty(name)) {
+ var mod = _ref[name];
+ if (bundler.asset.includeSystemModule(mod.name,mod.content,mod.options)) {
+ var code = ss.bundler.wrapModule(name, mod.content);
+ mods.push({ name:mod.name, content:code,options:mod.options,type:mod.type });
+ }
+ }
+ }
+
+ var initCode = bundler.asset.launch();
+ if (initCode) {
+ //parts.push(initCode);
+ }
+ return ss.bundler.minifyJS(libs.concat(mods).concat(files).concat(systemAssets.initCode));
}
};
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 85398d01..ed7829c8 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -7,7 +7,6 @@ var fs = require('fs'),
cleanCSS = require('clean-css'),
system = require('../system'),
view = require('../view'),
- wrap = require('../wrap'),
magicPath = require('../magic_path'),
uglifyjs = require('uglify-js'),
jsp = uglifyjs.parser,
@@ -89,31 +88,14 @@ module.exports = function(ss,options) {
}
// Output CSS
- bundler.pack.css(function(files) {
- var minified, original;
- original = files.join('\n');
- minified = cleanCSS.process(original);
- log.info((' Minified CSS from ' + (exports.formatKb(original.length)) + ' to ' + (exports.formatKb(minified.length))).grey);
- return minified;
- });
+ ss.bundler.packAssetSet('css', client, bundler.toMinifiedCSS);
// Output JS
- bundler.pack.js(function(files) {
- var parts = [];
- if (client.includes.system) {
- parts.push( system.serve.js({ compress:true }) );
- }
- parts = parts.concat(files);
- if (client.includes.initCode) {
- parts.push( system.serve.initCode() );
- }
-
- return parts.join(";");
- });
+ ss.bundler.packAssetSet('js', client, bundler.toMinifiedJS);
// Output HTML view
return view(ss, client, options, function(html) {
- fs.writeFileSync(bundler.dests.paths.html, html);
+ fs.writeFileSync(getBundler(client).dests.paths.html, html);
return log.info('✓'.green, 'Created and cached HTML file ' + bundler.dests.relPaths.html);
});
},
@@ -139,12 +121,26 @@ module.exports = function(ss,options) {
return formatter.compile(p.replace(/\\/g, '/'), options, cb);
},
+ minifyCSS: function minifyCSS(files) {
+ var original = files.join('\n');
+ var minified = cleanCSS().minify(original);
+ log.info((' Minified CSS from ' + (formatKb(original.length)) + ' to ' + (formatKb(minified.length))).grey);
+ return minified;
+ },
+
+ minifyJS: function minifyJS_(files) {
+ var min = files.map(function(js) {
+ return js.options.minified ? js.content : minifyJS(js.content);
+ });
+ return min.join('\n');
+ },
+
minifyJSFile: function minifyJSFile(originalCode, fileName) {
var ast = jsp.parse(originalCode);
ast = pro.ast_mangle(ast);
ast = pro.ast_squeeze(ast);
var minifiedCode = pro.gen_code(ast);
- log.info((' Minified ' + fileName + ' from ' + (exports.formatKb(originalCode.length)) + ' to ' + (exports.formatKb(minifiedCode.length))).grey);
+ log.info((' Minified ' + fileName + ' from ' + (formatKb(originalCode.length)) + ' to ' + (formatKb(minifiedCode.length))).grey);
return minifiedCode;
},
@@ -196,16 +192,25 @@ module.exports = function(ss,options) {
},
launchCode: function(client) {
- var initCode = system.serve.initCode(),
- entryInit = 'require("/entry");';
- initCode = initCode.replace(entryInit, 'require(' + client.entryInitPath + ');')
+ var initCode = system.assets.initCode.map(function(ic) { return ic.content; }).join('\n'),
+ entryInit = options.defaultEntryInit,
+ realInit = 'require(' + client.entryInitPath + ');';
+
+ if (typeof options.entryModuleName === 'string' || options.entryModuleName === null) {
+ realInit = options.entryModuleName? 'require("/'+options.entryModuleName+'");' : '';
+ }
+
+ initCode = initCode.replace(entryInit, realInit)
return initCode;
},
- packAssetSet: function packAssetSet(assetType, dir, client, bundler, postProcess) {
- var filePaths,
- prefix,
- paths = client.paths[assetType];
+ packAssetSet: function packAssetSet(assetType, client, postProcess) {
+ var bundler = getBundler(client),
+ filePaths = bundler.asset.entries(assetType),
+ dir = options.dirs.client;
+
+ return processFiles();
+
function writeFile(fileContents) {
var fileName = bundler.dests.paths[assetType];
@@ -214,19 +219,18 @@ module.exports = function(ss,options) {
}
function processFiles(fileContents, i) {
- var file, path, _ref;
if (!fileContents) {
fileContents = [];
}
if (!i) {
i = 0;
}
- _ref = filePaths[i], path = _ref.path, file = _ref.file;
+ var _ref = filePaths[i], path = _ref.importedBy, file = _ref.file;
return bundler.asset[assetType](file, {
pathPrefix: path,
compress: true
}, function(output) {
- fileContents.push(output);
+ fileContents.push({content:output,options:{}});
if (filePaths[++i]) {
return processFiles(fileContents, i);
} else {
@@ -234,26 +238,40 @@ module.exports = function(ss,options) {
}
});
}
+ },
- // Expand any dirs into real files
- if (paths && paths.length > 0) {
- filePaths = [];
- prefix = path.join(ss.root, dir);
- paths.forEach(function(path) {
- return magicPath.files(prefix, path).forEach(function(file) {
- return filePaths.push({
- path: path,
- file: file
- });
- });
- });
- return processFiles();
+ // css, js, worker,
+ entries: function entries(client, assetType) {
+
+ var entries = [],
+ pathType;
+ switch(assetType) {
+ case 'css': pathType = 'css'; break;
+ case 'js': pathType = 'code'; break;
+ case 'worker': pathType = 'code'; break;
}
+ client.paths[pathType].forEach(function(from) {
+ return magicPath.files(path.join(ss.root, options.dirs.client), from).forEach(function(file) {
+ return entries.push({file:file,importedBy:from});
+ });
+ });
+ return entries;
+
},
+ formatKb: formatKb,
- formatKb: function formatKb(size) {
- return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
+ htmlTag : {
+ css: function(path) {
+ return '';
+ },
+ js: function(path) {
+ return '';
+ }
+ },
+
+ wrapModule: function(modPath, code) {
+ return 'require.define("' + modPath + '", function (require, module, exports, __dirname, __filename){\n' + code + '\n});';
},
// Before client-side code is sent to the browser any file which is NOT a library (e.g. /client/code/libs)
@@ -280,11 +298,11 @@ module.exports = function(ss,options) {
// Don't add a leading slash if this is a 'system' module
if (pathAry.indexOf('system') >= 0) {
- return wrap.module(pathAry[pathAry.length - 1], code);
+ return ss.bundler.wrapModule(pathAry[pathAry.length - 1], code);
} else {
// Otherwise treat as a regular module
- var modPath = options.globalModules? pathAry.join("/") : pathAry.slice(1).join('/');
+ var modPath = /*options.globalModules? pathAry.join("/") :*/ pathAry.slice(1).join('/');
// Work out namespace for module
if (pathPrefix) {
@@ -297,7 +315,7 @@ module.exports = function(ss,options) {
}
modPath = path.substr(pathPrefix.length + 1);
}
- return wrap.module('/' + modPath, code);
+ return ss.bundler.wrapModule('/' + modPath, code);
}
}
@@ -318,3 +336,17 @@ function mkdir(dir) {
}
}
+function formatKb(size) {
+ return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
+}
+
+// Private
+function minifyJS(originalCode) {
+ var ast, jsp, pro;
+ jsp = uglifyjs.parser;
+ pro = uglifyjs.uglify;
+ ast = jsp.parse(originalCode);
+ ast = pro.ast_mangle(ast);
+ ast = pro.ast_squeeze(ast);
+ return pro.gen_code(ast) + ';';
+}
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 261a8bfc..235391eb 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -10,12 +10,15 @@ module.exports = function(webpack) {
var bundler = {
define: define,
load: load,
- pack: {
- js: packJS,
- css: packCSS
- },
+ toMinifiedCSS: toMinifiedCSS,
+ toMinifiedJS: toMinifiedJS,
asset: {
+ includeSystemLib: includeSystemLib,
+ includeSystemModule: includeSystemModule,
+ entries: entries,
+
html: assetHTML,
+ system: assetSystem,
js: assetJS,
worker: assetWorker,
launch: assetLaunch,
@@ -37,7 +40,6 @@ module.exports = function(webpack) {
// Define new client object
client.paths = ss.bundler.sourcePaths(paths);
- client.includes = {}; //TODO post-define default?
return ss.bundler.destsFor(client);
}
@@ -46,6 +48,26 @@ module.exports = function(webpack) {
}
+ function includeSystemLib(name,content,options) {
+ switch(name) {
+ case "browserify":
+ }
+ return true;
+ }
+
+ function includeSystemModule(name,content,options) {
+ switch(name) {
+ case "eventemitter2":
+ case "socketstream":
+ }
+ return true;
+ }
+
+ // list of entries for an asset type relative to the client directory
+ function entries(assetType) {
+ return ss.bundler.entries(bundler.client, assetType);
+ }
+
function assetCSS(path, opts, cb) {
return ss.bundler.loadFile(options.dirs.client, path, 'css', opts, cb);
}
@@ -54,6 +76,10 @@ module.exports = function(webpack) {
return ss.bundler.loadFile(options.dirs.client, path, 'html', opts, cb);
}
+ function assetSystem(cb) {
+ cb('');
+ }
+
function assetJS(path, opts, cb) {
webpack({}, function() {
cb('//');
@@ -70,15 +96,14 @@ module.exports = function(webpack) {
webpack({}, function() {
cb('//');
});
-
}
- function packCSS(postProcess) {
- ss.bundler.packAssetSet('css', options.dirs.client, bundler.client, bundler, postProcess);
+ function toMinifiedCSS(files) {
+ return ss.bundler.minifyCSS(files.join('\n'));
}
- function packJS() {
-
+ function toMinifiedJS(files) {
+ return '// minified JS for '+bundler.client.name;
}
};
diff --git a/lib/client/index.js b/lib/client/index.js
index e94fee42..fafaa4cd 100644
--- a/lib/client/index.js
+++ b/lib/client/index.js
@@ -20,6 +20,7 @@ var packAssets = process.env['SS_PACK'];
var options = {
packedAssets: packAssets || false,
liveReload: ['code', 'css', 'static', 'templates', 'views'],
+ defaultEntryInit: 'require("/entry");',
dirs: {
client: '/client',
code: '/client/code',
@@ -38,7 +39,7 @@ var clients = {};
module.exports = function(ss, router) {
// make bundler methods available for default and other implementations
- var bundler = ss.bundler = require('./bundler/index')(ss,options);
+ ss.bundler = require('./bundler/index')(ss,options);
// Require sub modules
var templateEngine = require('./template_engine')(ss),
@@ -137,19 +138,25 @@ module.exports = function(ss, router) {
// if a function is used construct a bundler with it otherwise use default bundler
var client = clients[name] = { name: name };
client.id = Number(Date.now());
- bundler.define(client,arguments);
+ client.paths = {};
+ client.includes = {
+ css: true,
+ html: true,
+ system: true,
+ initCode: true
+ };
//TODO reconsider relative paths of all these
client.entryInitPath = '/code/' + client.name + '/entry';
+ ss.bundler.define(client,arguments);
+
return client;
},
// Listen and serve incoming asset requests
load: function() {
- var client, id, name, pack, entryInit;
-
- bundler.load();
+ ss.bundler.load();
// Cache instances of code formatters and template engines here
// This may change in the future as I don't like hanging system objects
@@ -159,13 +166,7 @@ module.exports = function(ss, router) {
ss.client.templateEngines = templateEngine.load();
// Code to execute once everything is loaded
- entryInit = 'require("/entry");';
- if (typeof options.entryModuleName === 'string' || options.entryModuleName === null) {
- entryInit = options.entryModuleName? 'require("/'+options.entryModuleName+'");' : '';
- }
- if (entryInit) {
- systemAssets.send('code', 'init', entryInit);
- }
+ systemAssets.send('code', 'init', options.defaultEntryInit);
if (options.packedAssets) {
@@ -173,10 +174,10 @@ module.exports = function(ss, router) {
// If unsuccessful, assets will be re-packed automatically
if (!packAssets) {
log.info('i'.green, 'Attempting to find pre-packed assets... (force repack with SS_PACK=1)'.grey);
- for (name in clients) {
+ for (var name in clients) {
if (clients.hasOwnProperty(name)) {
- client = clients[name];
- id = options.packedAssets.id || determineLatestId(client);
+ var client = clients[name],
+ id = options.packedAssets.id || determineLatestId(client);
if (id) {
client.id = id;
log.info('✓'.green, ('Serving client \'' + client.name + '\' using pre-packed assets (ID ' + client.id + ')').grey);
@@ -190,9 +191,9 @@ module.exports = function(ss, router) {
// Pack Assets
if (packAssets) {
- for (name in clients) {
+ for (var name in clients) {
if (clients.hasOwnProperty(name)) {
- bundler.pack(clients[name]);
+ ss.bundler.pack(clients[name]);
}
}
}
diff --git a/lib/client/pack.js b/lib/client/pack.js
deleted file mode 100644
index 83d8b471..00000000
--- a/lib/client/pack.js
+++ /dev/null
@@ -1,85 +0,0 @@
-// Asset Packer
-// ------------
-// Packs all CSS, JS and HTML assets declared in the ss.client.define() call to be sent upon initial connection
-// Other code modules can still be served asynchronously later on
-'use strict';
-
-require('colors');
-
-var fs = require('fs'),
- pathlib = require('path'),
- cleanCSS = require('clean-css'),
- magicPath = require('./magic_path'),
- system = require('./system'),
- view = require('./view'),
- log = require('../utils/log');
-
-module.exports = function(ss, client, options) {
- var bundler = ss.bundler.get(client);
- var clientDir, containerDir; //TODO
- client.pack = true;
-
- /* PACKER */
-
- log(('Pre-packing and minifying the \'' + client.name + '\' client...').yellow);
-
- var description = ss.client.describeAssets(client.name);
-
- // Prepare folder
- description.ensureDirs();
- if (!(options.packedAssets && options.packedAssets.keepOldFiles)) {
- deleteOldFiles(description.dir);
- }
-
- // Output CSS
- bundler.packCSS(client, function(files) {
- var minified, original;
- original = files.join('\n');
- minified = cleanCSS.process(original);
- log.info((' Minified CSS from ' + (formatKb(original.length)) + ' to ' + (formatKb(minified.length))).grey);
- return minified;
- });
-
- // Output JS
- bundler.packJS(client, function(files) {
- var parts = [];
- if (client.includes.system) {
- parts.push( system.serve.js({ compress:true }) );
- }
- parts = parts.concat(files);
- if (client.includes.initCode) {
- parts.push( system.serve.initCode() );
- }
-
- return parts.join(';');
- });
-
- // Output HTML view
- return view(ss, client, options, function(html) {
- var fileName;
- fileName = pathlib.join(clientDir, client.id + '.html');
- fs.writeFileSync(fileName, html);
- return log.info('✓'.green, 'Created and cached HTML file ' + fileName.substr(ss.root.length));
- });
-};
-
-// PRIVATE
-
-function formatKb(size) {
- return '' + (Math.round((size / 1024) * 1000) / 1000) + ' KB';
-}
-
-function mkdir(dir) {
- if (!fs.existsSync(dir)) {
- return fs.mkdirSync(dir);
- }
-}
-
-function deleteOldFiles(clientDir) {
- var filesDeleted, numFilesDeleted;
- numFilesDeleted = 0;
- filesDeleted = fs.readdirSync(clientDir).map(function(fileName) {
- return fs.unlinkSync(pathlib.join(clientDir, fileName));
- });
- return filesDeleted.length > 1 && log('✓'.green, '' + filesDeleted.length + ' previous packaged files deleted');
-}
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index 92699f42..bb4f9908 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -18,7 +18,12 @@ module.exports = function (ss, router, options) {
// Serve system libraries and modules
router.on('/_serveDev/system?*', function(request, response) {
- return utils.serve.js(system.serve.js(), response);
+ var thisUrl = url.parse(request.url),
+ params = qs.parse(thisUrl.query);
+
+ return bundler.get(params).asset.system(function(output) {
+ return utils.serve.js(output, response);
+ });
});
// Listen for requests for application client code
@@ -42,7 +47,6 @@ module.exports = function (ss, router, options) {
bundler.get(params).asset.launch(function(output) {
return utils.serve.js(output, response);
});
-
});
// CSS
diff --git a/lib/client/system/index.js b/lib/client/system/index.js
index 8a32b171..6be49b5f 100644
--- a/lib/client/system/index.js
+++ b/lib/client/system/index.js
@@ -8,12 +8,10 @@
var fs = require('fs'),
pathlib = require('path'),
uglifyjs = require('uglify-js'),
- wrap = require('../wrap'),
fsUtils = require('../../utils/file');
// Allow internal modules to deliver assets to the browser
-var assets = {
- shims: [],
+var assets = exports.assets = {
libs: [],
modules: {},
initCode: []
@@ -37,17 +35,12 @@ var send = exports.send = function (type, name, content, options) {
switch (type) {
case 'code':
- return assets.initCode.push(content);
- case 'shim':
- return pushUniqueAsset('shims',{
- name: name,
- content: content,
- options: options
- });
+ return assets.initCode.push({content:content,options:options});
case 'lib':
case 'library':
return pushUniqueAsset('libs',{
name: name,
+ type: type,
content: content,
options: options
});
@@ -57,6 +50,8 @@ var send = exports.send = function (type, name, content, options) {
throw new Error('System module name \'' + name + '\' already exists');
} else {
assets.modules[name] = {
+ name: name,
+ type: type,
content: content,
options: options
};
@@ -66,7 +61,6 @@ var send = exports.send = function (type, name, content, options) {
};
exports.unload = function() {
- assets.shims = [];
assets.libs = [];
assets.modules = {};
assets.initCode = [];
@@ -76,22 +70,6 @@ exports.unload = function() {
exports.load = function() {
var modDir;
- // System shims for backwards compatibility with all browsers.
- // Load order is not important
- modDir = pathlib.join(__dirname, '/shims');
- fsUtils.readDirSync(modDir).files.forEach(function(fileName) {
- var code, extension, modName, sp, preMinified;
- code = fs.readFileSync(fileName, 'utf8');
- sp = fileName.split('.');
- extension = sp[sp.length - 1];
- preMinified = fileName.indexOf('.min') >= 0;
- modName = fileName.substr(modDir.length + 1);
- return send('shim', modName, code, {
- minified: preMinified,
- coffee: extension === 'coffee'
- });
- });
-
// System Libs. Including browserify client code
// Load order is not important
modDir = pathlib.join(__dirname, '/libs');
@@ -120,53 +98,3 @@ exports.load = function() {
});
});
};
-
-// Serve system assets
-exports.serve = {
- js: function (options) {
- var code, mod, name, output, _ref;
- if (options === null || options === undefined) {
- options = {};
- }
-
- // Shims
- output = assets.shims.map(function(code) {
- return options.compress && !code.options.minified && minifyJS(code.content) || code.content;
- });
-
- // Libs
- output = output.concat(assets.libs.map(function(code) {
- return options.compress && !code.options.minified && minifyJS(code.content) || code.content;
- }));
-
- // Modules
- _ref = assets.modules;
- for (name in _ref) {
- if (_ref.hasOwnProperty(name)) {
-
- mod = _ref[name];
- code = wrap.module(name, mod.content);
- if (options.compress && !mod.options.minified) {
- code = minifyJS(code);
- }
- output.push(code);
-
- }
- }
- return output.join('\n');
- },
- initCode: function() {
- return assets.initCode.join(' ');
- }
-};
-
-// Private
-function minifyJS(originalCode) {
- var ast, jsp, pro;
- jsp = uglifyjs.parser;
- pro = uglifyjs.uglify;
- ast = jsp.parse(originalCode);
- ast = pro.ast_mangle(ast);
- ast = pro.ast_squeeze(ast);
- return pro.gen_code(ast) + ';';
-}
diff --git a/lib/client/view.js b/lib/client/view.js
index d40502ae..91d5b1c1 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -4,8 +4,7 @@
'use strict';
var pathlib = require('path'),
- magicPath = require('./magic_path'),
- wrap = require('./wrap');
+ magicPath = require('./magic_path');
module.exports = function(ss, client, options, cb) {
var templateEngine = require('./template_engine')(ss),
@@ -77,38 +76,30 @@ module.exports = function(ss, client, options, cb) {
if (options.packedAssets) {
css = resolveAssetLink('css');
js = resolveAssetLink('js');
- output.push(wrap.htmlTag.css(css));
- output.push(wrap.htmlTag.js(js));
+ output.push(ss.bundler.htmlTag.css(css));
+ output.push(ss.bundler.htmlTag.js(js));
} else {
// Otherwise, in development, list all files individually so debugging is easier
// SocketStream system libs and modules
if (client.includes.system) {
- output.push(wrap.htmlTag.js('/_serveDev/system?ts=' + client.id));
+ output.push(ss.bundler.htmlTag.js('/_serveDev/system?ts=' + client.id));
}
// Send all CSS
if (client.includes.css) {
- client.paths.css.forEach(function(path) {
- return magicPath.files(pathlib.join(ss.root, options.dirs.client), path).forEach(function(file) {
- return output.push(wrap.htmlTag.css('/_serveDev/css/' + file + '?ts=' + client.id + '&client=' + client.name));
- });
- });
+ output.concat( bundler.asset.entries('css')
+ .map(function(entry) { return ss.bundler.htmlTag.css('/_serverDev/css/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
}
// Send Application Code
- client.paths.code.forEach(function(path) {
- return magicPath.files(pathlib.join(ss.root, options.dirs.client), path).forEach(function(file) {
- var url = '/_serveDev/code/' + file + '?ts=' + client.id + '&client=' + client.name;
- if (! options.globalModules) url += '&pathPrefix=' + path;
- return output.push(wrap.htmlTag.js(url));
- });
- });
+ output.concat( bundler.asset.entries('js')
+ .map(function(entry) { return ss.bundler.htmlTag.js('/_serverDev/code/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
- // Start your app and connect to SocketStream
+ // Start your app and connect to SocketStream
if (client.includes.initCode) {
- output.push(wrap.htmlTag.js('/_serveDev/start?ts=' + client.id));
+ output.push(ss.bundler.htmlTag.js('/_serveDev/start?ts=' + client.id));
}
}
return output;
diff --git a/lib/client/wrap.js b/lib/client/wrap.js
deleted file mode 100644
index c91e2046..00000000
--- a/lib/client/wrap.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// Simple wrapper for modules
-'use strict';
-
-//TODO review if this should be isolated in bundler API
-
-exports.module = function(modPath, code) {
- return 'require.define("' + modPath + '", function (require, module, exports, __dirname, __filename){\n' + code + '\n});';
-};
-
-exports.htmlTag = {
- css: function(path) {
- return '';
- },
- js: function(path) {
- return '';
- }
-};
\ No newline at end of file
From 4359210e0c2d903eaf3baa74f7bc06c20dd93992 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 8 Feb 2015 02:53:21 +0100
Subject: [PATCH 31/59] chore(lint): Down to some obscure obstacle
Couldn't figure out how to silence inner functions warning
---
.jshintrc | 2 -
lib/client/bundler/default.js | 79 ++++++++++++++++++++++++++-----
lib/client/bundler/index.js | 14 +++---
lib/client/bundler/webpack.js | 88 +++++++++++++++++++++++++++++++----
4 files changed, 153 insertions(+), 30 deletions(-)
diff --git a/.jshintrc b/.jshintrc
index 33d439aa..904eb73b 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -3,7 +3,6 @@
"curly" : true,
"eqeqeq" : true,
"eqnull" : true,
- "forin" : true,
"immed" : true,
"latedef" : "nofunc",
"newcap" : true,
@@ -20,7 +19,6 @@
"sub" : true,
"supernew" : true,
"node" : true,
- "onevar" : true,
"unused" : true,
"multistr" : true,
"smarttabs": true,
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index a5f3e263..b7ff903f 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -1,10 +1,7 @@
// Default bundler implementation
'use strict';
-var fs = require('fs'),
- path = require('path'),
- log = require('../../utils/log'),
- systemAssets = require('../system').assets;
+var systemAssets = require('../system').assets;
function includeFlags(overrides) {
var includes = {
@@ -59,14 +56,28 @@ module.exports = function(ss,client,options){
}
- function includeSystemLib(name,content,options) {
+ /**
+ *
+ * @param name
+ * @param content
+ * @param options
+ * @returns {boolean}
+ */
+ function includeSystemLib(name) {
switch(name) {
case "browserify":
}
return true;
}
- function includeSystemModule(name,content,options) {
+ /**
+ *
+ * @param name
+ * @param content
+ * @param options
+ * @returns {boolean}
+ */
+ function includeSystemModule(name) {
switch(name) {
case "eventemitter2":
case "socketstream":
@@ -74,11 +85,23 @@ module.exports = function(ss,client,options){
return true;
}
- // list of entries for an asset type relative to the client directory
+ /**
+ * list of entries for an asset type relative to the client directory
+ *
+ * @param assetType
+ * @returns {*}
+ */
function entries(assetType) {
return ss.bundler.entries(client, assetType);
}
+ /**
+ *
+ * @param path
+ * @param opts
+ * @param cb
+ * @returns {*}
+ */
function assetJS(path, opts, cb) {
return ss.bundler.loadFile(options.dirs.client, path, 'js', opts, function(output) {
//TODO with options compress saved to avoid double compression
@@ -89,6 +112,14 @@ module.exports = function(ss,client,options){
return cb(output);
});
}
+
+ /**
+ *
+ * @param path
+ * @param opts
+ * @param cb
+ * @returns {*}
+ */
function assetWorker(path, opts, cb) {
return ss.bundler.loadFile(options.dirs.client, path, 'js', opts, function(output) {
if (opts.compress) {
@@ -98,22 +129,50 @@ module.exports = function(ss,client,options){
});
}
+ /**
+ *
+ * @returns {*}
+ */
function assetLaunch() {
return ss.bundler.launchCode(client);
}
+ /**
+ *
+ * @param path
+ * @param opts
+ * @param cb
+ * @returns {*}
+ */
function assetCSS(path, opts, cb) {
return ss.bundler.loadFile(options.dirs.client, path, 'css', opts, cb);
}
+ /**
+ *
+ * @param path
+ * @param opts
+ * @param cb
+ * @returns {*}
+ */
function assetHTML(path, opts, cb) {
return ss.bundler.loadFile(options.dirs.client, path, 'html', opts, cb);
}
+ /**
+ *
+ * @param files
+ * @returns {*}
+ */
function toMinifiedCSS(files) {
return ss.bundler.minifyCSS(files);
}
+ /**
+ *
+ * @param files
+ * @returns {*}
+ */
function toMinifiedJS(files) {
// Libs
var libs = systemAssets.libs.map(function(lib) {
@@ -136,10 +195,8 @@ module.exports = function(ss,client,options){
}
var initCode = bundler.asset.launch();
- if (initCode) {
- //parts.push(initCode);
- }
- return ss.bundler.minifyJS(libs.concat(mods).concat(files).concat(systemAssets.initCode));
+
+ return ss.bundler.minifyJS(libs.concat(mods).concat(files).concat(initCode));
}
};
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index ed7829c8..6a58db62 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -201,13 +201,12 @@ module.exports = function(ss,options) {
}
initCode = initCode.replace(entryInit, realInit)
- return initCode;
+ return { content:initCode };
},
packAssetSet: function packAssetSet(assetType, client, postProcess) {
var bundler = getBundler(client),
- filePaths = bundler.asset.entries(assetType),
- dir = options.dirs.client;
+ filePaths = bundler.asset.entries(assetType);
return processFiles();
@@ -243,7 +242,7 @@ module.exports = function(ss,options) {
// css, js, worker,
entries: function entries(client, assetType) {
- var entries = [],
+ var _entries = [],
pathType;
switch(assetType) {
case 'css': pathType = 'css'; break;
@@ -252,10 +251,10 @@ module.exports = function(ss,options) {
}
client.paths[pathType].forEach(function(from) {
return magicPath.files(path.join(ss.root, options.dirs.client), from).forEach(function(file) {
- return entries.push({file:file,importedBy:from});
+ return _entries.push({file:file,importedBy:from});
});
});
- return entries;
+ return _entries;
},
@@ -323,8 +322,7 @@ module.exports = function(ss,options) {
};
function deleteOldFiles(clientDir) {
- var numFilesDeleted = 0,
- filesDeleted = fs.readdirSync(clientDir).map(function(fileName) {
+ var filesDeleted = fs.readdirSync(clientDir).map(function(fileName) {
return fs.unlinkSync(path.join(clientDir, fileName));
});
return filesDeleted.length > 1 && log('✓'.green, '' + filesDeleted.length + ' previous packaged files deleted');
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 235391eb..8b5d913a 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -1,9 +1,9 @@
// Webpack bundler implementation
'use strict';
-var fs = require('fs'),
- path = require('path'),
- log = require('../../utils/log');
+//var fs = require('fs'),
+// path = require('path'),
+// log = require('../../utils/log');
module.exports = function(webpack) {
return function(ss,options){
@@ -27,6 +27,12 @@ module.exports = function(webpack) {
};
return bundler;
+ /**
+ *
+ * @param client
+ * @param paths
+ * @returns {*}
+ */
function define(client, paths) {
if (typeof paths.view !== 'string') {
@@ -48,14 +54,28 @@ module.exports = function(webpack) {
}
- function includeSystemLib(name,content,options) {
+ /**
+ *
+ * @param name
+ * @param content
+ * @param options
+ * @returns {boolean}
+ */
+ function includeSystemLib(name) {
switch(name) {
case "browserify":
}
return true;
}
- function includeSystemModule(name,content,options) {
+ /**
+ *
+ * @param name
+ * @param content
+ * @param options
+ * @returns {boolean}
+ */
+ function includeSystemModule(name) {
switch(name) {
case "eventemitter2":
case "socketstream":
@@ -63,23 +83,52 @@ module.exports = function(webpack) {
return true;
}
- // list of entries for an asset type relative to the client directory
+ /**
+ * list of entries for an asset type relative to the client directory
+ *
+ * @param assetType
+ * @returns {*}
+ */
function entries(assetType) {
return ss.bundler.entries(bundler.client, assetType);
}
+ /**
+ *
+ * @param path
+ * @param opts
+ * @param cb
+ * @returns {*}
+ */
function assetCSS(path, opts, cb) {
return ss.bundler.loadFile(options.dirs.client, path, 'css', opts, cb);
}
+ /**
+ *
+ * @param path
+ * @param opts
+ * @param cb
+ * @returns {*}
+ */
function assetHTML(path, opts, cb) {
return ss.bundler.loadFile(options.dirs.client, path, 'html', opts, cb);
}
+ /**
+ *
+ * @param cb
+ */
function assetSystem(cb) {
cb('');
}
+ /**
+ *
+ * @param path
+ * @param opts
+ * @param cb
+ */
function assetJS(path, opts, cb) {
webpack({}, function() {
cb('//');
@@ -87,22 +136,43 @@ module.exports = function(webpack) {
}
+ /**
+ *
+ * @param cb
+ * @returns {*}
+ */
function assetLaunch(cb) {
- var output = ss.bundler.launchCode(client);
+ var output = ss.bundler.launchCode(bundler.client);
return cb(output);
}
+ /**
+ *
+ * @param path
+ * @param opts
+ * @param cb
+ */
function assetWorker(path, opts, cb) {
webpack({}, function() {
cb('//');
});
}
+ /**
+ *
+ * @param files
+ * @returns {*}
+ */
function toMinifiedCSS(files) {
- return ss.bundler.minifyCSS(files.join('\n'));
+ return ss.bundler.minifyCSS(files);
}
- function toMinifiedJS(files) {
+ /**
+ *
+ * @param files
+ * @returns {string}
+ */
+ function toMinifiedJS() {
return '// minified JS for '+bundler.client.name;
}
};
From 4ad8085c15ea4535cdbe9f69eecc50cf64e9dbf1 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 8 Feb 2015 10:42:10 +0100
Subject: [PATCH 32/59] chore(lint): bundler pass on jshint
---
lib/client/bundler/default.js | 4 ++--
lib/client/bundler/index.js | 5 ++---
lib/client/bundler/webpack.js | 3 ++-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index b7ff903f..d58ec501 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -34,8 +34,6 @@ module.exports = function(ss,client,options){
}
};
- return bundler;
-
function define(paths) {
if (typeof paths.view !== 'string') {
@@ -198,5 +196,7 @@ module.exports = function(ss,client,options){
return ss.bundler.minifyJS(libs.concat(mods).concat(files).concat(initCode));
}
+
+ return bundler;
};
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 6a58db62..3c6b75e1 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -208,9 +208,6 @@ module.exports = function(ss,options) {
var bundler = getBundler(client),
filePaths = bundler.asset.entries(assetType);
- return processFiles();
-
-
function writeFile(fileContents) {
var fileName = bundler.dests.paths[assetType];
fs.writeFileSync(fileName, postProcess(fileContents));
@@ -237,6 +234,8 @@ module.exports = function(ss,options) {
}
});
}
+
+ return processFiles();
},
// css, js, worker,
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 8b5d913a..72415369 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -25,7 +25,6 @@ module.exports = function(webpack) {
css: assetCSS
}
};
- return bundler;
/**
*
@@ -175,6 +174,8 @@ module.exports = function(webpack) {
function toMinifiedJS() {
return '// minified JS for '+bundler.client.name;
}
+
+ return bundler;
};
};
From fc93d394d4405cdfa57c005dff38eb1ebef42424 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 8 Feb 2015 16:49:34 +0100
Subject: [PATCH 33/59] feat(assets): URL scheme for assets
First draft of a document explaining the URL rationale in development and production
---
docs/js/docs-setup.js | 9 +++++++++
docs/partials/tutorials/url_scheme.html | 22 ++++++++++++++++++++++
src/docs/tutorials/en/url_scheme.ngdoc | 0
3 files changed, 31 insertions(+)
create mode 100644 docs/partials/tutorials/url_scheme.html
create mode 100644 src/docs/tutorials/en/url_scheme.ngdoc
diff --git a/docs/js/docs-setup.js b/docs/js/docs-setup.js
index 0b168bf7..3655b0ae 100644
--- a/docs/js/docs-setup.js
+++ b/docs/js/docs-setup.js
@@ -185,6 +185,15 @@ NG_DOCS={
"shortDescription": "Template Engine Wrappers",
"keywords": "add app as-is attach automatically based bearing behavior best browser building bytes call called calls case catch client client-side clientcode closing code command compile compiled compiledtemplate compiling config consider console contents create default defaultformatter directly dot easy engine engines error example exports extension false file files find folder formatter formatters fs function functions github good guides handles hasownproperty hogan hogan-template ht html idea include init inside jade join js key language large lib library loads log map message mind module modules needed occasionally opening overview overwrite party pass passing path performance pick points pre-compile pre-processing preferred prefix process prototype prove readfilesync ready red reference relative render require return returns selectformatter selecting selects send sending server side simply socketstream ss suffix supports tag template templates templating text third throw time tips tmpl trade transform transforming true tutorials twitter type uncommon utf8 var variety vm wide wire wrap wrapper wrappers written"
},
+ {
+ "section": "tutorials",
+ "id": "url_scheme",
+ "shortName": "URL Scheme",
+ "type": "overview",
+ "moduleName": "URL Scheme",
+ "shortDescription": "URL Scheme",
+ "keywords": "ad assets calling change choose client code common completely consider considered contents css current demand development directory equivalent exported fetching files fly form future handled hoc html ideally js level loading middleware minified module modules on-demand open overview packed partially path paths production relative root saved scheme sense serve serveclient served serving static support time tutorials url urls view views whitelist work"
+ },
{
"section": "tutorials",
"id": "using_emberjs",
diff --git a/docs/partials/tutorials/url_scheme.html b/docs/partials/tutorials/url_scheme.html
new file mode 100644
index 00000000..ba29c523
--- /dev/null
+++ b/docs/partials/tutorials/url_scheme.html
@@ -0,0 +1,22 @@
+
+
+
+
+
URL Scheme
+
The common URL for a view is its name at the root level, but you can choose whatever you will calling serveClient(..).
+
Assets
+
The contents of the client assets directory will be served under /assets.
+
When views are packed for production they are saved under the client assets directory. This will change in the future
+to make relative URLs work the same in development and production.
+
Middleware
+
At development time middleware is added to serve HTML, JS and CSS on the fly.
+
Serving CSS
+
CSS files are served under /assets//123.css in production. When served ad hoc in development, and on-demand in
+production all CSS must be served on the same level and ideally in an equivalent URL.
+
JS Module Paths
+
On Demand Loading
+
The current on-demand fetching of JS is handled by middleware. It should be possible to do it using static files.
+
In production it would make sense to support a path like /assets/require/...
+
We will have to consider whether all client code is considered completely open, or only partially. Should all client
+modules be exported in minified form, or only those in a whitelist.
+
diff --git a/src/docs/tutorials/en/url_scheme.ngdoc b/src/docs/tutorials/en/url_scheme.ngdoc
new file mode 100644
index 00000000..e69de29b
From 0e82774f443705366e90eb2de04be3b1d835078f Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 8 Feb 2015 16:50:50 +0100
Subject: [PATCH 34/59] feat(assets): missing file
---
src/docs/tutorials/en/url_scheme.ngdoc | 37 ++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/src/docs/tutorials/en/url_scheme.ngdoc b/src/docs/tutorials/en/url_scheme.ngdoc
index e69de29b..1618772f 100644
--- a/src/docs/tutorials/en/url_scheme.ngdoc
+++ b/src/docs/tutorials/en/url_scheme.ngdoc
@@ -0,0 +1,37 @@
+@ngdoc overview
+@name URL Scheme
+
+@description
+# URL Scheme
+
+The common URL for a view is its name at the root level, but you can choose whatever you will calling `serveClient(..)`.
+
+## Assets
+
+The contents of the client assets directory will be served under `/assets`.
+
+
+When views are packed for production they are saved under the client assets directory. This will change in the future
+to make relative URLs work the same in development and production.
+
+## Middleware
+
+At development time middleware is added to serve HTML, JS and CSS on the fly.
+
+
+## Serving CSS
+
+CSS files are served under /assets//123.css in production. When served ad hoc in development, and on-demand in
+production all CSS must be served on the same level and ideally in an equivalent URL.
+
+## JS Module Paths
+
+
+## On Demand Loading
+
+The current on-demand fetching of JS is handled by middleware. It should be possible to do it using static files.
+
+In production it would make sense to support a path like `/assets/require/..`.
+
+We will have to consider whether all client code is considered completely open, or only partially. Should all client
+modules be exported in minified form, or only those in a whitelist.
\ No newline at end of file
From ddc6bc58829a168abd5e7322782bb1920cc1e049 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 8 Feb 2015 18:24:58 +0100
Subject: [PATCH 35/59] chore(simplify): client dir is always base for assets
---
lib/client/bundler/default.js | 8 ++++----
lib/client/bundler/index.js | 10 ++++------
lib/client/bundler/webpack.js | 4 ++--
3 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index d58ec501..9ba4725f 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -101,7 +101,7 @@ module.exports = function(ss,client,options){
* @returns {*}
*/
function assetJS(path, opts, cb) {
- return ss.bundler.loadFile(options.dirs.client, path, 'js', opts, function(output) {
+ return ss.bundler.loadFile(path, 'js', opts, function(output) {
//TODO with options compress saved to avoid double compression
output = ss.bundler.wrapCode(output, path, opts.pathPrefix);
if (opts.compress && path.indexOf('.min') === -1) {
@@ -119,7 +119,7 @@ module.exports = function(ss,client,options){
* @returns {*}
*/
function assetWorker(path, opts, cb) {
- return ss.bundler.loadFile(options.dirs.client, path, 'js', opts, function(output) {
+ return ss.bundler.loadFile(path, 'js', opts, function(output) {
if (opts.compress) {
output = ss.bundler.minifyJSFile(output, path);
}
@@ -143,7 +143,7 @@ module.exports = function(ss,client,options){
* @returns {*}
*/
function assetCSS(path, opts, cb) {
- return ss.bundler.loadFile(options.dirs.client, path, 'css', opts, cb);
+ return ss.bundler.loadFile(path, 'css', opts, cb);
}
/**
@@ -154,7 +154,7 @@ module.exports = function(ss,client,options){
* @returns {*}
*/
function assetHTML(path, opts, cb) {
- return ss.bundler.loadFile(options.dirs.client, path, 'html', opts, cb);
+ return ss.bundler.loadFile(path, 'html', opts, cb);
}
/**
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 3c6b75e1..5f7d68a6 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -54,8 +54,6 @@ module.exports = function(ss,options) {
bundlers[name] = require('./default')(ss,client,options);
bundlers[name].dests = bundlers[name].define(args[1]);
}
-
- //console.warn('client defined',name,client,bundlers[name].dests);
},
/**
@@ -95,7 +93,7 @@ module.exports = function(ss,options) {
// Output HTML view
return view(ss, client, options, function(html) {
- fs.writeFileSync(getBundler(client).dests.paths.html, html);
+ fs.writeFileSync(bundler.dests.paths.html, html);
return log.info('✓'.green, 'Created and cached HTML file ' + bundler.dests.relPaths.html);
});
},
@@ -103,8 +101,8 @@ module.exports = function(ss,options) {
// API for implementing bundlers
- loadFile: function loadFile(dir, fileName, type, options, cb) {
- dir = path.join(ss.root, dir);
+ loadFile: function loadFile(fileName, type, opts, cb) {
+ var dir = path.join(ss.root, options.dirs.client);
var p = path.join(dir, fileName);
var extension = path.extname(p);
extension = extension && extension.substring(1); // argh!
@@ -118,7 +116,7 @@ module.exports = function(ss,options) {
if (formatter.assetType !== type) {
throw new Error('Unable to render \'' + fileName + '\' as this appears to be a ' + (formatter.assetType.toUpperCase()) + ' file. Expecting some type of ' + (type.toUpperCase()) + ' file in ' + (dir.substr(ss.root.length)) + ' instead');
}
- return formatter.compile(p.replace(/\\/g, '/'), options, cb);
+ return formatter.compile(p.replace(/\\/g, '/'), opts, cb);
},
minifyCSS: function minifyCSS(files) {
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 72415369..f674e5f2 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -100,7 +100,7 @@ module.exports = function(webpack) {
* @returns {*}
*/
function assetCSS(path, opts, cb) {
- return ss.bundler.loadFile(options.dirs.client, path, 'css', opts, cb);
+ return ss.bundler.loadFile(path, 'css', opts, cb);
}
/**
@@ -111,7 +111,7 @@ module.exports = function(webpack) {
* @returns {*}
*/
function assetHTML(path, opts, cb) {
- return ss.bundler.loadFile(options.dirs.client, path, 'html', opts, cb);
+ return ss.bundler.loadFile(path, 'html', opts, cb);
}
/**
From 510fb53e4a53e7be36d4b91282526d0792dfefba Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 8 Feb 2015 18:43:56 +0100
Subject: [PATCH 36/59] feat(bundler): view with tags
---
lib/client/view.js | 31 +++++++++++++++----------------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/lib/client/view.js b/lib/client/view.js
index 91d5b1c1..7755f2b6 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -10,17 +10,6 @@ module.exports = function(ss, client, options, cb) {
var templateEngine = require('./template_engine')(ss),
bundler = ss.bundler.get(client);
- // Add links to CSS and JS files
- var includes = headers().concat(templates());
-
- // Output HTML
- var htmlOptions = {
- headers: includes.join(''),
- compress: options.packedAssets,
- filename: client.paths.view
- };
- return bundler.asset.html(client.paths.view, htmlOptions, cb);
-
// When packing assets the default path to the CSS or JS file can be overridden
// either with a string or a function, typically pointing to an resource on a CDN
function resolveAssetLink(type) {
@@ -79,8 +68,7 @@ module.exports = function(ss, client, options, cb) {
output.push(ss.bundler.htmlTag.css(css));
output.push(ss.bundler.htmlTag.js(js));
} else {
-
- // Otherwise, in development, list all files individually so debugging is easier
+ // Otherwise, in development, list all files individually so debugging is easier
// SocketStream system libs and modules
if (client.includes.system) {
@@ -89,12 +77,12 @@ module.exports = function(ss, client, options, cb) {
// Send all CSS
if (client.includes.css) {
- output.concat( bundler.asset.entries('css')
+ output = output.concat( bundler.asset.entries('css')
.map(function(entry) { return ss.bundler.htmlTag.css('/_serverDev/css/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
}
- // Send Application Code
- output.concat( bundler.asset.entries('js')
+ // Send Application Code
+ output = output.concat( bundler.asset.entries('js')
.map(function(entry) { return ss.bundler.htmlTag.js('/_serverDev/code/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
// Start your app and connect to SocketStream
@@ -104,4 +92,15 @@ module.exports = function(ss, client, options, cb) {
}
return output;
}
+
+ // Add links to CSS and JS files
+ var includes = headers().concat(templates());
+
+ // Output HTML
+ var htmlOptions = {
+ headers: includes.join(''),
+ compress: options.packedAssets,
+ filename: client.paths.view
+ };
+ return bundler.asset.html(client.paths.view, htmlOptions, cb);
};
From 7fd3833ceb6fb86ccd8ef83e0f56b38af0b4ed1b Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sun, 8 Feb 2015 19:01:10 +0100
Subject: [PATCH 37/59] feat(bundler): system modules are named without JS
extensions
---
lib/client/system/index.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/client/system/index.js b/lib/client/system/index.js
index 6be49b5f..85e442f3 100644
--- a/lib/client/system/index.js
+++ b/lib/client/system/index.js
@@ -92,7 +92,7 @@ exports.load = function() {
code = fs.readFileSync(fileName, 'utf8');
sp = fileName.split('.');
extension = sp[sp.length - 1];
- modName = fileName.substr(modDir.length + 1);
+ modName = fileName.substr(modDir.length + 1).replace('.js','').replace('.min.js','');
return send('mod', modName, code, {
coffee: extension === 'coffee'
});
From 9707a63a18404e3ee9ff3626dcc4075454507fa6 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Mon, 9 Feb 2015 09:08:23 +0100
Subject: [PATCH 38/59] chore(lint): var refactor
---
lib/client/http.js | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/lib/client/http.js b/lib/client/http.js
index b8e1e25e..49ec4fa1 100644
--- a/lib/client/http.js
+++ b/lib/client/http.js
@@ -30,9 +30,9 @@ module.exports = function(ss, clients, options) {
// Append the 'serveClient' method to the HTTP Response object
res.serveClient = function(name) {
- var client, fileName, self, sendHTML;
- self = this;
- sendHTML = function(html, code) {
+ var self = this;
+
+ function sendHTML(html, code) {
if (!code) {
code = 200;
}
@@ -45,9 +45,10 @@ module.exports = function(ss, clients, options) {
self.setHeader('Content-Length', Buffer.byteLength(html));
self.setHeader('Content-Type', 'text/html; charset=UTF-8');
self.end(html);
- };
+ }
+
try {
- client = typeof name === 'string' && clients[name];
+ var client = typeof name === 'string' && clients[name];
if (!client) {
throw new Error('Unable to find single-page client: ' + name);
}
@@ -57,7 +58,7 @@ module.exports = function(ss, clients, options) {
// Return from in-memory cache if possible
if (!cache[name]) {
- fileName = pathlib.join(ss.root, options.dirs.assets, client.name, client.id + '.html');
+ var fileName = pathlib.join(ss.root, options.dirs.assets, client.name, client.id + '.html');
cache[name] = fs.readFileSync(fileName, 'utf8');
}
From fda53a0f18710d96af466c5c70971ed90edfd540 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Mon, 9 Feb 2015 09:08:52 +0100
Subject: [PATCH 39/59] chore(lint): extracted getBundle function
---
lib/client/bundler/index.js | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 5f7d68a6..1e23c185 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -18,21 +18,21 @@ var fs = require('fs'),
*/
var bundlers = {};
-module.exports = function(ss,options) {
+function getBundler(client){
- function getBundler(client){
+ if (client.bundler) { return client.bundler; }
- if (client.bundler) { return client.bundler; }
+ if (typeof client.client === "string") {
+ return bundlers[client.client];
+ }
+ if (typeof client.name === "string") {
+ return bundlers[client.name];
+ }
- if (typeof client.client === "string") {
- return bundlers[client.client];
- }
- if (typeof client.name === "string") {
- return bundlers[client.name];
- }
+ throw new Error('Unknow client '+(client.name || client.client) );
+}
- throw new Error('Unknow client '+(client.name || client.client) );
- }
+module.exports = function(ss,options) {
return {
From 694aa2213819a6ffc47326f5e9bcb2c32c7476ae Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Tue, 10 Feb 2015 20:22:56 +0100
Subject: [PATCH 40/59] fix(bundler): fix _serveDev typo
---
lib/client/bundler/default.js | 4 ++--
lib/client/view.js | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index 9ba4725f..543a8b89 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -192,9 +192,9 @@ module.exports = function(ss,client,options){
}
}
- var initCode = bundler.asset.launch();
+ var initCodes = bundler.asset.launch();
- return ss.bundler.minifyJS(libs.concat(mods).concat(files).concat(initCode));
+ return ss.bundler.minifyJS(libs.concat(mods).concat(files).concat(initCodes));
}
return bundler;
diff --git a/lib/client/view.js b/lib/client/view.js
index 7755f2b6..e6bcc8c1 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -78,12 +78,12 @@ module.exports = function(ss, client, options, cb) {
// Send all CSS
if (client.includes.css) {
output = output.concat( bundler.asset.entries('css')
- .map(function(entry) { return ss.bundler.htmlTag.css('/_serverDev/css/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
+ .map(function(entry) { return ss.bundler.htmlTag.css('/_serveDev/css/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
}
// Send Application Code
output = output.concat( bundler.asset.entries('js')
- .map(function(entry) { return ss.bundler.htmlTag.js('/_serverDev/code/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
+ .map(function(entry) { return ss.bundler.htmlTag.js('/_serveDev/code/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
// Start your app and connect to SocketStream
if (client.includes.initCode) {
From ecfe64f2287e5eb843087e4caca06a12c46ad593 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Tue, 10 Feb 2015 23:34:43 +0100
Subject: [PATCH 41/59] fix(bundler): packing initCode
---
lib/client/bundler/index.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 1e23c185..f937888d 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -199,7 +199,7 @@ module.exports = function(ss,options) {
}
initCode = initCode.replace(entryInit, realInit)
- return { content:initCode };
+ return { content:initCode, options: {} };
},
packAssetSet: function packAssetSet(assetType, client, postProcess) {
From 295f72bc91a005152cb3781c3cfd63d098251731 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Wed, 11 Feb 2015 20:30:46 +0100
Subject: [PATCH 42/59] system modules + libs iteration
Run through them the same way when packing and adding html tags.
---
lib/client/bundler/default.js | 70 +++++++++++------------------------
lib/client/bundler/index.js | 70 ++++++++++++++++++++++++++++++++---
lib/client/bundler/webpack.js | 63 +++++++++++++------------------
lib/client/serve/dev.js | 31 +++++++++++-----
lib/client/system/index.js | 7 ++--
lib/client/view.js | 28 ++++++++------
6 files changed, 153 insertions(+), 116 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index 543a8b89..92fe5f29 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -23,12 +23,13 @@ module.exports = function(ss,client,options){
toMinifiedCSS: toMinifiedCSS,
toMinifiedJS: toMinifiedJS,
asset: {
- includeSystemLib: includeSystemLib,
- includeSystemModule: includeSystemModule,
entries: entries,
+
+ loader: assetLoader,
+ systemModule: systemModule,
js: assetJS,
worker: assetWorker,
- launch: assetLaunch,
+ start: assetStart,
css: assetCSS,
html: assetHTML
}
@@ -55,17 +56,17 @@ module.exports = function(ss,client,options){
}
/**
+ * list of entries for an asset type relative to the client directory
*
- * @param name
- * @param content
- * @param options
- * @returns {boolean}
+ * @param assetType
+ * @returns {*}
*/
- function includeSystemLib(name) {
- switch(name) {
- case "browserify":
- }
- return true;
+ function entries(assetType) {
+ return ss.bundler.entries(client, assetType);
+ }
+
+ function assetLoader() {
+ return client.includes.system? ss.bundler.systemLibs() : null;
}
/**
@@ -75,22 +76,15 @@ module.exports = function(ss,client,options){
* @param options
* @returns {boolean}
*/
- function includeSystemModule(name) {
+ function systemModule(name) {
switch(name) {
case "eventemitter2":
case "socketstream":
+ default:
+ if (client.includes.system) {
+ return ss.bundler.systemModule(name)
+ }
}
- return true;
- }
-
- /**
- * list of entries for an asset type relative to the client directory
- *
- * @param assetType
- * @returns {*}
- */
- function entries(assetType) {
- return ss.bundler.entries(client, assetType);
}
/**
@@ -131,8 +125,8 @@ module.exports = function(ss,client,options){
*
* @returns {*}
*/
- function assetLaunch() {
- return ss.bundler.launchCode(client);
+ function assetStart() {
+ return client.includes.initCode? ss.bundler.startCode(client) : null;
}
/**
@@ -172,29 +166,7 @@ module.exports = function(ss,client,options){
* @returns {*}
*/
function toMinifiedJS(files) {
- // Libs
- var libs = systemAssets.libs.map(function(lib) {
- return bundler.asset.includeSystemLib(lib.name, lib.content, lib.options)? lib : null;
- }).filter(function(content) {
- return !!content;
- });
-
- // Modules
- var mods = [],
- _ref = systemAssets.modules;
- for (var name in _ref) {
- if (_ref.hasOwnProperty(name)) {
- var mod = _ref[name];
- if (bundler.asset.includeSystemModule(mod.name,mod.content,mod.options)) {
- var code = ss.bundler.wrapModule(name, mod.content);
- mods.push({ name:mod.name, content:code,options:mod.options,type:mod.type });
- }
- }
- }
-
- var initCodes = bundler.asset.launch();
-
- return ss.bundler.minifyJS(libs.concat(mods).concat(files).concat(initCodes));
+ return ss.bundler.minifyJS(files);
}
return bundler;
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index f937888d..a70c6a81 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -189,8 +189,39 @@ module.exports = function(ss,options) {
};
},
- launchCode: function(client) {
- var initCode = system.assets.initCode.map(function(ic) { return ic.content; }).join('\n'),
+ systemLibs: function() {
+ var names = [];
+ return {
+ type: 'loader',
+ names: names,
+ content: system.assets.libs.map(function(lib) { names.push(lib.name); return lib.content; }).join('\n')
+ };
+ },
+
+ systemModule: function(name) {
+ var mod = system.assets.modules[name];
+ if (mod) {
+ var code = ss.bundler.wrapModule(name, mod.content);
+ return {
+ file: mod.name,
+ name: mod.name,
+ content: code,
+ options: mod.options,
+ type: mod.type
+ };
+ }
+ },
+
+ /**
+ * Default start/init codes to load the client view.
+ *
+ * Called in default bundler startCode.
+ *
+ * @param client Client Object
+ * @returns {{content: *, options: {}}} Single Entry for inclusion in entries()
+ */
+ startCode: function(client) {
+ var startCode = system.assets.startCode.map(function(ic) { return ic.content; }).join('\n'),
entryInit = options.defaultEntryInit,
realInit = 'require(' + client.entryInitPath + ');';
@@ -198,8 +229,8 @@ module.exports = function(ss,options) {
realInit = options.entryModuleName? 'require("/'+options.entryModuleName+'");' : '';
}
- initCode = initCode.replace(entryInit, realInit)
- return { content:initCode, options: {} };
+ startCode = startCode.replace(entryInit, realInit)
+ return { content:startCode, options: {}, type: 'start' };
},
packAssetSet: function packAssetSet(assetType, client, postProcess) {
@@ -236,23 +267,50 @@ module.exports = function(ss,options) {
return processFiles();
},
- // css, js, worker,
+ /**
+ * Make a list of asset entries for JS/CSS bundle.
+ *
+ * @param client
+ * @param assetType
+ * @returns {Array}
+ */
entries: function entries(client, assetType) {
var _entries = [],
+ bundler = getBundler(client),
pathType;
switch(assetType) {
case 'css': pathType = 'css'; break;
case 'js': pathType = 'code'; break;
case 'worker': pathType = 'code'; break;
}
+ if (pathType === 'code') {
+ // Libs
+ var libs = [bundler.asset.loader()];
+
+ // Modules
+ var mods = [],
+ _ref = system.assets.modules;
+ for (var name in _ref) {
+ if (_ref.hasOwnProperty(name)) {
+ mods.push( bundler.asset.systemModule(name) );
+ }
+ }
+ _entries = _entries.concat(libs).concat(mods);
+ }
client.paths[pathType].forEach(function(from) {
return magicPath.files(path.join(ss.root, options.dirs.client), from).forEach(function(file) {
return _entries.push({file:file,importedBy:from});
});
});
- return _entries;
+ if (pathType === 'code') {
+ _entries.push(bundler.asset.start());
+ }
+ // entries with blank ones stripped out
+ return _entries.filter(function(entry) {
+ return !!entry;
+ });
},
formatKb: formatKb,
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index f674e5f2..67e6dd3e 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -13,15 +13,14 @@ module.exports = function(webpack) {
toMinifiedCSS: toMinifiedCSS,
toMinifiedJS: toMinifiedJS,
asset: {
- includeSystemLib: includeSystemLib,
- includeSystemModule: includeSystemModule,
entries: entries,
html: assetHTML,
- system: assetSystem,
+ loader: assetLoader,
+ includeSystemModule: includeSystemModule,
js: assetJS,
worker: assetWorker,
- launch: assetLaunch,
+ start: assetStart,
css: assetCSS
}
};
@@ -53,35 +52,6 @@ module.exports = function(webpack) {
}
- /**
- *
- * @param name
- * @param content
- * @param options
- * @returns {boolean}
- */
- function includeSystemLib(name) {
- switch(name) {
- case "browserify":
- }
- return true;
- }
-
- /**
- *
- * @param name
- * @param content
- * @param options
- * @returns {boolean}
- */
- function includeSystemModule(name) {
- switch(name) {
- case "eventemitter2":
- case "socketstream":
- }
- return true;
- }
-
/**
* list of entries for an asset type relative to the client directory
*
@@ -118,10 +88,29 @@ module.exports = function(webpack) {
*
* @param cb
*/
- function assetSystem(cb) {
- cb('');
+ function assetLoader() {
+ return { type: 'loader', content: ';/* loader */' };
+ }
+
+ /**
+ *
+ * @param name
+ * @param content
+ * @param options
+ * @returns {boolean}
+ */
+ function systemModule(name) {
+ switch(name) {
+ case "eventemitter2":
+ case "socketstream":
+ default:
+ //if (client.includes.system) {
+ return ss.bundler.systemModule(name)
+ //}
+ }
}
+
/**
*
* @param path
@@ -140,8 +129,8 @@ module.exports = function(webpack) {
* @param cb
* @returns {*}
*/
- function assetLaunch(cb) {
- var output = ss.bundler.launchCode(bundler.client);
+ function assetStart(cb) {
+ var output = ss.bundler.startCode(bundler.client);
return cb(output);
}
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index bb4f9908..e3a306dd 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -12,27 +12,38 @@ var url = require('url'),
//
module.exports = function (ss, router, options) {
- var bundler = require('../bundler/index')(ss,options);
-
- // JAVASCRIPT
+ // JAVASCRIPT
// Serve system libraries and modules
router.on('/_serveDev/system?*', function(request, response) {
var thisUrl = url.parse(request.url),
- params = qs.parse(thisUrl.query);
+ params = qs.parse(thisUrl.query),
+ moduleName = utils.parseUrl(request.url);
- return bundler.get(params).asset.system(function(output) {
- return utils.serve.js(output, response);
- });
+ // no module name (probably ts=..)
+ if (moduleName.indexOf('=') >= 0) {
+ var loader = ss.bundler.get(params).asset.loader() || {},
+ namesComment = '/* ' + loader.names.join(',') + ' */';
+ utils.serve.js(namesComment+'\n'+loader.content || '', response);
+ }
+
+ // module
+ else {
+ var module = ss.bundler.get(params).asset.systemModule(moduleName) || {};
+ utils.serve.js(module.content || '', response);
+ }
});
+ //TODO bundler calculates entries. view builds according to entries. formatter is predetermined
+
// Listen for requests for application client code
router.on('/_serveDev/code?*', function(request, response) {
var thisUrl = url.parse(request.url),
params = qs.parse(thisUrl.query),
path = utils.parseUrl(request.url);
- return bundler.get(params).asset.js(path, {
+ return ss.bundler.get(params).asset.js(path, {
+ //TODO formatter: params.formatter,
client: params.client,
clientId: params.ts,
pathPrefix: params.pathPrefix
@@ -44,7 +55,7 @@ module.exports = function (ss, router, options) {
var thisUrl = url.parse(request.url),
params = qs.parse(thisUrl.query);
- bundler.get(params).asset.launch(function(output) {
+ ss.bundler.get(params).asset.launch(function(output) {
return utils.serve.js(output, response);
});
});
@@ -57,7 +68,7 @@ module.exports = function (ss, router, options) {
thisUrl = url.parse(request.url);
params = qs.parse(thisUrl.query);
path = utils.parseUrl(request.url);
- return bundler.get(params).asset.css(path, {
+ return ss.bundler.get(params).asset.css(path, {
client: params.client,
clientId: params.ts
}, function(output) {
diff --git a/lib/client/system/index.js b/lib/client/system/index.js
index 85e442f3..0759c72f 100644
--- a/lib/client/system/index.js
+++ b/lib/client/system/index.js
@@ -14,7 +14,7 @@ var fs = require('fs'),
var assets = exports.assets = {
libs: [],
modules: {},
- initCode: []
+ startCode: []
};
function pushUniqueAsset(listName,asset) {
@@ -34,8 +34,9 @@ var send = exports.send = function (type, name, content, options) {
}
switch (type) {
+ case 'start':
case 'code':
- return assets.initCode.push({content:content,options:options});
+ return assets.startCode.push({content:content,options:options, type:'start'});
case 'lib':
case 'library':
return pushUniqueAsset('libs',{
@@ -63,7 +64,7 @@ var send = exports.send = function (type, name, content, options) {
exports.unload = function() {
assets.libs = [];
assets.modules = {};
- assets.initCode = [];
+ assets.startCode = [];
};
// Load all system libs and modules
diff --git a/lib/client/view.js b/lib/client/view.js
index e6bcc8c1..67910cdc 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -70,25 +70,31 @@ module.exports = function(ss, client, options, cb) {
} else {
// Otherwise, in development, list all files individually so debugging is easier
- // SocketStream system libs and modules
- if (client.includes.system) {
- output.push(ss.bundler.htmlTag.js('/_serveDev/system?ts=' + client.id));
- }
-
// Send all CSS
if (client.includes.css) {
output = output.concat( bundler.asset.entries('css')
- .map(function(entry) { return ss.bundler.htmlTag.css('/_serveDev/css/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
+ .map(function(entry) {
+ return ss.bundler.htmlTag.css('/_serveDev/css/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
}
// Send Application Code
output = output.concat( bundler.asset.entries('js')
- .map(function(entry) { return ss.bundler.htmlTag.js('/_serveDev/code/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
+ .map(function(entry) {
+ switch(entry.type) {
+ case 'loader':
+ return ss.bundler.htmlTag.js('/_serveDev/system?ts=' + client.id + '&client=' + client.name);
- // Start your app and connect to SocketStream
- if (client.includes.initCode) {
- output.push(ss.bundler.htmlTag.js('/_serveDev/start?ts=' + client.id));
- }
+ case 'mod':
+ case 'module':
+ return ss.bundler.htmlTag.js('/_serveDev/system/' + entry.file + '?ts=' + client.id + '&client=' + client.name);
+
+ case 'start':
+ return ss.bundler.htmlTag.js('/_serveDev/start?ts=' + client.id + '&client=' + client.name);
+
+ default:
+ return ss.bundler.htmlTag.js('/_serveDev/code/' + entry.file + '?ts=' + client.id + '&client=' + client.name);
+ }
+ }) );
}
return output;
}
From c5adac7e0a7c2bade6e826cb79f4c8f746fa2555 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Wed, 11 Feb 2015 20:48:52 +0100
Subject: [PATCH 43/59] feat(id): unique client id can be used to look up
bundler
---
lib/client/bundler/index.js | 20 ++++++++++++++------
lib/client/index.js | 3 ++-
lib/client/view.js | 10 +++++-----
package.json | 1 +
4 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index a70c6a81..9c91aa05 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -16,12 +16,18 @@ var fs = require('fs'),
* Bundler by client name
* @type {{}}
*/
-var bundlers = {};
+var bundlers = {},
+ bundlerById = {};
function getBundler(client){
if (client.bundler) { return client.bundler; }
+ if (client.ts) {
+ if (bundlerById[client.ts]) {
+ return bundlerById[client.ts];
+ }
+ }
if (typeof client.client === "string") {
return bundlers[client.client];
}
@@ -45,15 +51,17 @@ module.exports = function(ss,options) {
define: function defineBundler(client,args) {
var name = args[0],
- pathsOrFunc = args[1];
+ pathsOrFunc = args[1],
+ bundler;
if (typeof pathsOrFunc === "function") {
- bundlers[name] = pathsOrFunc(ss,options);
- bundlers[name].dests = bundlers[name].define(client, args[2], args[3], args[4], args[5]);
+ bundler = bundlers[name] = pathsOrFunc(ss,options);
+ bundler.dests = bundler.define(client, args[2], args[3], args[4], args[5]);
} else {
- bundlers[name] = require('./default')(ss,client,options);
- bundlers[name].dests = bundlers[name].define(args[1]);
+ bundler = bundlers[name] = require('./default')(ss,client,options);
+ bundler.dests = bundler.define(args[1]);
}
+ bundlerById[client.id] = bundler;
},
/**
diff --git a/lib/client/index.js b/lib/client/index.js
index fafaa4cd..521e44f5 100644
--- a/lib/client/index.js
+++ b/lib/client/index.js
@@ -10,6 +10,7 @@ require('colors');
var fs = require('fs'),
path = require('path'),
+ shortid = require('shortid'),
log = require('../utils/log'),
systemAssets = require('./system');
@@ -137,7 +138,7 @@ module.exports = function(ss, router) {
}
// if a function is used construct a bundler with it otherwise use default bundler
var client = clients[name] = { name: name };
- client.id = Number(Date.now());
+ client.id = shortid.generate();
client.paths = {};
client.includes = {
css: true,
diff --git a/lib/client/view.js b/lib/client/view.js
index 67910cdc..8953ae68 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -74,7 +74,7 @@ module.exports = function(ss, client, options, cb) {
if (client.includes.css) {
output = output.concat( bundler.asset.entries('css')
.map(function(entry) {
- return ss.bundler.htmlTag.css('/_serveDev/css/' + entry.file + '?ts=' + client.id + '&client=' + client.name); }) );
+ return ss.bundler.htmlTag.css('/_serveDev/css/' + entry.file + '?ts=' + client.id); }) );
}
// Send Application Code
@@ -82,17 +82,17 @@ module.exports = function(ss, client, options, cb) {
.map(function(entry) {
switch(entry.type) {
case 'loader':
- return ss.bundler.htmlTag.js('/_serveDev/system?ts=' + client.id + '&client=' + client.name);
+ return ss.bundler.htmlTag.js('/_serveDev/system?ts=' + client.id);
case 'mod':
case 'module':
- return ss.bundler.htmlTag.js('/_serveDev/system/' + entry.file + '?ts=' + client.id + '&client=' + client.name);
+ return ss.bundler.htmlTag.js('/_serveDev/system/' + entry.file + '?ts=' + client.id);
case 'start':
- return ss.bundler.htmlTag.js('/_serveDev/start?ts=' + client.id + '&client=' + client.name);
+ return ss.bundler.htmlTag.js('/_serveDev/start?ts=' + client.id);
default:
- return ss.bundler.htmlTag.js('/_serveDev/code/' + entry.file + '?ts=' + client.id + '&client=' + client.name);
+ return ss.bundler.htmlTag.js('/_serveDev/code/' + entry.file + '?ts=' + client.id);
}
}) );
}
diff --git a/package.json b/package.json
index 5e9b8d6f..40c5b067 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"redis": "= 0.12.1",
"semver": "= 4.2.0",
"send": "0.11.0",
+ "shortid": "^2.1.3",
"uglify-js": "= 1.3.3",
"uid2": "0.0.3",
"utils-merge": "1.0.0"
From f7ed22a932437a9de8a6bc9c633dbe20c1802add Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Wed, 11 Feb 2015 21:21:03 +0100
Subject: [PATCH 44/59] feat(webpack): webpack bundler exceptions fixed
---
lib/client/bundler/webpack.js | 8 ++++----
lib/client/serve/dev.js | 5 ++---
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 67e6dd3e..3589b0a5 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -17,7 +17,7 @@ module.exports = function(webpack) {
html: assetHTML,
loader: assetLoader,
- includeSystemModule: includeSystemModule,
+ systemModule: systemModule,
js: assetJS,
worker: assetWorker,
start: assetStart,
@@ -89,7 +89,7 @@ module.exports = function(webpack) {
* @param cb
*/
function assetLoader() {
- return { type: 'loader', content: ';/* loader */' };
+ return { type: 'loader', names: [], content: ';/* loader */' };
}
/**
@@ -129,9 +129,9 @@ module.exports = function(webpack) {
* @param cb
* @returns {*}
*/
- function assetStart(cb) {
+ function assetStart() {
var output = ss.bundler.startCode(bundler.client);
- return cb(output);
+ return output;
}
/**
diff --git a/lib/client/serve/dev.js b/lib/client/serve/dev.js
index e3a306dd..6ca319c8 100644
--- a/lib/client/serve/dev.js
+++ b/lib/client/serve/dev.js
@@ -55,9 +55,8 @@ module.exports = function (ss, router, options) {
var thisUrl = url.parse(request.url),
params = qs.parse(thisUrl.query);
- ss.bundler.get(params).asset.launch(function(output) {
- return utils.serve.js(output, response);
- });
+ var start = ss.bundler.get(params).asset.start() || {};
+ return utils.serve.js(start.content || '', response);
});
// CSS
From 4999e76725519269790fde3323b1f80d8c95a1a2 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Wed, 18 Feb 2015 22:12:48 +0100
Subject: [PATCH 45/59] feat(bundler): pass system.assets to entries
---
lib/client/bundler/default.js | 73 +++++++++++++++++++++++++++++------
lib/client/bundler/index.js | 2 +-
lib/client/bundler/webpack.js | 3 +-
lib/client/view.js | 3 +-
4 files changed, 67 insertions(+), 14 deletions(-)
diff --git a/lib/client/bundler/default.js b/lib/client/bundler/default.js
index 92fe5f29..3b3ff0b9 100644
--- a/lib/client/bundler/default.js
+++ b/lib/client/bundler/default.js
@@ -16,7 +16,22 @@ function includeFlags(overrides) {
return includes;
}
+/**
+ * @typedef { name:string, path:string, content:string, options:string, type:string } AssetEntry
+ */
+
module.exports = function(ss,client,options){
+
+ /**
+ * @ngdoc service
+ * @name client.bundler:default
+ * @function
+ *
+ * @description
+ * The default bundler of HTML, CSS & JS
+ *
+ * @type {{define: define, load: load, toMinifiedCSS: toMinifiedCSS, toMinifiedJS: toMinifiedJS, asset: {entries: entries, loader: assetLoader, systemModule: systemModule, js: assetJS, worker: assetWorker, start: assetStart, css: assetCSS, html: assetHTML}}}
+ */
var bundler = {
define: define,
load: load,
@@ -51,30 +66,60 @@ module.exports = function(ss,client,options){
return ss.bundler.destsFor(client);
}
+ /**
+ *
+ * @returns {{a: string, b: string}}
+ */
function load() {
-
+ return {
+ a:'a',
+ b:'b'
+ }
}
/**
- * list of entries for an asset type relative to the client directory
+ * @ngdoc method
+ * @name client.bundler:default#entries
+ * @methodOf client.bundler:default
+ * @function
+ * @description
+ * Provides the view and the pack functions with a
+ * list of entries for an asset type relative to the client directory.
+ * The default implementation is used.
*
- * @param assetType
- * @returns {*}
+ * @param {String} assetType js/css
+ * @param {Object} systemAssets Collection of libs, modules, initCode
+ * @returns {[AssetEntry]} List of output entries
*/
- function entries(assetType) {
- return ss.bundler.entries(client, assetType);
+ function entries(assetType,systemAssets) {
+ return ss.bundler.entries(client, assetType, systemAssets);
}
+ /**
+ * @ngdoc method
+ * @name client.bundler:default#assetLoader
+ * @methodOf client.bundler:default
+ * @function
+ * @description
+ * Return entry for the JS loader depending on the includes.system client config.
+ *
+ * @returns {AssetEntry} Loader resource
+ */
function assetLoader() {
return client.includes.system? ss.bundler.systemLibs() : null;
}
/**
+ * @ngdoc method
+ * @name client.bundler:default#systemModule
+ * @methodOf client.bundler:default
+ * @function
+ * @description
+ * Return the resource for a registered system module by the given name. It uses
+ * the default wrapCode for module registration with require.
*
- * @param name
- * @param content
- * @param options
- * @returns {boolean}
+ * @param {String} name Logical Module Name
+ * @returns {AssetEntry} Module resource
*/
function systemModule(name) {
switch(name) {
@@ -122,8 +167,14 @@ module.exports = function(ss,client,options){
}
/**
+ * @ngdoc method
+ * @name client.bundler:default#assetStart
+ * @methodOf client.bundler:default
+ * @function
+ * @description
+ * Return the resource for starting the view. It is code for immediate execution at the end of the page.
*
- * @returns {*}
+ * @returns {AssetEntry} Start Script resource
*/
function assetStart() {
return client.includes.initCode? ss.bundler.startCode(client) : null;
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 9c91aa05..9202b9ec 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -243,7 +243,7 @@ module.exports = function(ss,options) {
packAssetSet: function packAssetSet(assetType, client, postProcess) {
var bundler = getBundler(client),
- filePaths = bundler.asset.entries(assetType);
+ filePaths = bundler.asset.entries(assetType,system.assets);
function writeFile(fileContents) {
var fileName = bundler.dests.paths[assetType];
diff --git a/lib/client/bundler/webpack.js b/lib/client/bundler/webpack.js
index 3589b0a5..9b027516 100644
--- a/lib/client/bundler/webpack.js
+++ b/lib/client/bundler/webpack.js
@@ -56,9 +56,10 @@ module.exports = function(webpack) {
* list of entries for an asset type relative to the client directory
*
* @param assetType
+ * @param systemAssets
* @returns {*}
*/
- function entries(assetType) {
+ function entries(assetType,systemAssets) {
return ss.bundler.entries(bundler.client, assetType);
}
diff --git a/lib/client/view.js b/lib/client/view.js
index 8953ae68..df77f2e7 100644
--- a/lib/client/view.js
+++ b/lib/client/view.js
@@ -4,6 +4,7 @@
'use strict';
var pathlib = require('path'),
+ system = require('./system'),
magicPath = require('./magic_path');
module.exports = function(ss, client, options, cb) {
@@ -78,7 +79,7 @@ module.exports = function(ss, client, options, cb) {
}
// Send Application Code
- output = output.concat( bundler.asset.entries('js')
+ output = output.concat( bundler.asset.entries('js',system.assets)
.map(function(entry) {
switch(entry.type) {
case 'loader':
From ee1dd954b083e131d160952d248ffcfbc4cc8522 Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Fri, 20 Feb 2015 22:42:10 +0100
Subject: [PATCH 46/59] feat(bundler): better systemModule
logical path/dir for system modules and libraries
optional wrap system modules
---
lib/client/bundler/index.js | 14 ++++++++++++--
lib/client/system/index.js | 4 ++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/lib/client/bundler/index.js b/lib/client/bundler/index.js
index 9202b9ec..69553a1f 100644
--- a/lib/client/bundler/index.js
+++ b/lib/client/bundler/index.js
@@ -206,13 +206,23 @@ module.exports = function(ss,options) {
};
},
- systemModule: function(name) {
+ /**
+ * @ngdoc
+ * @method
+ *
+ * @param {String} name Name of the system module to return in a descriptor
+ * @param {boolean} wrap Shall the content be wrapped in `require.define`. Default is true.
+ * @returns {{file: *, name: *, path: *, dir: *, content: (code|*), options: *, type: *}}
+ */
+ systemModule: function(name,wrap) {
var mod = system.assets.modules[name];
if (mod) {
- var code = ss.bundler.wrapModule(name, mod.content);
+ var code = wrap===false? mod.content: ss.bundler.wrapModule(name, mod.content);
return {
file: mod.name,
name: mod.name,
+ path: mod.path,
+ dir: mod.dir,
content: code,
options: mod.options,
type: mod.type
diff --git a/lib/client/system/index.js b/lib/client/system/index.js
index 0759c72f..725833ce 100644
--- a/lib/client/system/index.js
+++ b/lib/client/system/index.js
@@ -42,6 +42,8 @@ var send = exports.send = function (type, name, content, options) {
return pushUniqueAsset('libs',{
name: name,
type: type,
+ dir: pathlib.join(__dirname,'libs'),
+ path: pathlib.join(__dirname,'libs',name + '.js'),
content: content,
options: options
});
@@ -53,6 +55,8 @@ var send = exports.send = function (type, name, content, options) {
assets.modules[name] = {
name: name,
type: type,
+ dir: pathlib.join(__dirname,'modules'),
+ path: pathlib.join(__dirname,'modules',name + '.js'),
content: content,
options: options
};
From 41b515dff2d345de936574ba17dde9bcc7308dfe Mon Sep 17 00:00:00 2001
From: Henrik Vendelbo
Date: Sat, 21 Feb 2015 19:00:52 +0100
Subject: [PATCH 47/59] docs(bundler): revised documentation
---
docs/js/docs-setup.js | 108 ++++++++++++++++--
.../partials/api/bundler.default.default.html | 38 ++++++
docs/partials/api/bundler.html | 8 ++
.../partials/api/bundler.webpack.webpack.html | 21 ++++
docs/partials/api/ss.add.html | 18 +++
docs/partials/api/ss.bundler.bundler.html | 25 ++++
docs/partials/api/ss.client.client.html | 26 +++++
docs/partials/api/ss.env.html | 10 ++
docs/partials/api/ss.html | 7 ++
.../{utils.log.log.html => ss.log.log.html} | 22 ++--
docs/partials/api/ss.root.html | 13 +++
docs/partials/api/ss.version.html | 10 ++
.../tutorials/client_side_development.html | 3 +-
lib/client/bundler/default.js | 38 +++---
lib/client/bundler/index.js | 42 ++++++-
lib/client/bundler/webpack.js | 28 ++++-
lib/client/index.js | 10 ++
lib/client/system/index.js | 13 ++-
lib/socketstream.js | 38 +++++-
lib/utils/log.js | 28 ++---
.../en/client_side_development.ngdoc | 5 +-
21 files changed, 445 insertions(+), 66 deletions(-)
create mode 100644 docs/partials/api/bundler.default.default.html
create mode 100644 docs/partials/api/bundler.html
create mode 100644 docs/partials/api/bundler.webpack.webpack.html
create mode 100644 docs/partials/api/ss.add.html
create mode 100644 docs/partials/api/ss.bundler.bundler.html
create mode 100644 docs/partials/api/ss.client.client.html
create mode 100644 docs/partials/api/ss.env.html
create mode 100644 docs/partials/api/ss.html
rename docs/partials/api/{utils.log.log.html => ss.log.log.html} (54%)
create mode 100644 docs/partials/api/ss.root.html
create mode 100644 docs/partials/api/ss.version.html
diff --git a/docs/js/docs-setup.js b/docs/js/docs-setup.js
index 3655b0ae..97832ab0 100644
--- a/docs/js/docs-setup.js
+++ b/docs/js/docs-setup.js
@@ -39,7 +39,7 @@ NG_DOCS={
"type": "overview",
"moduleName": "Client-Side Development",
"shortDescription": "Client-Side Development",
- "keywords": "asset assets break browser bundle bundler caching client client-side css determine development directory entry file fly html http injected js overview path pattern relative separate separately served timestamp tutorials type url view"
+ "keywords": "amount asset assets break browser bundle bundler bundlers caching client client-side css determine development directory entry file files fly generally html http injected js overview path pattern reduce relative separate separately served timestamp tutorials type url view watch work"
},
{
"section": "tutorials",
@@ -221,6 +221,33 @@ NG_DOCS={
"shortDescription": "Custom Request Responder",
"keywords": "access action add adding additional aimed allow allowing allows annotated api apitree app appending application applications arbitrary argument arguments assigned assuming async automatically backbone basic basically best bi-directional browser build built-in bundled byte bytes calculate call callback callbacks called case channel character choice choose clicks client client-side clone code combination comfortable commas complete complex concepts config connection conscious continually control coordinate core create creating custom data default define defined desire destined develop developer developers digits directions directly documentation easier easily echo efficient ember encountered entirely errors event events exactly example experiment experimental explore extend external feature fewer files find flexibility flowing format freenode function functionally future gaming git github going groups handler handles heartbeat help hesitate high-speed http https ideas implement implementing incoming increase info inspiration interfaces internal introduction investigate invoked io irc issue javascript js json json-serialized left length libraries ll load loaded log lot low-bandwidth main message messages method middleware mode model models module modules mongodb-esq mouse movements moving namespacing node non-blocking note notice npm number numeric object objects online optional org outgoing overhead overview packet-sniff packing param1 param2 pass passed passing persistent pick pipe prepended presence process production protocol pub publish receives recommend register registerapi registering regular repl request requests responder responderid responders result rpc rpc-style runs schema second send sending sends separated sequential serialization serialize server server-side simple simply socket socketstream source ss ss-console ss-echo-responder stable stack stage started status store streaming streams string strings suite support synching takes test third-party time touch transforms transports tutorials types typical ultimate ultra ultra-simple unique unlimited user users ve versa vice view virtual ways website websocket wire world write writing zeromq"
},
+ {
+ "section": "api",
+ "id": "bundler",
+ "shortName": "bundler",
+ "type": "service",
+ "moduleName": "bundler",
+ "shortDescription": "Bundlers included.",
+ "keywords": "api bundler bundlers included service"
+ },
+ {
+ "section": "api",
+ "id": "bundler.default:default",
+ "shortName": "default",
+ "type": "service",
+ "moduleName": "bundler",
+ "shortDescription": "The default bundler of HTML, CSS & JS",
+ "keywords": "api asset assetcss assethtml assetjs assetloader assetstart assettype assetworker bundler client code collection config css default define depending directory entries entry execution functions html implementation includes initcode js libs list load loader logical method module modules output pack registered registration relative require resource return script service start starting system systemassets systemmodule tominifiedcss tominifiedjs type view worker wrapcode"
+ },
+ {
+ "section": "api",
+ "id": "bundler.webpack:webpack",
+ "shortName": "webpack",
+ "type": "service",
+ "moduleName": "bundler",
+ "shortDescription": "The webpack bundler of HTML, CSS & JS",
+ "keywords": "api asset assettype bundler client collection concept css custom demonstration directory entries functions html improved initcode js libs list method modules output pack purposes relative service systemassets type validate view webpack"
+ },
{
"section": "api",
"id": "http.index:index",
@@ -239,6 +266,76 @@ NG_DOCS={
"shortDescription": "Right now the router is simply an EventEmitter. This may change in the future",
"keywords": "allows api callback cb change clients ee eventemitter exists fall find fully function future html5 http instance mock multiple object original passed pushstate recursively req request res respond route router routing service simply single-page speed support url"
},
+ {
+ "section": "api",
+ "id": "ss",
+ "shortName": "ss",
+ "type": "overview",
+ "moduleName": "ss",
+ "shortDescription": "Internal API object which is passed to sub-modules and can be used within your app",
+ "keywords": "access add api app env exports function internal log object overview passed require root session socketstream ss string sub-modules var"
+ },
+ {
+ "section": "api",
+ "id": "ss.add",
+ "shortName": "ss.add",
+ "type": "function",
+ "moduleName": "ss",
+ "shortDescription": "Call from your app to safely extend the 'ss' internal API object passed through to your /server code",
+ "keywords": "add api app call code extend fn function internal key object passed safely ss"
+ },
+ {
+ "section": "api",
+ "id": "ss.bundler:bundler",
+ "shortName": "bundler",
+ "type": "service",
+ "moduleName": "ss",
+ "shortDescription": "Client bundling API",
+ "keywords": "api bundler bundling client content custom default define describe descriptor entry implementing libraries method module require return service single ss system systemlibs systemmodule true wrap wrapped"
+ },
+ {
+ "section": "api",
+ "id": "ss.client:client",
+ "shortName": "client",
+ "type": "service",
+ "moduleName": "ss",
+ "shortDescription": "Client serving, bundling, development, building.",
+ "keywords": "add allow allows api assets building bundling client clients code coffee compress content css defined development file flags format function html js lib library libs module options production require send served service serving single ss system type"
+ },
+ {
+ "section": "api",
+ "id": "ss.env",
+ "shortName": "ss.env",
+ "type": "property",
+ "moduleName": "ss",
+ "keywords": "api change default development env environment execution node_env property set ss ss_env type variable"
+ },
+ {
+ "section": "api",
+ "id": "ss.log:log",
+ "shortName": "log",
+ "type": "service",
+ "moduleName": "ss",
+ "shortDescription": "Contains method stubs for logging to console (by default) or",
+ "keywords": "api assigning choose console debug default error fairly function happened info informed keeping level log logging method override parameters provider require service socketstream ss stubs sysadmin takes time trivial unexpected var wakeup warn winston"
+ },
+ {
+ "section": "api",
+ "id": "ss.root",
+ "shortName": "ss.root",
+ "type": "property",
+ "moduleName": "ss",
+ "shortDescription": "By default the project root is the current working directory",
+ "keywords": "api current default directory project property root ss working"
+ },
+ {
+ "section": "api",
+ "id": "ss.version",
+ "shortName": "ss.version",
+ "type": "property",
+ "moduleName": "ss",
+ "keywords": "api major minor property ss version"
+ },
{
"section": "api",
"id": "utils",
@@ -257,15 +354,6 @@ NG_DOCS={
"shortDescription": "This is used to maintain lists of userIds to socketIds and channelIds to socketIds",
"keywords": "absolute adapted api array basename basepath channelids contents css dir directory dorectory eror extension file filepath files find findextforbase findextforbasepath github givven https isdir jade json lists loadpackagejson loads lookup maintain matching mode null object package parse path readdirsync reads returns root service socketids socketstream start synchronous thorws true unable userids utils views"
},
- {
- "section": "api",
- "id": "utils.log:log",
- "shortName": "log",
- "type": "service",
- "moduleName": "utils",
- "shortDescription": "Contains method stubs for logging to console (by default) or",
- "keywords": "api assigning choose console debug default error fairly function happened info informed keeping level log logging method override parameters provider require service socketstream ss stubs sysadmin takes time trivial unexpected utils var wakeup warn winston"
- },
{
"section": "api",
"id": "utils.misc:misc",
diff --git a/docs/partials/api/bundler.default.default.html b/docs/partials/api/bundler.default.default.html
new file mode 100644
index 00000000..da34af5e
--- /dev/null
+++ b/docs/partials/api/bundler.default.default.html
@@ -0,0 +1,38 @@
+
default
+
service in module bundler
+
+
+
+
Description
+
The default bundler of HTML, CSS & JS
+
+
Methods
+
assetLoader()
+
Return entry for the JS loader depending on the includes.system client config.
Provides the view and the pack functions with a
+list of entries for an asset type relative to the client directory.
+The default implementation is used.