Vue项目使用Nginx部署并发布到子目录

默认Vue项目是以根目录来发布的,但是我们要有时候希望以子目录来做发布,那么就需要做一些修改,Vue项目本身的配置,包括Nginx也需要做一些配置修改。

对Vue项目源码的修改

以下路径以vue-cli常见项目的文件结构来说明。

  • 修改路由:router/index.js,添加base部分的代码。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    function getAbsolutePath () {
      let path = location.pathname
      return path.substring(0, path.lastIndexOf('/') + 1)
    }
    
    export default new Router({
      mode: 'hash',
      base: getAbsolutePath(),
      routes: [...]
    })
    
  • 修改配置:config/index.js 文件,对于打包路径的定义,只处理build,将assetsPublicPath: '/'修改为assetsPublicPath: './'

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    module.exports = {
      build: {
        // Template for index.html
        index: path.resolve(__dirname, '../dist/index.html'),
    
        // Paths
        assetsRoot: path.resolve(__dirname, '../dist'),
        assetsSubDirectory: 'static',
        assetsPublicPath: './',
        ...
      }
    }
    
  • 修改build/utils.js对静态文件的处理,添加publicPath: '../../'

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
     // Extract CSS when that option is specified
        // (which is the case during production build)
        if (options.extract) {
          return ExtractTextPlugin.extract({
            use: loaders,
            fallback: 'vue-style-loader',
            publicPath: '../../'
          })
        } else {
          return ['vue-style-loader'].concat(loaders)
        }
      }
    

对Nginx配置的修改

当前项目结构如下:

game
├── bxfr
│   ├── index.html
│   └── static
│       ├── css
│       ├── images
│       ├── img
│       ├── js
│       └── mock
└── fwjt
    ├── index.html
    └── static
        ├── css
        ├── images
        ├── img
        ├── js
        └── mock

而我们要实现的目的是:使用my.server.name/bxfr/my.server.name/fwjt/分别访问不同的项目。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
server {

    server_name my.server.name;

    access_log /var/log/nginx/game.access.log;
    error_log /var/log/nginx/game.error.log;

    # 这里root只能放在game这一层,因为下一层的子目录是不固定的
    root /home/ubuntu/workspace/official-website/game/;

    # json文件使用mock来返回静态资源,这个block对于实现本文的目的并非必要
    location ~ \.json$ {
        rewrite ^/([^/]+).*/api/(.*) /$1/static/mock/$2 break; 
    }

    location @vue {
        # 匹配不含/的首段,目的是拿出bxfr和fwjt
        rewrite ^/([^/]+).* /$1/index.html last;
    }

    # 使用try files来fallback到vue
    location / {
        index index.html;
        try_files $uri $uri/ @vue;
    }

    listen 80;
    ...

}