浅谈 VueSSR 和 Express 结合的开发模式

引言

其实这种开发模式,我之前讲 VueSSR 的时候已经提过了。但是,当时只是简单的提及一个工作目录 entry-server.js 和 server.js 两个和服务端相关的文件,用来进行一些后端的查询之类的。但是如果是简单的 VueSSR,不能完全适应一些后端的开发,如果需要多写几个查询,项目的耦合性就不高了。现在,我把它补上。

目录结构

对比我之前将的目录结构,其实就多了个文件夹。然后,这个文件夹里面都是和 Express 和 MySQL 相关的文件,例如连接数据库、路由等等。并且,数据处理部分,我把它简单地分了两个部分 Controller、Model(一般我不用哈哈,留着已被不时之需)。所以,一个完整的 Express + VueSSR 的项目结构会是这样:

build
├── webpack.client.config.js # 用于服务端的打包
├── webpack.server.config.js # 用于客户端的打包

server # 和服务端相关的代码,可以理解为中间层
├── controllers # 进行数据的处理和返回
		├── index.js
├── db # 连接数据库相关
		├── index.js
├── routes # 后端路由
		├── index.js
├── index.js # 整个项目入口

src
├── store
    	├── index.js # 不同于传统的,它是一个工厂函数
├── routes 
    	├── index.js # 不同于传统的,它是一个工厂函数
├── components # 组件
├── views # 页面
		├── Home
				├── index.vue					
├── App.vue
├── main.js # 通用 entry(universal entry),不同于传统的,它是一个工厂函数
├── entry-client.js # 仅运行于客户端(浏览器)
└── entry-server.js # 仅运行于服务器

相比较之前的 VueSSR 其实还有一个小细节,就是我把项目入口文件改成 server 文件夹下的 index.js,其实就是为了方便阅读。接下来,来看看 Server 中文件夹具体作用。

作用

1.index.js 项目入口文件
首先,项目的入口迁到 server 文件夹中,也不是平白无故。因为,要用 express 框架实现中间层的概念,所以相应地也得在项目入口中,实例化 express 并绑定路由,不过需要注意的是原来的 SSR 逻辑保持不变,不过还得设置一些 Content-Type,毕竟我们后面要传输 JSON 数据给前端。

// 导入路由文件
const router = require('./routes/index')
// 实例化 express
const app = express()
// 绑定路由
router(app)
...
app.get('*', isProd ? render : (req, res) => {
    console.log('请求中')
    res.setHeader('Content-Type', 'text/html;charset=utf-8')
    readyPromise.then(() => render(req, res))
})

2.routes 路由文件夹
比如说现在有个首页 home 的 banner 对应的路由(即对应 home.js),它在 express 中路由是这样的:

const express = require('express')
const route = express.Router()
const home = require('../controllers/home')

route.get('/api/banner', home.getBanner)

module.exports = route

在平常的开发中我们可能存在很多模块,为了项目的解耦,我们也需要适当地将不同模块的路由分开在淡单独的文件。然后,通过新建一个 index.js 文件来统一导出项目所有路由。

const home = require('./home')

module.exports = function (app) {
    app.use(home)
}

3.db 数据库连接相关文件夹
实现中间层,意味着我们需要查询数据库,那就需要连接数据库。

const mysql = require('mysql')
var pool = mysql.createPool({
    host: 'localhost',
    port: '3306',
    user: 'root',
    password: '',
    database: 'myblog'
})

const query = function (sql, callback) {
    pool.getConnection(function(err, conn) {
        if (err) {
            callback(err, null, null)
        } else {
            conn.query(sql, function(qerr, vals, fields) {
                // 释放连接
                conn.release()
                callback(qerr, vals, fields)
            })
        }
    })
}

// 向外暴露连接数据库的db对象
module.exports = query

连接的操作很简单,这里用了连接池来管理我对数据库的连接。

4. controllers 文件夹

而 controllers 文件夹中,具体做的就是对查询的数据进行修饰,返回给前端可以直接使用的数据格式,这里继续延续我们前面的 homer 模块的 benner 路由。

const query = require("../db/index")

function getBanner(req, res, next) {
    const sql = "SELECT * FROM banner"

    query(sql, (err, result) => {
        if (err) {
            console.log(`[SELECT ERROR] - `, err.message)
            return
        }

        const data = {
            status: 1001,
            message: 'success',
            data: {
                bannerList: result
            }
        }

        res.json(data)
    })
}

module.exports = {
    getBanner
}

PS:model 文件夹就不讲了,没用过…这里后端的同学应该更懂

总结

其实,说白了就是将 Express 应用直接嵌入到 VueSSR 项目中。很类似与以前的 MVC,可以这么说,也可以不那么说。因为传统的 MVC 已经不符合这个时代的需要,并且随着前端的工程化,Node.js 搭建的服务更适合和 Vue、React 之类的框架搭配使用,它们所用的工具链,几乎都是基于 Node 实现的,所以夸张点就是无缝衔接。当然,话说回来,用这种开发要应场景而进行不同的选择,Node.js 并不是万能的~

发布了140 篇原创文章 · 获赞 16 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_42049445/article/details/104617983