@ -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 ( plugin s Scripts) ;
var scripts = Meta . js . scripts . base . concat ( plugin Scripts) ;
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 ( ) ;
} ;
} ;