Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

开发完成 isom-fetch #1

Closed
malcolmyu opened this issue Jun 11, 2016 · 4 comments
Closed

开发完成 isom-fetch #1

malcolmyu opened this issue Jun 11, 2016 · 4 comments
Assignees
Labels
Milestone

Comments

@malcolmyu
Copy link
Contributor

malcolmyu commented Jun 11, 2016

isom-fetch 工具的作用是在服务端渲染时提供首页数据。

背景方案

目前使用服务端渲染进行 react 同构实现,已经可以完成前后端大部分业务代码和路由的公用,但是尚不能解决首屏数据的问题。由于在同构项目中,首屏数据的获取在前端路由控制和后端路由控制时的处理逻辑不同(前端是使用 ajax 请求获取数据,后端是直接调用 controller 方法获取数据库数据),因此需要使用一种同构写法来弥合这种区别。

现有方案

贴吧 react 最佳实践

贴吧 react 最佳实践 提供了一种解决方案,给出了重要的思路:react 在渲染页面时是同步的,因此可以在每一次请求到来时构建一个新的 fetch 实例,将其置于全局中,在执行 action 的 fetch 时使用这个单例;但是本方案也有以下问题:

  1. 需要使用装饰器在 controller 中用 method 和 url 装饰,与路由本身有冲突,代码冗余;
  2. 一个请求只能对应一个 controller,无法走其他中间件;
  3. 改动的范围太大,还需要 hack 中间件。

本方案有自己的构建工具:fit-isomorphic-redux-tools

redial

redial 是一个给组件添加自定义生命周期,并能自由触发的组件,在项目breko-hubreact-production-starter 中对其使用方法有明确的展示。

但是这个方式也有自己的问题:它针对的是有 node 做中间层,而没有自己的数据库的项目,也就是说,前后端获取数据的方式都是使用 axios 进行请求发送,通过在初始 state 时写入不同的 host 和 protocol 来像不同的源发送请求。

尽管不适用于我们的场景,但是它解决了前端路由进入页面时,不重新发起请求的问题,值得研究。

期望实现方案

同构 fetch

目前期望实现的方式是简单的编写一个同构的 fetch 方法,该方法在前端的作用是发送请求,在后端的作用是处理中间件获取数据。该方法在前端的写法为:

import iFetch from 'isom-fetch';

const fetch = iFetch.create({
  baseURL: '/api',
  headers: {}
});

fetch.get('/user', { id });

在后端的写法为:

import iFetch from 'isom-fetch';

app.use(function* (next) {
  const location = this.originalUrl;
  match({ routes, location }, (
    error, redirectLocation, renderProps
  ) => {
    // 直接使用 app 本身,获取其全部中间件,模拟请求执行流程
    const fetch = iFetch.use(this);
    // begin SSR
    if (renderProps) {
      render();
      fetch.all(() => {
        // SSR actually
        render();
      });
    }
  });
});

遇到问题

在实现的过程中,遇到一些问题:

  1. 采用模拟请求执行的方式,如果在这些中间件里用户调用了 httpRequest 或 httpResponse 的某些方法会报错;
  2. 页面加载后,前端路由进入时依然会发送 ajax 请求,导致冗余。这一点可以参考 redial 的处理方式,思考怎么解决。
@malcolmyu malcolmyu added this to the 框架搭建完成 milestone Jun 11, 2016
@malcolmyu
Copy link
Contributor Author

后来经过研究发现……没必要访问函数啊!后端依然可以发 http 请求直接请求本服务的资源,因此可以直接使用 redial……

@malcolmyu malcolmyu self-assigned this Jun 11, 2016
@EdwonLim
Copy link
Member

发 http 很费 io 的,性能不行!

@malcolmyu
Copy link
Contributor Author

完成 isom-fetch 的开发,但是测试没有跑全。项目地址

@malcolmyu
Copy link
Contributor Author

先把工具引入到项目中再进行进一步的测试

malcolmyu pushed a commit that referenced this issue Dec 21, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants