項目地址:https://github.com/m-Ryan/typ...css
- 先後端分離
- typeScript
- 服務端渲染
- react-router按需加載
- redux
- 使用最新的react v.16.4
router.tsx 路由html
... function RouterConfig() { return ( <Switch> <Route path="/" exact={true} component={Home} /> <Route path="/about" component={About} /> <Route path="/hello" component={Hello} /> </Switch> ); }
ssr.tsx 匹配路徑前端
... export default (url: string | Object, context: any,store: any)=>{ return <Provider store={store}> <StaticRouter location={url} context={context}> <Routes/> </StaticRouter> </Provider> }
renderFullPage.ts 渲染頁面react
... const renderFullPage = (ctx : IRouterContext, newState:Object ) => { let context = {} const myHtml = fs.readFileSync("app/web/assets/dist/templete.html", 'utf-8'); // 獲得初始 state 建立新的 Redux store 實例 const store = createStore(reducers, newState); // 從 Redux store 獲得初始 state,注入到window const finalState = store.getState() let initState = `<script> window.__INITIAL_STATE__ = ${JSON.stringify(finalState)}</script>`; //根據路由獲取html並注入到<div id="root"></div>,將 initState 插到該節點後面 const html = ReactDOMServer.renderToString(ssr(ctx.req.url, context, store)); let renderPage = myHtml.replace(/(\<div\s+id\="root"\>)(.|\n|\r)*(\<\/div\>)/i, "$1" + html + "$3" + initState); ctx.type = 'html'; ctx.body = renderPage; } export default renderFullPage;
index.tsx 前端的路由處理webpack
... const preloadedState = window.__INITIAL_STATE__ || {} // // 使用初始 state 建立 Redux store const store = createStore(reducers, preloadedState) render( <Provider store={store}> <BrowserRouter> <Routes/> </BrowserRouter> </Provider>, document.getElementById('root') as HTMLElement )
1..redux方面,先建立新的 Redux store 實例,將咱們須要初始的state合併到 store
2.經過 store.getState() 獲取最終的finalState
3.經過 StaticRouter 能夠獲取路徑匹配的頁面組件,並經過 ReactDOMServer.renderToString 轉化爲HTML元素
ssr.tsx 主要作了兩件事:
1.將初始的 store 注入redux
2.返回帶有 store 數據的路徑匹配的頁面組件,也就是說這個頁面已是有初始數據了git4.將讀取的html模板注入數據,在這裏咱們須要經過簡單的正則替換一下
在 <div id="root"></div> 中插入咱們的html元素
在 <div id="root"></div> 後面插入<script> window.__INITIAL_STATE__ = ${JSON.stringify(finalState)}</script>
github5.將這個頁面發送出去
6.js加載的時候會讀取
window.__INITIAL_STATE__
的數據,合併到 store
export default (html, finalState)=>( ` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"> <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" /> <meta name="renderer" content="webkit"> <title>typeScript-koa-ssr-antd</title> <link href="/dist/index.076a9ad74b9f609c4d81.css" rel="stylesheet"> </head> <body> <div id="root">${html}</div> window.__INITIAL_STATE__ = ${JSON.stringify(finalState)}</script> </body> </html> ` )
git clone git@github.com:m-Ryan/typescript-koa-ssr-react-boilerplate.git
cd typescript-koa-ssr-react-boilerplate
- cd app/web 首次使用,先 npm install
- 開發環境 npm start
- 生產環境 npm run build
- 首次使用,先 npm install
- 開發環境 npm start
- 生產環境 npm run build