1.0.24 • Published 3 years ago

@weilluo/react-ssr v1.0.24

Weekly downloads
124
License
ISC
Repository
github
Last release
3 years ago

React SSR

  1. 页面需要放在 src/pages

pages/index.js

export default [
    {
        path: '/',
        getPage: () => import('./home')
    },
    {
        path: '/about',
        getPage: () => import('./about')
    },
    {
        path: '/demo',
        getPage: () => import('./demo')
    }
]

pages/about.js

import React from 'react';
import { Page, usePage, usePageState } from '@weilluo/react-ssr'

function View() {
    const page = usePage()
    const state = usePageState()

    return (
        <div className='about' onClick={page.plusNumber}>
            About {state.number}
        </div>
    )
}

export default class About extends Page {
    View = View
    styles = []

    getInitialState = async () => {
        return {
            title: 'About',
            number: 1,
        }
    }

    plusNumber = () => {
        const state = this.store.getState()
        this.store.dispatch({ number: state.number + 1 })
    }
}
  1. 服务路由放在 src/routes

routes/index.js

export * from './test';

routes/test.js

export function test(app) {
    app.use((req, res, next) => {
        res.json({ test: 'test api' })
    })
}
  1. 页面模版放在 src/routes 中, 文件名为 Layout
import React from 'react'

export default function Layout(props) {
    const { initialState, assets, publicPath, styleContents } = props

    const propsScript = `
        (function() {
            window.__INITIAL_STATE__ = ${JSON.stringify(initialState)}
        })()
    `;

    return (
        <html>
            <head>
                {styleContents?.map((styleContent, index) => 
                    <style key={index} type="text/css" dangerouslySetInnerHTML={{ __html: styleContent }}></style>
                )}
                <title>{initialState.title}</title>
            </head>
            <body>
                <div id="root" dangerouslySetInnerHTML={{ __html: props.content }} />

                <script dangerouslySetInnerHTML={{ __html: propsScript }}></script>

                <script src={`${publicPath}/js/${assets.index}`}></script>
                <script src={`${publicPath}/js/${assets.vendor}`}></script>
            </body>
        </html>
    )
}
  1. 接口请求

import { fetch } from '@weilluo/react-ssr'
依赖 [isomorphic-fetch](https://www.npmjs.com/package/isomorphic-fetch)

示例地址

Demo

Todo List

  1. 加载 css 时, 先取缓存
  2. fetch 请求时, 可以添加一些监控

QA

  1. 服务热重启时, 删除 require.cache, 对 server 目录中的文件无效, 但对 pages 中的有效 ??

PS

  1. 动态加载, 服务端使用 babel-plugin-dynamic-import-node, 客户端使用 @babel/plugin-syntax-dynamic-import

  2. 如果要支持 dynamic import 按照页面切分 js 文件, 需要使用 babel-load 处理ts,不能使用 awesome-typescript-loader

  3. webpack 配置, extensions 需要加入 .js .jsx, 其他依赖如 react-dom 中包含 js/jsx 文件

  4. 服务端渲染, 没法 load less / css 等, 所以不放入 webpack 流程, 单独开线程处理