一、传统 web 开发方式

这种方式开发和配置起来稍微有点复杂,这里先来讲一下从零开始配置的方式:

1、从零开始配置
// 引入 express
const express = require('express');
const app = express();
// 定义一个路由
app.get('/', (req, res) => {
  // 为/路由发送一个响应消息
  res.send('Hello World!');
})
// 开启 http 服务,监听 8080
app.listen(8080);

这是官方的标准示例,从零起步看起来非常简单,但也是最无用的,因为你无法用这些代码做什么事情。我们还差一个东西,就是 HTML。这个怎么来呢,有两种方法。

第一种:

res.send('<h1>我是 h1 标签</h1>');

因为 html 也是字符串,所以我们可以在响应消息中写 html,这样也能开发出一个网站来。但我们不会这么做,因为太不方便开发了,所以我们有了第二种方法:使用模板引擎。

模板引擎是一种把你写的类似于 html 的代码转换成标准 html 代码的工具。

模板引擎有很多种类,目的一样,写法不一样,唯一不变的就是:每个作者都认为自己开发的模板引擎是最好的。作为吃瓜群众,我不懂,也不敢问。

你也不用到处找了,这个链接是 14 个 js 模板引擎的介绍:
js 模板引擎介绍

要使用模板引擎也很简单,有两种方法,一种是使用 ExpressJs 官方提供的一个框架生成工具:express-generator

安装express-generator
$ yarn global add express-generator
// 或
$ npm i -g express-generator
使用
# 使用默认模板
$ express my-app
# 通过帮助命令查看支持哪些模板
$ express -h
# 使用 pug 模板
$ express -v pug my-app

执行完毕后,一个包含模板引擎配置的框架就生成好了。

另一种就是express-generator工具没有集成进去的模板引擎,得看着手册自己配。
比如我想要使用 React 模板,只能看着文档自己配了。

前后端分离开发习惯的改变

如果你做了很长时间的前后端分离开发,那么退回到原始的 web 开发可能会有点不适应,举个例子:

// pug 模板语法
button(class='div-class', onclick='play()') 按钮

如果你希望 onclick 里面的 play 函数要能执行的话,必须在 public 目录下有一个能在浏览器下运行的 js 文件,然后再引入进来:

script(src='/javascripts/index.js')

因为模板引擎只是帮你把模板转换为 html 字符串,发送给了浏览器。

传统开发方式的总结

自从接触了前后端分离的开发方式,再来看这种传统的 web 开发,就感觉开发起来很费劲,因为你得使用一套模板引擎才能让你的工作看起来轻松些。这种开发方式随着时间的推移我觉得会被慢慢地淘汰掉的。

二、前后端分离的开发方式

在研究完 express 的传统开发方式后,就把它给抛弃了,咱们还是得回到前后端分离的开发方式中来。

各开发方式还是有点不一样,

1、完全分离

即:纯前端 + 纯后端

express 作为后端服务,提供 api 接口。前端负责 html 页面的开发,调接口。

所以就会有两个服务:前端服务和后端服务。
这是目前最主流的开发方式,就不过多介绍了。

2、非完全分离

即:前端依赖后端服务

express 作为后端服务的同时也作为静态服务负责渲染前端页面。

这种方式我觉得比较有意思。

前端页面开发完后,打包生成前端资源(html,js,css等),放到后端 express 的静态目录下,假设是 public 目录:

public/
  js/
  css/
  index.html
app.js

在 app.js 中:

const express = require('express');
const app = express();
// 使用 express.static 中间件来处理静态资源
app.use(express.static(path.join(__dirname, 'public')));
app.listen(8080);

这样就可以了,如果你前端页面是采用 React,Vue 或 Angular 等开发的,那么你都无需设置任何路由。这种方式有点像 nginx 静态服务。

如果需要 api,那么就需要设置路由了。假设我们把/api/开头的路径都看成是接口服务:

// 使用专门的 api 路由来处理 api 请求
app.use('/api/', require('./routes/api.js'));

api.js 文件:

var express = require('express');
var router = express.Router();

// /api/user-list 接口
router.post('/user-list', function(req, res, next) {
  // 接口逻辑
  res.send('user');
});

module.exports = router;

启动前端服务时,就可以请求你自定义的接口了,这是一个典型的前端依赖后端服务的开发方式。

接下来我们扩展一下思路

在开发前端页面的时候,一般会开启一个前端开发服务,比如使用 webpack-dev-server。那么在开启这个服务的时候,我还想使用一些 mock 库来模拟接口来生成一些模拟数据要怎么办呢?

是有办法的。

因为 webpack-dev-server 也使用 express,所以就可以使用中间件来做这件事啦,还是有两种方式,第一种比较简单,适合接口不多的情况:

// 使用 app.post
devServer: {
  before: function(app, server) {
    // 对 /api/mock 的请求返回自定义数据
    app.post('/api/mock', function(req, res) {
      res.json({ custom: 'response' });
    });
  }
}

第二种呢稍微高级点,适合接口比较多的情况:

const mockMiddleware = require('./mock-middleware');

// 使用 app.use
devServer: {
  before: function(app, server) {
    // 拦截所有 /api 开头的请求,转发到 mockMiddleware 中进一步处理
    app.use('/api', mockMiddleware);
  }
}
// mock-middleware.js
const express = require('express');
const router = express.Router();

// 响应 /api/mock 请求
router.post('/mock', function(req, res, next) {
  res.json({
    data: {
      name: 123,
      sex: 1,
    }
  })
})

module.exports = router;

这样开启前端服务的同时,你也可以请求 mock 数据了。

咱们还可以再做的更高大上一点,比如我们只需要写 mock 配置,其余的事情则由别的工具来做:

// mock 配置文件
module.exports = {
  'POST /api/user-list': [
    {
      name: '张三',
      age: 13,
    },
    {
      name: '李四',
      age: 12,
    }
  ],
  'POST /api/user/123': {
    // ...
  }
}

我们只需要在一个专门用来存放 mock 的地方配置好 mock 数据,其它工具对这种数据先预解析一遍,最后会生成 app.post 之类的配置,目前网上就有这种工具,比如:功能强大的UmiJS

看完以上介绍,你是否已经对 express 开发 web 的方式有所认识和有所选择了呢?如果我文章中还有描述不清楚的地方还请指出,我会继续优化,先谢过了。


kybetter
483 声望10 粉丝

学无止境