phenomic
Version:
Modern website generator based on the React and Webpack ecosystem.
204 lines (147 loc) • 8.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
// module.exports is used
// eslint-disable-next-line import/default
var _path = require("path");
var _child_process = require("child_process");
var _express = require("express");
var _express2 = _interopRequireDefault(_express);
var _webpack = require("webpack");
var _webpack2 = _interopRequireDefault(_webpack);
var _webpackDevMiddleware = require("webpack-dev-middleware");
var _webpackDevMiddleware2 = _interopRequireDefault(_webpackDevMiddleware);
var _webpackHotMiddleware = require("webpack-hot-middleware");
var _webpackHotMiddleware2 = _interopRequireDefault(_webpackHotMiddleware);
var _connectHistoryApiFallback = require("connect-history-api-fallback");
var _connectHistoryApiFallback2 = _interopRequireDefault(_connectHistoryApiFallback);
var _portfinder = require("portfinder");
var _portfinder2 = _interopRequireDefault(_portfinder);
var _opn = require("opn");
var _opn2 = _interopRequireDefault(_opn);
var _log = require("../_utils/log");
var _log2 = _interopRequireDefault(_log);
var _plugin = require("../loader/plugin.js");
var _plugin2 = _interopRequireDefault(_plugin);
var _minify = require("../loader/minify");
var _minify2 = _interopRequireDefault(_minify);
var _serialize = require("../_utils/serialize");
var _serialize2 = _interopRequireDefault(_serialize);
var _pathToUri = require("../_utils/path-to-uri");
var _pathToUri2 = _interopRequireDefault(_pathToUri);
var _logFormatter = require("./webpack/log-formatter.js");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
var devServerNoScript = "Phenomic development server requires JavaScript.\nIf you want to check our your website works without JavaScript, you need to\nbuild the static version and server the result.\nYou can do this by doing: <code>npm run build -- --serve</code>\n";
exports.default = function (config) {
var webpackConfig = config.webpackConfigBrowser;
if (!config.baseUrl) {
throw new Error("You must provide a 'baseUrl' object that contains the following keys:" + "'href', 'port', 'hostname'. See https://nodejs.org/api/url.html");
}
var server = (0, _express2.default)();
if (config.static && config.server) {
server.use(config.baseUrl.pathname, _express2.default.static((0, _path.join)(config.cwd, config.destination)));
} else {
var devEntries = [require.resolve("webpack-hot-middleware/client")];
var devConfig = _extends({}, webpackConfig, {
entry: _extends({}, Object.keys(webpackConfig.entry).reduce(function (acc, key) {
return _extends({}, acc, _defineProperty({}, key, [].concat(devEntries, _toConsumableArray(Array.isArray(webpackConfig.entry[key]) ? webpackConfig.entry[key] : [webpackConfig.entry[key]]))));
}, {})),
plugins: [].concat(_toConsumableArray(webpackConfig.plugins || []), [
// for hot-middleware
new _webpack2.default.optimize.OccurrenceOrderPlugin(), new _webpack2.default.HotModuleReplacementPlugin(), new _webpack2.default.NoEmitOnErrorsPlugin()])
});
// webpack dev + hot middlewares
var webpackCompiler = (0, _webpack2.default)(devConfig);
server.use((0, _webpackDevMiddleware2.default)(webpackCompiler, _extends({
publicPath: webpackConfig.output.publicPath,
// skip compilation logs if !verbose
noInfo: !config.verbose,
quiet: !config.verbose
}, devConfig.devServer)));
server.use((0, _webpackHotMiddleware2.default)(webpackCompiler, {
// skip hot middleware logs if !verbose
log: config.verbose ? undefined : function () {}
}));
var entries = [];
webpackCompiler.plugin("done", function (stats) {
entries = [];
var namedChunks = stats.compilation.namedChunks;
Object.keys(namedChunks).forEach(function (chunkName) {
entries = [].concat(_toConsumableArray(entries), _toConsumableArray(namedChunks[chunkName].files.filter(function (file) {
return !file.endsWith(".hot-update.js");
})));
});
});
// if !verbose, use our custom minimal output
if (!config.verbose) {
(0, _logFormatter.handleInvalid)(); // start "Updating"
webpackCompiler.plugin("invalid", _logFormatter.handleInvalid);
webpackCompiler.plugin("done", _logFormatter.handleDone);
}
// user static assets
if (config.assets) {
server.use(config.baseUrl.pathname + config.assets.route, _express2.default.static(config.assets.path));
}
// routing for the part we want (starting to the baseUrl pathname)
var router = (0, _express.Router)();
server.use(config.baseUrl.pathname, router);
// fallback to index for unknow pages?
router.use((0, _connectHistoryApiFallback2.default)({
// https://github.com/MoOx/phenomic/issues/808
disableDotRule: true
}));
// webpack static ressources
router.get("*", _express2.default.static(webpackConfig.output.path));
// hardcoded entry point
router.get("/index.html", function (req, res) {
var collectionMin = (0, _minify2.default)(_plugin2.default.collection);
res.setHeader("Content-Type", "text/html");
/* eslint-disable max-len */
res.end("<!doctype html>\n <html>\n <head><meta charset=\"utf8\" /></head>\n <body>\n <div id=\"phenomic\">\n <div\n id=\"phenomic-DevLoader\"\n style=\"color: red; font: caption; font-size: 2rem; padding: 40vh 10vw; text-align: center;\"\n >\n <script>\n window.onerror = function(e) {\n var devLoader = document.querySelector(\"#phenomic-DevLoader\")\n if (devLoader) { devLoader.innerHTML = e.toString() }\n // only need to use this code once\n window.onerror = null\n }\n </script>\n <noscript>" + devServerNoScript + "</noscript>\n </div>\n </div>\n <script>\n window.__COLLECTION__ = " + (0, _serialize2.default)(collectionMin) + ";\n </script>\n " + entries.map(function (fileName) {
return "<script src=\"" + (0, _pathToUri2.default)(config.baseUrl.pathname, fileName) + "\"></script>";
}) + "\n </body>\n </html>"
/* eslint-enable max-len */
);
});
}
// THAT'S IT
var devHost = config.devHost,
devPort = config.devPort;
_portfinder2.default.basePort = devPort;
_portfinder2.default.getPort(function (err, port) {
if (err) {
throw err;
}
if (port !== devPort) {
(0, _log2.default)("Port " + devPort + " is not available. Using port " + port + " instead.");
}
server.listen(port, devHost, function (err) {
if (err) {
throw err;
}
var href = "http://" + devHost + ":" + port + config.baseUrl.pathname;
(0, _log2.default)("Development server listening on " + href);
if (config.open) {
var openUrl = href.replace(devHost, "localhost");
if (process.platform === "darwin") {
try {
// Try our best to reuse existing tab
// on OS X Google Chrome with AppleScript
(0, _child_process.execSync)("ps cax | grep \"Google Chrome\"");
(0, _child_process.execSync)("osascript openChrome.applescript " + openUrl, { cwd: __dirname, stdio: "ignore" });
return true;
} catch (err) {
// Ignore errors.
}
}
// Fallback to opn
// (It will always open new tab)
(0, _opn2.default)(openUrl);
}
});
});
};