用 Node.js 编写 后端RESTful API 接口给前端调用
github项目地址:https://github.com/HgzMaggie/Vue-Travel

不要看图,主要在vue2.x的基础上写的练手项目。
实质上在写模拟项目是,一般在前端中写后端的模拟数据,供前端方便使用和整体功能的调试;
但是到了实质上的项目,往往前端调用后端的Api,会更加的多一点;
为什么呢?
先谈谈前后端在这一个过程吧:
如果前端的代码已经编写完毕了,后端的接口也已经写好的时候,我们就需要把前端模拟的数据删掉,去尝试使用后端提供的数据进行一个前后端的一个调试,这个过程就称为前后端的联调;
接下来为具体的过程:
-
先在github上创建项目;
-
在本地的文件夹目录 通过git clone xxx (创建项目的地址)
-
一、初始化项目`
-
npm init 格式化项目,同时确认信息,提交更新到github上的项目;
主要是生成 package.json; -
二、安装依赖
1 2 | npm install express -s npm install body-parse -s |
express(node.js Web 应用框架)。
body-parser:node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据。
e:在git上面安装依赖包,便好;
- 三、模拟数据
- 我这里用的是vs code,打开本地拉取下来的项目;
- 新建api中的index.json等等json文件,代码之一如下:
- index.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | { "ret": true, "data": { "swiperList": [{ "id": "001", "src": "https://th.wallhaven.cc/small/96/96w8e8.jpg" }, { "id": "002", "src": "https://th.wallhaven.cc/small/13/13mk9v.jpg" }, { "id": "003", "src": "https://th.wallhaven.cc/small/r2/r2ze21.jpg" } ], "iconList": [{ "id": "001", "imgSrc": "http://img1.qunarzz.com/piao/fusion/1803/95/f3dd6c383aeb3b02.png", "txt": "景点门票" }, { "id": "002", "imgSrc": "http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/20193/f0f00d6dfe038c044dbc9a437f58b0eb.png", "txt": "一日游" }, { "id": "003", "imgSrc": "http://img1.qunarzz.com/piao/fusion/1804/ff/fdf170ee89594b02.png", "txt": "北京必游" }, { "id": "004", "imgSrc": "http://img1.qunarzz.com/piao/fusion/1803/47/c2b659e048b11602.png", "txt": "溜娃游" }, { "id": "005", "imgSrc": "http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/20191/0334cf5430b9b5505fd79e2b8d7e8670.png", "txt": "爬长城" }, { "id": "006", "imgSrc": "http://img1.qunarzz.com/piao/fusion/1803/6c/9e54a8540fee0102.png", "txt": "故宫" }, { "id": "007", "imgSrc": "http://img1.qunarzz.com/piao/fusion/1803/76/eb88861d78fb9902.png", "txt": "动植物园" }, { "id": "008", "imgSrc": "http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/20195/35d83bb968d80d54926f30cfb92cb6ff.png", "txt": "限时抢购" }, { "id": "009", "imgSrc": "http://mp-piao-admincp.qunarzz.com/mp_piao_admin_mp_piao_admin/admin/20194/b4511345827006994aa1980a3886f0ac.png", "txt": "北京世园会" } ], "recommendList": [ { "id": "001", "imgUrl": "http://img1.qunarzz.com/sight/p0/1902/84/84696f368bbec10da3.img.jpg_200x200_50323152.jpg", "infoTit": "北京世界园艺博览会", "infoTxt": "80条评论", "infoMoney": "108" }, { "id": "002", "imgUrl": "http://img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_200x200_1bc99086.jpg", "infoTit": "故宫", "infoTxt": "659条评论", "infoMoney": "60" } ], "weekendList": [ { "id": "001", "imgUrl": "http://img1.qunarzz.com/sight/source/1603/6d/2f67ae0659f41f.jpg_r_640x214_bf6cbd0b.jpg", "infoTit": "北京赏花好地方", "infoTxt": "乱花渐欲迷人眼,京城赏花大搜索" }, { "id": "002", "imgUrl": "http://img1.qunarzz.com/sight/source/1811/f3/86173f863bef61.jpg_r_640x214_52b003ac.jpg", "infoTit": "京城周末撒欢", "infoTxt": "在帝都过周末,不仅仅是城中游!" } ] } } |
- 如上的代码,用于测试;
- 四、新建 app.js 文件
- app.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | const fs = require("fs"); // 文件模块 const path = require("path"); // 系统路径模块 const express = require("express"); // node.js Web 应用框架 const bodyParser = require("body-parser"); // node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据 const app = express(); app.use(bodyParser.json()); // 返回一个只解析 json 的中间件,最后保存的数据都存放在 request.body 对象上 app.use( bodyParser.urlencoded({ extended: true }) ); // 返回的对象为任意类型 // 设置跨域访问 app.all("*", function(request, response, next) { response.header("Access-Control-Allow-Origin", "*"); // 设置跨域的域名,* 代表允许任意域名跨域 response.header("Access-Control-Allow-Headers", "X-Requested-With"); response.header( "Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS" ); response.header("X-Powered-By", " 3.2.1"); response.header("Content-Type", "application/json;charset=utf-8"); next(); }); // get 首页数据 app.get("/api/index.json", (request, response) => { request.statusCode = 200; const file = path.join(__dirname, "./api/index.json"); fs.readFile(file, "utf-8", (err, data) => { if (err) { response.send("文件读取失败!"); } else { response.send(data); } }); }); // get 城市列表数据 app.get("/api/city.json", (request, response) => { request.statusCode = 200; const file = path.join(__dirname, "./api/city.json"); fs.readFile(file, "utf-8", (err, data) => { if (err) { response.send("文件读取失败!"); } else { response.send(data); } }); }); // get 详情页数据 app.get("/api/detail.json", (request, response) => { request.statusCode = 200; const file = path.join(__dirname, "./api/detail.json"); fs.readFile(file, "utf-8", (err, data) => { if (err) { response.send("文件读取失败!"); } else { response.send(data); } }); }); // 配置服务端口 const hostname = "localhost"; const port = 8082; const server = app.listen(port, hostname, () => { console.log(`服务器运行在 http://${hostname}:${port}`); }); // const hostname = '127.0.0.1'; // const port = 3000; // const server = app.listen(port,hostname, () => { // console.log(`服务器运行在 http://${hostname}:${port}`); // }); |
- 五、新建 index.html 请求接口
- index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script src='https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js'></script> <script> $(function () { $.ajax({ type: "get", url: "http://localhost:3000/getAPITest", success: function (data) { console.log(data); }, error: function (err) { console.log(err) } }); }) </script> </body> </html> |
- 安装依赖:
npm install - 启动服务端:
node app.js - 大概这样:

