记录一下如何使用 Nginx 实现新老框架页面共存并且可相互跳转

一、需求背景

原项目使用 tornado 框架 动态 render 页面返回,现在需要慢慢引入前后端分离模式,考虑在新功能上用 Vue 实现页面,并且使新老页面可以相互跳转。

二、解决方案

给新页面分配唯一路由(比如 /example/,以下配置以该路由举例 ),

以该路由的开头的页面都会被 Nginx 通过路由正则匹配指向新的静态页面地址( Vue 打包之后的页面),

其他路由仍旧保持原来的路由匹配走原来的 tornado框架 动态 render,

新老页面的相互跳转直接用 href='xxx' 实现。

为实现以上方案,需做三步处理:

  • 在 Nginx 里进行特殊配置,正则匹配唯一路由并转发(和普通静态页面部署有所区别)
  • 把前端路由模式从兼容性较好的 hash 模式改成 history 模式
  • 前端打包的 baseUrl 需要设置为 Nginx 上配置的给新页面的唯一路由

1. Nginx配置

想要实现的效果是匹配到/example/路由后,这个路由就被前端接管,接下来任何操作都由前端路由来控制

添加以下配置至nginx.conf

# 匹配以/example/开头的路由,匹配后不匹配其他路由		
location ^~ /example/ {  
    alias /example/dist/; # 使用 alias 指向准确目录之后由前端接管
    index index.html;
    autoindex on;
    try_files $uri $uri/ /dist/index.html; # 前端 history 模式需加上该行配置,否则回车或刷新页面 404
}

配置后nginx.conf文件结构如下

...              # 全局块
events {         # events块
   ...
}
http      # http块
{
    ...   # http全局块
    server        # server块
    { 
        ...       # server全局块
        location [PATTERN]   # location块
        {
            ...
        }

        # 添加的配置
        location ^~ /example/ {    			
            alias /example/dist/;
            index index.html;
            autoindex on;
            try_files $uri $uri/ /dist/index.html;
        }
        
        location [PATTERN] 
        {
            ...
        }
    }
    server
    {
      ...
    }
    ...     # http全局块
}

alias 和 root 的区别

  • alias的处理结果是:使用alias路径替换location路径

    location /example/ {
        alias /home/www/example/;
    }

    在上面alias虚拟目录配置下,访问 http://www.example.com/example/a.html 实际指定的是 /home/www/example/a.html

  • root的处理结果是:root路径+location路径

    location /example/ {
    root /home/www/;
    }

    使用该配置 Nginx 就会去 /home/www/example 下寻找 http://www.example.com/example 的访问资源

2. 前端路由模式

前端路由模式分为2种,一种是 hash 模式,一种是 history 模式
|区别| hash 模式| history 模式|
|—-|——-|———–|
|地址栏表现|带 # 号|标准的 Url 格式,不带 #|
|路由的跳转实现|window.onhashchange 监听 hash 的改变|pushState 或者 replaceState API 改变路由|
|页面刷新|请求的地址中不携带 # 后面的内容,所以不需要后端的配合,也不会出现 404 |请求的是当前地址的完整路径,需要服务器做特殊处理,否则会出现 404|
|兼容性|可以兼容一些低版本的浏览器|不兼容低版本浏览器|

具体可见 Vue-router hash和history的区别

目前我们采用 history 模式主要是因为原项目是标准的Url格式,此处做统一,配置如下:

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

const routes = [
    // 本地开发时因为example路由下没有页面,直接重定向到A页面
    {
        path: '/example',
        redirect: '/example/aaa'
    },
    {
        path: '/example/a',
        name: 'ExampleA',
        component: () => import('../views/ExampleA.vue'),
        meta: {
        title: 'A页面'
        }
    },
    {
        path: '/example/b',
        name: 'ExampleB',
        component: () => import('../views/ExampleB.vue'),
        meta: {
        title: 'B页面'
        }
    },
]

// 采用history模式
const router = createRouter({
    mode: 'history',
    history: createWebHistory(), 
    routes
})
...

export default router

同时需在 Nginx 做特殊配置(添加 try_files $uri $uri/ /dist/index.html; 来保证回车或刷新时不出现404)。

一般实际开发场景中,用 hash 模式较为常见,

一是因为兼容性好(history 模式是 Html5 后提出的,故不兼容低版本浏览器),

二是 hash 模式不需要在 Nginx 上特殊配置。

若需要Url整洁或是别的需求,则考虑 history 模式,一切以实际开发需求为准。

3. build配置

目前新页面使用的脚手架为 Vite,故在vite.config.js里加上base: "/example/",如下(Vue-Cli也可以找到类似的配置)

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  base: "/example/",
  ... # 其他配置
})

这里的 base 表示 开发或生产环境服务的公共基础路径,默认值为'/'

此处需设为Nginx上配置的唯一匹配路由,主要是保证打包后的资源都能正常访问

以下搬运Vite官网对该配置字段的介绍:

如果你需要在嵌套的公共路径下部署项目,只需指定 base 配置项,然后所有资源的路径都将据此配置重写。这个选项也可以通过命令行参数指定,例如 vite build –base=/my/public/path/。

由 JS 引入的资源 URL,CSS 中的 url() 引用以及 .html 文件中引用的资源在构建过程中都会自动调整,以适配此选项。

当然,情况也有例外,当访问过程中需要使用动态连接的 url 时,可以使用全局注入的 import.meta.env.BASE_URL 变量,它的值为公共基础路径。注意,这个变量在构建时会被静态替换,因此,它必须按 import.meta.env.BASE_URL 的原样出现(例如 import.meta.env[‘BASE_URL’] 是无效的)


本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

Python处理Excel 下一篇