0. 引言

这篇来讲如何搭建一个 Express 后台,前端开发环境如何配置代理,以及生产环境的应用。

上一篇在初始化项目的时候,已经安装好了 Expresshttp-proxy-middleware,现在就来启动一个 Express 后台。

[Demo 的完整代码在 这里]

1. Express 服务器

我的 Demo 对后台的要求非常简单,只是作为一个 API 的请求中转,向微信拿 openid,仅此而已。至于其他的业务操作不在本文讨论范围。

所以,本文建立的是一个最简化的 Express 后台,只包括最简单的请求处理能力,一个文件,几行代码,就搞定了。

在项目根目录下创建 app_server.js:

const express = require('express')
const app = express()

app.get('/api/fetch-wechat-userinfo', (req, res) => {
  return res.json({
    status: 'ok',
  })
})

app.listen(3005, () => {
  console.log('App is listening on port 3005...')
})

服务简单到 “令人发指”:导入 express,写一个 route,然后在 3005 端口启动。

2. 前端代理

因为前端请求有跨域问题,不能直接发起 ajax 请求,所以采用官方推荐的做法,在开发环境配置代理(生产环境稍候介绍)。

http-proxy-middleware 已经安装完成,直接在 src 目录下创建 setupProxy.js 文件(文件名是约定好的):

const { createProxyMiddleware } = require('http-proxy-middleware')

module.exports = function(app) {
  app.use(
    '/api', 
    createProxyMiddleware({
      target: 'http://localhost:3005',
      changeOrigin: true
    })
  )
}

这个配置表示,代理服务会把所有 /api 开头的请求代理到本机 3005 端口即我们的 Express 服务。

然后我们就可以从前端发个测试请求,来验证一下整个流程了。

3. 验证请求

在 AuthorizedRoute 组件中加入一个 useEffect hook 如下:

// 别忘了引入 useEffect 和 axios 库
import React, { useContext, useEffect } from 'react'
import axios from 'axios'

...

const AuthorizedRoute = ({ children, ...rest }) => {

  ...

  useEffect(() => {
    axios(`/api/fetch-wechat-userinfo`)
      .then(res => console.log(res.data))
  })

  ...

然后启动 Express 服务:

node app_server.js

当我们再次访问 ‘/’ 页面的时候,发现控制台输出 {status: "ok"},后台响应测试成功。

接下来我们要做的,就是在这个后台响应中,完成真正的微信 API 请求。

4. 生产环境怎么办?

React 官方只提供了开发环境的代理模式,却只字未提生产环境的配置,网上也几乎没有什么有用的信息,生产环境也的确无法使用这个代理的方法。

我的生产环境是 nginx 直接使用打包后的静态文件,当然与开发环境的 npm start 不同,但我转念一想,后端的 Express 也只是一个服务而已,功能也很简单,只是转发微信 API,那只要在 nginx 匹配一下路由把 /api 请求转发到 3005 服务不就完了。

于是改写后的 nginx 配置如下:

location ^~ /api/ {
  proxy_redirect off;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header X-Forwarded-Host $host;

  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";

  proxy_pass http://localhost:3005;
}

location / {
  try_files $uri $uri/ /index.html;
}

这样,所有以 /api 开头的请求都会转发到 3005 端口的服务(后端 Express 服务),其余仍然用打包后的静态文件,成功地拆分了不同的服务。

5. 总结

Demo 只涉及微信手机客户端一键登录,功能非常简单,所以用到的 Express 也非常简单,而且没有设置数据库,后端分离的话可以扩展一下 api 把请求转发给真正的后端应用服务器(不是 Demo 的 Express),而复杂的应用就要彻底改一下架构了。

下一篇正式进入微信登录功能,注意是手机端通过微信客户端登录第三方网站的方式(网页授权)。