建站日记三,前后端应用的初始化

190 阅读3分钟

背景

本节的目标是在服务器上一个前端应用,一个后端应用,并完成前后端的交互。具体目标为:

  1. 能访问到前端页面
  2. 能调通一个接口

约定

  1. 前后端应用都使用docker部署
  2. 前端使用vue3 + vite,使用nginx作为web服务器,后端使用express
  3. 前端运行在3000端口,后端运行在4000端口。
  4. 前端路由加上/blog前缀,后端接口加上/api前缀,线上环境使用nginx转发完成接口交互,开发环境使用server.proxy完成接口交互。

前端代码:blog-app-fe
后端代码:blog-app-backend

后端应用部署

编写一个接口

编写一个简单的get接口,用于后面接口测试

const express = require("express");
const app = express();
const port = 4000;

app.get("/blogInfo", (req, res) => {
  const userInfo = {
    message: "Hello Blog",
  };
  res.json(userInfo);
});

app.listen(4000, () => {
  console.log(`Example app listening on port ${4000}`);
});

编写docker file

# 使用官方 Node.js 镜像作为构建基础镜像
FROM node:18.17.1 AS builder

# 安装 pnpm
RUN npm install -g pnpm@8.7.0

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 pnpm-lock.yaml(如果有的话)到工作目录
COPY package*.json pnpm-lock.yaml* ./

# 安装应用依赖
RUN pnpm install

# 复制应用源代码到工作目录
COPY . .

# 暴露端口 4000
EXPOSE 4000

# 启动应用程序
CMD ["npm", "run", "start"]

完成部署

  1. 本地构建镜像并推送到docker hub
    # m系列芯片需要指定架构
    docker buildx build --platform linux/amd64 -t mhhongfe/blog-app-backend:1.0 --push .
    # 非m系列芯片
    docker build -t mhhongfe/blog-app-backend:1.0 --push .
    
  2. 服务器上拉取镜像并运行
    # 如果之前有同名容器,需要先删掉
    docker ps
    docker stop 容器ID
    docker rm 容器ID
    # pull镜像
    docker pull mhhongfe/blog-app-backend:1.0
    docker run -p 4000:4000 mhhongfe/blog-app-backend:1.0
    
  3. 访问接口 访问serverIp:4000/blogInfo,显示{ message: "Hello Blog", }

后端服务部署成功!

阿里云的安全组需要开发4000端口

前端应用部署

前端路由增加/blog前缀

import { createWebHistory, createRouter } from 'vue-router'

import HomeView from '../pages/home/index.vue'
import AboutView from '../pages/about/index.vue'

const routes = [
  { path: '/', redirect: '/home' },
  { path: '/home', component: HomeView },
  { path: '/about', component: AboutView },
]

// 前端路由,使用blo前缀
const router = createRouter({
  history: createWebHistory('blog'),
  routes,
})

export default router;

测试接口

在home页面,点击发送请求,如果接口请求正常,会在alert中显示返回值

<template>
    <div>
        <span>Home页面</span>
        <div>
            <button @click="handleClick">发起请求</button>
        </div>
    </div>
</template>

<script setup lang= "ts">
async function handleClick() {
    const res = await fetch('/api/blogInfo').then(res => res.json());
    alert(res.message);
}
</script>

<style scoped>

</style>

配置nginx

项目根目录增加nginx.conf,加入如下内容:

# 全局上下文
worker_processes 1;  # 设置工作进程数

# 事件块
events {
    worker_connections 1024;  # 设置每个工作进程的最大连接数
}

# HTTP 块
http {
    include mime.types;
    default_type application/octet-stream;

    # 服务器块
    server {
        listen 80;
        server_name localhost;

        # 根目录的静态文件
        location / {
            root /usr/share/nginx/html;
            try_files $uri /index.html;  # 确保单页面应用的路由正常工作
        }

        # 如果需要其他处理
        location /api/ {
            proxy_pass http://serverIp:4000/;  # 替换成真实的ip
            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;
        }
    }
}

  • /api配置,具有这个前缀的请求都转发到后端服务
  • /配置,没有匹配/api的都会在/usr/share/nginx/html目录下找对应的资源,如果没找到就显示index.html
    • 这样配置可以解决访问localhost:80/正常显示,localhost:80/home显示nginx404的问题

配置docker

在项目根目录下增加Dockerfile

# 使用官方 Node.js 镜像作为构建基础镜像
FROM node:18.17.1 AS builder

# 安装 pnpm
RUN npm install -g pnpm@8.7.0

# 设置工作目录
WORKDIR /app

# 复制 package.json 和 pnpm-lock.yaml(如果有的话)到工作目录
COPY package*.json pnpm-lock.yaml* ./

# 安装应用依赖
RUN pnpm install

# 复制应用源代码到工作目录
COPY . .

# 构建应用
RUN pnpm run build

# 使用 Nginx 镜像作为生产环境镜像
FROM nginx:alpine

# 复制自定义 Nginx 配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 将构建产物从 /app/dist 复制到 Nginx 的默认服务目录
COPY --from=builder /app/dist /usr/share/nginx/html

# 暴露端口 80
EXPOSE 80

# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]

对应nginx的配置,把构建产物dist都放在/usr/share/nginx/html目录下,这样不管是页面还是图片等其他资源都能顺利找到。

完成部署

  1. 本地构建镜像并推送到docker hub。

    # m系列芯片需要指定架构
    docker buildx build --platform linux/amd64 -t mhhongfe/blog-app-fe:1.0 --push .
    # 非m系列芯片
    docker build -t mhhongfe/blog-app-fe:1.0 --push .
    
  2. 服务器上拉取镜像并运行

    docker pull mhhongfe/blog-app-fe:1.0
    # 程序在容器内的80端口运行,容器在宿主机的3000端口运行
    docker run -p 3000:80 mhhongfe/blog-app-fe:1.0
    
  3. 访问页面
    访问服务器ip:3000/blog/home,页面显示正常

    image.png

  4. 测试接口
    接口调用正常 image.png

部署完成!

总结

目前完成了前后端各自的应用部署,与接口的交互,之后只需要不断完善前后端功能即可。