UNPKG

@tdb/web

Version:

Common condiguration for serving a web-site and testing web-based UI components.

458 lines (377 loc) 14.6 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime-corejs2/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.render = render; exports.renderError = renderError; exports.default = exports.emitter = exports.ErrorComponent = exports.router = void 0; var _objectSpread2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/objectSpread")); var _regenerator = _interopRequireDefault(require("@babel/runtime-corejs2/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/asyncToGenerator")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/slicedToArray")); var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise")); var _react = _interopRequireDefault(require("react")); var _reactDom = _interopRequireDefault(require("react-dom")); var _headManager = _interopRequireDefault(require("./head-manager")); var _router2 = require("../lib/router"); var _EventEmitter = _interopRequireDefault(require("../lib/EventEmitter")); var _utils = require("../lib/utils"); var _pageLoader = _interopRequireDefault(require("../lib/page-loader")); var asset = _interopRequireWildcard(require("../lib/asset")); var envConfig = _interopRequireWildcard(require("../lib/runtime-config")); var _errorBoundary = _interopRequireDefault(require("./error-boundary")); var _loadable = _interopRequireDefault(require("../lib/loadable")); // Polyfill Promise globally // This is needed because Webpack's dynamic loading(common chunks) code // depends on Promise. // So, we need to polyfill it. // See: https://webpack.js.org/guides/code-splitting/#dynamic-imports if (!window.Promise) { window.Promise = _promise.default; } var _window = window, _window$__NEXT_DATA__ = _window.__NEXT_DATA__, props = _window$__NEXT_DATA__.props, err = _window$__NEXT_DATA__.err, page = _window$__NEXT_DATA__.page, query = _window$__NEXT_DATA__.query, buildId = _window$__NEXT_DATA__.buildId, assetPrefix = _window$__NEXT_DATA__.assetPrefix, runtimeConfig = _window$__NEXT_DATA__.runtimeConfig, dynamicIds = _window$__NEXT_DATA__.dynamicIds; var prefix = assetPrefix || ''; // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time // So, this is how we do it in the client side at runtime __webpack_public_path__ = "".concat(prefix, "/_next/"); //eslint-disable-line // Initialize next/asset with the assetPrefix asset.setAssetPrefix(prefix); // Initialize next/config with the environment configuration envConfig.setConfig({ serverRuntimeConfig: {}, publicRuntimeConfig: runtimeConfig }); var asPath = (0, _utils.getURL)(); var pageLoader = new _pageLoader.default(buildId, prefix); window.__NEXT_LOADED_PAGES__.forEach(function (_ref) { var _ref2 = (0, _slicedToArray2.default)(_ref, 2), r = _ref2[0], f = _ref2[1]; pageLoader.registerPage(r, f); }); delete window.__NEXT_LOADED_PAGES__; window.__NEXT_REGISTER_PAGE = pageLoader.registerPage.bind(pageLoader); var headManager = new _headManager.default(); var appContainer = document.getElementById('__next'); var lastAppProps; var webpackHMR; var router; exports.router = router; var ErrorComponent; exports.ErrorComponent = ErrorComponent; var Component; var App; var emitter = new _EventEmitter.default(); exports.emitter = emitter; var _default = /*#__PURE__*/ (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee() { var _ref4, passedWebpackHMR, initialErr, _args = arguments; return _regenerator.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _ref4 = _args.length > 0 && _args[0] !== undefined ? _args[0] : {}, passedWebpackHMR = _ref4.webpackHMR; // This makes sure this specific line is removed in production if (process.env.NODE_ENV === 'development') { webpackHMR = passedWebpackHMR; } _context.next = 4; return pageLoader.loadPage('/_error'); case 4: exports.ErrorComponent = ErrorComponent = _context.sent; _context.next = 7; return pageLoader.loadPage('/_app'); case 7: App = _context.sent; initialErr = err; _context.prev = 9; _context.next = 12; return pageLoader.loadPage(page); case 12: Component = _context.sent; if (!(typeof Component !== 'function')) { _context.next = 15; break; } throw new Error("The default export is not a React Component in page: \"".concat(page, "\"")); case 15: _context.next = 20; break; case 17: _context.prev = 17; _context.t0 = _context["catch"](9); // This catches errors like throwing in the top level of a module initialErr = _context.t0; case 20: _context.next = 22; return _loadable.default.preloadReady(dynamicIds || []); case 22: exports.router = router = (0, _router2.createRouter)(page, query, asPath, { initialProps: props, pageLoader: pageLoader, App: App, Component: Component, ErrorComponent: ErrorComponent, err: initialErr }); router.subscribe(function (_ref5) { var App = _ref5.App, Component = _ref5.Component, props = _ref5.props, err = _ref5.err; render({ App: App, Component: Component, props: props, err: err, emitter: emitter }); }); render({ App: App, Component: Component, props: props, err: initialErr, emitter: emitter }); return _context.abrupt("return", emitter); case 26: case "end": return _context.stop(); } } }, _callee, this, [[9, 17]]); })); exports.default = _default; function render(_x) { return _render.apply(this, arguments); } // This method handles all runtime and debug errors. // 404 and 500 errors are special kind of errors // and they are still handle via the main render method. function _render() { _render = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee2(props) { return _regenerator.default.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: if (!props.err) { _context2.next = 4; break; } _context2.next = 3; return renderError(props); case 3: return _context2.abrupt("return"); case 4: _context2.prev = 4; _context2.next = 7; return doRender(props); case 7: _context2.next = 13; break; case 9: _context2.prev = 9; _context2.t0 = _context2["catch"](4); _context2.next = 13; return renderError((0, _objectSpread2.default)({}, props, { err: _context2.t0 })); case 13: case "end": return _context2.stop(); } } }, _callee2, this, [[4, 9]]); })); return _render.apply(this, arguments); } function renderError(_x2) { return _renderError.apply(this, arguments); } function _renderError() { _renderError = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee3(props) { var App, err, initProps; return _regenerator.default.wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: App = props.App, err = props.err; if (!(process.env.NODE_ENV !== 'production')) { _context3.next = 3; break; } throw webpackHMR.prepareError(err); case 3: // Make sure we log the error to the console, otherwise users can't track down issues. console.error(err); // In production we do a normal render with the `ErrorComponent` as component. // If we've gotten here upon initial render, we can use the props from the server. // Otherwise, we need to call `getInitialProps` on `App` before mounting. if (!props.props) { _context3.next = 8; break; } _context3.t0 = props.props; _context3.next = 11; break; case 8: _context3.next = 10; return (0, _utils.loadGetInitialProps)(App, { Component: ErrorComponent, router: router, ctx: { err: err, pathname: page, query: query, asPath: asPath } }); case 10: _context3.t0 = _context3.sent; case 11: initProps = _context3.t0; _context3.next = 14; return doRender((0, _objectSpread2.default)({}, props, { err: err, Component: ErrorComponent, props: initProps })); case 14: case "end": return _context3.stop(); } } }, _callee3, this); })); return _renderError.apply(this, arguments); } var isInitialRender = true; function renderReactElement(reactEl, domEl) { // The check for `.hydrate` is there to support React alternatives like preact if (isInitialRender && typeof _reactDom.default.hydrate === 'function') { _reactDom.default.hydrate(reactEl, domEl); isInitialRender = false; } else { _reactDom.default.render(reactEl, domEl); } } function doRender(_x3) { return _doRender.apply(this, arguments); } function _doRender() { _doRender = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee5(_ref6) { var App, Component, props, err, _ref6$emitter, emitterProp, _router, pathname, _query, _asPath, appProps, onError; return _regenerator.default.wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: App = _ref6.App, Component = _ref6.Component, props = _ref6.props, err = _ref6.err, _ref6$emitter = _ref6.emitter, emitterProp = _ref6$emitter === void 0 ? emitter : _ref6$emitter; if (!(!props && Component && Component !== ErrorComponent && lastAppProps.Component === ErrorComponent)) { _context5.next = 6; break; } _router = router, pathname = _router.pathname, _query = _router.query, _asPath = _router.asPath; _context5.next = 5; return (0, _utils.loadGetInitialProps)(App, { Component: Component, router: router, ctx: { err: err, pathname: pathname, query: _query, asPath: _asPath } }); case 5: props = _context5.sent; case 6: Component = Component || lastAppProps.Component; props = props || lastAppProps.props; appProps = (0, _objectSpread2.default)({ Component: Component, err: err, router: router, headManager: headManager }, props); // lastAppProps has to be set before ReactDom.render to account for ReactDom throwing an error. lastAppProps = appProps; emitterProp.emit('before-reactdom-render', { Component: Component, ErrorComponent: ErrorComponent, appProps: appProps }); // In development runtime errors are caught by react-error-overlay. if (process.env.NODE_ENV === 'development') { renderReactElement(_react.default.createElement(App, appProps), appContainer); } else { // In production we catch runtime errors using componentDidCatch which will trigger renderError. onError = /*#__PURE__*/ function () { var _ref7 = (0, _asyncToGenerator2.default)( /*#__PURE__*/ _regenerator.default.mark(function _callee4(error) { return _regenerator.default.wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: _context4.prev = 0; _context4.next = 3; return renderError({ App: App, err: error }); case 3: _context4.next = 8; break; case 5: _context4.prev = 5; _context4.t0 = _context4["catch"](0); console.error('Error while rendering error page: ', _context4.t0); case 8: case "end": return _context4.stop(); } } }, _callee4, this, [[0, 5]]); })); return function onError(_x4) { return _ref7.apply(this, arguments); }; }(); renderReactElement(_react.default.createElement(_errorBoundary.default, { onError: onError }, _react.default.createElement(App, appProps)), appContainer); } emitterProp.emit('after-reactdom-render', { Component: Component, ErrorComponent: ErrorComponent, appProps: appProps }); case 13: case "end": return _context5.stop(); } } }, _callee5, this); })); return _doRender.apply(this, arguments); }