Open closertb opened 5 years ago
大佬我用的dva-core 为啥store老是公用,我设成回调函数了,还是不行
大佬我用的dva-core 为啥store老是公用,我设成回调函数了,还是不行
你store 是那种概念的,model 中的初始state? 比如:
export default ({
namespace: 'index',
state: {
total: 0,
num: Math.floor(Math.random() * 1000),
},
// ...
}
上面这种写法肯定是公用的,因为其实质就是一个静态导出,这是语法决定的。
如果不是,show your code
就是上面的那种用法,跟直接的客户端的用法是一样的,我看打包输出的是全局的store,所以肯定是所有用户公用了,但是我看你源码中也是这么写的,在你里面没有发现这个问题。
export default {
namespace: 'menuTree',
state: {
routes: []
},
effects: {
* reset(payload, {call, put, select, update}) {
const {routes} = yield select(state => state.menuTree);
routes.push(111111)
yield put({
type: 'save',
payload: {
routes: [...routes]
},
});
},
},
reducers: {
save(state, {payload}) {
return {...state, ...payload};
},
},
};
经你这么点播,我把model原有的对象形式,换成换成函数的形式,然后在导出没问题了。
起
过去一年半一直在用React + Dva + Antd写中后台项目,从最初的6小时一个页面,到现在的两小时一套页面,其中的秘诀就是不断总结与熟悉,写一些适合业务的轮子,比如:antd-doddle。今年随着业务稳定,有机会去尝试一些自己感兴趣的方向,比如前端工程化、SSR、 小程序;最近由于苹果对App上架流程的调整,部门需要写一个官网。虽然说一个上午就写出来了,但从官网的角度,以及对成品不断追求的态度,现在这个官网太Low了, 无Seo,无移动端适配,无首屏渲染。所以最近开始接触SSR,试图用一个更加专业的方案去重新打造这个官网。
方案筛选
其实没啥筛选的,页面框架React是铁打的。而React的服务端渲染,市面上一般就有完全自己搭和选择NextJs。
细说方案
同构渲染一套代码两端运行:即可以像SPA项目一样,打包一套静态资源代码,在浏览器独立运行;又可以像传统jsp,php页面一样,由服务端页面直出,但又高于这些技术,因为在首屏时依赖直出,而在后面的操作又有SPA一样的操作体验,这就是同构的优势所在。但这也要求了更高的架构思想,对前端提出了更高的要求,主要体现在下面几个方面:
路由的兼容
如果对SPA和SSR了解的话,就知道:SPA一般我们用Hash路由HashRoutr(#/home),而SSR在浏览器端则采用传统路由,即浏览器路由BrowserRouter(/home),但只有去尝试SSR后我才知道,还有一种路由被称之为静态路由StaticRouter(/home),看起来和BrowserRouter相似,之所以称之为静态的,就是它没有前进,后退,跳转这些路由操作。具体可参考React-Router的相关介绍。这三种路由分别对应三种入口:
const history = createHistory(); const app = createApp({ history }); app.start();
const App = () => (
);
render( , document.getElementById('app'));
// ssr渲染,浏览器端渲染入口 const history = createHistory();
const app = createApp({ history, initialState: window.states && JSON.parse(window.states), }); app.start(); delete window.states; const App = () => (
);
ReactDOM.hydrate( , document.getElementById('app'));
代码非常简短,没有做什么差异化的兼容处理,只做了dva数据对象的初始化;扩展了这个数据对象;加了一个history属性,目的是listen插件需要;model对象的加载。
SPA渲染与SSR渲染数据流处理的差异就在首屏。通常我们在做SPA时,将获取页面初始状态的操作都放在页面监听中(dva model的subsciption),而不是最初的componentDidMount这个钩子里。但在服务端做首屏渲染时,这种方案就不可取,没有history变化这一说,所以需要采用其他方案。最早写React的人都知道,曾今还有个方法叫getInitialState,但后面这个方法被弃用。在NextJs中也存在一个这样一个方法,其目的就是做服务端渲染的首屏数据获取。我在自己的设计中也沿用了这个思想,具体是:
这样做还有一个好处就是,BrowerRouter由于是初次进这个页面,所以listen监听不会生效,所以不会存在重复获取初始状态这个问题。以上就是数据流方案的整体思路,也是整个SSR中比较重点的。
服务端代码实现
SSR渲染和纯前端渲染最大的区别就是,你需要写一个服务器。而Node给我们提供了这样的能力,让我们可以用js语言写后端服务。之所以从众多的后端框架中选择了Koa,是因为前段时间刚好对Koa有一个比较全面的了解。Koa经典的洋葱模型,将服务实现插件化,非常易于扩展,Async Await的插件语法,也非常符合时代的潮流。后端服务主要在功能上要实现:
html的动态生成: renderToString服务端渲染
静态资源服务和路由的转发拦截比较简单,基本几行代码就搞定。
重点还是在服务端渲染这一块,在我的项目里,这部分是由ssrMiddleware中间件来完成的,源码也比较简单,如果认真读且理解了前面讲的,那这一部分的源码就比较好理解了。大体上讲,做了三件事:
动态html生成
好了以上,就是主要代码的实现,关于stateMiddleaWare,实现就简单了,感兴趣的,可以看源码了解。
一些没提到但又很重要的点
写在最后
由于公司项目,不便提供源码,如果你感兴趣,可以去fork我的示例项目SSrTemplate, 分支ssr, 也可通过下面两种方式下载:
关联文章收集
从零到一搭建React SSR工程架构