- 用 Node.js 编写好数据接口后,我们可以测试一下,启动服务,访问以下三个地址:
1 2 3 | http://localhost:8082/api/index.json http://localhost:8082/api/city.json http://localhost:8082/api/detail.json |

看到数据可以请求成功,那就回到我们的 Vue 项目中,试用一下这三个接口,这回不用本地 mock 下的数据了,而是去访问后端服务器的数据。打开 config/index.js,在“Vue.js第6课-项目实战-首页开发(part03)”中讲过一个 proxy 代理的功能,之前我们将 /api 开头的请求替换成了本地的 /static/mock/ 下的数据,也就是将请求转发到前端 8080 这个服务器下,现在我要把他转发到后端的服务器上,我们将 target 中的地址换为后端服务器的地址(上面我在 Node.js 中设置的服务器端口号为 8082),在 pathRewrite 中,将 /api 的地址映射到服务器的 api 的路径下,而不是我本地的 /static/mock/ 路径:

config/index.js
1 2 3 4 5 6 7 8 | proxyTable: { '/api': { target: 'http://localhost:8082', // 后端提供的接口地址 pathRewrite: { '^/api': 'http://localhost:8082/api/', } } }, |
这个时候,回到页面,我们可以看到 Node.js 提供的接口数据可以正常请求到,页面渲染也没有任何问题:

但是在 pathRewrite 中这么写,其实是没有任何意义的,直接将 pathRewrite 删除就可以了。此时 proxyTable 变得非常简单,只要你在开发服务器上请求 api 下面的地址,我都帮你转发到后台服务器上面。当改变了 config 目录下的配置文件的时候,需要重启前端项目服务。
这个时候,打开页面,可以看到成功请求到后端接口的数据并渲染到页面上了。当然,现在我们的前后端都是在我们本地,在做真实的前后端联调的项目中,如果后端服务不在本地,而是在后端程序员的电脑上,或者是内网/外网的服务器,如果是这样的话,你的代理就不能写 localhost 了,可以去写一个内网的 ip 地址,或者外网域名,通过这种形式,我们就可以把 /api 这个地址的任何请求代理转发给任何一台后端服务器从而非常方便的实现前后端的联调。
我们修改一下后端服务的主机名和端口号来做个测试,在 Node.js 服务器下这样修改:
app.js
1 2 3 4 5 | const hostname = '127.0.0.1'; const port = 3000; const server = app.listen(port,hostname, () => { console.log(`服务器运行在 http://${hostname}:${port}`); }); |
然后打开 Vue项目的 config/index.js,这样修改就可以了。
1 2 3 4 5 6 | proxyTable: { '/api': { target:'http://127.0.0.1:3000', pathRewrite: {} } }, |
相当于将后端的Api地址换掉本地地址,重新定义后端的地址,而前端的代理proxyTable将引用这个地址,实现前后的联调,不限于前后端非得再本地
以上,往常API接口和前后联调功能的基本解释。
接着将是测试打包上线:
这一章来看一下 Vue 项目如何进行真机测试。我们在通过 npm run dev 启动项目服务的时候,终端会显示出项目的服务地址,通过这个地址我们就可以访问项目了:
我再启动一个终端,执行 ifconfig(如果是 window 操作系统,命令就是 ipconfig),通过这个命令,我们可以获取到当前机器的 ip 地址:
本地的后端服务器是可以正常启动的,也就是说 ip 地址没问题,只是 8080 端口无法被外界访问,原因是我们前端的项目是通过 webpack-dev-server 启动的,webpack-dev-server 默认不支持通过 ip 的形式进行页面的问问,所以我们要对他默认的配置项做一个修改。
打开项目根目录下的 package.json 文件,我们每次执行 npm run dev 的时候,实际上都是在运行这样一段话:
package.json
1 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", |
也就是帮我们启动一个 webpack-dev-server,如果想让这个 webpack-dev-server 能够通过 ip 地址被访问的话,我们需要在上面那行代码中加一端代码“–host 0.0.0.0”:
1 | "dev": "webpack-dev-server --host 0.0.0.0 --inline --progress --config build/webpack.dev.conf.js", |
这样去修改一下配置项就可以了。重启一服务,这个时候,访问 xxx.xxx.xxx.xxx:8080/#/ 就没有问题了。

注意正确的ip地址和端口号,便完成真机的测试。。
可以通过 ip 地址访问网站之后呢,我们就可以让我们的手机直接在内网里通过这个地址访问该网站了。这样就可以做一个真机测试。
三、Vue 项目打包上线
在对 Vue 项目进行了联调与真机测试之后,我们把项目打包上线,那 Vue 的项目如何真正的完成上线的流程呢?
当我们做 Vue 项目上线的时候,首先第一步,在项目下打开命令窗口,运行
完成之后,打开我们的项目目录,可以看到里面多了一个 dist 目录,这个目录中的代码,就是我们最终要上线的代码,我先讲这个目录放到桌面上去。

下一步,我会将 dist 目录里的内容给到后端的开发人员,后端会把这个代码放到服务器上,然后和后端代码一起上线,这样就完成了最简单的上线。
如何将 Vue 项目部署到阿里云的 Linux 服务器上。
涉及到
- 阿里云官网购买云服务器 ECS
- shell终端模拟软件
- 文件传输软件 Xftp
- nginx,下载 nginx,然后使用 Xftp 将nginx压缩包上传到的 Linux 服务器
- 打包 Vue 项目并上传至服务器,主要是dist发送送服务器中
- 如何通过shell配置nginx服务器,便好!
慕课网上通过学习 DellLee 老师的Vue2.5 开发去哪儿网 App 从零基础入门到实战项目;
详细配置服务器请参考:https://www.jianshu.com/p/03d17156616d
问题待解:无论是移动端还是pc端,都是存在兼容的问题,不同的主流浏览器就显示出了不同的样式问题
1 2 3 | 参考: 作者:LK30265 链接:https://www.jianshu.com/p/ddeb21877d92 |
