src/index.tsx
`import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import App from './app';
import { loadableReady } from '@loadable/component';
loadableReady(() =>
ReactDOM.hydrate(
,
document.getElementById('root')
)
).then(() => console.log('loaded'));`
server/index.ts
`import path from 'path';
import Koa from 'koa';
import router from './route';
import serve from 'koa-static';
import proxy from 'koa2-proxy-middleware';
const app = new Koa();
/*静态资源访问 访问client打包之后的js文件*/
const main = serve(path.resolve('dist'));
app.use(main);
// 后台请求转发
const options = {
targets: {
'/api/(.*)': {
target: 'http://forum-api.kdocs.cn/',
changeOrigin: true
}
}
};
app.use(proxy(options));
app.use(router.routes());
app.listen(3002, () => {
console.log('服务端渲染 run in port 3002');
});
`
server/route.tsx
`import { Context } from 'koa';
import Router from 'koa-router';
import React from 'react';
import { StaticRouter } from 'react-router-dom';
import { renderToString } from 'react-dom/server';
import App from '../src/App';
import { ChunkExtractor } from '@loadable/server';
import path from 'path';
import { enableStaticRendering } from 'mobx-react-lite';
enableStaticRendering(true);
const router = new Router();
//对于所有的路由 我们都返回这个
//只有手动刷新的时候 才会执行这个方法
//否则是 客户端的 broswerRouter接管路由
router.get('(.*)', async (ctx: Context) => {
console.log(ctx.request.url);
// This is the stats file generated by webpack loadable plugin
const statsFile = path.resolve('dist/loadable-stats.json');
// We create an extractor from the statsFile
const extractor = new ChunkExtractor({ statsFile, entrypoints: ['index'] });
// Wrap your application using "collectChunks"
const jsx = extractor.collectChunks(
);
// Render your application
const html = renderToString(jsx);
// You can now collect your script tags
const scriptTags = extractor.getScriptTags(); // or extractor.getScriptElements();
// You can also collect your "preload/prefetch" links
const linkTags = extractor.getLinkTags();
ctx.response.body = `
${linkTags}
环境版本说明: os: win10 node: v14.17.5 antd-mobile: ^5.0.0-beta.15 @loadable/component: ^5.15.0 @loadable/server: ^5.15.1
app.tsx `import { Switch, Route } from 'react-router-dom'; import loadable from '@loadable/component'; import './main.css';
const Index = loadable(() => import('./pages/index')); const Announcement = loadable(() => import('./pages/announcement')); const Me = loadable(() => import('./pages/me')); const Faq = loadable(() => import('./pages/faq')); const Mainsite = loadable(() => import('./pages/mainsite')); const AnswerEditor = loadable(() => import('./components/answer/editor')); const Search = loadable(() => import('./pages/search')); const SearchResult = loadable(() => import('./pages/searchResult')); const QuestionEditor = loadable(() => import('./components/question/editor'));
function App() { return (
} export default App; `
src/index.tsx `import ReactDOM from 'react-dom'; import { BrowserRouter as Router } from 'react-router-dom'; import App from './app'; import { loadableReady } from '@loadable/component';
loadableReady(() => ReactDOM.hydrate(