react-middleware
Version:
Connect middleware for serving React components from a standard folder structure.
238 lines (192 loc) • 8.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _ramda = require('ramda');
var _ramda2 = _interopRequireDefault(_ramda);
var _chalk = require('chalk');
var _chalk2 = _interopRequireDefault(_chalk);
var _express = require('express');
var _express2 = _interopRequireDefault(_express);
var _compression = require('compression');
var _compression2 = _interopRequireDefault(_compression);
var _fileSystemCss = require('file-system-css');
var _fileSystemCss2 = _interopRequireDefault(_fileSystemCss);
var _filesize = require('filesize');
var _filesize2 = _interopRequireDefault(_filesize);
var _paths = require('./paths');
var _paths2 = _interopRequireDefault(_paths);
var _routerCss = require('./router-css');
var _routerCss2 = _interopRequireDefault(_routerCss);
var _routerHtml = require('./router-html');
var _routerHtml2 = _interopRequireDefault(_routerHtml);
var _routerJs = require('./router-js');
var _routerJs2 = _interopRequireDefault(_routerJs);
var _webpackBuilder = require('./webpack-builder');
var _webpackBuilder2 = _interopRequireDefault(_webpackBuilder);
var _templates = require('./templates');
var _templates2 = _interopRequireDefault(_templates);
var _log = require('./log');
var _log2 = _interopRequireDefault(_log);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var IS_PRODUCTION = process.env.NODE_ENV === 'production'; /* eslint max-len:0 new-cap:0 */
var buildFunction = function buildFunction(middleware, paths, routes, loaders) {
var builtResponse = void 0;
return function () {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
return new Promise(function (resolve, reject) {
if (builtResponse && options.force !== true) {
// Don't rebuild if compilation has already occured.
resolve(builtResponse);
} else {
(0, _webpackBuilder2.default)({ paths: paths, routes: routes, loaders: loaders }).then(function (result) {
builtResponse = result;
resolve(result);
}).catch(function (err) {
// Failed to build.
if (err.errors) {
_log2.default.error(_chalk2.default.red('FAILED to compile javascript.\n'));
err.errors.forEach(function (error) {
return _log2.default.error(error.message);
});
}
reject(err);
});
}
});
};
};
/**
* Returns the server middleware.
*
* @param options:
* - base: The relative or absolute path to the base for all other relative paths.
* - css: The relative or absolute path to the global CSS folder.
* - public: The relative or absolute path to the public assets folder.
* - layouts: The relative or absolute path to the page layouts folder.
* - components: The relative or absolute path to the shared components folder.
* - pages: The relative or absolute path to the pages folder.
* - data: An {Object} or {Function} to pass as the root data object to the React page(s).
* If a function is passed, details about the URL and rendering page are passed
* as an argument.
* This is useful as an API hook when creating a `react-middleware` package
* to be shared as a module.
* - watch: Flag indicating if changes to files should invalidate the cache.
* True by default when not in 'production'.
* - webpackLoaders: An array of webpack loaders to use.
* Default loaders are replaced with this array.
* - logger: Custom logger to use (object that exposes [info, warn, error] methods).
*
*/
var api = function api() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
// Setup initial conditions.
var watch = _ramda2.default.is(Boolean, options.watch) ? options.watch : !IS_PRODUCTION;
// Prepare the middleware.
var middleware = _express2.default.Router();
var paths = middleware.paths = (0, _paths2.default)(options);
var templates = middleware.templates = (0, _templates2.default)(middleware.paths);
var routes = templates.routes.import();
middleware.use((0, _compression2.default)());
middleware.use(_express2.default.static(paths.public, { maxage: '60 days' }));
(0, _routerHtml2.default)(middleware, paths, routes, options.data);
(0, _routerCss2.default)(middleware, paths, { watch: watch });
(0, _routerJs2.default)(middleware, routes);
// Decorate the middleware with functions.
middleware.start = function (startOptions) {
return api.start((0, _express2.default)(), middleware, startOptions);
};
middleware.clearCache = function () {
return api.clearCache();
};
middleware.build = buildFunction(middleware, paths, routes, options.webpackLoaders);
middleware.logger = options.logger || _log2.default;
// Finish up.
return middleware;
};
/**
* Starts a web server.
* @param {function} app: The express instance (eg. app = express();)
* If not specified a new express instance is created.
* @param {function} middleware: The react-middleware instance to use.
* @param {options}
* - port: The port to run on.
* - name: The display name of the server (emitted to the console).
* - version: The version of the app (emitted to the console).
* - silent: Flag indicating if startup output should be suppressed.
* @return Promise.
*/
api.start = function (app, middleware) {
var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
// Ensure required parameters were passed.
if (!_ramda2.default.is(Function, app)) {
throw new Error('Start Method: An express instance must be specified.');
}
if (!_ramda2.default.is(Function, middleware)) {
throw new Error('Start Method: The [react-middleware] instance must be specified.');
}
// Extract startup values.
if (_ramda2.default.is(Number, options)) {
options = { port: options };
}
var PORT = options.port || (IS_PRODUCTION ? 80 : 3030);
var NAME = options.name || 'Server';
var SILENT = options.silent === undefined ? false : options.silent;
var VERSION = options.version;
var logger = middleware.logger;
var logStarted = function logStarted(js) {
logger.info('');
logger.info(_chalk2.default.green('Started: ' + NAME));
if (VERSION) {
logger.info(_chalk2.default.grey(' - version:'), VERSION);
}
logger.info(_chalk2.default.grey(' - port: '), PORT);
logger.info(_chalk2.default.grey(' - env: '), process.env.NODE_ENV || 'development');
if (js.files.length > 0) {
var seconds = js.elapsed / 1000;
logger.info(_chalk2.default.grey(' - js: '), Math.round(seconds * 10) / 10 + ' second build time');
js.files.forEach(function (item) {
logger.info(_chalk2.default.grey(' - ' + item.path + ','), (0, _filesize2.default)(item.fileSize));
});
}
logger.info('');
};
return new Promise(function (resolve, reject) {
// Build the javascript (webpack).
logger.info(_chalk2.default.grey('Starting \'' + NAME + '\'...'));
middleware.build().then(function (js) {
// Configure and start the express server.
app.use(middleware).listen(PORT, function () {
if (!SILENT) {
logStarted(js);
}
resolve();
});
}).catch(function (err) {
logger.error('err', err);
reject(err);
});
});
};
/**
* Initalizes the default folder/template structure.
* @param {string} path: The base-path. Use './' to create
* relative to the root of the host module.
*/
api.init = function (path) {
if (!_ramda2.default.is(String, path)) {
path = './site';
}
api({ base: path }).templates.createSync();
return api;
};
/**
* Clears all cached content.
*/
api.clearCache = function () {
_fileSystemCss2.default.delete();
return api;
};
// ----------------------------------------------------------------------------
exports.default = api;
//# sourceMappingURL=middleware.js.map