|
|
|
@ -1,136 +1,128 @@
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
var winston = require('winston');
|
|
|
|
|
var fork = require('child_process').fork;
|
|
|
|
|
var path = require('path');
|
|
|
|
|
var async = require('async');
|
|
|
|
|
var fs = require('fs');
|
|
|
|
|
var mkdirp = require('mkdirp');
|
|
|
|
|
var rimraf = require('rimraf');
|
|
|
|
|
var uglifyjs = require('uglify-js');
|
|
|
|
|
|
|
|
|
|
var file = require('../file');
|
|
|
|
|
var plugins = require('../plugins');
|
|
|
|
|
|
|
|
|
|
var minifierPath = path.join(__dirname, 'minifier.js');
|
|
|
|
|
var minifier = require('./minifier');
|
|
|
|
|
|
|
|
|
|
module.exports = function (Meta) {
|
|
|
|
|
Meta.js = {
|
|
|
|
|
target: {},
|
|
|
|
|
scripts: {
|
|
|
|
|
base: [
|
|
|
|
|
'node_modules/jquery/dist/jquery.js',
|
|
|
|
|
'node_modules/socket.io-client/dist/socket.io.js',
|
|
|
|
|
'public/vendor/jquery/timeago/jquery.timeago.js',
|
|
|
|
|
'public/vendor/jquery/js/jquery.form.min.js',
|
|
|
|
|
'public/vendor/visibility/visibility.min.js',
|
|
|
|
|
'node_modules/bootstrap/dist/js/bootstrap.js',
|
|
|
|
|
'public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.min.js',
|
|
|
|
|
'public/vendor/jquery/textcomplete/jquery.textcomplete.js',
|
|
|
|
|
'public/vendor/requirejs/require.js',
|
|
|
|
|
'public/src/require-config.js',
|
|
|
|
|
'public/vendor/bootbox/bootbox.js',
|
|
|
|
|
'public/vendor/bootbox/wrapper.js',
|
|
|
|
|
'public/vendor/tinycon/tinycon.js',
|
|
|
|
|
'public/vendor/xregexp/xregexp.js',
|
|
|
|
|
'public/vendor/xregexp/unicode/unicode-base.js',
|
|
|
|
|
'node_modules/templates.js/lib/templates.js',
|
|
|
|
|
'public/src/utils.js',
|
|
|
|
|
'public/src/sockets.js',
|
|
|
|
|
'public/src/app.js',
|
|
|
|
|
'public/src/ajaxify.js',
|
|
|
|
|
'public/src/overrides.js',
|
|
|
|
|
'public/src/widgets.js',
|
|
|
|
|
'node_modules/promise-polyfill/promise.js',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// files listed below are only available client-side, or are bundled in to reduce # of network requests on cold load
|
|
|
|
|
rjs: [
|
|
|
|
|
'public/src/client/footer.js',
|
|
|
|
|
'public/src/client/chats.js',
|
|
|
|
|
'public/src/client/infinitescroll.js',
|
|
|
|
|
'public/src/client/pagination.js',
|
|
|
|
|
'public/src/client/recent.js',
|
|
|
|
|
'public/src/client/unread.js',
|
|
|
|
|
'public/src/client/topic.js',
|
|
|
|
|
'public/src/client/topic/events.js',
|
|
|
|
|
'public/src/client/topic/fork.js',
|
|
|
|
|
'public/src/client/topic/move.js',
|
|
|
|
|
'public/src/client/topic/posts.js',
|
|
|
|
|
'public/src/client/topic/images.js',
|
|
|
|
|
'public/src/client/topic/postTools.js',
|
|
|
|
|
'public/src/client/topic/threadTools.js',
|
|
|
|
|
'public/src/client/categories.js',
|
|
|
|
|
'public/src/client/category.js',
|
|
|
|
|
'public/src/client/category/tools.js',
|
|
|
|
|
|
|
|
|
|
'public/src/modules/translator.js',
|
|
|
|
|
'public/src/modules/notifications.js',
|
|
|
|
|
'public/src/modules/chat.js',
|
|
|
|
|
'public/src/modules/components.js',
|
|
|
|
|
'public/src/modules/sort.js',
|
|
|
|
|
'public/src/modules/navigator.js',
|
|
|
|
|
'public/src/modules/topicSelect.js',
|
|
|
|
|
'public/src/modules/share.js',
|
|
|
|
|
'public/src/modules/search.js',
|
|
|
|
|
'public/src/modules/alerts.js',
|
|
|
|
|
'public/src/modules/taskbar.js',
|
|
|
|
|
'public/src/modules/helpers.js',
|
|
|
|
|
'public/src/modules/string.js',
|
|
|
|
|
'public/src/modules/flags.js',
|
|
|
|
|
'public/src/modules/storage.js',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// modules listed below are built (/src/modules) so they can be defined anonymously
|
|
|
|
|
modules: {
|
|
|
|
|
'Chart.js': 'node_modules/chart.js/dist/Chart.min.js',
|
|
|
|
|
'mousetrap.js': 'node_modules/mousetrap/mousetrap.min.js',
|
|
|
|
|
'cropper.js': 'node_modules/cropperjs/dist/cropper.min.js',
|
|
|
|
|
'jqueryui.js': 'public/vendor/jquery/js/jquery-ui.js',
|
|
|
|
|
'zxcvbn.js': 'node_modules/zxcvbn/dist/zxcvbn.js',
|
|
|
|
|
ace: 'node_modules/ace-builds/src-min',
|
|
|
|
|
},
|
|
|
|
|
Meta.js = {};
|
|
|
|
|
|
|
|
|
|
Meta.js.scripts = {
|
|
|
|
|
base: [
|
|
|
|
|
'node_modules/jquery/dist/jquery.js',
|
|
|
|
|
'node_modules/socket.io-client/dist/socket.io.js',
|
|
|
|
|
'public/vendor/jquery/timeago/jquery.timeago.js',
|
|
|
|
|
'public/vendor/jquery/js/jquery.form.min.js',
|
|
|
|
|
'public/vendor/visibility/visibility.min.js',
|
|
|
|
|
'node_modules/bootstrap/dist/js/bootstrap.js',
|
|
|
|
|
'public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.min.js',
|
|
|
|
|
'public/vendor/jquery/textcomplete/jquery.textcomplete.js',
|
|
|
|
|
'public/vendor/requirejs/require.js',
|
|
|
|
|
'public/src/require-config.js',
|
|
|
|
|
'public/vendor/bootbox/bootbox.js',
|
|
|
|
|
'public/vendor/bootbox/wrapper.js',
|
|
|
|
|
'public/vendor/tinycon/tinycon.js',
|
|
|
|
|
'public/vendor/xregexp/xregexp.js',
|
|
|
|
|
'public/vendor/xregexp/unicode/unicode-base.js',
|
|
|
|
|
'node_modules/templates.js/lib/templates.js',
|
|
|
|
|
'public/src/utils.js',
|
|
|
|
|
'public/src/sockets.js',
|
|
|
|
|
'public/src/app.js',
|
|
|
|
|
'public/src/ajaxify.js',
|
|
|
|
|
'public/src/overrides.js',
|
|
|
|
|
'public/src/widgets.js',
|
|
|
|
|
'node_modules/promise-polyfill/promise.js',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// files listed below are only available client-side, or are bundled in to reduce # of network requests on cold load
|
|
|
|
|
rjs: [
|
|
|
|
|
'public/src/client/footer.js',
|
|
|
|
|
'public/src/client/chats.js',
|
|
|
|
|
'public/src/client/infinitescroll.js',
|
|
|
|
|
'public/src/client/pagination.js',
|
|
|
|
|
'public/src/client/recent.js',
|
|
|
|
|
'public/src/client/unread.js',
|
|
|
|
|
'public/src/client/topic.js',
|
|
|
|
|
'public/src/client/topic/events.js',
|
|
|
|
|
'public/src/client/topic/fork.js',
|
|
|
|
|
'public/src/client/topic/move.js',
|
|
|
|
|
'public/src/client/topic/posts.js',
|
|
|
|
|
'public/src/client/topic/images.js',
|
|
|
|
|
'public/src/client/topic/postTools.js',
|
|
|
|
|
'public/src/client/topic/threadTools.js',
|
|
|
|
|
'public/src/client/categories.js',
|
|
|
|
|
'public/src/client/category.js',
|
|
|
|
|
'public/src/client/category/tools.js',
|
|
|
|
|
|
|
|
|
|
'public/src/modules/translator.js',
|
|
|
|
|
'public/src/modules/notifications.js',
|
|
|
|
|
'public/src/modules/chat.js',
|
|
|
|
|
'public/src/modules/components.js',
|
|
|
|
|
'public/src/modules/sort.js',
|
|
|
|
|
'public/src/modules/navigator.js',
|
|
|
|
|
'public/src/modules/topicSelect.js',
|
|
|
|
|
'public/src/modules/share.js',
|
|
|
|
|
'public/src/modules/search.js',
|
|
|
|
|
'public/src/modules/alerts.js',
|
|
|
|
|
'public/src/modules/taskbar.js',
|
|
|
|
|
'public/src/modules/helpers.js',
|
|
|
|
|
'public/src/modules/string.js',
|
|
|
|
|
'public/src/modules/flags.js',
|
|
|
|
|
'public/src/modules/storage.js',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// modules listed below are built (/src/modules) so they can be defined anonymously
|
|
|
|
|
modules: {
|
|
|
|
|
'Chart.js': 'node_modules/chart.js/dist/Chart.min.js',
|
|
|
|
|
'mousetrap.js': 'node_modules/mousetrap/mousetrap.min.js',
|
|
|
|
|
'cropper.js': 'node_modules/cropperjs/dist/cropper.min.js',
|
|
|
|
|
'jqueryui.js': 'public/vendor/jquery/js/jquery-ui.js',
|
|
|
|
|
'zxcvbn.js': 'node_modules/zxcvbn/dist/zxcvbn.js',
|
|
|
|
|
ace: 'node_modules/ace-builds/src-min',
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function minifyModules(modules, callback) {
|
|
|
|
|
function minifyModules(modules, fork, callback) {
|
|
|
|
|
// for it to never fork
|
|
|
|
|
// otherwise it spawns way too many processes
|
|
|
|
|
// maybe eventually we can pool modules
|
|
|
|
|
// and pass the pools to the minifer
|
|
|
|
|
// to reduce the total number of threads
|
|
|
|
|
fork = false;
|
|
|
|
|
|
|
|
|
|
async.eachLimit(modules, 500, function (mod, next) {
|
|
|
|
|
var srcPath = mod.srcPath;
|
|
|
|
|
var destPath = mod.destPath;
|
|
|
|
|
var minified;
|
|
|
|
|
|
|
|
|
|
async.parallel([
|
|
|
|
|
function (cb) {
|
|
|
|
|
async.parallel({
|
|
|
|
|
dirped: function (cb) {
|
|
|
|
|
mkdirp(path.dirname(destPath), cb);
|
|
|
|
|
},
|
|
|
|
|
function (cb) {
|
|
|
|
|
minified: function (cb) {
|
|
|
|
|
fs.readFile(srcPath, function (err, buffer) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return cb(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (srcPath.endsWith('.min.js') || path.dirname(srcPath).endsWith('min')) {
|
|
|
|
|
minified = { code: buffer.toString() };
|
|
|
|
|
return cb();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
minified = uglifyjs.minify(buffer.toString(), {
|
|
|
|
|
fromString: true,
|
|
|
|
|
compress: false,
|
|
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
return cb(e);
|
|
|
|
|
return cb(null, { code: buffer.toString() });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cb();
|
|
|
|
|
minifier.js.minify(buffer.toString(), fork, cb);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
], function (err) {
|
|
|
|
|
}, function (err, results) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return next(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var minified = results.minified;
|
|
|
|
|
fs.writeFile(destPath, minified.code, next);
|
|
|
|
|
});
|
|
|
|
|
}, callback);
|
|
|
|
@ -233,7 +225,7 @@ module.exports = function (Meta) {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Meta.js.buildModules = function (callback) {
|
|
|
|
|
Meta.js.buildModules = function (fork, callback) {
|
|
|
|
|
async.waterfall([
|
|
|
|
|
clearModules,
|
|
|
|
|
function (next) {
|
|
|
|
@ -244,7 +236,7 @@ module.exports = function (Meta) {
|
|
|
|
|
getModuleList(next);
|
|
|
|
|
},
|
|
|
|
|
function (modules, next) {
|
|
|
|
|
minifyModules(modules, next);
|
|
|
|
|
minifyModules(modules, fork, next);
|
|
|
|
|
},
|
|
|
|
|
], callback);
|
|
|
|
|
};
|
|
|
|
@ -269,52 +261,13 @@ module.exports = function (Meta) {
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Meta.js.minify = function (target, callback) {
|
|
|
|
|
winston.verbose('[meta/js] Minifying ' + target);
|
|
|
|
|
|
|
|
|
|
var forkProcessParams = setupDebugging();
|
|
|
|
|
var minifier = fork(minifierPath, [], forkProcessParams);
|
|
|
|
|
Meta.js.minifierProc = minifier;
|
|
|
|
|
|
|
|
|
|
Meta.js.target[target] = {};
|
|
|
|
|
|
|
|
|
|
Meta.js.prepare(target, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
|
return callback(err);
|
|
|
|
|
}
|
|
|
|
|
minifier.send({
|
|
|
|
|
action: 'js',
|
|
|
|
|
minify: global.env !== 'development',
|
|
|
|
|
scripts: Meta.js.target[target].scripts,
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
minifier.on('message', function (message) {
|
|
|
|
|
switch (message.type) {
|
|
|
|
|
case 'end':
|
|
|
|
|
Meta.js.target[target].cache = message.minified;
|
|
|
|
|
Meta.js.target[target].map = message.sourceMap;
|
|
|
|
|
winston.verbose('[meta/js] ' + target + ' minification complete');
|
|
|
|
|
minifier.kill();
|
|
|
|
|
|
|
|
|
|
Meta.js.commitToFile(target, callback);
|
|
|
|
|
break;
|
|
|
|
|
case 'error':
|
|
|
|
|
winston.error('[meta/js] Could not compile ' + target + ': ' + message.message);
|
|
|
|
|
minifier.kill();
|
|
|
|
|
|
|
|
|
|
callback(new Error(message.message));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Meta.js.prepare = function (target, callback) {
|
|
|
|
|
var pluginsScripts = [];
|
|
|
|
|
|
|
|
|
|
function getBundleScriptList(target, callback) {
|
|
|
|
|
var pluginDirectories = [];
|
|
|
|
|
|
|
|
|
|
pluginsScripts = plugins[target === 'nodebb.min.js' ? 'clientScripts' : 'acpScripts'].filter(function (path) {
|
|
|
|
|
if (target === 'admin') {
|
|
|
|
|
target = 'acp';
|
|
|
|
|
}
|
|
|
|
|
var pluginScripts = plugins[target + 'Scripts'].filter(function (path) {
|
|
|
|
|
if (path.endsWith('.js')) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -325,8 +278,12 @@ module.exports = function (Meta) {
|
|
|
|
|
|
|
|
|
|
async.each(pluginDirectories, function (directory, next) {
|
|
|
|
|
file.walk(directory, function (err, scripts) {
|
|
|
|
|
pluginsScripts = pluginsScripts.concat(scripts);
|
|
|
|
|
next(err);
|
|
|
|
|
if (err) {
|
|
|
|
|
return next(err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pluginScripts = pluginScripts.concat(scripts);
|
|
|
|
|
next();
|
|
|
|
|
});
|
|
|
|
|
}, function (err) {
|
|
|
|
|
if (err) {
|
|
|
|
@ -335,52 +292,43 @@ module.exports = function (Meta) {
|
|
|
|
|
|
|
|
|
|
var basePath = path.resolve(__dirname, '../..');
|
|
|
|
|
|
|
|
|
|
Meta.js.target[target].scripts = Meta.js.scripts.base.concat(pluginsScripts);
|
|
|
|
|
var scripts = Meta.js.scripts.base.concat(pluginScripts);
|
|
|
|
|
|
|
|
|
|
if (target === 'nodebb.min.js') {
|
|
|
|
|
Meta.js.target[target].scripts = Meta.js.target[target].scripts.concat(Meta.js.scripts.rjs);
|
|
|
|
|
if (target === 'client' && global.env !== 'development') {
|
|
|
|
|
scripts = scripts.concat(Meta.js.scripts.rjs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Meta.js.target[target].scripts = Meta.js.target[target].scripts.map(function (script) {
|
|
|
|
|
scripts = scripts.map(function (script) {
|
|
|
|
|
return path.resolve(basePath, script).replace(/\\/g, '/');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
callback();
|
|
|
|
|
callback(null, scripts);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Meta.js.killMinifier = function () {
|
|
|
|
|
if (Meta.js.minifierProc) {
|
|
|
|
|
Meta.js.minifierProc.kill('SIGTERM');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
Meta.js.buildBundle = function (target, fork, callback) {
|
|
|
|
|
var fileNames = {
|
|
|
|
|
client: 'nodebb.min.js',
|
|
|
|
|
admin: 'acp.min.js',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Meta.js.commitToFile = function (target, callback) {
|
|
|
|
|
fs.writeFile(path.join(__dirname, '../../build/public', target), Meta.js.target[target].cache, function (err) {
|
|
|
|
|
callback(err);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
async.waterfall([
|
|
|
|
|
function (next) {
|
|
|
|
|
getBundleScriptList(target, next);
|
|
|
|
|
},
|
|
|
|
|
function (files, next) {
|
|
|
|
|
var minify = global.env !== 'development';
|
|
|
|
|
|
|
|
|
|
function setupDebugging() {
|
|
|
|
|
/**
|
|
|
|
|
* Check if the parent process is running with the debug option --debug (or --debug-brk)
|
|
|
|
|
*/
|
|
|
|
|
var forkProcessParams = {};
|
|
|
|
|
if (global.v8debug || parseInt(process.execArgv.indexOf('--debug'), 10) !== -1) {
|
|
|
|
|
/**
|
|
|
|
|
* use the line below if you want to debug minifier.js script too (or even --debug-brk option, but
|
|
|
|
|
* you'll have to setup your debugger and connect to the forked process)
|
|
|
|
|
*/
|
|
|
|
|
// forkProcessParams = {execArgv: ['--debug=' + (global.process.debugPort + 1), '--nolazy']};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* otherwise, just clean up --debug/--debug-brk options which are set up by default from the parent one
|
|
|
|
|
*/
|
|
|
|
|
forkProcessParams = {
|
|
|
|
|
execArgv: [],
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
minifier.js.bundle(files, minify, fork, next);
|
|
|
|
|
},
|
|
|
|
|
function (bundle, next) {
|
|
|
|
|
var filePath = path.join(__dirname, '../../build/public', fileNames[target]);
|
|
|
|
|
fs.writeFile(filePath, bundle.code, next);
|
|
|
|
|
},
|
|
|
|
|
], callback);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return forkProcessParams;
|
|
|
|
|
}
|
|
|
|
|
Meta.js.killMinifier = function () {
|
|
|
|
|
minifier.killAll();
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|