手把手教前端从0到1通过 Node + Express 开发简易接口,项目开发+部署服务器(亲身痛苦经历)

2,690 阅读6分钟

🧨 大家好,我是 Smooth,一名大二的 SCAU 前端er
🙌 如文章有误,恳请评论区指正,谢谢!
❤ 写作不易,「点赞」+「收藏」+「转发」 谢谢支持!

背景

经过网上各种博客的洗礼与寻找,花了一早上终于解决了这个基本问题,完成了前端到后端从 0 到 1 的第一小步,为了记录一下痛苦的过程以及帮助后人少走弯路,因此写下这篇博客

前置知识

  1. 拥有一台服务器,这里我选用阿里云(后续直接通过阿里云界面的远程连接来操作服务器,而懒得用 SSH 客户端软件了)
  2. 安装了 Node 环境(具体操作请自行查看官网文档 nodejs.org/zh-cn/downl…

准备好后,那么便开始,争取十分钟拿下!

开发阶段 创建一个 express 项目

远程连接服务器,进入命令行界面,然后开始下面步骤

1. 创建文件夹,初始化项目

  1. mkdir demo // 新建一个文件夹

  2. cd demo // 进入该文件夹

  3. npm init -y // 初始化一个 npm 库

2. 安装该项目所需依赖

  1. npm install express // 安装 express 依赖
  2. npm install body-parser // 安装 body-parser 依赖

并不需要安装 cors 这个依赖,我看很多项目都有这个,其实根本没必要

3. 开始写接口

此处为了演示,只写一个简单的常用的 get 接口,具体代码如下:

// app.js

const express = require('express');
const app = express();
const bodyParser = require('body-parser');

// 允许跨域访问
app.all('*', function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*"); // 所有 Origin 来源都允许
   res.header("Access-Control-Allow-Headers", "X-Requested-With");
   res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
   res.header("X-Powered-By",' 3.2.1');
   res.header("Content-Type", "application/json;charset=utf-8");
   next();
});

// 处理http请求,解析
app.use(bodyParser.urlencoded({ extended: false }));

// 定义变量,做为返回数据
let myGet = {method:"get",age:20,name:"Smooth",url:"https://juejin.cn/user/1302297507801358"}

// get 请求
app.get('/getDemo',(req,res)=>{
    res.status(200);
    res.json(myGet);  // 返回处理结果,即将一个对象转换成 JSON 字符串返回
});

app.listen(3000, () => console.log('Example app listening on port 3000!'))

4. 本地测试

先输入 node app.js 将 express 项目暂时跑起来

若出现如下提示则表示运行成功

image.png

5. 写一个简单的 html 请求一下接口

// index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>痛苦经历</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <style>
        body {
          margin: 0;
          padding: 0;
          font-family: sans-serif;
          background-color: #ecf0f1;
        }

        .box {
          width: 300px;
          padding: 40px;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          position: absolute;
          background-color: #34495e;
          text-align: center;
        }

        .box input[type="text"] {
          background: none;
          display: block;
          text-align: center;
          border: 0;
          margin: 20px auto;
          border: 2px solid #2980b9;
          padding: 14px 10px;
          width: 200px;
          outline: none;
          color: white;
          border-radius: 24px;
          transition: 0.5s;
        }

        .box input[type="text"]:focus {
          width: 280px;
          border-color: #3498db;
        }

        .box input[type="button"] {
          color: white;
          background: none;
          display: block;
          text-align: center;
          border: 0;
          margin: 20px auto;
          border: 2px solid #2ecc71;
          padding: 14px 10px;
          cursor: pointer;
          width: 180px;
          outline: none;
          border-radius: 24px;
          transition: 0.25s;
        }

        .box input[type="button"]:hover {
          background-color: #2ecc71;
        }

        h1 {
          color: #ecf0f1;
        }

    </style>
  </head>

  <body>
    <form class="box" method="post">
      <h1>痛苦经历</h1>
      <input type="text" name="firstName" placeholder="姓名" class="name" />
      <input
        type="text"
        name="firstPassword"
        placeholder="博客链接"
        class="url"
      />
      <input
        type="button"
        name="firstSubmit"
        value="点击读取信息"
        class="btn"
      />
    </form>
  </body>
  <script type="text/javascript">
    // CORS
    $(".btn").on("click", function () {
      console.log("CORS 方法发生更改");
      $.ajax({
        type: "get",
        url: "http://localhost:3000/getDemo",
        success: function (res) {
          console.log(res);
          // document.getElementsByClassName('url')[0].value = res.url;
          // document.getElementsByClassName('name')[0].value = res.name;
        },
        error: function (err) {
          console.log(err);
        },
      });
    });
  </script>
</html>

浏览器运行结果如下,则表示成功~

image.png

本地测试代码没问题后,到了这里接口开发阶段完成啦!!!

