初探全栈,基于vue全家桶和nodejs写的一个小项目,讲述开发和部署过程
发布于 7 年前 作者 xxxgitone 27797 次浏览 来自 分享

vn-pastime

基于vue全家桶、mongodb和nodejs的全栈项目,其实是个大杂烩。通过这个项目,了解前后端的整合,以及产品上线的基本流程

前端使用axios与后台api交互获取数据,vue全家桶进行数据的管理和渲染,mongodb存储网上爬取的原始数据以及用户后期产生的数据,nodejs主要提供api接口以及token的签发与验证

线上使用阿里云服务器部署,nginx进行http反向代理,pm2管理Node应用的进程

功能介绍

这个项目本身并不复杂,最主要的是清扫了一些后台的盲区,满足了自己的好奇心,特别是在项目部署这一块。虽然还没有达到熟悉的地步,但提起也不至于什么也不知道。

后期将会优化前端的代码,比如代码的结构和书写规范,以及vue的组件规范,还有响应式的实现,也可能会添加一些新的模块。

主要目录

    ├── app.js   // 后台入口
    ├── index.html
    ├── server  // 服务端文件
    │   ├── api  // api借口
    │   ├── middlewares
    │   │   └── jwtMid.js  // token验证中间件
    │   ├── models  // mongodb的文档模型
    │   └── public
    ├── src  // 前端主文件
    │   ├── api  // 前端api,与后台api的交互
    │   ├── App.vue
    │   ├── assets  // 静态资源
    │   │   ├── font
    │   │   ├── img
    │   │   └── scss
    │   ├── components // 单个组件
    │   ├── main.js
    │   ├── router
    │   ├── store
    │   ├── utils // axios拦截器
    │   │   └── axiosService.js
    │   └── views // 页面级组件

主要功能(期待更多)

  • [x] 视频播放列表的展示
  • [x] 视频播放器自定义样式
  • [x] 视频评论功能,包括二级评论,自定义简单的富文本组件,用于评论的编辑
  • [x] 基于token进行登录验证
  • [x] 图片的展示列表
  • [x] 图片滚动加载
  • [x] 图片详情页展示,支持上下张切换以及评论
  • [x] 使用socket.io进行简单聊天室
  • [x] 图片上传预览

项目总结和感想

组件编写应该规范

vue上手容易,可以很轻松的实现一些功能。但是要让代码变得更加容易维护和扩展,还得做点其他工作。组件编写规范化便是一个非常有效的方法,组件一般分为基础组件和业务组件,组件应该各司其职,比如基础组件就不应该包含跟业务相关的具体代码,只是返回一个信息,给引用它的组件。这样可以降低组件的耦合度,提升组件的可复用性。

比如一个confirm组件

<template>
  <transition name="confirm">
    <div class="info-confirm" v-show="showFlag">
      <div class="info-header">
          <span>提示信息</span>
      </div>
      <div class="info-text">
        {{ text }}
      </div>
      <div class="info-button">
        <a href="#" @click.prevent="confirm">{{ confirmBtnText }}</a>
        <a href="#" @click.prevent="cancle">{{ cancleBtnText }}</a>
      </div>
    </div>
  </transition>
</template>

<script>
export default {
  props: {
    text: {
      type: String,
      default: ''
    },
    confirmBtnText: {
      type: String,
      default: '确定'
    },
    cancleBtnText: {
      type: String,
      default: '取消'
    }
  },
  data () {
    return {
      showFlag: false
    }
  },
  methods: {
    hide () {
      this.showFlag = false
    },
    show () {
      this.showFlag = true
    },
    confirm () {
      this.hide()
      this.$emit('confirm')
    },
    cancle () {
      this.hide()
      this.$emit('cancle')
    }
  }
}
</script>

在点击确认后,不应该直接在这里组件里面处理接下来的逻辑(比如删除或着清空),而是应该通过this.$emit('confirm')向父组件传递一个确认的信息,父组件监听这个方法,然后再处理接下来的逻辑

这个项目后续将会重点围绕这点来进行优化

前后端如何分离

这是之前我最想知道的问题,听过很多前后端分离,但是都是只闻其声,不见其形。

之前同学问过我这样一个问题,为什么前端也要单独起一个服务,当时我脑海里,闪过的第一个答案就是,现在前端构建项目需要依赖很多包,需要通过node环境来安装各种依赖工作,帮助我们工作。

现在看来这个答案大错特错了,问的是服务,而不是node环境。其实这个问题的答案和前后端分离也和相关

在传统web开发的时候,前端和后端的工作比较耦合,后端人员要做着很多前端的工作,不停切换,比如发送后台请求。这样导致前后端分工不明确,效率反而更加低。不仅如此,而且前后端还要搭建同样的开发环境,让前端开发去搭建一个Java开发环境,显得有些复杂,而且确实没必要。

现代web开发,前后端各司其职,开发之前约定好数据接口和格式,就可以同时开发了。

