mirror of
				https://github.com/NodeBB/NodeBB.git
				synced 2025-10-31 19:15:58 +01:00 
			
		
		
		
	Build pipeline improvements
- Refactor meta/css - `fs.link` usage consolidated to `file.link` - rimraf built modules directory to fix error - Remove `local-assets` flag
This commit is contained in:
		
							
								
								
									
										10
									
								
								build.js
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								build.js
									
									
									
									
									
								
							| @@ -46,7 +46,11 @@ exports.buildTargets = function (targets, callback) { | ||||
| 	var meta = require('./src/meta'); | ||||
| 	buildStart = buildStart || Date.now(); | ||||
|  | ||||
| 	var step = function (startTime, target, next) { | ||||
| 	var step = function (startTime, target, next, err) { | ||||
| 		if (err) { | ||||
| 			winston.error('Build failed: ' + err.message); | ||||
| 			process.exit(1); | ||||
| 		} | ||||
| 		winston.info('[build] ' + target + ' => Completed in ' + ((Date.now() - startTime) / 1000) + 's'); | ||||
| 		next(); | ||||
| 	}; | ||||
| @@ -75,13 +79,13 @@ exports.buildTargets = function (targets, callback) { | ||||
| 					case 'clientCSS': | ||||
| 						winston.info('[build] Building client-side CSS'); | ||||
| 						startTime = Date.now(); | ||||
| 						meta.css.minify('stylesheet.css', step.bind(this, startTime, target, next)); | ||||
| 						meta.css.minify('client', step.bind(this, startTime, target, next)); | ||||
| 						break; | ||||
|  | ||||
| 					case 'acpCSS': | ||||
| 						winston.info('[build] Building admin control panel CSS'); | ||||
| 						startTime = Date.now(); | ||||
| 						meta.css.minify('admin.css', step.bind(this, startTime, target, next)); | ||||
| 						meta.css.minify('admin', step.bind(this, startTime, target, next)); | ||||
| 						break; | ||||
|  | ||||
| 					case 'tpl': | ||||
|   | ||||
| @@ -108,11 +108,7 @@ uploadsController.uploadSound = function (req, res, next) { | ||||
| 		var	soundsPath = path.join(__dirname, '../../../build/public/sounds'), | ||||
| 			filePath = path.join(__dirname, '../../../public/uploads/sounds', uploadedFile.name); | ||||
|  | ||||
| 		if (process.platform === 'win32') { | ||||
| 			fs.link(filePath, path.join(soundsPath, path.basename(filePath))); | ||||
| 		} else { | ||||
| 			fs.symlink(filePath, path.join(soundsPath, path.basename(filePath)), 'file'); | ||||
| 		} | ||||
| 		file.link(filePath, path.join(soundsPath, path.basename(filePath))); | ||||
|  | ||||
| 		fs.unlink(uploadedFile.path, function (err) { | ||||
| 			if (err) { | ||||
|   | ||||
| @@ -102,4 +102,12 @@ file.existsSync = function (path) { | ||||
| 	return !!exists; | ||||
| }; | ||||
|  | ||||
| file.link = function link(filePath, destPath, cb) { | ||||
| 	if (process.platform === 'win32') { | ||||
| 		fs.link(filePath, destPath, cb); | ||||
| 	} else { | ||||
| 		fs.symlink(filePath, destPath, 'file', cb); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| module.exports = file; | ||||
|   | ||||
| @@ -18,8 +18,32 @@ var utils = require('../../public/src/utils'); | ||||
| module.exports = function (Meta) { | ||||
|  | ||||
| 	Meta.css = {}; | ||||
| 	Meta.css.cache = undefined; | ||||
| 	Meta.css.acpCache = undefined; | ||||
|  | ||||
| 	var buildImports = { | ||||
| 		client: function (source) { | ||||
| 			return '@import "./theme";\n' + source + '\n' + [ | ||||
| 				'@import "font-awesome";', | ||||
| 				'@import (inline) "../../public/vendor/jquery/css/smoothness/jquery-ui.css";', | ||||
| 				'@import (inline) "../../public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";', | ||||
| 				'@import (inline) "..' + path.sep + 'public/vendor/colorpicker/colorpicker.css";', | ||||
| 				'@import "../../public/less/flags.less";', | ||||
| 				'@import "../../public/less/blacklist.less";', | ||||
| 				'@import "../../public/less/generics.less";', | ||||
| 				'@import "../../public/less/mixins.less";', | ||||
| 				'@import "../../public/less/global.less";', | ||||
| 			].map(function (str) { return str.replace(/\//g, path.sep); }).join('\n'); | ||||
| 		}, | ||||
| 		admin: function (source) { | ||||
| 			return source + '\n' + [ | ||||
| 				'@import "font-awesome";', | ||||
| 				'@import "../public/less/admin/admin";', | ||||
| 				'@import "../public/less/generics.less";', | ||||
| 				'@import (inline) "../public/vendor/colorpicker/colorpicker.css";', | ||||
| 				'@import (inline) "../public/vendor/jquery/css/smoothness/jquery-ui.css";', | ||||
| 				'@import (inline) "../public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";', | ||||
| 			].map(function (str) { return str.replace(/\//g, path.sep); }).join('\n'); | ||||
| 		}, | ||||
| 	}; | ||||
|  | ||||
| 	Meta.css.minify = function (target, callback) { | ||||
| 		callback = callback || function () {}; | ||||
| @@ -30,25 +54,25 @@ module.exports = function (Meta) { | ||||
| 				return callback(err); | ||||
| 			} | ||||
|  | ||||
| 			var themeId = (themeData['theme:id'] || 'nodebb-theme-persona'), | ||||
| 				baseThemePath = path.join(nconf.get('themes_path'), (themeData['theme:type'] && themeData['theme:type'] === 'local' ? themeId : 'nodebb-theme-vanilla')), | ||||
| 				paths = [ | ||||
| 			var themeId = (themeData['theme:id'] || 'nodebb-theme-persona'); | ||||
| 			var baseThemePath = path.join(nconf.get('themes_path'), (themeData['theme:type'] && themeData['theme:type'] === 'local' ? themeId : 'nodebb-theme-vanilla')); | ||||
| 			var paths = [ | ||||
| 				baseThemePath, | ||||
| 				path.join(__dirname, '../../node_modules'), | ||||
| 				path.join(__dirname, '../../public/vendor/fontawesome/less') | ||||
| 				], | ||||
| 				source = '@import "font-awesome";'; | ||||
| 			]; | ||||
| 			var source = ''; | ||||
|  | ||||
| 			plugins.lessFiles = filterMissingFiles(plugins.lessFiles); | ||||
| 			plugins.cssFiles = filterMissingFiles(plugins.cssFiles); | ||||
| 			var lessFiles = filterMissingFiles(plugins.lessFiles); | ||||
| 			var cssFiles = filterMissingFiles(plugins.cssFiles); | ||||
|  | ||||
| 			async.waterfall([ | ||||
| 				function (next) { | ||||
| 					getStyleSource(plugins.cssFiles, '\n@import (inline) ".', '.css', next); | ||||
| 					getStyleSource(cssFiles, '\n@import (inline) ".', '.css', next); | ||||
| 				}, | ||||
| 				function (src, next) { | ||||
| 					source += src; | ||||
| 					getStyleSource(plugins.lessFiles, '\n@import ".', '.less', next); | ||||
| 					getStyleSource(lessFiles, '\n@import ".', '.less', next); | ||||
| 				}, | ||||
| 				function (src, next) { | ||||
| 					source += src; | ||||
| @@ -59,29 +83,7 @@ module.exports = function (Meta) { | ||||
| 					return callback(err); | ||||
| 				} | ||||
|  | ||||
| 				var acpSource = source; | ||||
|  | ||||
| 				if (target !== 'admin.css') { | ||||
| 					source += '\n@import (inline) "..' + path.sep + '..' + path.sep + 'public/vendor/jquery/css/smoothness/jquery-ui.css";'; | ||||
| 					source += '\n@import (inline) "..' + path.sep + '..' + path.sep + 'public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";'; | ||||
| 					source += '\n@import (inline) "..' + path.sep + 'public/vendor/colorpicker/colorpicker.css";'; | ||||
| 					source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/flags.less";'; | ||||
| 					source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/blacklist.less";'; | ||||
| 					source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/generics.less";'; | ||||
| 					source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/mixins.less";'; | ||||
| 					source += '\n@import "..' + path.sep + '..' + path.sep + 'public/less/global.less";'; | ||||
| 					source = '@import "./theme";\n' + source; | ||||
|  | ||||
| 					minify(source, paths, 'cache', callback); | ||||
| 				} else { | ||||
| 					acpSource += '\n@import "..' + path.sep + 'public/less/admin/admin";\n'; | ||||
| 					acpSource += '\n@import "..' + path.sep + 'public/less/generics.less";\n'; | ||||
| 					acpSource += '\n@import (inline) "..' + path.sep + 'public/vendor/colorpicker/colorpicker.css";\n'; | ||||
| 					acpSource += '\n@import (inline) "..' + path.sep + 'public/vendor/jquery/css/smoothness/jquery-ui.css";'; | ||||
| 					acpSource += '\n@import (inline) "..' + path.sep + 'public/vendor/jquery/bootstrap-tagsinput/bootstrap-tagsinput.css";'; | ||||
|  | ||||
| 					minify(acpSource, paths, 'acpCache', callback); | ||||
| 				} | ||||
| 				minify(buildImports[target](source), paths, target, callback); | ||||
| 			}); | ||||
| 		}); | ||||
| 	}; | ||||
| @@ -115,22 +117,22 @@ module.exports = function (Meta) { | ||||
| 		}); | ||||
| 	} | ||||
|  | ||||
| 	Meta.css.commitToFile = function (filename, callback) { | ||||
| 		var file = (filename === 'acpCache' ? 'admin' : 'stylesheet') + '.css'; | ||||
| 	Meta.css.commitToFile = function (target, source, callback) { | ||||
| 		var filename = (target === 'client' ? 'stylesheet' : 'admin') + '.css'; | ||||
|  | ||||
| 		fs.writeFile(path.join(__dirname, '../../build/public/' + file), Meta.css[filename], function (err) { | ||||
| 		fs.writeFile(path.join(__dirname, '../../build/public/' + filename), source, function (err) { | ||||
| 			if (!err) { | ||||
| 				winston.verbose('[meta/css] ' + file + ' committed to disk.'); | ||||
| 				winston.verbose('[meta/css] ' + target + ' CSS committed to disk.'); | ||||
| 			} else { | ||||
| 				winston.error('[meta/css] ' + err.message); | ||||
| 				process.exit(0); | ||||
| 				process.exit(1); | ||||
| 			} | ||||
|  | ||||
| 			callback(); | ||||
| 		}); | ||||
| 	}; | ||||
|  | ||||
| 	function minify(source, paths, destination, callback) { | ||||
| 	function minify(source, paths, target, callback) { | ||||
| 		callback = callback || function () {}; | ||||
| 		less.render(source, { | ||||
| 			paths: paths | ||||
| @@ -140,20 +142,14 @@ module.exports = function (Meta) { | ||||
| 				return callback(err); | ||||
| 			} | ||||
|  | ||||
| 			postcss([ autoprefixer, clean() ]).process(lessOutput.css).then(function (result) { | ||||
| 			postcss(global.env === 'development' ? [ autoprefixer ] : [ autoprefixer, clean() ]).process(lessOutput.css).then(function (result) { | ||||
| 				result.warnings().forEach(function (warn) { | ||||
| 					winston.verbose(warn.toString()); | ||||
| 				}); | ||||
| 				Meta.css[destination] = result.css; | ||||
|  | ||||
| 				// Save the compiled CSS in public/ so things like nginx can serve it | ||||
| 				if (nconf.get('local-assets') === undefined || nconf.get('local-assets') !== false) { | ||||
| 					return Meta.css.commitToFile(destination, function () { | ||||
| 				return Meta.css.commitToFile(target, result.css, function () { | ||||
| 					callback(null, result.css); | ||||
| 				}); | ||||
| 				} | ||||
|  | ||||
| 				callback(null, result.css); | ||||
| 			}); | ||||
| 		}); | ||||
| 	} | ||||
|   | ||||
| @@ -4,9 +4,11 @@ var winston = require('winston'); | ||||
| var fork = require('child_process').fork; | ||||
| var path = require('path'); | ||||
| var async = require('async'); | ||||
| var nconf = require('nconf'); | ||||
| var fs = require('fs'); | ||||
| var mkdirp = require('mkdirp'); | ||||
| var rimraf = require('rimraf'); | ||||
|  | ||||
| var file = require('../file'); | ||||
| var plugins = require('../plugins'); | ||||
| var utils = require('../../public/src/utils'); | ||||
|  | ||||
| @@ -88,19 +90,10 @@ module.exports = function (Meta) { | ||||
| 	}; | ||||
| 	 | ||||
| 	Meta.js.linkModules = function (callback) { | ||||
| 		function link(filePath, destPath, cb) { | ||||
| 			if (process.platform === 'win32') { | ||||
| 				fs.link(filePath, destPath, cb); | ||||
| 			} else { | ||||
| 				fs.symlink(filePath, destPath, 'file', cb); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		plugins.reload(function (err) { | ||||
| 		rimraf(path.join(__dirname, '../../build/public/src/modules'), function (err) { | ||||
| 			if (err) { | ||||
| 				return callback(err); | ||||
| 			} | ||||
| 			 | ||||
| 			async.each(Object.keys(Meta.js.scripts.modules), function (relPath, next) { | ||||
| 				var filePath = path.join(__dirname, '../../', Meta.js.scripts.modules[relPath]); | ||||
| 				var destPath = path.join(__dirname, '../../build/public/src/modules', relPath); | ||||
| @@ -110,7 +103,7 @@ module.exports = function (Meta) { | ||||
| 						return next(err); | ||||
| 					} | ||||
|  | ||||
| 					link(filePath, destPath, next); | ||||
| 					file.link(filePath, destPath, next); | ||||
| 				}); | ||||
| 			}, callback); | ||||
| 		}); | ||||
| @@ -143,12 +136,7 @@ module.exports = function (Meta) { | ||||
| 				winston.verbose('[meta/js] ' + target + ' minification complete'); | ||||
| 				minifier.kill(); | ||||
|  | ||||
| 				if (nconf.get('local-assets') === undefined || nconf.get('local-assets') !== false) { | ||||
| 					return Meta.js.commitToFile(target, callback); | ||||
| 				} else { | ||||
| 					return callback(); | ||||
| 				} | ||||
|  | ||||
| 				Meta.js.commitToFile(target, callback); | ||||
| 				break; | ||||
| 			case 'error': | ||||
| 				winston.error('[meta/js] Could not compile ' + target + ': ' + message.message); | ||||
|   | ||||
| @@ -8,6 +8,7 @@ var rimraf = require('rimraf'); | ||||
| var mkdirp = require('mkdirp'); | ||||
| var async = require('async'); | ||||
|  | ||||
| var file = require('../file'); | ||||
| var plugins = require('../plugins'); | ||||
| var db = require('../database'); | ||||
|  | ||||
| @@ -107,21 +108,6 @@ module.exports = function (Meta) { | ||||
| 						return; | ||||
| 					} | ||||
|  | ||||
| 					if (nconf.get('local-assets') === false) { | ||||
| 						// Don't regenerate the public/sounds/ directory. Instead, create a mapping for the router to use | ||||
| 						Meta.sounds._filePathHash = filePaths.reduce(function (hash, filePath) { | ||||
| 							hash[path.basename(filePath)] = filePath; | ||||
| 							return hash; | ||||
| 						}, {}); | ||||
|  | ||||
| 						winston.verbose('[sounds] Sounds OK'); | ||||
| 						if (typeof next === 'function') { | ||||
| 							return next(); | ||||
| 						} else { | ||||
| 							return; | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					// Clear the sounds directory | ||||
| 					async.series([ | ||||
| 						function (next) { | ||||
| @@ -138,11 +124,7 @@ module.exports = function (Meta) { | ||||
|  | ||||
| 						// Link paths | ||||
| 						async.each(filePaths, function (filePath, next) { | ||||
| 							if (process.platform === 'win32') { | ||||
| 								fs.link(filePath, path.join(soundsPath, path.basename(filePath)), next); | ||||
| 							} else { | ||||
| 								fs.symlink(filePath, path.join(soundsPath, path.basename(filePath)), 'file', next); | ||||
| 							} | ||||
| 							file.link(filePath, path.join(soundsPath, path.basename(filePath)), next); | ||||
| 						}, function (err) { | ||||
| 							if (!err) { | ||||
| 								winston.verbose('[sounds] Sounds OK'); | ||||
|   | ||||
| @@ -54,7 +54,8 @@ module.exports = function (Plugins) { | ||||
| 					async.parallel([ | ||||
| 						async.apply(mapFiles, pluginData, 'css', 'cssFiles'), | ||||
| 						async.apply(mapFiles, pluginData, 'less', 'lessFiles'), | ||||
| 						async.apply(mapClientSideScripts, pluginData) | ||||
| 						async.apply(mapClientSideScripts, pluginData), | ||||
| 						async.apply(mapClientModules, pluginData), | ||||
| 					], next); | ||||
| 				}, next); | ||||
| 			} | ||||
|   | ||||
| @@ -167,7 +167,8 @@ module.exports = function (app, middleware, hotswapIds) { | ||||
| 		'/templates/', | ||||
| 		'/src/', | ||||
| 		'/images/', | ||||
| 		// '/sounds/', | ||||
| 		'/language/', | ||||
| 		'/sounds/', | ||||
| 	]; | ||||
| 	app.use(relativePath, function (req, res, next) { | ||||
| 		if (deprecatedPaths.some(function (path) { return req.path.startsWith(path); })) { | ||||
|   | ||||
| @@ -1,20 +1,5 @@ | ||||
| "use strict"; | ||||
|  | ||||
| var path = require('path'); | ||||
| var nconf = require('nconf'); | ||||
|  | ||||
| var meta = require('../meta'); | ||||
|  | ||||
| function sendSoundFile(req, res, next) { | ||||
| 	var resolved = meta.sounds._filePathHash[path.basename(req.path)]; | ||||
|  | ||||
| 	if (resolved) { | ||||
| 		res.status(200).sendFile(resolved); | ||||
| 	} else { | ||||
| 		next(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| module.exports = function (app, middleware, controllers) { | ||||
| 	app.get('/sitemap.xml', controllers.sitemap.render); | ||||
| 	app.get('/sitemap/pages.xml', controllers.sitemap.getPages); | ||||
| @@ -23,8 +8,4 @@ module.exports = function (app, middleware, controllers) { | ||||
| 	app.get('/robots.txt', controllers.robots); | ||||
| 	app.get('/manifest.json', controllers.manifest); | ||||
| 	app.get('/css/previews/:theme', controllers.admin.themes.get); | ||||
|  | ||||
| 	if (nconf.get('local-assets') === false) { | ||||
| 		app.get('/sounds/*', middleware.addExpiresHeaders, sendSoundFile); | ||||
| 	} | ||||
| }; | ||||
|   | ||||
| @@ -45,7 +45,7 @@ server.on('error', function (err) { | ||||
| 	winston.error(err); | ||||
| 	if (err.code === 'EADDRINUSE') { | ||||
| 		winston.error('NodeBB address in use, exiting...'); | ||||
| 		process.exit(0); | ||||
| 		process.exit(1); | ||||
| 	} else { | ||||
| 		throw err; | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user