diff --git a/example/ssr-with-ts/.editorconfig b/example/ssr-with-ts/.editorconfig
new file mode 100644
index 00000000..fdaed3a3
--- /dev/null
+++ b/example/ssr-with-ts/.editorconfig
@@ -0,0 +1,17 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
+
+[Makefile]
+indent_style = tab
diff --git a/example/ssr-with-ts/.gitignore b/example/ssr-with-ts/.gitignore
new file mode 100644
index 00000000..3a98c47f
--- /dev/null
+++ b/example/ssr-with-ts/.gitignore
@@ -0,0 +1,16 @@
+logs/
+output/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+dist/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+.tsbuildinfo
+.tsbuildinfo.*
diff --git a/example/ssr-with-ts/README.md b/example/ssr-with-ts/README.md
new file mode 100644
index 00000000..8a78b10c
--- /dev/null
+++ b/example/ssr-with-ts/README.md
@@ -0,0 +1,18 @@
+# Egg + React + SSR应用骨架
+
+详细用法实现请查看[官方文档](http://ykfe.net)
+
+# 功能/特性
+
+- [x] 基于cra脚手架开发,由cra开发的React App可无缝迁移,如果你熟悉cra的配置,上手成本几乎为0
+- [x] 小而美,相比于beidou,next.js这样的高度封装方案,我们的实现原理和开发模式一目了然
+- [x] 同时支持SSR以及CSR两种开发模式,本地开发环境以及线上环境皆可无缝切换两种渲染模式
+- [x] 统一前端路由与服务端路由,无需重复编写路由文件配置
+- [x] 支持切换路由时自动获取数据
+- [x] 支持本地开发HMR
+- [x] 稳定性经过线上大规模应用验证,可提供性能优化方案
+- [x] 支持tree shaking以及打包去重依赖,使得打包的bundle非常小,为同样复杂度的next.js项目的0.4倍
+- [x] 支持csr/ssr自定义layout,无需通过path来手动区分
+- [x] 抛弃传统模版引擎,拥抱 React 组件,使用JSX来作为模版
+- [ ] 配套[TypeScript](https://github.com/ykfe/egg-react-ssr-typescript)版本的实现
+- [ ] 配套serverless版本的实现
diff --git a/example/ssr-with-ts/build/env.js b/example/ssr-with-ts/build/env.js
new file mode 100755
index 00000000..afe5d437
--- /dev/null
+++ b/example/ssr-with-ts/build/env.js
@@ -0,0 +1,93 @@
+'use strict'
+
+const fs = require('fs')
+const path = require('path')
+const paths = require('./paths')
+
+// Make sure that including paths.js after env.js will read .env variables.
+delete require.cache[require.resolve('./paths')]
+
+const NODE_ENV = process.env.NODE_ENV
+if (!NODE_ENV) {
+ throw new Error(
+ 'The NODE_ENV environment variable is required but was not specified.'
+ )
+}
+
+// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
+var dotenvFiles = [
+ `${paths.dotenv}.${NODE_ENV}.local`,
+ `${paths.dotenv}.${NODE_ENV}`,
+ // Don't include `.env.local` for `test` environment
+ // since normally you expect tests to produce the same
+ // results for everyone
+ NODE_ENV !== 'test' && `${paths.dotenv}.local`,
+ paths.dotenv
+].filter(Boolean)
+
+// Load environment variables from .env* files. Suppress warnings using silent
+// if this file is missing. dotenv will never modify any environment variables
+// that have already been set. Variable expansion is supported in .env files.
+// https://github.com/motdotla/dotenv
+// https://github.com/motdotla/dotenv-expand
+dotenvFiles.forEach(dotenvFile => {
+ if (fs.existsSync(dotenvFile)) {
+ require('dotenv-expand')(
+ require('dotenv').config({
+ path: dotenvFile
+ })
+ )
+ }
+})
+
+// We support resolving modules according to `NODE_PATH`.
+// This lets you use absolute paths in imports inside large monorepos:
+// https://github.com/facebook/create-react-app/issues/253.
+// It works similar to `NODE_PATH` in Node itself:
+// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
+// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
+// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims.
+// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
+// We also resolve them to make sure all tools using them work consistently.
+const appDirectory = fs.realpathSync(process.cwd())
+process.env.NODE_PATH = (process.env.NODE_PATH || '')
+ .split(path.delimiter)
+ .filter(folder => folder && !path.isAbsolute(folder))
+ .map(folder => path.resolve(appDirectory, folder))
+ .join(path.delimiter)
+
+// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
+// injected into the application via DefinePlugin in Webpack configuration.
+const REACT_APP = /^REACT_APP_/i
+
+function getClientEnvironment (publicUrl) {
+ const raw = Object.keys(process.env)
+ .filter(key => REACT_APP.test(key))
+ .reduce(
+ (env, key) => {
+ env[key] = process.env[key]
+ return env
+ },
+ {
+ // Useful for determining whether we’re running in production mode.
+ // Most importantly, it switches React into the correct mode.
+ NODE_ENV: process.env.NODE_ENV || 'development',
+ // Useful for resolving the correct path to static assets in `public`.
+ // For example, .
+ // This should only be used as an escape hatch. Normally you would put
+ // images into the `src` and `import` them in code to get their paths.
+ PUBLIC_URL: publicUrl
+ }
+ )
+ // Stringify all values so we can feed into Webpack DefinePlugin
+ const stringified = {
+ 'process.env': Object.keys(raw).reduce((env, key) => {
+ env[key] = JSON.stringify(raw[key])
+ return env
+ }, {})
+ }
+
+ return { raw, stringified }
+}
+
+module.exports = getClientEnvironment
diff --git a/example/ssr-with-ts/build/jest/cssTransform.js b/example/ssr-with-ts/build/jest/cssTransform.js
new file mode 100755
index 00000000..10a0a4c1
--- /dev/null
+++ b/example/ssr-with-ts/build/jest/cssTransform.js
@@ -0,0 +1,14 @@
+'use strict'
+
+// This is a custom Jest transformer turning style imports into empty objects.
+// http://facebook.github.io/jest/docs/en/webpack.html
+
+module.exports = {
+ process () {
+ return 'module.exports = {};'
+ },
+ getCacheKey () {
+ // The output is always the same.
+ return 'cssTransform'
+ }
+}
diff --git a/example/ssr-with-ts/build/jest/fileTransform.js b/example/ssr-with-ts/build/jest/fileTransform.js
new file mode 100755
index 00000000..c0d0f075
--- /dev/null
+++ b/example/ssr-with-ts/build/jest/fileTransform.js
@@ -0,0 +1,30 @@
+'use strict'
+
+const path = require('path')
+
+// This is a custom Jest transformer turning file imports into filenames.
+// http://facebook.github.io/jest/docs/en/webpack.html
+
+module.exports = {
+ process (src, filename) {
+ const assetFilename = JSON.stringify(path.basename(filename))
+
+ if (filename.match(/\.svg$/)) {
+ return `module.exports = {
+ __esModule: true,
+ default: ${assetFilename},
+ ReactComponent: (props) => ({
+ $$typeof: Symbol.for('react.element'),
+ type: 'svg',
+ ref: null,
+ key: null,
+ props: Object.assign({}, props, {
+ children: ${assetFilename}
+ })
+ }),
+ };`
+ }
+
+ return `module.exports = ${assetFilename};`
+ }
+}
diff --git a/example/ssr-with-ts/build/paths.js b/example/ssr-with-ts/build/paths.js
new file mode 100755
index 00000000..dda9626b
--- /dev/null
+++ b/example/ssr-with-ts/build/paths.js
@@ -0,0 +1,41 @@
+'use strict'
+
+const path = require('path')
+const fs = require('fs')
+
+// Make sure any symlinks in the project folder are resolved:
+// https://github.com/facebook/create-react-app/issues/637
+const appDirectory = fs.realpathSync(__dirname)
+const resolveApp = relativePath => path.resolve(appDirectory, relativePath)
+
+const envPublicUrl = process.env.PUBLIC_URL
+
+const getPublicUrl = appPackageJson =>
+ envPublicUrl || require(appPackageJson).homepage
+
+const moduleFileExtensions = [
+ 'web.mjs',
+ 'mjs',
+ 'web.js',
+ 'js',
+ 'web.ts',
+ 'ts',
+ 'web.tsx',
+ 'tsx',
+ 'json',
+ 'web.jsx',
+ 'jsx'
+]
+
+// config after eject: we're in ./config/
+module.exports = {
+ appPath: resolveApp('../'),
+ appBuild: resolveApp('../output'),
+ appSrc: resolveApp('../web'),
+ entry: resolveApp('../web/entry'),
+ appNodeModules: resolveApp('node_modules'),
+ publicUrl: getPublicUrl(resolveApp('../package.json')),
+ resolveApp: resolveApp
+}
+
+module.exports.moduleFileExtensions = moduleFileExtensions
diff --git a/example/ssr-with-ts/build/util.js b/example/ssr-with-ts/build/util.js
new file mode 100644
index 00000000..d74975fc
--- /dev/null
+++ b/example/ssr-with-ts/build/util.js
@@ -0,0 +1,46 @@
+const paths = require('./paths')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const publicPath = paths.servedPath
+const shouldUseRelativeAssetPaths = publicPath === './'
+const isDev = process.env.NODE_ENV === 'development'
+const getStyleLoaders = (cssOptions, preProcessor) => {
+ const loaders = [
+ {
+ loader: MiniCssExtractPlugin.loader,
+ options: Object.assign(
+ {},
+ shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined
+ )
+ },
+ {
+ loader: require.resolve('css-loader'),
+ options: cssOptions
+ },
+ {
+ loader: require.resolve('postcss-loader'),
+ options: {
+ ident: 'postcss',
+ plugins: () => [
+ require('postcss-flexbugs-fixes'),
+ require('postcss-preset-env')({
+ autoprefixer: {
+ flexbox: 'no-2009'
+ },
+ stage: 3
+ })
+ ]
+ }
+ }
+ ]
+ if (isDev) {
+ loaders.unshift(require.resolve('css-hot-loader'))
+ }
+ if (preProcessor) {
+ // 添加额外的loader
+ loaders.push(require.resolve(preProcessor))
+ }
+ return loaders
+}
+module.exports = {
+ getStyleLoaders
+}
diff --git a/example/ssr-with-ts/build/webpack.config.base.js b/example/ssr-with-ts/build/webpack.config.base.js
new file mode 100755
index 00000000..1ee8fd30
--- /dev/null
+++ b/example/ssr-with-ts/build/webpack.config.base.js
@@ -0,0 +1,115 @@
+'use strict'
+
+const paths = require('./paths')
+const path = require('path')
+// style files regexes
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent')
+const getStyleLoaders = require('./util').getStyleLoaders
+const webpackModule = {
+ strictExportPresence: true,
+ rules: [
+ { parser: { requireEnsure: false } },
+ {
+ oneOf: [
+ {
+ test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
+ loader: require.resolve('url-loader'),
+ options: {
+ limit: 10000,
+ name: 'static/media/[name].[hash:8].[ext]'
+ }
+ },
+ {
+ test: /\.(js|mjs|jsx|ts|tsx)$/,
+ exclude: /node_modules/,
+ loader: require.resolve('babel-loader'),
+ options: {
+ cacheDirectory: true,
+ cacheCompression: false,
+ presets: [
+ [
+ require.resolve('@babel/preset-env'),
+ {
+ modules: 'false'
+ }
+ ],
+ ['react-app', { 'flow': false, 'typescript': true }]
+ ],
+ plugins: [
+ require.resolve('@babel/plugin-transform-runtime')
+ ]
+ }
+ },
+ {
+ test: /\.css$/,
+ exclude: /\.module\.css$/,
+ use: getStyleLoaders({
+ importLoaders: 1
+ })
+ },
+ {
+ test: /\.module\.css$/,
+ use: getStyleLoaders({
+ importLoaders: 1,
+ modules: true,
+ getLocalIdent: getCSSModuleLocalIdent
+ })
+ },
+ {
+ test: /\.less$/,
+ exclude: /\.module\.less$/,
+ use: getStyleLoaders(
+ {
+ importLoaders: 2,
+ localIdentName: '[local]'
+ },
+ 'less-loader'
+ ),
+ sideEffects: true
+ },
+ {
+ test: /\.module\.less$/,
+ use: getStyleLoaders(
+ {
+ importLoaders: 2,
+ modules: true,
+ getLocalIdent: getCSSModuleLocalIdent
+ },
+ 'less-loader'
+ )
+ },
+ {
+ exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
+ loader: require.resolve('file-loader'),
+ options: {
+ name: 'static/media/[name].[hash:8].[ext]'
+ }
+ }
+ ]
+ }
+ ]
+}
+
+module.exports = {
+ stats: {
+ children: false,
+ entrypoints: false
+ },
+ mode: process.env.NODE_ENV,
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, '../web')
+ },
+ extensions: paths.moduleFileExtensions
+ .map(ext => `.${ext}`)
+ },
+ module: webpackModule,
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: 'static/css/[name].css',
+ chunkFilename: 'static/css/[name].chunk.css'
+ })
+ ],
+ performance: false
+}
diff --git a/example/ssr-with-ts/build/webpack.config.client.js b/example/ssr-with-ts/build/webpack.config.client.js
new file mode 100644
index 00000000..00937c06
--- /dev/null
+++ b/example/ssr-with-ts/build/webpack.config.client.js
@@ -0,0 +1,129 @@
+'use strict'
+
+const path = require('path')
+const webpack = require('webpack')
+const merge = require('webpack-merge')
+const TerserPlugin = require('terser-webpack-plugin')
+const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
+const ManifestPlugin = require('webpack-manifest-plugin')
+const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin')
+const safePostCssParser = require('postcss-safe-parser')
+const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+const paths = require('./paths')
+const baseConfig = require('./webpack.config.base')
+const publicPath = '/'
+const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'
+const isDev = process.env.NODE_ENV === 'development'
+const devtool = isDev ? 'cheap-module-source-map' : (shouldUseSourceMap ? 'source-map' : false)
+
+const optimization = {
+ runtimeChunk: true,
+ splitChunks: {
+ chunks: 'all',
+ name: false,
+ cacheGroups: {
+ vendors: {
+ test: (module) => {
+ return module.resource &&
+ /\.js$/.test(module.resource) &&
+ module.resource.match('node_modules')
+ },
+ name: 'vendor'
+ }
+ }
+ }
+}
+
+if (!isDev) {
+ optimization.minimizer = [
+ new TerserPlugin({
+ terserOptions: {
+ parse: {
+ ecma: 8
+ },
+ compress: {
+ ecma: 5,
+ warnings: false,
+ comparisons: false,
+ inline: 2
+ },
+ mangle: {
+ safari10: true
+ },
+ output: {
+ ecma: 5,
+ comments: false,
+ ascii_only: true
+ }
+ },
+ // Use multi-process parallel running to improve the build speed
+ // Default number of concurrent runs: os.cpus().length - 1
+ parallel: true,
+ // Enable file caching
+ cache: true,
+ sourceMap: shouldUseSourceMap
+ }),
+ new OptimizeCSSAssetsPlugin({
+ cssProcessorOptions: {
+ parser: safePostCssParser,
+ map: shouldUseSourceMap
+ ? {
+ // `inline: false` forces the sourcemap to be output into a
+ // separate file
+ inline: false,
+ // `annotation: true` appends the sourceMappingURL to the end of
+ // the css file, helping the browser find the sourcemap
+ annotation: true
+ }
+ : false
+ }
+ })
+ ]
+}
+const plugins = [
+ new webpack.DefinePlugin({
+ '__isBrowser__': true // eslint-disable-line
+ }),
+ new ModuleNotFoundPlugin(paths.appPath),
+ new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
+ new ManifestPlugin({
+ fileName: 'asset-manifest.json',
+ publicPath: publicPath
+ })
+]
+
+if (process.env.npm_config_report === 'true') {
+ plugins.push(new BundleAnalyzerPlugin())
+}
+module.exports = merge(baseConfig, {
+ devtool: devtool,
+ entry: {
+ Page: [require.resolve('@babel/polyfill'), paths.entry]
+ },
+ resolve: {
+ alias: {
+ // for this issue https://github.com/ykfe/egg-react-ssr/issues/36
+ 'react-router': require.resolve('react-router')
+ }
+ },
+ output: {
+ path: paths.appBuild,
+ pathinfo: true,
+ filename: 'static/js/[name].js',
+ chunkFilename: 'static/js/[name].chunk.js',
+ publicPath: publicPath,
+ hotUpdateChunkFilename: '[hash].hot-update.js',
+ devtoolModuleFilenameTemplate: info =>
+ path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')
+ },
+ optimization: optimization,
+ plugins: plugins.filter(Boolean),
+ node: {
+ dgram: 'empty',
+ fs: 'empty',
+ net: 'empty',
+ tls: 'empty',
+ child_process: 'empty'
+ },
+ performance: false
+})
diff --git a/example/ssr-with-ts/build/webpack.config.server.js b/example/ssr-with-ts/build/webpack.config.server.js
new file mode 100755
index 00000000..b49d5949
--- /dev/null
+++ b/example/ssr-with-ts/build/webpack.config.server.js
@@ -0,0 +1,29 @@
+const webpack = require('webpack')
+const merge = require('webpack-merge')
+const nodeExternals = require('webpack-node-externals')
+const baseConfig = require('./webpack.config.base')
+const paths = require('./paths')
+const isDev = process.env.NODE_ENV === 'development'
+
+const plugins = [
+ new webpack.DefinePlugin({
+ '__isBrowser__': false //eslint-disable-line
+ })
+]
+module.exports = merge(baseConfig, {
+ devtool: isDev ? 'eval-source-map' : '',
+ entry: {
+ Page: paths.entry
+ },
+ target: 'node',
+ externals: nodeExternals({
+ whitelist: /\.(css|less|sass|scss)$/
+ }),
+ output: {
+ path: paths.appBuild,
+ publicPath: '/',
+ filename: '[name].server.js',
+ libraryTarget: 'commonjs2'
+ },
+ plugins: plugins
+})
diff --git a/example/ssr-with-ts/config/config.ssr.js b/example/ssr-with-ts/config/config.ssr.js
new file mode 100644
index 00000000..b8d52521
--- /dev/null
+++ b/example/ssr-with-ts/config/config.ssr.js
@@ -0,0 +1,31 @@
+const resolvePath = (path) => require('path').resolve(__dirname, path)
+
+module.exports = {
+ type: 'ssr', // 指定运行类型可设置为csr切换为客户端渲染
+ routes: [
+ {
+ path: '/',
+ exact: true,
+ Component: () => (require('@/page/index').default), // 这里使用一个function包裹为了让它延迟require
+ controller: 'page',
+ handler: 'index'
+ },
+ {
+ path: '/news/:id',
+ exact: true,
+ Component: () => (require('@/page/news').default),
+ controller: 'page',
+ handler: 'index'
+ }
+ ],
+ baseDir: resolvePath('../'),
+ injectCss: [
+ `/static/css/Page.chunk.css`
+ ], // 客户端需要加载的静态样式表
+ injectScript: [
+ ``,
+ ``,
+ ``
+ ], // 客户端需要加载的静态资源文件表
+ serverJs: resolvePath(`../output/Page.server.js`)
+}
diff --git a/example/ssr-with-ts/output/Page.server.js b/example/ssr-with-ts/output/Page.server.js
new file mode 100644
index 00000000..daee47e5
--- /dev/null
+++ b/example/ssr-with-ts/output/Page.server.js
@@ -0,0 +1,282 @@
+module.exports =
+/******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "/";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "./web/entry.tsx");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "./config/config.ssr.js":
+/*!******************************!*\
+ !*** ./config/config.ssr.js ***!
+ \******************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("/* WEBPACK VAR INJECTION */(function(__dirname) {var resolvePath = function resolvePath(path) {\n return __webpack_require__(/*! path */ \"path\").resolve(__dirname, path);\n};\n\nmodule.exports = {\n type: 'ssr',\n // 指定运行类型可设置为csr切换为客户端渲染\n routes: [{\n path: '/',\n exact: true,\n Component: function Component() {\n return __webpack_require__(/*! @/page/index */ \"./web/page/index/index.tsx\")[\"default\"];\n },\n // 这里使用一个function包裹为了让它延迟require\n controller: 'page',\n handler: 'index'\n }, {\n path: '/news/:id',\n exact: true,\n Component: function Component() {\n return __webpack_require__(/*! @/page/news */ \"./web/page/news/index.tsx\")[\"default\"];\n },\n controller: 'page',\n handler: 'index'\n }],\n baseDir: resolvePath('../'),\n injectCss: [\"/static/css/Page.chunk.css\"],\n // 客户端需要加载的静态样式表\n injectScript: [\"\", \"\", \"\"],\n // 客户端需要加载的静态资源文件表\n serverJs: resolvePath(\"../output/Page.server.js\")\n};\n/* WEBPACK VAR INJECTION */}.call(this, \"/\"))//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9jb25maWcvY29uZmlnLnNzci5qcz8yNThiIl0sIm5hbWVzIjpbInJlc29sdmVQYXRoIiwicGF0aCIsInJlcXVpcmUiLCJyZXNvbHZlIiwiX19kaXJuYW1lIiwibW9kdWxlIiwiZXhwb3J0cyIsInR5cGUiLCJyb3V0ZXMiLCJleGFjdCIsIkNvbXBvbmVudCIsImNvbnRyb2xsZXIiLCJoYW5kbGVyIiwiYmFzZURpciIsImluamVjdENzcyIsImluamVjdFNjcmlwdCIsInNlcnZlckpzIl0sIm1hcHBpbmdzIjoiQUFBQSxxREFBTUEsV0FBVyxHQUFHLFNBQWRBLFdBQWMsQ0FBQ0MsSUFBRDtBQUFBLFNBQVVDLG1CQUFPLENBQUMsa0JBQUQsQ0FBUCxDQUFnQkMsT0FBaEIsQ0FBd0JDLFNBQXhCLEVBQW1DSCxJQUFuQyxDQUFWO0FBQUEsQ0FBcEI7O0FBRUFJLE1BQU0sQ0FBQ0MsT0FBUCxHQUFpQjtBQUNmQyxNQUFJLEVBQUUsS0FEUztBQUNGO0FBQ2JDLFFBQU0sRUFBRSxDQUNOO0FBQ0VQLFFBQUksRUFBRSxHQURSO0FBRUVRLFNBQUssRUFBRSxJQUZUO0FBR0VDLGFBQVMsRUFBRTtBQUFBLGFBQU9SLG1CQUFPLENBQUMsZ0RBQUQsQ0FBUCxXQUFQO0FBQUEsS0FIYjtBQUdzRDtBQUNwRFMsY0FBVSxFQUFFLE1BSmQ7QUFLRUMsV0FBTyxFQUFFO0FBTFgsR0FETSxFQVFOO0FBQ0VYLFFBQUksRUFBRSxXQURSO0FBRUVRLFNBQUssRUFBRSxJQUZUO0FBR0VDLGFBQVMsRUFBRTtBQUFBLGFBQU9SLG1CQUFPLENBQUMsOENBQUQsQ0FBUCxXQUFQO0FBQUEsS0FIYjtBQUlFUyxjQUFVLEVBQUUsTUFKZDtBQUtFQyxXQUFPLEVBQUU7QUFMWCxHQVJNLENBRk87QUFrQmZDLFNBQU8sRUFBRWIsV0FBVyxDQUFDLEtBQUQsQ0FsQkw7QUFtQmZjLFdBQVMsRUFBRSw4QkFuQkk7QUFxQlo7QUFDSEMsY0FBWSxFQUFFLGdLQXRCQztBQTBCWjtBQUNIQyxVQUFRLEVBQUVoQixXQUFXO0FBM0JOLENBQWpCLEMiLCJmaWxlIjoiLi9jb25maWcvY29uZmlnLnNzci5qcy5qcyIsInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHJlc29sdmVQYXRoID0gKHBhdGgpID0+IHJlcXVpcmUoJ3BhdGgnKS5yZXNvbHZlKF9fZGlybmFtZSwgcGF0aClcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHR5cGU6ICdzc3InLCAvLyDmjIflrprov5DooYznsbvlnovlj6/orr7nva7kuLpjc3LliIfmjaLkuLrlrqLmiLfnq6/muLLmn5NcbiAgcm91dGVzOiBbXG4gICAge1xuICAgICAgcGF0aDogJy8nLFxuICAgICAgZXhhY3Q6IHRydWUsXG4gICAgICBDb21wb25lbnQ6ICgpID0+IChyZXF1aXJlKCdAL3BhZ2UvaW5kZXgnKS5kZWZhdWx0KSwgLy8g6L+Z6YeM5L2/55So5LiA5LiqZnVuY3Rpb27ljIXoo7nkuLrkuoborqnlroPlu7bov59yZXF1aXJlXG4gICAgICBjb250cm9sbGVyOiAncGFnZScsXG4gICAgICBoYW5kbGVyOiAnaW5kZXgnXG4gICAgfSxcbiAgICB7XG4gICAgICBwYXRoOiAnL25ld3MvOmlkJyxcbiAgICAgIGV4YWN0OiB0cnVlLFxuICAgICAgQ29tcG9uZW50OiAoKSA9PiAocmVxdWlyZSgnQC9wYWdlL25ld3MnKS5kZWZhdWx0KSxcbiAgICAgIGNvbnRyb2xsZXI6ICdwYWdlJyxcbiAgICAgIGhhbmRsZXI6ICdpbmRleCdcbiAgICB9XG4gIF0sXG4gIGJhc2VEaXI6IHJlc29sdmVQYXRoKCcuLi8nKSxcbiAgaW5qZWN0Q3NzOiBbXG4gICAgYC9zdGF0aWMvY3NzL1BhZ2UuY2h1bmsuY3NzYFxuICBdLCAvLyDlrqLmiLfnq6/pnIDopoHliqDovb3nmoTpnZnmgIHmoLflvI/ooahcbiAgaW5qZWN0U2NyaXB0OiBbXG4gICAgYDxzY3JpcHQgc3JjPScvc3RhdGljL2pzL3J1bnRpbWV+UGFnZS5qcyc+PC9zY3JpcHQ+YCxcbiAgICBgPHNjcmlwdCBzcmM9Jy9zdGF0aWMvanMvdmVuZG9yLmNodW5rLmpzJz48L3NjcmlwdD5gLFxuICAgIGA8c2NyaXB0IHNyYz0nL3N0YXRpYy9qcy9QYWdlLmNodW5rLmpzJz48L3NjcmlwdD5gXG4gIF0sIC8vIOWuouaIt+err+mcgOimgeWKoOi9veeahOmdmeaAgei1hOa6kOaWh+S7tuihqFxuICBzZXJ2ZXJKczogcmVzb2x2ZVBhdGgoYC4uL291dHB1dC9QYWdlLnNlcnZlci5qc2ApXG59XG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./config/config.ssr.js\n");
+
+/***/ }),
+
+/***/ "./node_modules/babel-preset-react-app/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js":
+/*!*********************************************************************************************************!*\
+ !*** ./node_modules/babel-preset-react-app/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js ***!
+ \*********************************************************************************************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"default\", function() { return _asyncToGenerator; });\nfunction asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {\n try {\n var info = gen[key](arg);\n var value = info.value;\n } catch (error) {\n reject(error);\n return;\n }\n\n if (info.done) {\n resolve(value);\n } else {\n Promise.resolve(value).then(_next, _throw);\n }\n}\n\nfunction _asyncToGenerator(fn) {\n return function () {\n var self = this,\n args = arguments;\n return new Promise(function (resolve, reject) {\n var gen = fn.apply(self, args);\n\n function _next(value) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"next\", value);\n }\n\n function _throw(err) {\n asyncGeneratorStep(gen, resolve, reject, _next, _throw, \"throw\", err);\n }\n\n _next(undefined);\n });\n };\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvYmFiZWwtcHJlc2V0LXJlYWN0LWFwcC9ub2RlX21vZHVsZXMvQGJhYmVsL3J1bnRpbWUvaGVscGVycy9lc20vYXN5bmNUb0dlbmVyYXRvci5qcz82ZWViIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQSIsImZpbGUiOiIuL25vZGVfbW9kdWxlcy9iYWJlbC1wcmVzZXQtcmVhY3QtYXBwL25vZGVfbW9kdWxlcy9AYmFiZWwvcnVudGltZS9oZWxwZXJzL2VzbS9hc3luY1RvR2VuZXJhdG9yLmpzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gYXN5bmNHZW5lcmF0b3JTdGVwKGdlbiwgcmVzb2x2ZSwgcmVqZWN0LCBfbmV4dCwgX3Rocm93LCBrZXksIGFyZykge1xuICB0cnkge1xuICAgIHZhciBpbmZvID0gZ2VuW2tleV0oYXJnKTtcbiAgICB2YXIgdmFsdWUgPSBpbmZvLnZhbHVlO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJlamVjdChlcnJvcik7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGluZm8uZG9uZSkge1xuICAgIHJlc29sdmUodmFsdWUpO1xuICB9IGVsc2Uge1xuICAgIFByb21pc2UucmVzb2x2ZSh2YWx1ZSkudGhlbihfbmV4dCwgX3Rocm93KTtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBfYXN5bmNUb0dlbmVyYXRvcihmbikge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzZWxmID0gdGhpcyxcbiAgICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdmFyIGdlbiA9IGZuLmFwcGx5KHNlbGYsIGFyZ3MpO1xuXG4gICAgICBmdW5jdGlvbiBfbmV4dCh2YWx1ZSkge1xuICAgICAgICBhc3luY0dlbmVyYXRvclN0ZXAoZ2VuLCByZXNvbHZlLCByZWplY3QsIF9uZXh0LCBfdGhyb3csIFwibmV4dFwiLCB2YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIGZ1bmN0aW9uIF90aHJvdyhlcnIpIHtcbiAgICAgICAgYXN5bmNHZW5lcmF0b3JTdGVwKGdlbiwgcmVzb2x2ZSwgcmVqZWN0LCBfbmV4dCwgX3Rocm93LCBcInRocm93XCIsIGVycik7XG4gICAgICB9XG5cbiAgICAgIF9uZXh0KHVuZGVmaW5lZCk7XG4gICAgfSk7XG4gIH07XG59Il0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./node_modules/babel-preset-react-app/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js\n");
+
+/***/ }),
+
+/***/ "./web/assets/common.less":
+/*!********************************!*\
+ !*** ./web/assets/common.less ***!
+ \********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("// extracted by mini-css-extract-plugin\n if(false) { var cssReload; }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi93ZWIvYXNzZXRzL2NvbW1vbi5sZXNzP2VkNDciXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQSxPQUFPLEtBQVUsRUFBRSxrQkFLZCIsImZpbGUiOiIuL3dlYi9hc3NldHMvY29tbW9uLmxlc3MuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBleHRyYWN0ZWQgYnkgbWluaS1jc3MtZXh0cmFjdC1wbHVnaW5cbiAgICBpZihtb2R1bGUuaG90KSB7XG4gICAgICAvLyAxNTcxMjE4NDQzMTgwXG4gICAgICB2YXIgY3NzUmVsb2FkID0gcmVxdWlyZShcIiEuLi8uLi9ub2RlX21vZHVsZXMvY3NzLWhvdC1sb2FkZXIvaG90TW9kdWxlUmVwbGFjZW1lbnQuanNcIikobW9kdWxlLmlkLCB7XCJmaWxlTWFwXCI6XCJ7ZmlsZU5hbWV9XCJ9KTtcbiAgICAgIG1vZHVsZS5ob3QuZGlzcG9zZShjc3NSZWxvYWQpO1xuICAgICAgbW9kdWxlLmhvdC5hY2NlcHQodW5kZWZpbmVkLCBjc3NSZWxvYWQpOztcbiAgICB9XG4gICJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./web/assets/common.less\n");
+
+/***/ }),
+
+/***/ "./web/entry.tsx":
+/*!***********************!*\
+ !*** ./web/entry.tsx ***!
+ \***********************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/regenerator */ \"@babel/runtime/regenerator\");\n/* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _Users_yuxiangjie_workspace_github_ykfe_egg_react_ssr_example_ssr_with_ts_node_modules_babel_preset_react_app_node_modules_babel_runtime_helpers_esm_asyncToGenerator__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./node_modules/babel-preset-react-app/node_modules/@babel/runtime/helpers/esm/asyncToGenerator */ \"./node_modules/babel-preset-react-app/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-dom */ \"react-dom\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react-router-dom */ \"react-router-dom\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_router_dom__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _layout__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./layout */ \"./web/layout/index.tsx\");\n\n\nvar _jsxFileName = \"/Users/yuxiangjie/workspace/github/ykfe/egg-react-ssr/example/ssr-with-ts/web/entry.tsx\";\n\n\n\n\n\nvar _require = __webpack_require__(/*! ../config/config.ssr */ \"./config/config.ssr.js\"),\n routes = _require.routes;\n\nvar _require2 = __webpack_require__(/*! ykfe-utils */ \"ykfe-utils\"),\n getWrappedComponent = _require2.getWrappedComponent,\n getComponent = _require2.getComponent;\n\nvar clientRender =\n/*#__PURE__*/\nfunction () {\n var _ref = Object(_Users_yuxiangjie_workspace_github_ykfe_egg_react_ssr_example_ssr_with_ts_node_modules_babel_preset_react_app_node_modules_babel_runtime_helpers_esm_asyncToGenerator__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\n /*#__PURE__*/\n _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default.a.mark(function _callee() {\n return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default.a.wrap(function _callee$(_context) {\n while (1) {\n switch (_context.prev = _context.next) {\n case 0:\n // 客户端渲染||hydrate\n react_dom__WEBPACK_IMPORTED_MODULE_3___default.a[window.__USE_SSR__ ? 'hydrate' : 'render'](react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_4__[\"BrowserRouter\"], {\n __source: {\n fileName: _jsxFileName,\n lineNumber: 15\n },\n __self: this\n }, // 使用高阶组件getWrappedComponent使得csr首次进入页面以及csr/ssr切换路由时调用getInitialProps\n routes.map(function (item) {\n var ActiveComponent = item.Component();\n var Layout = ActiveComponent.Layout || _layout__WEBPACK_IMPORTED_MODULE_5__[\"default\"];\n return react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_4__[\"Route\"], {\n exact: item.exact,\n key: item.path,\n path: item.path,\n render: function render() {\n var WrappedComponent = getWrappedComponent(ActiveComponent);\n return react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(Layout, {\n __source: {\n fileName: _jsxFileName,\n lineNumber: 23\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(WrappedComponent, {\n __source: {\n fileName: _jsxFileName,\n lineNumber: 23\n },\n __self: this\n }));\n },\n __source: {\n fileName: _jsxFileName,\n lineNumber: 21\n },\n __self: this\n });\n })), document.getElementById('app'));\n\n if (false) {}\n\n case 2:\n case \"end\":\n return _context.stop();\n }\n }\n }, _callee, this);\n }));\n\n return function clientRender() {\n return _ref.apply(this, arguments);\n };\n}();\n\nvar serverRender =\n/*#__PURE__*/\nfunction () {\n var _ref2 = Object(_Users_yuxiangjie_workspace_github_ykfe_egg_react_ssr_example_ssr_with_ts_node_modules_babel_preset_react_app_node_modules_babel_runtime_helpers_esm_asyncToGenerator__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(\n /*#__PURE__*/\n _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default.a.mark(function _callee2(ctx) {\n var ActiveComponent, Layout, serverData;\n return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default.a.wrap(function _callee2$(_context2) {\n while (1) {\n switch (_context2.prev = _context2.next) {\n case 0:\n // 服务端渲染 根据ctx.path获取请求的具体组件,调用getInitialProps并渲染\n ActiveComponent = getComponent(routes, ctx.path)();\n Layout = ActiveComponent.Layout || _layout__WEBPACK_IMPORTED_MODULE_5__[\"default\"];\n\n if (!ActiveComponent.getInitialProps) {\n _context2.next = 8;\n break;\n }\n\n _context2.next = 5;\n return ActiveComponent.getInitialProps(ctx);\n\n case 5:\n _context2.t0 = _context2.sent;\n _context2.next = 9;\n break;\n\n case 8:\n _context2.t0 = {};\n\n case 9:\n serverData = _context2.t0;\n ctx.serverData = serverData;\n return _context2.abrupt(\"return\", react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_4__[\"StaticRouter\"], {\n location: ctx.req.url,\n context: serverData,\n __source: {\n fileName: _jsxFileName,\n lineNumber: 40\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(Layout, {\n layoutData: ctx,\n __source: {\n fileName: _jsxFileName,\n lineNumber: 41\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_2___default.a.createElement(ActiveComponent, Object.assign({}, serverData, {\n __source: {\n fileName: _jsxFileName,\n lineNumber: 42\n },\n __self: this\n })))));\n\n case 12:\n case \"end\":\n return _context2.stop();\n }\n }\n }, _callee2, this);\n }));\n\n return function serverRender(_x) {\n return _ref2.apply(this, arguments);\n };\n}();\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ( false ? undefined : serverRender);//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi93ZWIvZW50cnkudHN4PzFlYTIiXSwibmFtZXMiOlsicmVxdWlyZSIsInJvdXRlcyIsImdldFdyYXBwZWRDb21wb25lbnQiLCJnZXRDb21wb25lbnQiLCJjbGllbnRSZW5kZXIiLCJSZWFjdERPTSIsIndpbmRvdyIsIl9fVVNFX1NTUl9fIiwibWFwIiwiaXRlbSIsIkFjdGl2ZUNvbXBvbmVudCIsIkNvbXBvbmVudCIsIkxheW91dCIsImRlZmF1bHRMYXlvdXQiLCJleGFjdCIsInBhdGgiLCJXcmFwcGVkQ29tcG9uZW50IiwiZG9jdW1lbnQiLCJnZXRFbGVtZW50QnlJZCIsInByb2Nlc3MiLCJzZXJ2ZXJSZW5kZXIiLCJjdHgiLCJnZXRJbml0aWFsUHJvcHMiLCJzZXJ2ZXJEYXRhIiwicmVxIiwidXJsIiwiX19pc0Jyb3dzZXJfXyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7ZUFJbUJBLG1CQUFPLENBQUMsb0RBQUQsQztJQUFsQkMsTSxZQUFBQSxNOztnQkFDc0NELG1CQUFPLENBQUMsOEJBQUQsQztJQUE3Q0UsbUIsYUFBQUEsbUI7SUFBcUJDLFksYUFBQUEsWTs7QUFFN0IsSUFBTUMsWUFBWTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEseUVBQUc7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUVuQjtBQUNBQyw0REFBUSxDQUFDQyxNQUFNLENBQUNDLFdBQVAsR0FBcUIsU0FBckIsR0FBaUMsUUFBbEMsQ0FBUixDQUNFLDJEQUFDLDhEQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGVBRUk7QUFDQU4sa0JBQU0sQ0FBQ08sR0FBUCxDQUFXLFVBQUNDLElBQUQsRUFBcUI7QUFDOUIsa0JBQU1DLGVBQWUsR0FBR0QsSUFBSSxDQUFDRSxTQUFMLEVBQXhCO0FBQ0Esa0JBQU1DLE1BQU0sR0FBR0YsZUFBZSxDQUFDRSxNQUFoQixJQUEwQkMsK0NBQXpDO0FBQ0EscUJBQU8sMkRBQUMsc0RBQUQ7QUFBTyxxQkFBSyxFQUFFSixJQUFJLENBQUNLLEtBQW5CO0FBQTBCLG1CQUFHLEVBQUVMLElBQUksQ0FBQ00sSUFBcEM7QUFBMEMsb0JBQUksRUFBRU4sSUFBSSxDQUFDTSxJQUFyRDtBQUEyRCxzQkFBTSxFQUFFLGtCQUFNO0FBQzlFLHNCQUFNQyxnQkFBZ0IsR0FBR2QsbUJBQW1CLENBQUNRLGVBQUQsQ0FBNUM7QUFDQSx5QkFBTywyREFBQyxNQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHFCQUFRLDJEQUFDLGdCQUFEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLG9CQUFSLENBQVA7QUFDRCxpQkFITTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxnQkFBUDtBQUlELGFBUEQsQ0FISixDQURGLEVBY0lPLFFBQVEsQ0FBQ0MsY0FBVCxDQUF3QixLQUF4QixDQWRKOztBQWVBLGdCQUFJQyxLQUFKLEVBQTBELEVBRXpEOztBQXBCa0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsR0FBSDs7QUFBQSxrQkFBWmYsWUFBWTtBQUFBO0FBQUE7QUFBQSxHQUFsQjs7QUF1QkEsSUFBTWdCLFlBQVk7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHlFQUFHLGtCQUFPQyxHQUFQO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNuQjtBQUNNWCwyQkFGYSxHQUVLUCxZQUFZLENBQUNGLE1BQUQsRUFBU29CLEdBQUcsQ0FBQ04sSUFBYixDQUFaLEVBRkw7QUFHYkgsa0JBSGEsR0FHSkYsZUFBZSxDQUFDRSxNQUFoQixJQUEwQkMsK0NBSHRCOztBQUFBLGlCQUlBSCxlQUFlLENBQUNZLGVBSmhCO0FBQUE7QUFBQTtBQUFBOztBQUFBO0FBQUEsbUJBSXdDWixlQUFlLENBQUNZLGVBQWhCLENBQWdDRCxHQUFoQyxDQUp4Qzs7QUFBQTtBQUFBO0FBQUE7QUFBQTs7QUFBQTtBQUFBLDJCQUkrRSxFQUovRTs7QUFBQTtBQUliRSxzQkFKYTtBQUtuQkYsZUFBRyxDQUFDRSxVQUFKLEdBQWlCQSxVQUFqQjtBQUxtQiw4Q0FNWiwyREFBQyw2REFBRDtBQUFjLHNCQUFRLEVBQUVGLEdBQUcsQ0FBQ0csR0FBSixDQUFRQyxHQUFoQztBQUFxQyxxQkFBTyxFQUFFRixVQUE5QztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxlQUNMLDJEQUFDLE1BQUQ7QUFBUSx3QkFBVSxFQUFFRixHQUFwQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxlQUNFLDJEQUFDLGVBQUQsb0JBQXFCRSxVQUFyQjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxlQURGLENBREssQ0FOWTs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxHQUFIOztBQUFBLGtCQUFaSCxZQUFZO0FBQUE7QUFBQTtBQUFBLEdBQWxCOztBQVllTSxxRUFBYSxHQUFHdEIsU0FBSCxHQUFvQmdCLFlBQWhEIiwiZmlsZSI6Ii4vd2ViL2VudHJ5LnRzeC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCBSZWFjdERPTSBmcm9tICdyZWFjdC1kb20nXG5pbXBvcnQgeyBCcm93c2VyUm91dGVyLCBTdGF0aWNSb3V0ZXIsIFJvdXRlIH0gZnJvbSAncmVhY3Qtcm91dGVyLWRvbSdcbmltcG9ydCBkZWZhdWx0TGF5b3V0IGZyb20gJy4vbGF5b3V0J1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gJ21pZHdheSdcblxuaW1wb3J0IHsgUm91dGVJdGVtIH0gZnJvbSAnLi9pbnRlcmZhY2Uvcm91dGUnXG5jb25zdCB7IHJvdXRlcyB9ID0gcmVxdWlyZSgnLi4vY29uZmlnL2NvbmZpZy5zc3InKVxuY29uc3QgeyBnZXRXcmFwcGVkQ29tcG9uZW50LCBnZXRDb21wb25lbnQgfSA9IHJlcXVpcmUoJ3lrZmUtdXRpbHMnKVxuXG5jb25zdCBjbGllbnRSZW5kZXIgPSBhc3luYyAoKTogUHJvbWlzZTx2b2lkPiA9PiB7XG5cbiAgLy8g5a6i5oi356uv5riy5p+TfHxoeWRyYXRlXG4gIFJlYWN0RE9NW3dpbmRvdy5fX1VTRV9TU1JfXyA/ICdoeWRyYXRlJyA6ICdyZW5kZXInXShcbiAgICA8QnJvd3NlclJvdXRlcj5cbiAgICAgIHtcbiAgICAgICAgLy8g5L2/55So6auY6Zi257uE5Lu2Z2V0V3JhcHBlZENvbXBvbmVudOS9v+W+l2Nzcummluasoei/m+WFpemhtemdouS7peWPimNzci9zc3LliIfmjaLot6/nlLHml7bosIPnlKhnZXRJbml0aWFsUHJvcHNcbiAgICAgICAgcm91dGVzLm1hcCgoaXRlbTogUm91dGVJdGVtKSA9PiB7XG4gICAgICAgICAgY29uc3QgQWN0aXZlQ29tcG9uZW50ID0gaXRlbS5Db21wb25lbnQoKVxuICAgICAgICAgIGNvbnN0IExheW91dCA9IEFjdGl2ZUNvbXBvbmVudC5MYXlvdXQgfHwgZGVmYXVsdExheW91dFxuICAgICAgICAgIHJldHVybiA8Um91dGUgZXhhY3Q9e2l0ZW0uZXhhY3R9IGtleT17aXRlbS5wYXRofSBwYXRoPXtpdGVtLnBhdGh9IHJlbmRlcj17KCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgV3JhcHBlZENvbXBvbmVudCA9IGdldFdyYXBwZWRDb21wb25lbnQoQWN0aXZlQ29tcG9uZW50KVxuICAgICAgICAgICAgcmV0dXJuIDxMYXlvdXQ+PFdyYXBwZWRDb21wb25lbnQgLz48L0xheW91dD5cbiAgICAgICAgICB9fSAvPlxuICAgICAgICB9KVxuICAgICAgfVxuICAgIDwvQnJvd3NlclJvdXRlcj5cbiAgICAsIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhcHAnKSlcbiAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAnZGV2ZWxvcG1lbnQnICYmIG1vZHVsZS5ob3QpIHtcbiAgICBtb2R1bGUuaG90LmFjY2VwdCgpXG4gIH1cbn1cblxuY29uc3Qgc2VydmVyUmVuZGVyID0gYXN5bmMgKGN0eDogQ29udGV4dCk6IFByb21pc2U8SlNYLkVsZW1lbnQ+ID0+IHtcbiAgLy8g5pyN5Yqh56uv5riy5p+TIOagueaNrmN0eC5wYXRo6I635Y+W6K+35rGC55qE5YW35L2T57uE5Lu277yM6LCD55SoZ2V0SW5pdGlhbFByb3Bz5bm25riy5p+TXG4gIGNvbnN0IEFjdGl2ZUNvbXBvbmVudCA9IGdldENvbXBvbmVudChyb3V0ZXMsIGN0eC5wYXRoKSgpXG4gIGNvbnN0IExheW91dCA9IEFjdGl2ZUNvbXBvbmVudC5MYXlvdXQgfHwgZGVmYXVsdExheW91dFxuICBjb25zdCBzZXJ2ZXJEYXRhID0gQWN0aXZlQ29tcG9uZW50LmdldEluaXRpYWxQcm9wcyA/IGF3YWl0IEFjdGl2ZUNvbXBvbmVudC5nZXRJbml0aWFsUHJvcHMoY3R4KSA6IHt9XG4gIGN0eC5zZXJ2ZXJEYXRhID0gc2VydmVyRGF0YVxuICByZXR1cm4gPFN0YXRpY1JvdXRlciBsb2NhdGlvbj17Y3R4LnJlcS51cmx9IGNvbnRleHQ9e3NlcnZlckRhdGF9PlxuICAgIDxMYXlvdXQgbGF5b3V0RGF0YT17Y3R4fT5cbiAgICAgIDxBY3RpdmVDb21wb25lbnQgey4uLnNlcnZlckRhdGF9IC8+XG4gICAgPC9MYXlvdXQ+XG4gIDwvU3RhdGljUm91dGVyPlxufVxuZXhwb3J0IGRlZmF1bHQgX19pc0Jyb3dzZXJfXyA/IGNsaWVudFJlbmRlcigpIDogc2VydmVyUmVuZGVyXG4iXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./web/entry.tsx\n");
+
+/***/ }),
+
+/***/ "./web/layout/index.less":
+/*!*******************************!*\
+ !*** ./web/layout/index.less ***!
+ \*******************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("// extracted by mini-css-extract-plugin\n if(false) { var cssReload; }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi93ZWIvbGF5b3V0L2luZGV4Lmxlc3M/MWM3YyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBLE9BQU8sS0FBVSxFQUFFLGtCQUtkIiwiZmlsZSI6Ii4vd2ViL2xheW91dC9pbmRleC5sZXNzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXh0cmFjdGVkIGJ5IG1pbmktY3NzLWV4dHJhY3QtcGx1Z2luXG4gICAgaWYobW9kdWxlLmhvdCkge1xuICAgICAgLy8gMTU3MTIxODQ0MzE1NFxuICAgICAgdmFyIGNzc1JlbG9hZCA9IHJlcXVpcmUoXCIhLi4vLi4vbm9kZV9tb2R1bGVzL2Nzcy1ob3QtbG9hZGVyL2hvdE1vZHVsZVJlcGxhY2VtZW50LmpzXCIpKG1vZHVsZS5pZCwge1wiZmlsZU1hcFwiOlwie2ZpbGVOYW1lfVwifSk7XG4gICAgICBtb2R1bGUuaG90LmRpc3Bvc2UoY3NzUmVsb2FkKTtcbiAgICAgIG1vZHVsZS5ob3QuYWNjZXB0KHVuZGVmaW5lZCwgY3NzUmVsb2FkKTs7XG4gICAgfVxuICAiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./web/layout/index.less\n");
+
+/***/ }),
+
+/***/ "./web/layout/index.tsx":
+/*!******************************!*\
+ !*** ./web/layout/index.tsx ***!
+ \******************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var serialize_javascript__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! serialize-javascript */ \"serialize-javascript\");\n/* harmony import */ var serialize_javascript__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(serialize_javascript__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react-router-dom */ \"react-router-dom\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(react_router_dom__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _assets_common_less__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/assets/common.less */ \"./web/assets/common.less\");\n/* harmony import */ var _assets_common_less__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_assets_common_less__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _index_less__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./index.less */ \"./web/layout/index.less\");\n/* harmony import */ var _index_less__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_index_less__WEBPACK_IMPORTED_MODULE_4__);\nvar _jsxFileName = \"/Users/yuxiangjie/workspace/github/ykfe/egg-react-ssr/example/ssr-with-ts/web/layout/index.tsx\";\n\n\n\n\n\n\nvar commonNode = function commonNode(props) {\n return (// 为了同时兼容ssr/csr请保留此判断,如果你的layout没有内容请使用 props.children ?
{ props.children }
: ''\n react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"normal\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 11\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"h1\", {\n className: \"title\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 12\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_2__[\"Link\"], {\n to: \"/\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 13\n },\n __self: this\n }, \"Egg + React + SSR\"), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"author\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 14\n },\n __self: this\n }, \"by ykfe\")), props.children ? props.children : '')\n );\n};\n\nvar Layout = function Layout(props) {\n if (false) {} else {\n var serverData = props.layoutData.serverData;\n var _props$layoutData$app = props.layoutData.app.config,\n injectCss = _props$layoutData$app.injectCss,\n injectScript = _props$layoutData$app.injectScript;\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"html\", {\n lang: \"en\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 30\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"head\", {\n __source: {\n fileName: _jsxFileName,\n lineNumber: 31\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"meta\", {\n charSet: \"utf-8\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 32\n },\n __self: this\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"meta\", {\n name: \"viewport\",\n content: \"width=device-width, initial-scale=1, shrink-to-fit=no\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 33\n },\n __self: this\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"meta\", {\n name: \"theme-color\",\n content: \"#000000\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 34\n },\n __self: this\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"title\", {\n __source: {\n fileName: _jsxFileName,\n lineNumber: 35\n },\n __self: this\n }, \"React App\"), injectCss && injectCss.map(function (item) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"link\", {\n rel: \"stylesheet\",\n href: item,\n key: item,\n __source: {\n fileName: _jsxFileName,\n lineNumber: 37\n },\n __self: this\n });\n })), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"body\", {\n __source: {\n fileName: _jsxFileName,\n lineNumber: 40\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n id: \"app\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 41\n },\n __self: this\n }, commonNode(props)), serverData && react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"script\", {\n dangerouslySetInnerHTML: {\n __html: \"window.__USE_SSR__=true; window.__INITIAL_DATA__ =\".concat(serialize_javascript__WEBPACK_IMPORTED_MODULE_1___default()(serverData))\n },\n __source: {\n fileName: _jsxFileName,\n lineNumber: 43\n },\n __self: this\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n dangerouslySetInnerHTML: {\n __html: injectScript && injectScript.join('')\n },\n __source: {\n fileName: _jsxFileName,\n lineNumber: 47\n },\n __self: this\n })));\n }\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Layout);//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi93ZWIvbGF5b3V0L2luZGV4LnRzeD9jODY2Il0sIm5hbWVzIjpbImNvbW1vbk5vZGUiLCJwcm9wcyIsImNoaWxkcmVuIiwiTGF5b3V0IiwiX19pc0Jyb3dzZXJfXyIsInNlcnZlckRhdGEiLCJsYXlvdXREYXRhIiwiYXBwIiwiY29uZmlnIiwiaW5qZWN0Q3NzIiwiaW5qZWN0U2NyaXB0IiwibWFwIiwiaXRlbSIsIl9faHRtbCIsInNlcmlhbGl6ZSIsImpvaW4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0EsSUFBTUEsVUFBVSxHQUFHLFNBQWJBLFVBQWEsQ0FBQ0MsS0FBRDtBQUFBLFNBQ2pCO0FBQ0E7QUFBSyxlQUFTLEVBQUMsUUFBZjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxPQUNFO0FBQUksZUFBUyxFQUFDLE9BQWQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsT0FDRSwyREFBQyxxREFBRDtBQUFNLFFBQUUsRUFBQyxHQUFUO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLDJCQURGLEVBRUU7QUFBSyxlQUFTLEVBQUMsUUFBZjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxpQkFGRixDQURGLEVBSVFBLEtBQUssQ0FBQ0MsUUFBTixHQUFpQkQsS0FBSyxDQUFDQyxRQUF2QixHQUFrQyxFQUoxQztBQUZpQjtBQUFBLENBQW5COztBQWNBLElBQU1DLE1BQXdCLEdBQUcsU0FBM0JBLE1BQTJCLENBQUNGLEtBQUQsRUFBcUM7QUFDcEUsTUFBSUcsS0FBSixFQUFtQixFQUFuQixNQUVPO0FBQUEsUUFDR0MsVUFESCxHQUNrQkosS0FBSyxDQUFDSyxVQUR4QixDQUNHRCxVQURIO0FBQUEsZ0NBRStCSixLQUFLLENBQUNLLFVBQU4sQ0FBaUJDLEdBQWpCLENBQXFCQyxNQUZwRDtBQUFBLFFBRUdDLFNBRkgseUJBRUdBLFNBRkg7QUFBQSxRQUVjQyxZQUZkLHlCQUVjQSxZQUZkO0FBR0wsV0FDRTtBQUFNLFVBQUksRUFBQyxJQUFYO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE9BQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsT0FDRTtBQUFNLGFBQU8sRUFBQyxPQUFkO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BREYsRUFFRTtBQUFNLFVBQUksRUFBQyxVQUFYO0FBQXNCLGFBQU8sRUFBQyx1REFBOUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFGRixFQUdFO0FBQU0sVUFBSSxFQUFDLGFBQVg7QUFBeUIsYUFBTyxFQUFDLFNBQWpDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE1BSEYsRUFJRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxtQkFKRixFQU1JRCxTQUFTLElBQUlBLFNBQVMsQ0FBQ0UsR0FBVixDQUFjLFVBQUNDLElBQUQ7QUFBQSxhQUFrQjtBQUFNLFdBQUcsRUFBQyxZQUFWO0FBQXVCLFlBQUksRUFBRUEsSUFBN0I7QUFBbUMsV0FBRyxFQUFFQSxJQUF4QztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxRQUFsQjtBQUFBLEtBQWQsQ0FOakIsQ0FERixFQVVFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE9BQ0U7QUFBSyxRQUFFLEVBQUMsS0FBUjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxPQUFlWixVQUFVLENBQUNDLEtBQUQsQ0FBekIsQ0FERixFQUdJSSxVQUFVLElBQUk7QUFBUSw2QkFBdUIsRUFBRTtBQUM3Q1EsY0FBTSw4REFBdURDLDJEQUFTLENBQUNULFVBQUQsQ0FBaEU7QUFEdUMsT0FBakM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFIbEIsRUFPRTtBQUFLLDZCQUF1QixFQUFFO0FBQzVCUSxjQUFNLEVBQUVILFlBQVksSUFBSUEsWUFBWSxDQUFDSyxJQUFiLENBQWtCLEVBQWxCO0FBREksT0FBOUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsTUFQRixDQVZGLENBREY7QUF3QkQ7QUFDRixDQS9CRDs7QUFpQ2VaLHFFQUFmIiwiZmlsZSI6Ii4vd2ViL2xheW91dC9pbmRleC50c3guanMiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCBzZXJpYWxpemUgZnJvbSAnc2VyaWFsaXplLWphdmFzY3JpcHQnXG5pbXBvcnQgeyBMaW5rIH0gZnJvbSAncmVhY3Qtcm91dGVyLWRvbSdcbmltcG9ydCAnQC9hc3NldHMvY29tbW9uLmxlc3MnXG5pbXBvcnQgJy4vaW5kZXgubGVzcydcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tICdtaWR3YXknXG5cbmNvbnN0IGNvbW1vbk5vZGUgPSAocHJvcHM6IExheW91dFByb3BzKSA9PiAoXG4gIC8vIOS4uuS6huWQjOaXtuWFvOWuuXNzci9jc3Lor7fkv53nlZnmraTliKTmlq3vvIzlpoLmnpzkvaDnmoRsYXlvdXTmsqHmnInlhoXlrrnor7fkvb/nlKggcHJvcHMuY2hpbGRyZW4gPyA8ZGl2PnsgcHJvcHMuY2hpbGRyZW4gfTwvZGl2PiA6ICcnXG4gIDxkaXYgY2xhc3NOYW1lPSdub3JtYWwnPlxuICAgIDxoMSBjbGFzc05hbWU9J3RpdGxlJz5cbiAgICAgIDxMaW5rIHRvPScvJz5FZ2cgKyBSZWFjdCArIFNTUjwvTGluaz5cbiAgICAgIDxkaXYgY2xhc3NOYW1lPSdhdXRob3InPmJ5IHlrZmU8L2Rpdj5cbiAgICA8L2gxPntwcm9wcy5jaGlsZHJlbiA/IHByb3BzLmNoaWxkcmVuIDogJyd9PC9kaXY+XG4pXG5cbmludGVyZmFjZSBMYXlvdXRQcm9wcyB7XG4gIGxheW91dERhdGE/OiBDb250ZXh0LFxuICBjaGlsZHJlbj86IFJlYWN0LlJlYWN0Q2hpbGRyZW4gfCBSZWFjdC5SZWFjdEVsZW1lbnRcbn1cblxuY29uc3QgTGF5b3V0OiBTRkM8TGF5b3V0UHJvcHM+ID0gKHByb3BzOiBMYXlvdXRQcm9wcyk6IEpTWC5FbGVtZW50ID0+IHtcbiAgaWYgKF9faXNCcm93c2VyX18pIHtcbiAgICByZXR1cm4gY29tbW9uTm9kZShwcm9wcylcbiAgfSBlbHNlIHtcbiAgICBjb25zdCB7IHNlcnZlckRhdGEgfSA9IHByb3BzLmxheW91dERhdGFcbiAgICBjb25zdCB7IGluamVjdENzcywgaW5qZWN0U2NyaXB0IH0gPSBwcm9wcy5sYXlvdXREYXRhLmFwcC5jb25maWdcbiAgICByZXR1cm4gKFxuICAgICAgPGh0bWwgbGFuZz0nZW4nPlxuICAgICAgICA8aGVhZD5cbiAgICAgICAgICA8bWV0YSBjaGFyU2V0PSd1dGYtOCcgLz5cbiAgICAgICAgICA8bWV0YSBuYW1lPSd2aWV3cG9ydCcgY29udGVudD0nd2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEsIHNocmluay10by1maXQ9bm8nIC8+XG4gICAgICAgICAgPG1ldGEgbmFtZT0ndGhlbWUtY29sb3InIGNvbnRlbnQ9JyMwMDAwMDAnIC8+XG4gICAgICAgICAgPHRpdGxlPlJlYWN0IEFwcDwvdGl0bGU+XG4gICAgICAgICAge1xuICAgICAgICAgICAgaW5qZWN0Q3NzICYmIGluamVjdENzcy5tYXAoKGl0ZW06IHN0cmluZykgPT4gPGxpbmsgcmVsPSdzdHlsZXNoZWV0JyBocmVmPXtpdGVtfSBrZXk9e2l0ZW19IC8+KVxuICAgICAgICAgIH1cbiAgICAgICAgPC9oZWFkPlxuICAgICAgICA8Ym9keT5cbiAgICAgICAgICA8ZGl2IGlkPSdhcHAnPntjb21tb25Ob2RlKHByb3BzKX08L2Rpdj5cbiAgICAgICAgICB7XG4gICAgICAgICAgICBzZXJ2ZXJEYXRhICYmIDxzY3JpcHQgZGFuZ2Vyb3VzbHlTZXRJbm5lckhUTUw9e3tcbiAgICAgICAgICAgICAgX19odG1sOiBgd2luZG93Ll9fVVNFX1NTUl9fPXRydWU7IHdpbmRvdy5fX0lOSVRJQUxfREFUQV9fID0ke3NlcmlhbGl6ZShzZXJ2ZXJEYXRhKX1gXG4gICAgICAgICAgICB9fSAvPlxuICAgICAgICAgIH1cbiAgICAgICAgICA8ZGl2IGRhbmdlcm91c2x5U2V0SW5uZXJIVE1MPXt7XG4gICAgICAgICAgICBfX2h0bWw6IGluamVjdFNjcmlwdCAmJiBpbmplY3RTY3JpcHQuam9pbignJylcbiAgICAgICAgICB9fSAvPlxuICAgICAgICA8L2JvZHk+XG4gICAgICA8L2h0bWw+XG4gICAgKVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IExheW91dFxuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./web/layout/index.tsx\n");
+
+/***/ }),
+
+/***/ "./web/page/index/index.less":
+/*!***********************************!*\
+ !*** ./web/page/index/index.less ***!
+ \***********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("// extracted by mini-css-extract-plugin\n if(false) { var cssReload; }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi93ZWIvcGFnZS9pbmRleC9pbmRleC5sZXNzPzFlZGEiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQSxPQUFPLEtBQVUsRUFBRSxrQkFLZCIsImZpbGUiOiIuL3dlYi9wYWdlL2luZGV4L2luZGV4Lmxlc3MuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBleHRyYWN0ZWQgYnkgbWluaS1jc3MtZXh0cmFjdC1wbHVnaW5cbiAgICBpZihtb2R1bGUuaG90KSB7XG4gICAgICAvLyAxNTcxMjE4NDQzMTkzXG4gICAgICB2YXIgY3NzUmVsb2FkID0gcmVxdWlyZShcIiEuLi8uLi8uLi9ub2RlX21vZHVsZXMvY3NzLWhvdC1sb2FkZXIvaG90TW9kdWxlUmVwbGFjZW1lbnQuanNcIikobW9kdWxlLmlkLCB7XCJmaWxlTWFwXCI6XCJ7ZmlsZU5hbWV9XCJ9KTtcbiAgICAgIG1vZHVsZS5ob3QuZGlzcG9zZShjc3NSZWxvYWQpO1xuICAgICAgbW9kdWxlLmhvdC5hY2NlcHQodW5kZWZpbmVkLCBjc3NSZWxvYWQpOztcbiAgICB9XG4gICJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./web/page/index/index.less\n");
+
+/***/ }),
+
+/***/ "./web/page/index/index.tsx":
+/*!**********************************!*\
+ !*** ./web/page/index/index.tsx ***!
+ \**********************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-router-dom */ \"react-router-dom\");\n/* harmony import */ var react_router_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_router_dom__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var _index_less__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./index.less */ \"./web/page/index/index.less\");\n/* harmony import */ var _index_less__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_index_less__WEBPACK_IMPORTED_MODULE_2__);\nvar _jsxFileName = \"/Users/yuxiangjie/workspace/github/ykfe/egg-react-ssr/example/ssr-with-ts/web/page/index/index.tsx\";\n\n\n\n\nvar Page = function Page(props) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"normal\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 15\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"welcome\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 16\n },\n __self: this\n }), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"ul\", {\n className: \"list\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 17\n },\n __self: this\n }, props.news && props.news.map(function (item) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"li\", {\n key: item.id,\n __source: {\n fileName: _jsxFileName,\n lineNumber: 20\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n __source: {\n fileName: _jsxFileName,\n lineNumber: 21\n },\n __self: this\n }, \"\\u6587\\u7AE0\\u6807\\u9898: \", item.title), react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"toDetail\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 22\n },\n __self: this\n }, react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_router_dom__WEBPACK_IMPORTED_MODULE_1__[\"Link\"], {\n to: \"/news/\".concat(item.id),\n __source: {\n fileName: _jsxFileName,\n lineNumber: 22\n },\n __self: this\n }, \"\\u70B9\\u51FB\\u67E5\\u770B\\u8BE6\\u60C5\")));\n })));\n};\n\nPage.getInitialProps = function () {\n return Promise.resolve({\n news: [{\n id: '1',\n title: 'Racket v7.3 Release Notes'\n }, {\n id: '2',\n title: 'Free Dropbox Accounts Now Only Sync to Three Devices'\n }, {\n id: '3',\n title: 'Voynich Manuscript Decoded by Bristol Academic'\n }, {\n id: '4',\n title: 'Burger King to Deliver Whoppers to LA Drivers Stuck in Traffic'\n }, {\n id: '5',\n title: 'How much do YouTube celebrities charge to advertise your product? '\n }]\n });\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Page);//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi93ZWIvcGFnZS9pbmRleC9pbmRleC50c3g/YmU2MCJdLCJuYW1lcyI6WyJQYWdlIiwicHJvcHMiLCJuZXdzIiwibWFwIiwiaXRlbSIsImlkIiwidGl0bGUiLCJnZXRJbml0aWFsUHJvcHMiLCJQcm9taXNlIiwicmVzb2x2ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7O0FBVUEsSUFBTUEsSUFBZ0IsR0FBRyxTQUFuQkEsSUFBbUIsQ0FBQ0MsS0FBRCxFQUErQjtBQUN0RCxTQUNFO0FBQUssYUFBUyxFQUFDLFFBQWY7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsS0FDRTtBQUFLLGFBQVMsRUFBQyxTQUFmO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLElBREYsRUFFRTtBQUFJLGFBQVMsRUFBQyxNQUFkO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEtBRUlBLEtBQUssQ0FBQ0MsSUFBTixJQUFjRCxLQUFLLENBQUNDLElBQU4sQ0FBV0MsR0FBWCxDQUFlLFVBQUNDLElBQUQ7QUFBQSxXQUMzQjtBQUFJLFNBQUcsRUFBRUEsSUFBSSxDQUFDQyxFQUFkO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLE9BQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEscUNBQVlELElBQUksQ0FBQ0UsS0FBakIsQ0FERixFQUVFO0FBQUssZUFBUyxFQUFDLFVBQWY7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsT0FBMEIsMkRBQUMscURBQUQ7QUFBTSxRQUFFLGtCQUFXRixJQUFJLENBQUNDLEVBQWhCLENBQVI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsOENBQTFCLENBRkYsQ0FEMkI7QUFBQSxHQUFmLENBRmxCLENBRkYsQ0FERjtBQWVELENBaEJEOztBQWtCQUwsSUFBSSxDQUFDTyxlQUFMLEdBQXVCLFlBQXNCO0FBQzNDLFNBQU9DLE9BQU8sQ0FBQ0MsT0FBUixDQUFnQjtBQUNyQlAsUUFBSSxFQUFFLENBQ0o7QUFDRUcsUUFBRSxFQUFFLEdBRE47QUFFRUMsV0FBSyxFQUFFO0FBRlQsS0FESSxFQUtKO0FBQ0VELFFBQUUsRUFBRSxHQUROO0FBRUVDLFdBQUssRUFBRTtBQUZULEtBTEksRUFTSjtBQUNFRCxRQUFFLEVBQUUsR0FETjtBQUVFQyxXQUFLLEVBQUU7QUFGVCxLQVRJLEVBYUo7QUFDRUQsUUFBRSxFQUFFLEdBRE47QUFFRUMsV0FBSyxFQUFFO0FBRlQsS0FiSSxFQWlCSjtBQUNFRCxRQUFFLEVBQUUsR0FETjtBQUVFQyxXQUFLLEVBQUU7QUFGVCxLQWpCSTtBQURlLEdBQWhCLENBQVA7QUF3QkQsQ0F6QkQ7O0FBMEJlTixtRUFBZiIsImZpbGUiOiIuL3dlYi9wYWdlL2luZGV4L2luZGV4LnRzeC5qcyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IExpbmsgfSBmcm9tICdyZWFjdC1yb3V0ZXItZG9tJ1xuaW1wb3J0ICcuL2luZGV4Lmxlc3MnXG5cbmludGVyZmFjZSBQcm9wcyB7XG4gIG5ld3M6IE5ld3NJdGVtW11cbn1cbmludGVyZmFjZSBOZXdzSXRlbSB7XG4gIGlkOiBzdHJpbmcsXG4gIHRpdGxlOiBzdHJpbmdcbn1cblxuY29uc3QgUGFnZTogU0ZDPFByb3BzPiA9IChwcm9wczogUHJvcHMpOiBKU1guRWxlbWVudCA9PiB7XG4gIHJldHVybiAoXG4gICAgPGRpdiBjbGFzc05hbWU9J25vcm1hbCc+XG4gICAgICA8ZGl2IGNsYXNzTmFtZT0nd2VsY29tZScgLz5cbiAgICAgIDx1bCBjbGFzc05hbWU9J2xpc3QnPlxuICAgICAgICB7XG4gICAgICAgICAgcHJvcHMubmV3cyAmJiBwcm9wcy5uZXdzLm1hcCgoaXRlbTogTmV3c0l0ZW0pID0+IChcbiAgICAgICAgICAgIDxsaSBrZXk9e2l0ZW0uaWR9PlxuICAgICAgICAgICAgICA8ZGl2PuaWh+eroOagh+mimDoge2l0ZW0udGl0bGV9PC9kaXY+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPSd0b0RldGFpbCc+PExpbmsgdG89e2AvbmV3cy8ke2l0ZW0uaWR9YH0+54K55Ye75p+l55yL6K+m5oOFPC9MaW5rPjwvZGl2PlxuICAgICAgICAgICAgPC9saT5cbiAgICAgICAgICApKVxuICAgICAgICB9XG4gICAgICA8L3VsPlxuICAgIDwvZGl2PlxuICApXG59XG5cblBhZ2UuZ2V0SW5pdGlhbFByb3BzID0gKCk6IFByb21pc2U8UHJvcHM+ID0+IHtcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7XG4gICAgbmV3czogW1xuICAgICAge1xuICAgICAgICBpZDogJzEnLFxuICAgICAgICB0aXRsZTogJ1JhY2tldCB2Ny4zIFJlbGVhc2UgTm90ZXMnXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBpZDogJzInLFxuICAgICAgICB0aXRsZTogJ0ZyZWUgRHJvcGJveCBBY2NvdW50cyBOb3cgT25seSBTeW5jIHRvIFRocmVlIERldmljZXMnXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBpZDogJzMnLFxuICAgICAgICB0aXRsZTogJ1ZveW5pY2ggTWFudXNjcmlwdCBEZWNvZGVkIGJ5IEJyaXN0b2wgQWNhZGVtaWMnXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICBpZDogJzQnLFxuICAgICAgICB0aXRsZTogJ0J1cmdlciBLaW5nIHRvIERlbGl2ZXIgV2hvcHBlcnMgdG8gTEEgRHJpdmVycyBTdHVjayBpbiBUcmFmZmljJ1xuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaWQ6ICc1JyxcbiAgICAgICAgdGl0bGU6ICdIb3cgbXVjaCBkbyBZb3VUdWJlIGNlbGVicml0aWVzIGNoYXJnZSB0byBhZHZlcnRpc2UgeW91ciBwcm9kdWN0PyAnXG4gICAgICB9XG4gICAgXVxuICB9KVxufVxuZXhwb3J0IGRlZmF1bHQgUGFnZVxuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./web/page/index/index.tsx\n");
+
+/***/ }),
+
+/***/ "./web/page/news/index.less":
+/*!**********************************!*\
+ !*** ./web/page/news/index.less ***!
+ \**********************************/
+/*! no static exports found */
+/***/ (function(module, exports, __webpack_require__) {
+
+eval("// extracted by mini-css-extract-plugin\n if(false) { var cssReload; }\n //# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi93ZWIvcGFnZS9uZXdzL2luZGV4Lmxlc3M/ZDBhOCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBLE9BQU8sS0FBVSxFQUFFLGtCQUtkIiwiZmlsZSI6Ii4vd2ViL3BhZ2UvbmV3cy9pbmRleC5sZXNzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXh0cmFjdGVkIGJ5IG1pbmktY3NzLWV4dHJhY3QtcGx1Z2luXG4gICAgaWYobW9kdWxlLmhvdCkge1xuICAgICAgLy8gMTU3MTIxODQ0MzI1OFxuICAgICAgdmFyIGNzc1JlbG9hZCA9IHJlcXVpcmUoXCIhLi4vLi4vLi4vbm9kZV9tb2R1bGVzL2Nzcy1ob3QtbG9hZGVyL2hvdE1vZHVsZVJlcGxhY2VtZW50LmpzXCIpKG1vZHVsZS5pZCwge1wiZmlsZU1hcFwiOlwie2ZpbGVOYW1lfVwifSk7XG4gICAgICBtb2R1bGUuaG90LmRpc3Bvc2UoY3NzUmVsb2FkKTtcbiAgICAgIG1vZHVsZS5ob3QuYWNjZXB0KHVuZGVmaW5lZCwgY3NzUmVsb2FkKTs7XG4gICAgfVxuICAiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./web/page/news/index.less\n");
+
+/***/ }),
+
+/***/ "./web/page/news/index.tsx":
+/*!*********************************!*\
+ !*** ./web/page/news/index.tsx ***!
+ \*********************************/
+/*! exports provided: default */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _index_less__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./index.less */ \"./web/page/news/index.less\");\n/* harmony import */ var _index_less__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_index_less__WEBPACK_IMPORTED_MODULE_1__);\nvar _jsxFileName = \"/Users/yuxiangjie/workspace/github/ykfe/egg-react-ssr/example/ssr-with-ts/web/page/news/index.tsx\";\n\n\nvar mockData = {\n 1: \"Racket-on-Chez continues to improve. Snapshot builds are currently available at pre.racket-lang.org, and we expect that Racket-on-Chez will be included as a download option in the next release.\",\n 2: \"This means anyone with more than three devices connected doesn't have to worry right this instant. That will change, however, when it comes time to replace one of your current devices or if you add another device to your collection. At that point, you will have to make a decision.\",\n 3: \"World's most mysterious text is finally cracked: Bristol academic deciphers lost language of 600-year-old Voynich manuscript to reveal astrological sex tips, herbal remedies and other pagan beliefs\",\n 4: \"After a successful test in Mexico City, fast-food chain Burger King will begin delivering food to drivers caught in traffic in Los Angeles in what they have dubbed The Traffic Jam Whopper.\",\n 5: \"Product advertisement and promotion on YouTube is a function of the dedicated audience (or influence) of the individual (influencer) anchoring the advertising or promotion.\"\n};\n\nvar News = function News(props) {\n return react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(\"div\", {\n className: \"news-container\",\n __source: {\n fileName: _jsxFileName,\n lineNumber: 27\n },\n __self: this\n }, \"\\u6587\\u7AE0\\u8BE6\\u60C5: \", props.newsDetail);\n};\n\nNews.getInitialProps = function (ctx) {\n var newsId = false ? undefined : ctx.params.id;\n return Promise.resolve({\n newsDetail: mockData[newsId]\n });\n};\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (News);//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi93ZWIvcGFnZS9uZXdzL2luZGV4LnRzeD8wMWJmIl0sIm5hbWVzIjpbIm1vY2tEYXRhIiwiTmV3cyIsInByb3BzIiwibmV3c0RldGFpbCIsImdldEluaXRpYWxQcm9wcyIsImN0eCIsIm5ld3NJZCIsIl9faXNCcm93c2VyX18iLCJwYXJhbXMiLCJpZCIsIlByb21pc2UiLCJyZXNvbHZlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQTtBQUNBO0FBRUEsSUFBTUEsUUFBUSxHQUFHO0FBQ2Ysd01BRGU7QUFFZixnU0FGZTtBQUdmLDRNQUhlO0FBSWYsbU1BSmU7QUFLZjtBQUxlLENBQWpCOztBQXFCQSxJQUFNQyxJQUFnQixHQUFHLFNBQW5CQSxJQUFtQixDQUFDQyxLQUFELEVBQWtCO0FBQ3pDLFNBQ0U7QUFBSyxhQUFTLEVBQUMsZ0JBQWY7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsbUNBQ1NBLEtBQUssQ0FBQ0MsVUFEZixDQURGO0FBS0QsQ0FORDs7QUFRQUYsSUFBSSxDQUFDRyxlQUFMLEdBQXVCLFVBQUNDLEdBQUQsRUFBYztBQUNuQyxNQUFNQyxNQUFNLEdBQUdDLE1BQWEsR0FBR0YsU0FBSCxHQUF5QkEsR0FBRyxDQUFDRyxNQUFKLENBQVdDLEVBQWhFO0FBQ0EsU0FBT0MsT0FBTyxDQUFDQyxPQUFSLENBQWdCO0FBQ3JCUixjQUFVLEVBQUVILFFBQVEsQ0FBQ00sTUFBRDtBQURDLEdBQWhCLENBQVA7QUFHRCxDQUxEOztBQU9lTCxtRUFBZiIsImZpbGUiOiIuL3dlYi9wYWdlL25ld3MvaW5kZXgudHN4LmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0ICcuL2luZGV4Lmxlc3MnXG5cbmNvbnN0IG1vY2tEYXRhID0ge1xuICAxOiBgUmFja2V0LW9uLUNoZXogY29udGludWVzIHRvIGltcHJvdmUuIFNuYXBzaG90IGJ1aWxkcyBhcmUgY3VycmVudGx5IGF2YWlsYWJsZSBhdCBwcmUucmFja2V0LWxhbmcub3JnLCBhbmQgd2UgZXhwZWN0IHRoYXQgUmFja2V0LW9uLUNoZXogd2lsbCBiZSBpbmNsdWRlZCBhcyBhIGRvd25sb2FkIG9wdGlvbiBpbiB0aGUgbmV4dCByZWxlYXNlLmAsXG4gIDI6IGBUaGlzIG1lYW5zIGFueW9uZSB3aXRoIG1vcmUgdGhhbiB0aHJlZSBkZXZpY2VzIGNvbm5lY3RlZCBkb2Vzbid0IGhhdmUgdG8gd29ycnkgcmlnaHQgdGhpcyBpbnN0YW50LiBUaGF0IHdpbGwgY2hhbmdlLCBob3dldmVyLCB3aGVuIGl0IGNvbWVzIHRpbWUgdG8gcmVwbGFjZSBvbmUgb2YgeW91ciBjdXJyZW50IGRldmljZXMgb3IgaWYgeW91IGFkZCBhbm90aGVyIGRldmljZSB0byB5b3VyIGNvbGxlY3Rpb24uIEF0IHRoYXQgcG9pbnQsIHlvdSB3aWxsIGhhdmUgdG8gbWFrZSBhIGRlY2lzaW9uLmAsXG4gIDM6IGBXb3JsZCdzIG1vc3QgbXlzdGVyaW91cyB0ZXh0IGlzIGZpbmFsbHkgY3JhY2tlZDogQnJpc3RvbCBhY2FkZW1pYyBkZWNpcGhlcnMgbG9zdCBsYW5ndWFnZSBvZiA2MDAteWVhci1vbGQgVm95bmljaCBtYW51c2NyaXB0IHRvIHJldmVhbCBhc3Ryb2xvZ2ljYWwgc2V4IHRpcHMsIGhlcmJhbCByZW1lZGllcyBhbmQgb3RoZXIgcGFnYW4gYmVsaWVmc2AsXG4gIDQ6IGBBZnRlciBhIHN1Y2Nlc3NmdWwgdGVzdCBpbiBNZXhpY28gQ2l0eSwgZmFzdC1mb29kIGNoYWluIEJ1cmdlciBLaW5nIHdpbGwgYmVnaW4gZGVsaXZlcmluZyBmb29kIHRvIGRyaXZlcnMgY2F1Z2h0IGluIHRyYWZmaWMgaW4gTG9zIEFuZ2VsZXMgaW4gd2hhdCB0aGV5IGhhdmUgZHViYmVkIFRoZSBUcmFmZmljIEphbSBXaG9wcGVyLmAsXG4gIDU6IGBQcm9kdWN0IGFkdmVydGlzZW1lbnQgYW5kIHByb21vdGlvbiBvbiBZb3VUdWJlIGlzIGEgZnVuY3Rpb24gb2YgdGhlIGRlZGljYXRlZCBhdWRpZW5jZSAob3IgaW5mbHVlbmNlKSBvZiB0aGUgaW5kaXZpZHVhbCAoaW5mbHVlbmNlcikgYW5jaG9yaW5nIHRoZSBhZHZlcnRpc2luZyBvciBwcm9tb3Rpb24uYFxufVxuXG5pbnRlcmZhY2UgTWF0Y2gge1xuICBwYXJhbXM6IFBhcmFtc1xufVxuaW50ZXJmYWNlIFBhcmFtcyB7XG4gIGlkPzogc3RyaW5nXG59XG5pbnRlcmZhY2UgQ3R4IHtcbiAgbWF0Y2g6IE1hdGNoLFxuICBwYXJhbXM/OiBQYXJhbXNcbn1cbmludGVyZmFjZSBQcm9wcyB7XG4gIG5ld3NEZXRhaWw6IHN0cmluZ1xufVxuY29uc3QgTmV3czogU0ZDPFByb3BzPiA9IChwcm9wczogUHJvcHMpID0+IHtcbiAgcmV0dXJuIChcbiAgICA8ZGl2IGNsYXNzTmFtZT0nbmV3cy1jb250YWluZXInID5cbiAgICAgIOaWh+eroOivpuaDhToge3Byb3BzLm5ld3NEZXRhaWx9XG4gICAgPC9kaXY+XG4gIClcbn1cblxuTmV3cy5nZXRJbml0aWFsUHJvcHMgPSAoY3R4OiBDdHgpID0+IHtcbiAgY29uc3QgbmV3c0lkID0gX19pc0Jyb3dzZXJfXyA/IGN0eC5tYXRjaC5wYXJhbXMuaWQgOiBjdHgucGFyYW1zLmlkXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoe1xuICAgIG5ld3NEZXRhaWw6IG1vY2tEYXRhW25ld3NJZF1cbiAgfSlcbn1cblxuZXhwb3J0IGRlZmF1bHQgTmV3c1xuIl0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./web/page/news/index.tsx\n");
+
+/***/ }),
+
+/***/ "@babel/runtime/regenerator":
+/*!*********************************************!*\
+ !*** external "@babel/runtime/regenerator" ***!
+ \*********************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+eval("module.exports = require(\"@babel/runtime/regenerator\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJAYmFiZWwvcnVudGltZS9yZWdlbmVyYXRvclwiPzY4NGYiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEiLCJmaWxlIjoiQGJhYmVsL3J1bnRpbWUvcmVnZW5lcmF0b3IuanMiLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJAYmFiZWwvcnVudGltZS9yZWdlbmVyYXRvclwiKTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///@babel/runtime/regenerator\n");
+
+/***/ }),
+
+/***/ "path":
+/*!***********************!*\
+ !*** external "path" ***!
+ \***********************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+eval("module.exports = require(\"path\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJwYXRoXCI/NzRiYiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsImZpbGUiOiJwYXRoLmpzIiwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicGF0aFwiKTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///path\n");
+
+/***/ }),
+
+/***/ "react":
+/*!************************!*\
+ !*** external "react" ***!
+ \************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+eval("module.exports = require(\"react\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWFjdFwiPzU4OGUiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEiLCJmaWxlIjoicmVhY3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJyZWFjdFwiKTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///react\n");
+
+/***/ }),
+
+/***/ "react-dom":
+/*!****************************!*\
+ !*** external "react-dom" ***!
+ \****************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+eval("module.exports = require(\"react-dom\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWFjdC1kb21cIj81ZTlhIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6InJlYWN0LWRvbS5qcyIsInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcInJlYWN0LWRvbVwiKTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///react-dom\n");
+
+/***/ }),
+
+/***/ "react-router-dom":
+/*!***********************************!*\
+ !*** external "react-router-dom" ***!
+ \***********************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+eval("module.exports = require(\"react-router-dom\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJyZWFjdC1yb3V0ZXItZG9tXCI/NTNiOSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsImZpbGUiOiJyZWFjdC1yb3V0ZXItZG9tLmpzIiwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwicmVhY3Qtcm91dGVyLWRvbVwiKTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///react-router-dom\n");
+
+/***/ }),
+
+/***/ "serialize-javascript":
+/*!***************************************!*\
+ !*** external "serialize-javascript" ***!
+ \***************************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+eval("module.exports = require(\"serialize-javascript\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJzZXJpYWxpemUtamF2YXNjcmlwdFwiPzE2ZjkiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEiLCJmaWxlIjoic2VyaWFsaXplLWphdmFzY3JpcHQuanMiLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJzZXJpYWxpemUtamF2YXNjcmlwdFwiKTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///serialize-javascript\n");
+
+/***/ }),
+
+/***/ "ykfe-utils":
+/*!*****************************!*\
+ !*** external "ykfe-utils" ***!
+ \*****************************/
+/*! no static exports found */
+/***/ (function(module, exports) {
+
+eval("module.exports = require(\"ykfe-utils\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vZXh0ZXJuYWwgXCJ5a2ZlLXV0aWxzXCI/NDBlMyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsImZpbGUiOiJ5a2ZlLXV0aWxzLmpzIiwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKFwieWtmZS11dGlsc1wiKTsiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///ykfe-utils\n");
+
+/***/ })
+
+/******/ });
\ No newline at end of file
diff --git a/example/ssr-with-ts/output/static/css/Page.css b/example/ssr-with-ts/output/static/css/Page.css
new file mode 100644
index 00000000..d0a92cce
--- /dev/null
+++ b/example/ssr-with-ts/output/static/css/Page.css
@@ -0,0 +1,64 @@
+* {
+ margin: 0;
+ padding: 0;
+}
+a {
+ color: #fff;
+ text-decoration: none;
+}
+ul {
+ list-style: none;
+}
+
+.normal {
+ font-family: Georgia, sans-serif;
+ text-align: center;
+}
+body {
+ background-color: #f2f3f5;
+}
+.title {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 55px;
+ background-color: darkslateblue;
+ color: #fff;
+}
+.author {
+ position: absolute;
+ font-size: 15px;
+ bottom: 10px;
+ right: 100px;
+}
+
+.list {
+ background-color: #fff;
+ width: 1000px;
+ margin: 100px auto;
+}
+.list li {
+ display: flex;
+ justify-content: space-between;
+ background-color: #fff;
+ padding: 20px 30px 20px 80px;
+ border-bottom: 1px solid #eee;
+ position: relative;
+ line-height: 20px;
+}
+.list li .toDetail a {
+ font-size: 14px;
+ color: #888;
+}
+
+.news-container {
+ width: 1000px;
+ background-color: #fff;
+ margin: 100px auto;
+ text-align: left;
+ line-height: 30px;
+ letter-spacing: 1px;
+ padding: 10px;
+}
+
diff --git a/example/ssr-with-ts/package.json b/example/ssr-with-ts/package.json
new file mode 100644
index 00000000..9d92dc83
--- /dev/null
+++ b/example/ssr-with-ts/package.json
@@ -0,0 +1,93 @@
+{
+ "name": "ssr-with-ts",
+ "version": "1.0.0",
+ "description": "",
+ "private": true,
+ "dependencies": {
+ "egg-scripts": "^2.10.0",
+ "midway": "^1.0.0",
+ "react": "^16.10.2",
+ "react-dom": "^16.10.2",
+ "typescript": "3.6.4",
+ "yk-cli": "^2.6.0",
+ "ykfe-utils": "^2.1.2"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.4.4",
+ "@babel/plugin-transform-runtime": "^7.5.5",
+ "@babel/polyfill": "^7.4.4",
+ "@babel/preset-env": "^7.5.5",
+ "@babel/register": "^7.0.0",
+ "@babel/runtime": "^7.5.5",
+ "@types/mocha": "^5.2.7",
+ "@types/node": "^10.6.0",
+ "@types/react": "16.9.5",
+ "@types/react-dom": "16.9.1",
+ "@types/react-router-dom": "^5.1.0",
+ "@types/serialize-javascript": "^1.5.0",
+ "babel-loader": "8.0.4",
+ "babel-preset-react-app": "^9.0.2",
+ "concurrently": "^4.1.0",
+ "cross-env": "^5.2.0",
+ "css-hot-loader": "^1.4.3",
+ "css-loader": "1.0.0",
+ "css-modules-require-hook": "^4.2.3",
+ "egg-proxy": "^1.1.0",
+ "egg-static": "^2.2.0",
+ "file-loader": "2.0.0",
+ "less": "^3.9.0",
+ "less-loader": "^4.1.0",
+ "midway-bin": "1",
+ "midway-demo-lib": "1",
+ "mini-css-extract-plugin": "^0.5.0",
+ "optimize-css-assets-webpack-plugin": "5.0.1",
+ "postcss-flexbugs-fixes": "4.1.0",
+ "postcss-loader": "3.0.0",
+ "postcss-preset-env": "^6.0.5",
+ "postcss-safe-parser": "4.0.1",
+ "react-dev-utils": "^8.0.0",
+ "react-router-dom": "^5.1.2",
+ "rimraf": "^2.6.3",
+ "terser-webpack-plugin": "^1.2.0",
+ "ts-node": "^8.3.0",
+ "tslib": "^1.8.1",
+ "tslint": "^5.11.0",
+ "tslint-config-standard": "^8.0.1",
+ "tslint-midway-contrib": "1",
+ "typescript": "^3.5.0",
+ "url-loader": "1.1.1",
+ "webpack": "4.19.1",
+ "webpack-bundle-analyzer": "^3.0.3",
+ "webpack-cli": "^3.3.3",
+ "webpack-dev-server": "3.3.1",
+ "webpack-manifest-plugin": "^2.0.4",
+ "webpack-merge": "^4.1.4",
+ "webpack-node-externals": "^1.7.2"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ },
+ "scripts": {
+ "prod": "rimraf dist && npm run build && egg-scripts start --title=egg-server-ssr-with-ts --framework=midway --ts",
+ "start": "concurrently \"npm run ssr\" \"npm run csr\"",
+ "stop": "egg-scripts stop --title=egg-server-ssr-with-ts",
+ "clean": "midway-bin clean",
+ "ssr": "concurrently \"cross-env NODE_ENV=local midway-bin dev --ts\" \"cross-env NODE_ENV=development webpack --watch --config ./build/webpack.config.server.js\"",
+ "csr": "cross-env NODE_ENV=development ykcli dev",
+ "build": "rimraf dist && npm run build:midway && npm run build:fe",
+ "build:midway": "midway-bin build -c",
+ "build:fe": "npm run build:ssr && npm run build:csr",
+ "build:ssr": "cross-env NODE_ENV=production webpack --config ./build/webpack.config.server.js",
+ "build:csr": "cross-env NODE_ENV=production ykcli build"
+ },
+ "midway-bin-clean": [
+ ".vscode/.tsbuildinfo",
+ "dist"
+ ],
+ "repository": {
+ "type": "git",
+ "url": ""
+ },
+ "author": "ykfe",
+ "license": "MIT"
+}
diff --git a/example/ssr-with-ts/src/app/controller/page.ts b/example/ssr-with-ts/src/app/controller/page.ts
new file mode 100644
index 00000000..0586d52e
--- /dev/null
+++ b/example/ssr-with-ts/src/app/controller/page.ts
@@ -0,0 +1,44 @@
+import { controller, get, provide, inject, Context } from 'midway'
+const renderToStream = require('ykfe-utils/lib/renderToStream')
+const ssrConfig = require('../../../config/config.ssr')
+
+@provide()
+@controller('/')
+export class Page {
+
+ @inject()
+ ctx: Context
+ async index () {
+ try {
+ // Page为webpack打包的chunkName,项目默认的entry为Page
+ this.ctx.type = 'text/html'
+ this.ctx.status = 200
+ Object.assign(this.ctx.app.config, ssrConfig)
+ const stream = await renderToStream(this.ctx, this.ctx.app.config)
+ this.ctx.body = stream
+ } catch (error) {
+ this.ctx.logger.error(`Page Controller renderToStream Error ${error}`)
+ }
+ }
+
+}
+@provide()
+@controller('/user')
+export class User {
+
+ @inject()
+ ctx: Context
+
+ @get('/')
+ async index () {
+ try {
+ // Page为webpack打包的chunkName,项目默认的entry为Page
+ this.ctx.type = 'text/html'
+ this.ctx.status = 200
+ this.ctx.body = 'hello user'
+ } catch (error) {
+ this.ctx.logger.error(`Page Controller renderToStream Error ${error}`)
+ }
+ }
+
+}
diff --git a/example/ssr-with-ts/src/app/public/README.md b/example/ssr-with-ts/src/app/public/README.md
new file mode 100644
index 00000000..eda21ab1
--- /dev/null
+++ b/example/ssr-with-ts/src/app/public/README.md
@@ -0,0 +1 @@
+## public static file directory!
\ No newline at end of file
diff --git a/example/ssr-with-ts/src/app/router.ts b/example/ssr-with-ts/src/app/router.ts
new file mode 100644
index 00000000..63089d65
--- /dev/null
+++ b/example/ssr-with-ts/src/app/router.ts
@@ -0,0 +1,11 @@
+const config = require('../../config/config.ssr')
+
+module.exports = function (app: any) {
+ const { router } = app
+ console.log('前端路由已经自动绑定,规则如下:')
+ config.routes.map((route: any) => {
+ console.log(route.path + ' => ' + route.controller + '.' + route.handler)
+ router.get(`${route.path}`, app.generateController(`${route.controller}.${route.handler}`))
+ })
+
+}
diff --git a/example/ssr-with-ts/src/config/config.default.ts b/example/ssr-with-ts/src/config/config.default.ts
new file mode 100644
index 00000000..c9d469a3
--- /dev/null
+++ b/example/ssr-with-ts/src/config/config.default.ts
@@ -0,0 +1,22 @@
+import { EggAppConfig, EggAppInfo, PowerPartial } from 'midway'
+const path = require('path')
+export type DefaultConfig = PowerPartial
+interface MyEggAppInfo extends EggAppInfo {
+ appDir?: string
+}
+export default (appInfo: MyEggAppInfo) => {
+ const config = {} as DefaultConfig
+
+ // use for cookie sign key, should change to your own and keep security
+ config.keys = appInfo.name + '_1570684373953_5206'
+
+ // add your config here
+ config.middleware = [
+ ]
+ config.static = {
+ dir: [path.join(appInfo.appDir, '/output'), path.join(appInfo.appDir, '/src/public')],
+ prefix: '/'
+
+ }
+ return config
+}
diff --git a/example/ssr-with-ts/src/config/config.local.ts b/example/ssr-with-ts/src/config/config.local.ts
new file mode 100644
index 00000000..48000197
--- /dev/null
+++ b/example/ssr-with-ts/src/config/config.local.ts
@@ -0,0 +1,17 @@
+export const development = {
+ watchDirs: [
+ 'app',
+ 'lib',
+ 'service',
+ 'config',
+ 'app.ts',
+ 'agent.ts',
+ 'interface.ts'
+ ],
+ overrideDefault: true
+}
+
+export const proxy = {
+ host: 'http://127.0.0.1:8000', // 本地开发的时候代理前端打包出来的资源地址
+ match: /(\/static)|(\/sockjs-node)|(\/__webpack_dev_server__)|hot-update/
+}
diff --git a/example/ssr-with-ts/src/config/plugin.ts b/example/ssr-with-ts/src/config/plugin.ts
new file mode 100644
index 00000000..7dc1ca53
--- /dev/null
+++ b/example/ssr-with-ts/src/config/plugin.ts
@@ -0,0 +1,8 @@
+import { EggPlugin } from 'midway'
+export default {
+ static: true, // default is true
+ proxy: {
+ package: 'egg-proxy',
+ enable: true
+ }
+} as EggPlugin
diff --git a/example/ssr-with-ts/tsconfig.json b/example/ssr-with-ts/tsconfig.json
new file mode 100644
index 00000000..271e3f4e
--- /dev/null
+++ b/example/ssr-with-ts/tsconfig.json
@@ -0,0 +1,35 @@
+{
+ "compileOnSave": true,
+ "compilerOptions": {
+ "esModuleInterop": true,
+ "lib": [
+ "esnext"
+ ],
+ "declaration": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "incremental": true,
+ "inlineSourceMap": true,
+ "module": "commonjs",
+ "newLine": "lf",
+ "noFallthroughCasesInSwitch": true,
+ "noUnusedLocals": true,
+ "outDir": "dist",
+ "pretty": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "strictPropertyInitialization": false,
+ "stripInternal": true,
+ "target": "ES2017",
+ "jsx": "react"
+ },
+ "exclude": [
+ "app/public",
+ "app/views",
+ "dist",
+ "node_modules*",
+ "test",
+ "**/*.spec.ts",
+ "web"
+ ]
+}
\ No newline at end of file
diff --git a/example/ssr-with-ts/tslint.json b/example/ssr-with-ts/tslint.json
new file mode 100644
index 00000000..68ccd7c7
--- /dev/null
+++ b/example/ssr-with-ts/tslint.json
@@ -0,0 +1,6 @@
+{
+ "extends": [
+ "tslint-midway-contrib",
+ "tslint-config-standard"
+ ]
+}
diff --git a/example/ssr-with-ts/web/assets/common.less b/example/ssr-with-ts/web/assets/common.less
new file mode 100755
index 00000000..b78da2a3
--- /dev/null
+++ b/example/ssr-with-ts/web/assets/common.less
@@ -0,0 +1,13 @@
+* {
+ margin: 0;
+ padding: 0;
+}
+
+a {
+ color: #fff;
+ text-decoration: none;
+}
+
+ul {
+ list-style: none;
+}
\ No newline at end of file
diff --git a/example/ssr-with-ts/web/entry.tsx b/example/ssr-with-ts/web/entry.tsx
new file mode 100644
index 00000000..6b38a3aa
--- /dev/null
+++ b/example/ssr-with-ts/web/entry.tsx
@@ -0,0 +1,46 @@
+import React from 'react'
+import ReactDOM from 'react-dom'
+import { BrowserRouter, StaticRouter, Route } from 'react-router-dom'
+import defaultLayout from './layout'
+import { Context } from 'midway'
+
+import { RouteItem } from './interface/route'
+const { routes } = require('../config/config.ssr')
+const { getWrappedComponent, getComponent } = require('ykfe-utils')
+
+const clientRender = async (): Promise => {
+
+ // 客户端渲染||hydrate
+ ReactDOM[window.__USE_SSR__ ? 'hydrate' : 'render'](
+
+ {
+ // 使用高阶组件getWrappedComponent使得csr首次进入页面以及csr/ssr切换路由时调用getInitialProps
+ routes.map((item: RouteItem) => {
+ const ActiveComponent = item.Component()
+ const Layout = ActiveComponent.Layout || defaultLayout
+ return {
+ const WrappedComponent = getWrappedComponent(ActiveComponent)
+ return
+ }} />
+ })
+ }
+
+ , document.getElementById('app'))
+ if (process.env.NODE_ENV === 'development' && module.hot) {
+ module.hot.accept()
+ }
+}
+
+const serverRender = async (ctx: Context): Promise => {
+ // 服务端渲染 根据ctx.path获取请求的具体组件,调用getInitialProps并渲染
+ const ActiveComponent = getComponent(routes, ctx.path)()
+ const Layout = ActiveComponent.Layout || defaultLayout
+ const serverData = ActiveComponent.getInitialProps ? await ActiveComponent.getInitialProps(ctx) : {}
+ ctx.serverData = serverData
+ return
+
+
+
+
+}
+export default __isBrowser__ ? clientRender() : serverRender
diff --git a/example/ssr-with-ts/web/interface/config.ts b/example/ssr-with-ts/web/interface/config.ts
new file mode 100644
index 00000000..f10954f6
--- /dev/null
+++ b/example/ssr-with-ts/web/interface/config.ts
@@ -0,0 +1,7 @@
+export interface Config {
+ type: string,
+ serverJs: string,
+ baseDir: string,
+ injectScript: string[],
+ injectCss: string[]
+}
diff --git a/example/ssr-with-ts/web/interface/route.ts b/example/ssr-with-ts/web/interface/route.ts
new file mode 100644
index 00000000..c60e28f9
--- /dev/null
+++ b/example/ssr-with-ts/web/interface/route.ts
@@ -0,0 +1,9 @@
+export interface RouteItem {
+ path: string,
+ exact?: boolean,
+ Component (): Component
+}
+
+export interface Component {
+ Layout?: new () => React.Component