react-static
Version:
A progressive static site generator for React
621 lines (481 loc) • 19.8 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.onLoading = exports.setLoading = exports.prefetch = exports.needsPrefetch = exports.prefetchTemplate = exports.prefetchData = exports.getRouteInfo = exports.reloadRouteData = exports.propsByHash = exports.routeInfoByPath = undefined;
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
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; };
var prefetchData = exports.prefetchData = function () {
var _ref9 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee4(path) {
var _this = this;
var _ref10 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
priority = _ref10.priority;
var routeInfo, allProps;
return _regenerator2.default.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
_context4.next = 2;
return getRouteInfo(path, { priority: priority });
case 2:
routeInfo = _context4.sent;
if (routeInfo) {
_context4.next = 5;
break;
}
return _context4.abrupt('return');
case 5:
if (!routeInfo.allProps) {
_context4.next = 7;
break;
}
return _context4.abrupt('return', routeInfo.allProps);
case 7:
// Request and build the props one by one
allProps = _extends({}, routeInfo.localProps || {});
// Request the template and loop over the routeInfo.sharedPropsHashes, requesting each prop
_context4.next = 10;
return Promise.all(Object.keys(routeInfo.sharedPropsHashes).map(function () {
var _ref11 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee3(key) {
var hash, _ref12, prop, _ref13, _prop;
return _regenerator2.default.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
hash = routeInfo.sharedPropsHashes[key];
// Check the propsByHash first
if (propsByHash[hash]) {
_context3.next = 24;
break;
}
_context3.prev = 2;
if (!priority) {
_context3.next = 11;
break;
}
_context3.next = 6;
return _axios2.default.get(process.env.REACT_STATIC_PUBLIC_PATH + 'staticData/' + hash + '.json');
case 6:
_ref12 = _context3.sent;
prop = _ref12.data;
propsByHash[hash] = prop;
_context3.next = 17;
break;
case 11:
// Non priority, share inflight requests and use pool
if (!inflightPropHashes[hash]) {
inflightPropHashes[hash] = requestPool.add(function () {
return _axios2.default.get(process.env.REACT_STATIC_PUBLIC_PATH + 'staticData/' + hash + '.json');
});
}
_context3.next = 14;
return inflightPropHashes[hash];
case 14:
_ref13 = _context3.sent;
_prop = _ref13.data;
// Place it in the cache
propsByHash[hash] = _prop;
case 17:
_context3.next = 23;
break;
case 19:
_context3.prev = 19;
_context3.t0 = _context3['catch'](2);
console.log('Error: There was an error retrieving a prop for this route! hashID:', hash);
console.error(_context3.t0);
case 23:
if (!priority) {
delete inflightPropHashes[hash];
}
case 24:
// Otherwise, just set it as the key
allProps[key] = propsByHash[hash];
case 25:
case 'end':
return _context3.stop();
}
}
}, _callee3, _this, [[2, 19]]);
}));
return function (_x5) {
return _ref11.apply(this, arguments);
};
}()));
case 10:
// Cache the entire props for the route
routeInfo.allProps = allProps;
// Return the props
return _context4.abrupt('return', routeInfo.allProps);
case 12:
case 'end':
return _context4.stop();
}
}
}, _callee4, this);
}));
return function prefetchData(_x3) {
return _ref9.apply(this, arguments);
};
}();
var prefetchTemplate = exports.prefetchTemplate = function () {
var _ref14 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee5(path) {
var _ref15 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
priority = _ref15.priority;
var routeInfo, pathTemplate;
return _regenerator2.default.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
// Clean the path
path = (0, _shared.cleanPath)(path);
// Get route info so we can check if path has any data
_context5.next = 3;
return getRouteInfo(path);
case 3:
routeInfo = _context5.sent;
if (routeInfo) {
registerTemplateIDForPath(path, routeInfo.templateID);
}
// Preload the template if available
pathTemplate = getComponentForPath(path);
if (!(pathTemplate && pathTemplate.preload)) {
_context5.next = 16;
break;
}
if (!priority) {
_context5.next = 12;
break;
}
_context5.next = 10;
return pathTemplate.preload();
case 10:
_context5.next = 14;
break;
case 12:
_context5.next = 14;
return requestPool.add(function () {
return pathTemplate.preload();
});
case 14:
routeInfo.templateLoaded = true;
return _context5.abrupt('return', pathTemplate);
case 16:
case 'end':
return _context5.stop();
}
}
}, _callee5, this);
}));
return function prefetchTemplate(_x6) {
return _ref14.apply(this, arguments);
};
}();
var needsPrefetch = exports.needsPrefetch = function () {
var _ref16 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee6(path) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var routeInfo;
return _regenerator2.default.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
// Clean the path
path = (0, _shared.cleanPath)(path);
if (path) {
_context6.next = 3;
break;
}
return _context6.abrupt('return', false);
case 3:
_context6.next = 5;
return getRouteInfo(path, options);
case 5:
routeInfo = _context6.sent;
if (routeInfo) {
_context6.next = 8;
break;
}
return _context6.abrupt('return', true);
case 8:
if (!(!routeInfo.allProps || !routeInfo.templateLoaded)) {
_context6.next = 10;
break;
}
return _context6.abrupt('return', true);
case 10:
case 'end':
return _context6.stop();
}
}
}, _callee6, this);
}));
return function needsPrefetch(_x8) {
return _ref16.apply(this, arguments);
};
}();
var prefetch = exports.prefetch = function () {
var _ref17 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee7(path) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var type, data, _ref18, _ref19;
return _regenerator2.default.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
// Clean the path
path = (0, _shared.cleanPath)(path);
type = options.type;
if (options.priority) {
requestPool.stop();
}
data = void 0;
if (!(type === 'data')) {
_context7.next = 10;
break;
}
_context7.next = 7;
return prefetchData(path, options);
case 7:
data = _context7.sent;
_context7.next = 20;
break;
case 10:
if (!(type === 'template')) {
_context7.next = 15;
break;
}
_context7.next = 13;
return prefetchTemplate(path, options);
case 13:
_context7.next = 20;
break;
case 15:
_context7.next = 17;
return Promise.all([prefetchData(path, options), prefetchTemplate(path, options)]);
case 17:
_ref18 = _context7.sent;
_ref19 = _slicedToArray(_ref18, 1);
data = _ref19[0];
case 20:
if (options.priority) {
requestPool.start();
}
return _context7.abrupt('return', data);
case 22:
case 'end':
return _context7.stop();
}
}
}, _callee7, this);
}));
return function prefetch(_x10) {
return _ref17.apply(this, arguments);
};
}();
exports.getComponentForPath = getComponentForPath;
exports.registerTemplateIDForPath = registerTemplateIDForPath;
var _axios = require('axios');
var _axios2 = _interopRequireDefault(_axios);
var _shared = require('../utils/shared');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } /* eslint-disable import/no-mutable-exports */
var routeInfoByPath = exports.routeInfoByPath = {};
var propsByHash = exports.propsByHash = {};
var erroredPaths = {};
var inflightRouteInfo = {};
var inflightPropHashes = {};
var loading = 0;
var loadingSubscribers = [];
var disableRouteInfoWarning = process.env.REACT_STATIC_DISABLE_ROUTE_INFO_WARNING === 'true';
var requestPool = (0, _shared.createPool)({
concurrency: Number(process.env.REACT_STATIC_PREFETCH_RATE) || 3
});
var reloadRouteData = exports.reloadRouteData = function reloadRouteData() {
// Delete all cached data
[routeInfoByPath, propsByHash, erroredPaths, inflightRouteInfo, inflightPropHashes].forEach(function (part) {
Object.keys(part).forEach(function (key) {
delete part[key];
});
});
// Force each RouteData component to reload
global.reloadAll();
};
if (process.env.REACT_STATIC_ENV === 'development') {
var io = require('socket.io-client');
var run = function () {
var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee() {
var _ref2, port, socket;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
_context.next = 3;
return _axios2.default.get('/__react-static__/getMessagePort');
case 3:
_ref2 = _context.sent;
port = _ref2.data.port;
socket = io('http://localhost:' + port);
socket.on('connect', function () {
console.log('React-Static data hot-loader websocket connected. Listening for data changes...');
});
socket.on('message', function (_ref3) {
var type = _ref3.type;
if (type === 'reloadRoutes') {
reloadRouteData();
}
});
_context.next = 14;
break;
case 10:
_context.prev = 10;
_context.t0 = _context['catch'](0);
console.log('React-Static data hot-loader websocket encountered the following error:');
console.error(_context.t0);
case 14:
case 'end':
return _context.stop();
}
}
}, _callee, undefined, [[0, 10]]);
}));
return function run() {
return _ref.apply(this, arguments);
};
}();
run();
}
var getRouteInfo = exports.getRouteInfo = function () {
var _ref4 = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee2(path) {
var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
priority = _ref5.priority;
var originalPath, routeInfo, _ref6, data, routeInfoRoot, cacheBuster, getPath, _ref7, _data, _ref8, _data2;
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (!(typeof document === 'undefined')) {
_context2.next = 2;
break;
}
return _context2.abrupt('return');
case 2:
originalPath = path;
path = (0, _shared.cleanPath)(path);
// Check the cache first
if (!routeInfoByPath[path]) {
_context2.next = 6;
break;
}
return _context2.abrupt('return', routeInfoByPath[path]);
case 6:
if (!erroredPaths[path]) {
_context2.next = 8;
break;
}
return _context2.abrupt('return');
case 8:
routeInfo = void 0;
_context2.prev = 9;
if (!(process.env.REACT_STATIC_ENV === 'development')) {
_context2.next = 19;
break;
}
// In dev, request from the webpack dev server
if (!inflightRouteInfo[path]) {
inflightRouteInfo[path] = _axios2.default.get('/__react-static__/routeInfo/' + (path === '/' ? '' : path));
}
_context2.next = 14;
return inflightRouteInfo[path];
case 14:
_ref6 = _context2.sent;
data = _ref6.data;
routeInfo = data;
_context2.next = 36;
break;
case 19:
routeInfoRoot = (process.env.REACT_STATIC_DISABLE_ROUTE_PREFIXING === 'true' ? process.env.REACT_STATIC_SITE_ROOT : process.env.REACT_STATIC_PUBLIC_PATH) || '/';
cacheBuster = process.env.REACT_STATIC_CACHE_BUST ? '?' + process.env.REACT_STATIC_CACHE_BUST : '';
getPath = '' + routeInfoRoot + (0, _shared.pathJoin)(path, 'routeInfo.json') + cacheBuster;
if (!priority) {
_context2.next = 30;
break;
}
_context2.next = 25;
return _axios2.default.get(getPath);
case 25:
_ref7 = _context2.sent;
_data = _ref7.data;
routeInfo = _data;
_context2.next = 36;
break;
case 30:
if (!inflightRouteInfo[path]) {
inflightRouteInfo[path] = requestPool.add(function () {
return _axios2.default.get(getPath);
});
}
_context2.next = 33;
return inflightRouteInfo[path];
case 33:
_ref8 = _context2.sent;
_data2 = _ref8.data;
routeInfo = _data2;
case 36:
_context2.next = 44;
break;
case 38:
_context2.prev = 38;
_context2.t0 = _context2['catch'](9);
erroredPaths[path] = true;
if (!(process.env.REACT_STATIC_ENV === 'production' || disableRouteInfoWarning)) {
_context2.next = 43;
break;
}
return _context2.abrupt('return');
case 43:
console.warn('Could not load routeInfo for path: ' + originalPath + '. If this is a static route, make sure any link to this page is valid! If this is not a static route, you can desregard this warning.');
case 44:
if (!priority) {
delete inflightRouteInfo[path];
}
routeInfoByPath[path] = routeInfo;
return _context2.abrupt('return', routeInfoByPath[path]);
case 47:
case 'end':
return _context2.stop();
}
}
}, _callee2, undefined, [[9, 38]]);
}));
return function getRouteInfo(_x) {
return _ref4.apply(this, arguments);
};
}();
var setLoading = exports.setLoading = function setLoading(d) {
if (loading !== d) {
loading = d;
loadingSubscribers.forEach(function (s) {
return s();
});
}
};
var onLoading = exports.onLoading = function onLoading(cb) {
var ccb = function ccb() {
return cb(loading);
};
loadingSubscribers.push(ccb);
return function () {
loadingSubscribers = loadingSubscribers.filter(function (d) {
return d !== ccb;
});
};
};
function getComponentForPath(path) {
path = (0, _shared.cleanPath)(path);
return global.reactStaticGetComponentForPath && global.reactStaticGetComponentForPath(path);
}
function registerTemplateIDForPath(path, templateID) {
path = (0, _shared.cleanPath)(path);
return global.reactStaticGetComponentForPath && global.reactStaticRegisterTemplateIDForPath(path, templateID);
}