reacthtmlpack
Version:
Using HTML templates as entry points for webpack
428 lines (341 loc) • 12.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; })();
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; };
exports.filepath$ToBabelResult$ = filepath$ToBabelResult$;
exports.babelResult$ToReactElement$ = babelResult$ToReactElement$;
exports.reactElement$ToChunkList$ = reactElement$ToChunkList$;
exports.chunkList$ToWebpackConfig$ = chunkList$ToWebpackConfig$;
exports.webpackConfig$ToWebpackCompiler$ = webpackConfig$ToWebpackCompiler$;
exports.webpackCompiler$ToWebpackStats$ = webpackCompiler$ToWebpackStats$;
exports.webpackConfig$ToChunkList$ = webpackConfig$ToChunkList$;
exports.chunkList$ToStaticMarkup$ = chunkList$ToStaticMarkup$;
exports.evaluateAsES2015Module = evaluateAsES2015Module;
exports.fromBabelCodeToReactElement = fromBabelCodeToReactElement;
exports.isEntryType = isEntryType;
exports.entryWithConfigReducer = entryWithConfigReducer;
exports.extractWebpackConfigFilepathList = extractWebpackConfigFilepathList;
exports.toEntryReducer = toEntryReducer;
exports.groupedObsToWebpackConfig = groupedObsToWebpackConfig;
exports.runWebpackCompiler = runWebpackCompiler;
exports.mergeWebpackStats$ToChunkList$WithWebpackConfig$ = mergeWebpackStats$ToChunkList$WithWebpackConfig$;
exports.chunkListWithStats = chunkListWithStats;
exports.entryWithOutputMapper = entryWithOutputMapper;
exports.groupedObsToStaticMarkup = groupedObsToStaticMarkup;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": 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 _path = require("path");
var _rx = require("rx");
var _rx2 = _interopRequireDefault(_rx);
var _transducersJs = require("transducers-js");
var _evalAsModule = require("eval-as-module");
var _evalAsModule2 = _interopRequireDefault(_evalAsModule);
var _react = require("react");
var _react2 = _interopRequireDefault(_react);
var _webpack = require("webpack");
var _webpack2 = _interopRequireDefault(_webpack);
var _entryEntryPropTypeKeyList = require("./entry/entryPropTypeKeyList");
var _entryEntryPropTypeKeyList2 = _interopRequireDefault(_entryEntryPropTypeKeyList);
_rx2["default"].config.longStackSupport = true;
// Note babel-core/index.js is NOT a ES6 module
var babel = require("babel-core");
var transformFile = _rx.Observable.fromNodeCallback(babel.transformFile);
var xfFilepath$ToWebpackConfig$ = _transducersJs.comp.apply(undefined, [(0, _transducersJs.map)(filepath$ToBabelResult$), (0, _transducersJs.map)(babelResult$ToReactElement$), (0, _transducersJs.map)(reactElement$ToChunkList$), (0, _transducersJs.map)(chunkList$ToWebpackConfig$)]);
exports.xfFilepath$ToWebpackConfig$ = xfFilepath$ToWebpackConfig$;
/**
* @public
*/
function filepath$ToBabelResult$(filepath$) {
return filepath$.selectMany(function (filepath) {
return transformFile(filepath).map(function (_ref) {
var code = _ref.code;
return { filepath: filepath, code: code };
});
});
}
/**
* @public
*/
function babelResult$ToReactElement$(babelResult$) {
return babelResult$.map(fromBabelCodeToReactElement);
}
/**
* @public
*/
function reactElement$ToChunkList$(reactElement$) {
return reactElement$.selectMany(extractWebpackConfigFilepathList);
}
/**
* @public
*/
function chunkList$ToWebpackConfig$(chunkList$) {
return chunkList$.groupBy(function (it) {
return it.webpackConfigFilepath;
}).selectMany(groupedObsToWebpackConfig);
}
/**
* @package
*/
function webpackConfig$ToWebpackCompiler$(webpackConfig$) {
return webpackConfig$.reduce(function (acc, _ref2) {
var webpackConfig = _ref2.webpackConfig;
// Your Client config should always be first
if (webpackConfig.reacthtmlpackDevServer) {
return [webpackConfig].concat(acc);
} else {
return acc.concat(webpackConfig);
}
}, []).first().tap(function (webpackConfig) {
var notMultipleConfig = 2 > webpackConfig.length;
if (notMultipleConfig) {
return;
}
var _webpackConfig = _slicedToArray(webpackConfig, 1);
var _webpackConfig$0 = _webpackConfig[0];
var reacthtmlpackDevServer = _webpackConfig$0.reacthtmlpackDevServer;
var outputPath = _webpackConfig$0.output.path;
var notInDevServerMode = !reacthtmlpackDevServer;
if (notInDevServerMode) {
return;
}
// In devServer command, you have to keep all output.path the same.
var theyDontHaveTheSameOutputPath = webpackConfig.some(function (it) {
return it.output.path !== outputPath;
});
if (theyDontHaveTheSameOutputPath) {
throw new Error("Make all your output.path the same in all of your webpack.config.js");
}
})
// The webpackCompiler should be an instance of MultiCompiler
.map(function (webpackConfig) {
return (0, _webpack2["default"])(webpackConfig);
});
}
/**
* @package
*/
function webpackCompiler$ToWebpackStats$(webpackCompiler$) {
return webpackCompiler$.selectMany(runWebpackCompiler).selectMany(function (stats) {
return(
// See MultiCompiler - MultiStats
_rx.Observable.fromArray(stats.stats).map(function (stats) {
return { stats: stats, statsJson: stats.toJson() };
})
);
});
}
/**
* @public
*/
function webpackConfig$ToChunkList$(webpackConfig$) {
return _rx.Observable.of(webpackConfig$).map(webpackConfig$ToWebpackCompiler$).map(webpackCompiler$ToWebpackStats$).selectMany(mergeWebpackStats$ToChunkList$WithWebpackConfig$(webpackConfig$));
}
/**
* @public
*/
function chunkList$ToStaticMarkup$(chunkList$) {
return chunkList$.groupBy(function (it) {
return it.filepath;
}).selectMany(groupedObsToStaticMarkup);
}
/**
* @package
*/
function evaluateAsES2015Module(code, filepath) {
var cjsModule = (0, _evalAsModule2["default"])(code, filepath);
if (cjsModule.exports && cjsModule.__esModule) {
return cjsModule.exports;
} else {
return {
"default": cjsModule.exports
};
};
}
/**
* @private
*/
function fromBabelCodeToReactElement(_ref3) {
var filepath = _ref3.filepath;
var code = _ref3.code;
var ComponentModule = evaluateAsES2015Module(code, filepath);
var element = ComponentModule["default"];
var doctypeHTML = ComponentModule.doctypeHTML || "<!DOCTYPE html>";
return {
filepath: filepath,
element: element,
doctypeHTML: doctypeHTML
};
}
/**
* @private
*/
function isEntryType(type) {
return _entryEntryPropTypeKeyList2["default"].every(function (key) {
return type.propTypes && type.propTypes[key];
});
}
/**
* @private
*/
function entryWithConfigReducer(children) {
var acc = [];
_react.Children.forEach(children, function (child) {
if (!_react2["default"].isValidElement(child)) {
return;
}
if (isEntryType(child.type)) {
var _child$props = child.props;
var chunkName = _child$props.chunkName;
var chunkFilepath = _child$props.chunkFilepath;
var configFilepath = _child$props.configFilepath;
acc.push({
chunkName: chunkName,
chunkFilepath: chunkFilepath,
configFilepath: configFilepath
});
}
acc.push.apply(acc, _toConsumableArray(entryWithConfigReducer(child.props.children)));
});
return acc;
}
/**
* @private
*/
function extractWebpackConfigFilepathList(_ref4) {
var filepath = _ref4.filepath;
var element = _ref4.element;
var doctypeHTML = _ref4.doctypeHTML;
var entryWithConfigList = entryWithConfigReducer(element.props.children);
return _rx.Observable.fromArray(entryWithConfigList).map(function (_ref5) {
var chunkName = _ref5.chunkName;
var chunkFilepath = _ref5.chunkFilepath;
var configFilepath = _ref5.configFilepath;
return {
filepath: filepath,
element: element,
doctypeHTML: doctypeHTML,
chunkName: chunkName,
chunkFilepath: chunkFilepath,
webpackConfigFilepath: (0, _path.resolve)((0, _path.dirname)(filepath), configFilepath)
};
});
}
/**
* @private
*/
function toEntryReducer(acc, item) {
var chunkName = item.chunkName;
var chunkFilepath = item.chunkFilepath;
if (!acc.entry.hasOwnProperty(chunkName)) {
acc.entry[chunkName] = chunkFilepath;
acc.chunkList.push(item);
}
return acc;
}
/**
* @private
*/
function groupedObsToWebpackConfig(groupedObservable) {
// http://requirebin.com/?gist=fe2c7d8fe7083d8bcd2d
var webpackConfigFilepath = groupedObservable.key;
return groupedObservable.reduce(toEntryReducer, { entry: {}, chunkList: [] }).first().map(function (_ref6) {
var entry = _ref6.entry;
var chunkList = _ref6.chunkList;
return {
webpackConfigFilepath: webpackConfigFilepath,
chunkList: chunkList,
webpackConfig: _extends({}, require(webpackConfigFilepath), {
entry: entry
})
};
});
}
/**
* @private
*/
function runWebpackCompiler(compiler) {
return _rx.Observable.fromNodeCallback(compiler.run.bind(compiler))();
}
/**
* @package
*/
function mergeWebpackStats$ToChunkList$WithWebpackConfig$(webpackConfig$) {
return function (webpackStats$) {
return _rx.Observable.zip(webpackStats$, webpackConfig$, function (_ref7, _ref8) {
var stats = _ref7.stats;
var statsJson = _ref7.statsJson;
var chunkList = _ref8.chunkList;
return { chunkList: chunkList, stats: stats, statsJson: statsJson };
}).selectMany(chunkListWithStats);
};
}
/**
* @private
*/
function chunkListWithStats(_ref9) {
var chunkList = _ref9.chunkList;
var stats = _ref9.stats;
var statsJson = _ref9.statsJson;
return _rx.Observable.fromArray(chunkList).map(function (it) {
var outputAssetList = [].concat(statsJson.assetsByChunkName[it.chunkName]).map(function (assetName) {
return {
rawAsset: stats.compilation.assets[assetName],
publicFilepath: "" + statsJson.publicPath + assetName
};
});
return _extends({}, it, {
outputAssetList: outputAssetList
});
});
}
/**
* @private
*/
function entryWithOutputMapper(children, outputAssetListByChunkName) {
return _react.Children.map(children, function (child) {
if (!_react2["default"].isValidElement(child)) {
return child;
}
var _child$props2 = child.props;
var chunkName = _child$props2.chunkName;
var children = _child$props2.children;
var extraProps = {
children: entryWithOutputMapper(children, outputAssetListByChunkName)
};
if (isEntryType(child.type)) {
extraProps.outputAssetList = outputAssetListByChunkName[chunkName];
}
return _react2["default"].cloneElement(child, extraProps);
});
}
/**
* @private
*/
function groupedObsToStaticMarkup(groupedObservable) {
// http://requirebin.com/?gist=fe2c7d8fe7083d8bcd2d
return groupedObservable.reduce(function (acc, item) {
var chunkName = item.chunkName;
var outputAssetList = item.outputAssetList;
acc.outputAssetListByChunkName[chunkName] = outputAssetList;
acc.filepath = item.filepath;
acc.element = item.element;
acc.doctypeHTML = item.doctypeHTML;
return acc;
}, { outputAssetListByChunkName: {} }).first().map(function (_ref10) {
var outputAssetListByChunkName = _ref10.outputAssetListByChunkName;
var filepath = _ref10.filepath;
var element = _ref10.element;
var doctypeHTML = _ref10.doctypeHTML;
var clonedElement = _react2["default"].cloneElement(element, {
children: entryWithOutputMapper(element.props.children, outputAssetListByChunkName)
});
var reactHtmlMarkup = _react2["default"].renderToStaticMarkup(clonedElement);
var markup = "" + doctypeHTML + reactHtmlMarkup;
return {
filepath: filepath,
markup: markup
};
});
}