"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.watcherIgnoreRegExp = void 0; function _react() { const data = _interopRequireDefault(require("react")); _react = function _react() { return data; }; return data; } function _path() { const data = require("path"); _path = function _path() { return data; }; return data; } function _fs() { const data = require("fs"); _fs = function _fs() { return data; }; return data; } function _mkdirp() { const data = _interopRequireDefault(require("mkdirp")); _mkdirp = function _mkdirp() { return data; }; return data; } function _chokidar() { const data = _interopRequireDefault(require("chokidar")); _chokidar = function _chokidar() { return data; }; return data; } function _assert() { const data = _interopRequireDefault(require("assert")); _assert = function _assert() { return data; }; return data; } function _chalk() { const data = _interopRequireDefault(require("chalk")); _chalk = function _chalk() { return data; }; return data; } function _lodash() { const data = require("lodash"); _lodash = function _lodash() { return data; }; return data; } function _mustache() { const data = _interopRequireDefault(require("mustache")); _mustache = function _mustache() { return data; }; return data; } function _umiUtils() { const data = require("umi-utils"); _umiUtils = function _umiUtils() { return data; }; return data; } var _stripJSONQuote = _interopRequireDefault(require("./routes/stripJSONQuote")); var _routesToJSON = _interopRequireDefault(require("./routes/routesToJSON")); var _importsToStr = _interopRequireDefault(require("./importsToStr")); var _constants = require("./constants"); var _getHtmlGenerator = _interopRequireDefault(require("./plugins/commands/getHtmlGenerator")); var _htmlToJSX = _interopRequireDefault(require("./htmlToJSX")); var _getRoutePaths = _interopRequireDefault(require("./routes/getRoutePaths")); var _writeContent = _interopRequireDefault(require("./utils/writeContent.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const debug = require('debug')('umi:FilesGenerator'); const watcherIgnoreRegExp = /(^|[\/\\])(_mock.js$|\..)/; exports.watcherIgnoreRegExp = watcherIgnoreRegExp; function normalizePath(path, base = '/') { if (path.startsWith(base)) { path = path.replace(base, '/'); } return path; } class FilesGenerator { constructor(opts) { Object.keys(opts).forEach(key => { this[key] = opts[key]; }); this.routesContent = null; this.hasRebuildError = false; } generate() { debug('generate'); const paths = this.service.paths; const absTmpDirPath = paths.absTmpDirPath, tmpDirPath = paths.tmpDirPath; debug(`mkdir tmp dir: ${tmpDirPath}`); _mkdirp().default.sync(absTmpDirPath); this.generateFiles(); } createWatcher(path) { const watcher = _chokidar().default.watch(path, { ignored: watcherIgnoreRegExp, // ignore .dotfiles and _mock.js ignoreInitial: true }); watcher.on('all', (0, _lodash().throttle)((event, path) => { debug(`${event} ${path}`); this.rebuild(); }, 100)); return watcher; } watch() { if (process.env.WATCH_FILES === 'none') return; const _this$service = this.service, paths = _this$service.paths, singular = _this$service.config.singular; const layout = singular ? 'layout' : 'layouts'; let pageWatchers = [paths.absPagesPath, ..._constants.EXT_LIST.map(ext => (0, _path().join)(paths.absSrcPath, `${layout}/index${ext}`)), ..._constants.EXT_LIST.map(ext => (0, _path().join)(paths.absSrcPath, `app${ext}`))]; if (this.modifyPageWatcher) { pageWatchers = this.modifyPageWatcher(pageWatchers); } this.watchers = pageWatchers.map(p => { return this.createWatcher(p); }); process.on('SIGINT', () => { this.unwatch(); }); } unwatch() { if (this.watchers) { this.watchers.forEach(watcher => { watcher.close(); }); } } rebuild() { const _this$service2 = this.service, refreshBrowser = _this$service2.refreshBrowser, printError = _this$service2.printError; const isDev = process.env.NODE_ENV === 'development'; try { this.service.applyPlugins('onGenerateFiles', { args: { isRebuild: true } }); this.generateRouterJS(); this.generateEntry(); this.generateHistory(); if (this.hasRebuildError) { if (isDev) refreshBrowser(); this.hasRebuildError = false; } } catch (e) { // 向浏览器发送出错信息 if (isDev) printError([e.message]); this.hasRebuildError = true; this.routesContent = null; // why? debug(`Generate failed: ${e.message}`); debug(e); console.error(_chalk().default.red(e.message)); } } generateFiles() { this.service.applyPlugins('onGenerateFiles'); this.generateRouterJS(); this.generateEntry(); this.generateHistory(); } generateEntry() { const _this$service3 = this.service, paths = _this$service3.paths, config = _this$service3.config; // Generate umi.js const entryTpl = (0, _fs().readFileSync)(paths.defaultEntryTplPath, 'utf-8'); const initialRender = this.service.applyPlugins('modifyEntryRender', { initialValue: ` window.g_isBrowser = true; let props = {}; // Both support SSR and CSR if (window.g_useSSR) { // 如果开启服务端渲染则客户端组件初始化 props 使用服务端注入的数据 props = window.g_initialData; } else { const pathname = location.pathname; const activeRoute = findRoute(require('@@/router').routes, pathname); // 在客户端渲染前,执行 getInitialProps 方法 // 拿到初始数据 if (activeRoute && activeRoute.component && activeRoute.component.getInitialProps) { const initialProps = plugins.apply('modifyInitialProps', { initialValue: {}, }); props = activeRoute.component.getInitialProps ? await activeRoute.component.getInitialProps({ route: activeRoute, isServer: false, location, ...initialProps, }) : {}; } } const rootContainer = plugins.apply('rootContainer', { initialValue: React.createElement(require('./router').default, props), }); ReactDOM[window.g_useSSR ? 'hydrate' : 'render']( rootContainer, document.getElementById('${config.mountElementId}'), ); `.trim() }); const moduleBeforeRenderer = this.service.applyPlugins('addRendererWrapperWithModule', { initialValue: [] }).map((source, index) => { return { source, specifier: `moduleBeforeRenderer${index}` }; }); const plugins = this.service.applyPlugins('addRuntimePlugin', { initialValue: [] }).map(plugin => { return (0, _umiUtils().winPath)((0, _path().relative)(paths.absTmpDirPath, plugin)); }); if ((0, _umiUtils().findJS)(paths.absSrcPath, 'app')) { plugins.push('@/app'); } const validKeys = this.service.applyPlugins('addRuntimePluginKey', { initialValue: ['patchRoutes', 'render', 'rootContainer', 'modifyRouteProps', 'onRouteChange', 'modifyInitialProps', 'initialProps'] }); (0, _assert().default)((0, _lodash().uniq)(validKeys).length === validKeys.length, `Conflict keys found in [${validKeys.join(', ')}]`); let htmlTemplateMap = []; if (config.ssr) { const isProd = process.env.NODE_ENV === 'production'; const routePaths = (0, _getRoutePaths.default)(this.RoutesManager.routes); htmlTemplateMap = routePaths.map(routePath => { let ssrHtml = '<>>'; const hg = (0, _getHtmlGenerator.default)(this.service, { chunksMap: { // TODO, for dynamic chunks // placeholder waiting manifest umi: [isProd ? '__UMI_SERVER__.js' : 'umi.js', isProd ? '__UMI_SERVER__.css' : 'umi.css'] }, headScripts: [{ content: 'window.g_useSSR=true;'.trim() }], scripts: [{ content: `window.g_initialData = \${stringify(props)};`.trim() }] }); const content = hg.getMatchedContent(normalizePath(routePath, config.base)); ssrHtml = (0, _htmlToJSX.default)(content).replace(`
`, `