首页 > 解决方案 > NGinx 上的 VueJS 路由器历史模式

问题描述

我一直在研究,我发现了许多与我的问题相似的问题。

我有一个 docker-compose 在 Digital Ocean 上运行,带有 NGinx、VueJS 和静态登陆页面。

在我用表格创建新路线之前,一切都很好。这条路线将通过一个通过电子邮件发送给客户的链接访问,该链接带有一个 ID 以识别谁正在访问该页面。

结构示例:

https://example.org -> 登陆页面

https://example.org/quiz -> 我的 vuejs 应用程序

https://example.org/quiz/confirmation/some-customer-id -> 我在 vuejs 上的路由器

VueJS 配置:

const webpack = require('webpack')

module.exports = {
    devServer: {
        port: '8092',
    },
    publicPath: '/quiz/',
    runtimeCompiler: true,
    configureWebpack: {
        entry: {
            main: path.resolve(__dirname, 'src/main.js'),
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            filename: process.env.production ? '[name].[contenthash:8].js' : '[name].[hash].js',
        },
        plugins: [
            new webpack.HashedModuleIdsPlugin(), // so that file hashes don't change unexpectedly
        ],
        optimization: {
            runtimeChunk: 'single',
            splitChunks: {
                chunks: 'all',
                maxInitialRequests: Infinity,
                minSize: 0,
                cacheGroups: {
                    vendor: {
                        test: /[\\/]node_modules[\\/]/,
                        name(module) {
                            // get the name. E.g. node_modules/packageName/not/this/part.js
                            // or node_modules/packageName
                            const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1]

                            // npm package names are URL-safe, but some servers don't like @ symbols
                            return `npm.${packageName.replace('@', '')}`
                        },
                    },
                },
            },
        },
    },
    lintOnSave: true,
    css: {
        loaderOptions: {
            sass: {
                prependData: `
          @import "@/assets/scss/app-custom.scss";
        `,
            },
        },
    },
    chainWebpack: (config) => {
        config.plugins.delete('prefetch')

    },
}

VueJS 路由器配置:

import VueRouter from 'vue-router'
import {Trans} from '@/plugins/translation'
import {ROUTER_NAME} from "./names";


const Quiz = () => import(/* webpackChunkName: "Quiz" */ '@/views/Quiz.vue')
const QuizResults = () => import(/* webpackChunkName: "QuizResults" */ '@/views/QuizResults.vue')
const QuizSuccess = () => import(/* webpackChunkName: "QuizSuccess" */ '@/views/QuizSuccess.vue')
const QuizConfirmation = () => import(/* webpackChunkName: "QuizResults" */ '@/views/QuizConfirmation.vue')
Vue.use(VueRouter)

const routes = [
    {
        path: '/:lang',
        component: {
            template: '<router-view></router-view>',
        },
        beforeEnter: Trans.routeMiddleware,
        children: [
            {

                path: '/',
                name: ROUTER_NAME.QUIZ,
                component: Quiz
            }, {
                path: '/results',
                name: ROUTER_NAME.QUIZ_RESULTS,
                component: QuizResults
            }, {
                path: '/success',
                name: ROUTER_NAME.QUIZ_SUCCESS,
                component: QuizSuccess
            }
        ]
    },
    {
        path: '/confirmation/:quizId',
        name: ROUTER_NAME.QUIZ_CONFIRMATION,
        component: QuizConfirmation,
        props: true
    },
    {
        // Redirect user to supported lang version.
        path: '*',
        redirect(to) {
            return Trans.defaultLanguage
        }
    }
]

const router = new VueRouter({
    mode: 'history',
    base: '/quiz/',
    routes
})

export default router

NGinx 配置:

        listen 80;
        listen [::]:80;
        server_name example.org www.example.org;

        location ~ /.well-known/acme-challenge {
          allow all;
          root /var/www/html;
        }

        location / {
            rewrite ^ https://$host$request_uri? permanent;
        }

        location /quiz {
            rewrite ^ https://$host$request_uri? permanent;
        }

        location /shop {
            rewrite ^ https://$host$request_uri? permanent;
        }
}

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name example.org www.example.org;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/mysite.org/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/mysite.org/privkey.pem;

        ssl_buffer_size 8k;

        ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

        ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
        ssl_prefer_server_ciphers on;

        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

        ssl_ecdh_curve secp384r1;
        ssl_session_tickets off;

        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.8.8;

        location / {
            try_files $uri $uri/ =404;
        }

        location /quiz {
            alias /var/www/html/quiz;
            expires -1;
            add_header Pragma "no-cache";
            add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
            try_files $uri $uri/ /quiz/index.html;
        }

        location = /favicon.ico {
            log_not_found off; access_log off;
        }

        location = /robots.txt {
            log_not_found off; access_log off; allow all;
        }

        location ~* \.(css|gif|ico|jpeg|jpg|js|png)$ {
            expires max;
            log_not_found off;
        }
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;

}

我已经关注了所有可用的文档和 stackoverflow 问题,但它们都不起作用。

基本上,当我单击链接https://example.org/quiz/confirmation/some-customer-id时,该站点将重定向到配置中/quiz/index.html定义的位置location /quiz

location /quiz {
            alias /var/www/html/quiz;
            expires -1;
            add_header Pragma "no-cache";
            add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
            try_files $uri $uri/ /quiz/index.html;
        }

你知道我能做些什么来解决这个问题吗?如果您需要更多信息,请告诉我。

多谢你们。

标签: javascriptdockervue.jsnginxvuejs2

解决方案


使用嵌套路由时,您必须删除子路径中的斜杠“/”,

所以你的 vue-router 配置将是这样的:

const routes = [
    {
        path: '/:lang',
        component: {
            template: '<router-view></router-view>',
        },
        beforeEnter: Trans.routeMiddleware,
        children: [
            {

                path: '',
                name: ROUTER_NAME.QUIZ,
                component: Quiz
            }, {
                path: 'results',
                name: ROUTER_NAME.QUIZ_RESULTS,
                component: QuizResults
            }, {
                path: 'success',
                name: ROUTER_NAME.QUIZ_SUCCESS,
                component: QuizSuccess
            }
        ]
    },
    {
        path: '/confirmation/:quizId',
        name: ROUTER_NAME.QUIZ_CONFIRMATION,
        component: QuizConfirmation,
        props: true
    },
    {
        // Redirect user to supported lang version.
        path: '*',
        redirect(to) {
            return Trans.defaultLanguage
        }
    }
]

你可以在这里查看 vue-router 文档。


推荐阅读