书接上回(React 同构),之前提到这个任务迟迟未完成,影响了业务进度,所以任务重新抛了出来,虽然暂时没交过来,但未雨绸缪就改造了下之前搭建的 React 脚手架,变成了 React 脚手架-同构版。
接下来聊一聊一些可能需要注意的点。
数据模型
注意区分浏览器和服务端的模型区别,在浏览器端只属于一个用户访问,但是服务端是大家都能访问,访问的又是一个地方,所以需要对每次请求生成新的实例。
// bad
let state = {};
app.get('*', (res) => {
state.username = res.username;
})
// good
app.get('*', (res) => {
let state = {};
state.username = res.username;
})
全局变量
window
下的全局变量,相比大家都不陌生,常用的 location
, localStorage
,但要注意的是这些都属于 BOM
,服务端没有这些东西,所以这些 API
需要框架注入进去。
- 第一种解决方法是确保这些
API
在第一次渲染时不会被调用,比如可以放到useEffect
中。 - 第二种是通过
webpack.DefinePlugin
去注入。 - 第三种是在
Node
中注入globalThis.location = { pathname: req.url, }
另外需要注意的是,新的 EcmaScript
规范中提供了 globalThis
对象,它指向了不同环境下的全局对象中的 this
,即浏览器中的 window
,Node
环境下的 global
。
WARNING: 但是更要注意的是,前端和后端的上下文,在 Node 中,globalThis 会共享到全局,所以如果 A 用户改了,B 用户会得到 A 用户修改后的结果。
导入资源
这里的资源泛指所有除 .js, .jsx
后缀的文件,比如 css-loader
,这里,注意不要从服务端运行时生成文件或者插入 DOM
,保留链接或者资源标识符即可。