ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vortigern同构数据加载深度解析:redux-thunk + asyncConnect客户端服务器双端取数

Vortigern同构数据加载深度解析:redux-thunk + asyncConnect客户端服务器双端取数 Vortigern同构数据加载深度解析redux-thunk asyncConnect客户端服务器双端取数【免费下载链接】vortigernA universal boilerplate for building web applications w/ TypeScript, React, Redux, Server Side Rendering and more.项目地址: https://gitcode.com/gh_mirrors/vo/vortigernVortigern 是一款基于 TypeScript、React、Redux 构建的通用 Web 应用脚手架它的同构数据加载机制由两把钥匙组成用redux-thunk处理异步取数用redux-connect 的 asyncConnect实现客户端与服务器端的双端取数。本文带你走通服务端先取数 → 序列化状态 → 客户端水合复用的完整链路快速看懂 Vortigern 同构渲染SSR下的数据层设计 一、什么是同构数据加载为什么需要双端取数在纯客户端渲染CSR的 SPA 里页面要等 JS 下载执行完才开始请求数据首屏空白、SEO 也不友好。而同构Universal应用的思路是服务器端先执行路由匹配和异步取数把带有真实数据的首屏 HTML 直接返回客户端加载后通过水合hydrate复用服务器已经取好的状态不重复发请求交互无缝衔接。Vortigern 把这套流程开箱即用地封装好了核心角色如下组件在双端取数中的职责所在文件redux-thunk编写异步 action按请求中/成功/失败分步 dispatchsrc/app/redux/store.tsasyncConnectredux-connect在组件上声明异步数据需求服务端执行、客户端复用src/app/containers/Stars/index.tsxloadOnServer让服务器等所有异步数据就绪后再渲染 HTMLsrc/server.tsxisomorphic-fetch统一浏览器与服务端的 fetch APIsrc/server.tsx、src/client.tsxreduxAsyncConnect reducer缓存已解析的异步结果是客户端不再重取的关键src/app/redux/reducers.ts二、redux-thunk把异步取数写成三步动作Vortigern 的官方示例是 Stars 页面——请求 GitHub API 获取仓库 star 数。数据模块位于src/app/redux/modules/stars/index.ts它定义了三种 action 类型stars/GET_REQUEST发起请求isFetching置为 truestars/GET_SUCCESS拿到stargazers_count写入countstars/GET_FAILURE记录错误信息error置为 true。对应的异步 action creator 就是一个 thunkexport function getStars() { return (dispatch) { dispatch(starsRequest()); return fetch(https://api.github.com/repos/barbar/vortigern) .then(res res.ok ? res.json().then(d dispatch(starsSuccess(d.stargazers_count))) : res.json().then(d dispatch(starsFailure(d)))) .catch(err dispatch(starsFailure(err))); }; }这种一个取数流程 三个可预测的 action的写法让状态变化模型定义在src/app/models/stars.ts完全可测试。而 redux-thunk 正是让dispatch(getStars())得以接收函数的中间件它与routerMiddleware一起在src/app/redux/store.ts中注册。三、asyncConnect客户端服务器双端取数的关键光有 thunk 还不够——谁来触发它、谁来保证两端行为一致答案是组件上的asyncConnect装饰器。src/app/containers/Stars/index.tsx的核心只有寥寥几行asyncConnect([{ promise: ({ store: { dispatch } }) dispatch(getStars()), }]) connect(state ({ stars: state.stars })) class Stars extends React.Component { /* ... */ }它的工作机制非常精巧服务端渲染到该组件时asyncConnect会执行promise回调把取数挂起取数结果被 redux-connect 缓存进独立的reduxAsyncConnect状态块该 reducer 在src/app/redux/reducers.ts中通过combineReducers注册客户端水合同一组件时检测到状态里已有缓存结果直接跳过取数逻辑。也就是说同一段asyncConnect声明在两端语义自动切换为取数与复用这就是双端取数零重复请求的秘密 ⚡四、服务端流程loadOnServer 先取数、后渲染服务器入口src/server.tsx对每个请求做了 4 件事用createMemoryHistory(req.originalUrl)创建内存路由并调用configureStore(memoryHistory)生成每请求独立的 store避免请求间状态串扰通过 react-router 的match匹配路由路由表在src/app/routes/index.tsx共/、/about、/counter、/stars四条调用loadOnServer(asyncRenderData).then(...)——等待全部 asyncConnect 的 promise 解析才执行ReactDOMServer.renderToString此时输出到浏览器的 HTML 已经包含了真实数据。顺序不能颠倒如果跳过loadOnServer直接渲染SSR 页面只会输出Fetching Stars的占位文案首屏数据就丢了。五、客户端流程window.INITIAL_STATE水合服务器渲染完页面后还要把状态交棒给浏览器src/app/containers/Html/index.tsx使用 serialize-javascript 把整个 store 状态序列化为window.__INITIAL_STATE__...内联进 HTML客户端入口src/client.tsx读出该状态作为初始参数传给configureStore(browserHistory, window.__INITIAL_STATE__)最后用ReactDOM.hydrate而非render让 React 复用服务器生成的 DOM 节点。完整链路可以浓缩为一句话浏览器请求 → 服务端路由匹配 → asyncConnect 触发 getStarsthunk→ loadOnServer 等待解析 → 输出带数据 HTML → 状态序列化进INITIAL_STATE→ 浏览器水合 → 客户端命中缓存、不再重复请求六、快速上手克隆 Vortigern 并启动想亲眼验证双端取数按下面命令即可本地跑起来git clone https://gitcode.com/gh_mirrors/vo/vortigern cd vortigern npm install npm start启动后访问/stars路由页面显示的数字正是服务器端经 GitHub API 取回的 star 数——你可以打开浏览器网络面板确认数据请求发生在服务端客户端并未重复发起。开发模式下 store 还自动挂上了 logger 与 Redux DevTools见src/app/redux/store.ts能直观看到三个 action 依次流过。七、如何测试同构取数逻辑异步取数的正确性靠单测保障Vortigern 提供了完整示例src/app/redux/modules/stars/index.test.ts用fetch-mock分别 mock 200 与 400 两种响应配合redux-mock-store断言 action 序列必须是GET_REQUEST → GET_SUCCESS或GET_FAILUREsrc/app/helpers/TestHelper.tsx封装了带 thunk 中间件的mockStore与组件渲染工具可直接复用执行npm test即可运行全部用例Karma Mocha Chai。八、常见问题 FAQQ为什么客户端水合后不会再次请求 GitHub APIAasyncConnect 的结果缓存在state.reduxAsyncConnect中注册于src/app/redux/reducers.ts客户端水合时 redux-connect 判定数据已存在即跳过 promise 执行。Q为什么服务端要为每个请求新建 storeAsrc/server.tsx中每个请求独立创建 store保证并发请求之间状态隔离互不污染。Q为什么用 serialize-javascript 而不是 JSON.stringifyA前者能安全处理 undefined、函数等值并规避内联脚本的 XSS 风险见src/app/containers/Html/index.tsx。QRedux DevTools 在生产环境会存在吗A不会。src/app/redux/store.ts仅在开发环境注入 logger 与 DevTools 增强生产构建自动剔除。一句话总结Vortigern 用 redux-thunk 把异步取数变成可预测、可测试的 action 流再用 asyncConnect 让同一段声明在服务端取数、在客户端复用配合 loadOnServer 与INITIAL_STATE序列化构成了一套简洁而完整的同构数据加载方案——这也是学习 SSR 应用数据层设计的一份优质样板。【免费下载链接】vortigernA universal boilerplate for building web applications w/ TypeScript, React, Redux, Server Side Rendering and more.项目地址: https://gitcode.com/gh_mirrors/vo/vortigern创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表