前端负责静态样式的编写,以及发送ajax请求,后台负责api的开发和测试。双方都不用管对方具体怎么实现。

前面也说到过前端不应该去搭建一个复杂的Java或者其他后台服务,我们可以通过nodejs来搭建一个服务器,寥寥几行代码,便可快速搭建,搭建nodejs服务器的好处

  • 可以模拟线上环境,毕竟本地静态文件和线上还是有些差别,比如路径等
  • 发送ajax,还要处理跨域
  • 部署线上,中间层,用于加载静态文件

前后端如何部署

在前后端完全分离的情况下,前端和后端当然是分别部署(本案例由于是自己一个人写的,并且后台语言正好是nodejs,所以没有将前后端分别部署),比如www.xxxuthus.cn,那么后台api可以使用一个二级域名api.xxxuthus.cn

前端部署,nodejs为一个中间层,作为静态文件服务器,比如将webpack打包后的dist作为静态资源

const express = require('express')
const env = process.env.NODE_ENV || 'development'
const app = express()

app.use(express.static('./dist'))

const server = app.listen(4000, () => {
  console.log(`Express started in ${app.get('env')} mode on http://localhsot:4000`)
})

使用nginx进行反向代理,当用户访问静态资源的时候,返回静态资源,当前台访问api的时候,转发到后台服务器

该配置文件是该项目的,该项目没有严格按照前后端分离部署,所以其它场景配置文件仅供参考

  upstream xxxuthus {
  server 127.0.0.1:4000;
}

server {
  listen 80;
  server_name www.xxxuthus.cn;

  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-Nginx-Proxt true;

    proxy_pass http://xxxuthus;
    proxy_redirect off;
  }

  location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|js|pdf|txt) {
    root /www/vnpastime/production/current/dist;
  }
}

跨域

前后端分离,就会面临着跨域问题,比较常用的跨域CORS,proxy代理以及nginx反向代理

在开发环境中我一般使用proxy代理的方式,通过在config/index.js下面设置

proxyTable: {
  '/api':{
    target: 'http://localhost:4000',
    changeOrigin: true
  },
  '/auth':{
    target: 'http://localhost:4000',
    changeOrigin: true
  }
},

我们前端服务为8080,当我们访问/api/**的时候,便会转发到端口为4000的服务上

生产环境我使用的是nginx代理,前面已经有所介绍

nodejs项目部署工具pm2

pm2是node的一个进程管理器,能够保证进程永远或者,使用它部署变得相当容易

npm install pm2 -g

配置文件,在项目根目录项新建文件ecosystem.json


{
  "apps": [
    {
      "name": "vnpastime",
      "script": "app.js",
      "env": {
        "COMMON_VARIABLE": "true"
      },
      "env_production" : {
        "NODE_ENV": "production"
      }
    }
  ],
  "deploy": {
    "production": {
      "user": "xuthus_y",
      "host": ["106.14.173.2"],
      "port": "22",
      "ref": "origin/master",
      "repo": "git@github.com:xxxgitone/vue-node-pastime.git",
      "path": "/www/vnpastime/production",
      "ssh_options": "StrictHostKeyChecking=no",
      "post-deploy" : "npm install && npm run build && pm2 startOrRestart ecosystem.json --env production",
      "env"  : {
        "NODE_ENV": "production"
      }
    }
  }
}

将该文件push到github中,初次启动执行

pm2 deploy ecosystem.json production setup

然后

pm2 deploy ecosystem.json production

可以在服务器,通过pm2 listpm2 logs分别查看部署成功的应用和部署日志

以后每次修改的项目,push到github后,直接在本地通过

pm2 deploy ecosystem.json production

就可以更新线上的内容了

这里记录了我部署过程中的一些关键步骤,可以参考

Build Setup

# clone项目
git clone git@github.com:xxxgitone/vue-node-pastime.git

cd vue-node-pastime

# install dependencies
npm install

# 还原数据,为了方便展示,我将数据库上传到了项目中,文件名为vnpastime
# --host 数据库服务
# -d 数据库名
# 最后面是备份文件的路径,如果不在该目录下记得填写绝对路径
mongorestore --host 127.0.0.1:27017 -d vnpastime ./vnpastime/

# 启动mongodb服务
mongo

# 启动后台服务
node app.js

# 再启动前台
npm run dev

# build for production with minification
npm run build
10 回复

跨域的问题 使用 cors 就可以解决了。。没必要用代理 多麻烦呀。。

@ipengyo cors确实也挺方便 自豪地采用 CNodeJS ionic

Thanks. Cancle应为cancel

爬虫在哪呢

@voocel 项目目录下的crawler.js文件

api 借口 [没错我就是来找事的,hahah]

@NanShanJi 哈哈,你也发现了,上次有个小伙伴在github提交了一个pr改掉了 自豪地采用 CNodeJS ionic

请问一下你的爬虫怎么启动的

回到顶部