服务器部署

1. 购置服务器

先买一个服务器,这里演示我买的是阿里云

2. 服务器安装 Node 环境

可以通过宝塔直接安装 Node,也可以通过在服务器上依次运行以下指令安装

  • yum install -y epel-release // 安装附加软件包项目epel
  • yum install -y nodejs // 安装 nodejs
  • node -v // 运行命令查看 nodejs 版本,测试是否安装成功,若如下图出现版本号则安装成功

image.png

3. 通过宝塔将写好的 app.js 文件上传到服务器

进入服务器的远程连接的黑窗口页面后

  1. 先输入:sudo su root 进入root用户

  2. 再查看面板入口:/etc/init.d/bt default

image.png

  1. 输入对应网址并输入账号密码即可来到宝塔界面,然后点击左侧的文件,然后上方点击根目录

image.png

  1. 新建一个 api 文件夹,并将 app.js 文件直接拖入该页面即可成功上传,如下图

image.png

4. 在服务器安装依赖并运行 app.js文件来运行后端

  1. 在服务器黑窗口页面通过 cd xxx 的指令运行到含有 app.js 文件的地方,即输入 ls 有该文件

image.png

  1. 然后依次执行 npm init -ynpm install body-parsernpm install express 安装依赖

  2. 执行 node app.js 运行该文件,出现如下图说明运行成功,此时可访问 http://服务器ip:3000/getDemo,如果是一个 JSON 文件,那么便部署成功!

image.png

如果执行文件后过 10s 还是无法通过以上 url 方式访问,那么可能是服务器防火墙没开该端口权限 或是 没开放该端口

防火墙

来到该页面,新填该端口即可

image.png

没开放该端口

一开始我是卡在这一步,气死了

开放端口命令: /sbin/iptables -I INPUT -p tcp --dport 3000 -j ACCEPT

以上两步都完成了话,按理来说是能访问到了,如果还不行欢迎在评论区提出

5. 保持服务器接口一直运行

由于刚刚我们是通过 node app.js 来运行后端接口,如果关掉这个黑窗口那该后端项目也随之停了,如果想一直运行在服务器上,可通过 pm2启动项目,并管理进程

pm2 是一个启动项目并管理程序的工具,如果你项目意外死掉了,它可以自动帮你重启。类似的工具还有很多,大家自行Google之~
如果有小伙伴不了解pm2,指路 pm2.keymetrics.io/docs/usage/…

  1. 安装pm2
npm i -g pm2
  1. 检测 pm2 是否安装成功
pm2 -v

若出现如下结果,则说明你pm2 安装ok啦!

image.png

  1. 使用 pm2 启动项目
cd 你服务器项目目录
pm2 start app.js // 启动即可

启动成功如下所示:

image.png

(4)测试

我的项目使用的是3000端口,所以 http://服务器ip:3000/getDemo 就可以访问啦,以下是我的 ip:端口/接口名称 访问结果

image.png

到此服务器端部署算是完成啦!

其他知识

由于此次教程是将 express 项目运行在服务器的 3000 端口,如果通过该端口访问不到 express 项目,可以通过以下方式逐步排查问题

查看该端口是否开放且有项目

lsof -i:端口号

如果没有任何输出则说明没有开启该端口号

下图以 3000 端口为例,检查是否开放

image.png

也可以使用 lsof -i 命令直接将开放的端口输出,来查看某些端口是否开放。



最后

我是 Smoothzjc,致力于产出更多且不仅限于前端方面的优质文章

大家也可以关注我的公众号 @ Smooth前端成长记录,及时通过移动端获取到最新文章消息!

写作不易,「点赞」+「收藏」+「转发」 谢谢支持❤

往期推荐

《都2022年了还不考虑来学React Hook吗?6k字带你从入门到吃透》

《一份不可多得的 Webpack 学习指南(1万字长文带你入门 Webpack 并掌握常用的进阶配置)》

《通过 React15 ~ 17 的优化迭代来简单聊聊 Fiber》

《【offer 收割机之面试必备】一篇非常全面的 从 URL 输入到页面展现的全过程 精华梳理》

《【offer 收割机之手写系列】10分钟带你掌握原理并手写防抖与节流的立即/非立即执行版本》

《【offer 收割机之 CSS 回顾系列】请你解释一下什么是 BFC ?他的应用场景有哪些?》

《Github + hexo 实现自己的个人博客、配置主题(超详细)》

《10分钟让你彻底理解如何配置子域名来部署多个项目》

《一文理解配置伪静态解决 部署项目刷新页面404问题

《带你3分钟掌握常见的水平垂直居中面试题》

《【建议收藏】长达万字的git常用指令总结!!!适合小白及在工作中想要对git基本指令有所了解的人群》

《浅谈javascript的原型和原型链(新手懵懂想学会原型链?看这篇文章就足够啦!!!)》