一、传统 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 的方式有所认识和有所选择了呢?如果我文章中还有描述不清楚的地方还请指出,我会继续优化,先谢过了。