nginx中location里面的try_files配置导致Vue设置history模式下的请求丢失参数
vue使用history模式在访问地址的参数会丢失,地址栏也会变成没有参数的地址,并且请求会发生301重定向。最后,发现vue从history模式改成hash模式可以解决参数丢失。但是产生301是nginx的问题,发现nginx配置的try_files有问题,所以会导致丢参数,try_files的配置是为了适配history模式。而nginx默认支持hash模式,不需要额外的配置,所以nginx默
nginx中location里面的try_files配置导致vue设置history模式下的请求丢失参数
背景描述:
在一次生产环境中,vue使用history模式在访问地址的参数会丢失,地址栏也会变成没有参数的地址,并且请求会发生301重定向。最后,发现vue从history模式改成hash模式可以解决参数丢失。但是产生301是nginx的问题,发现nginx配置的try_files有问题,所以会导致丢参数,try_files的配置是为了适配history模式。而nginx默认支持hash模式,不需要额外的配置,所以nginx默认hash是没有问题。最终,发现更改nginx的try_files也能让history模式的访问地址不丢参数。
复现history模式请求丢参数的情景
vue的模式设置为history:
mode: 'history'
有问题的location:
location /vuecay {
root html;
index index.html index.htm;
# 匹配history模式,histoty模式必须要配置,hash模式可以不用配置
#这里有两个坑:$uri/后面没有index.html,后面不会自动添加index.html,vuecay后面没有‘/’
try_files $uri $uri/ /vuecay;
}
访问路径:
http://ip/vuecay/path1/path2?name=lucy
访问截图:
nginx访问日志:
"GET /vuecay/path1/path2?name=lucy HTTP/1.1" 301 162 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay --args:
114.254.3.243 - - [12/Jul/2022:15:57:22 +0800] "GET /vuecay/ HTTP/1.1" 200 583 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/index.html --args:-
"GET /vuecay/js/chunk-vendors.a0183049.js HTTP/1.1" 200 46638 "http://ip/vuecay/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/chunk-vendors.a0183049.js --args:-
"GET /vuecay/js/app.a38bbab2.js HTTP/1.1" 200 1529 "http://ip/vuecay/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/app.a38bbab2.js --args:-
114.254.3.243 - - [12/Jul/2022:15:57:22 +0800] "GET /vuecay/js/app.a38bbab2.js.map HTTP/1.1" 200 19888 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/app.a38bbab2.js.map --args:-
"GET /vuecay/js/chunk-vendors.a0183049.js.map HTTP/1.1" 200 677730 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/chunk-vendors.a0183049.js.map --args:-
可以看到地址栏发生改变,参数丢失,第一次请求会发生301重定向,第二次请求地址发生改变,页面也没获取到参数。
修改nginx配置解决参数丢失
上面的location的try_files的配置会导致history模式下的请求参数丢失:
location /vuecay {
root html;
index index.html index.htm;
# 匹配history模式,histoty模式必须要配置,hash模式可以不用配置
#这里有两个坑:$uri/后面没有index.html,后面不会自动添加index.html,vuecay后面没有‘/’
try_files $uri $uri/ /vuecay;
}
改用这个location的try_files的配置就不会参数就丢失了。
location /vuecay {
root html;
index index.html index.htm;
# 匹配history模式,histoty模式必须要配置,hash模式可以不用配置
#这里有两个坑:$uri/后面没有index.html,后面不会自动添加index.html。
#vuecay后面有‘/index.html’,等同于“/”,vuecay后面有“/”会自动在“/”后面添加index.html
try_files $uri $uri/ /vuecay/index.html;
}
使用上面的访问路径:
http://ip/vuecay/path1/path2?name=cay
访问截图:
nginx访问日志:
"GET /vuecay/path1/path2?name=cay HTTP/1.1" 200 583 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/index.html --args:
"GET /vuecay/js/app.a38bbab2.js HTTP/1.1" 200 1529 "http://ip/vuecay/path1/path2?name=cay" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/app.a38bbab2.js --args:-
"GET /vuecay/js/chunk-vendors.a0183049.js HTTP/1.1" 200 46638 "http://ip/vuecay/path1/path2?name=cay" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/chunk-vendors.a0183049.js --args:-
"GET /vuecay/js/app.a38bbab2.js.map HTTP/1.1" 200 19888 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/app.a38bbab2.js.map --args:-
"GET /vuecay/js/chunk-vendors.a0183049.js.map HTTP/1.1" 200 677730 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/chunk-vendors.a0183049.js.map --args:-
可以看出来,地址栏未发生变化,正常显示参数,请求不会发生301,页面正常显示获取的参数。
对比两种情形的location配置
history模式丢参数的location中的try_files配置:
location /vuecay {
root html;
index index.html index.htm;
# 匹配history模式,histoty模式必须要配置,hash模式可以不用配置
#这里有两个坑:$uri/后面没有index.html,后面不会自动添加index.html,vuecay后面没有‘/’
try_files $uri $uri/ /vuecay;
}
history模式不丢参数的location中的try_files配置:
location /vuecay {
root html;
index index.html index.htm;
# 匹配history模式,histoty模式必须要配置,hash模式可以不用配置
#这里有两个坑:$uri/后面没有index.html,后面不会自动添加index.html。
#vuecay后面有‘/index.html’,等同于“/”,vuecay后面有“/”会自动在“/”后面添加index.html
try_files $uri $uri/ /vuecay/index.html;
}
-
两者最大的区别是try_files最后面的vuecay是有带有了“/”。如果vuecay后面没带“/”代表的是资源,vuecay后面带“/”代表的是vuecay目录下的index.html。
-
丢参数的location的try_files里的
- $uri
- $uri/
- /vuecay
这三个配置是一样的意思。网上有人说$uri/是为了访问uri对应目录下的资源,但是测试中并不会自动查找index.html,当我手动添加index.html,才会去查找uri目录下的index.html。
大家可以试试这个location:
location /vuecay { root html; index index.html index.htm; # 匹配history模式,histoty模式必须要配置,hash模式可以不用配置 # $uri/后面添加index.html try_files $uri $uri/index.html /vuecay; }
测试结果和$uri/后面没有index.html完全不同。
-
不丢参数的location的try_files里配置的是 /vuecay/index.html ,等价于/vuecay/,这里后面会自动添加index.html。而$uri/后面却 不会自动添加index.html,很奇怪。
hash模式解决参数丢失
mode: 'hash'
history模式丢参数的location的try_files的配置
location /vuecay {
root html;
index index.html index.htm;
# 匹配history模式,histoty模式必须要配置,hash模式可以不用配置
#这里有两个坑:$uri/后面没有index.html,后面不会自动添加index.html,vuecay后面没有‘/’
try_files $uri $uri/ /vuecay;
}
访问路径:
http://ip/vuecay/#/path1/path2?name=cay
访问截图:
nginx访问日志:
"GET /vuecay/ HTTP/1.1" 200 583 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-" --uri:/vuecay/index.html --args:-
"GET /vuecay/js/chunk-vendors.a0183049.js HTTP/1.1" 200 46638 "http://ip/vuecay/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/chunk-vendors.a0183049.js --args:-
"GET /vuecay/js/app.5c197350.js HTTP/1.1" 200 1534 "http://ip/vuecay/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/app.5c197350.js --args:-
"GET /vuecay/js/app.5c197350.js.map HTTP/1.1" 200 19920 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/app.5c197350.js.map --args:-
"GET /vuecay/favicon.ico HTTP/1.1" 200 4286 "http://ip/vuecay/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-" --uri:/vuecay/favicon.ico --args:-
"GET /vuecay/js/chunk-vendors.a0183049.js.map HTTP/1.1" 200 677730 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/chunk-vendors.a0183049.js.map --args:-
可以看出地址栏也未变化,参数未丢失,页面正常显示参数,请求未发生301,也解决了参数丢失。
history丢参数,hash模式不丢参数的原因
因为nginx默认是支持hash模式的,不像history模式还得额外配置try_files。而且这里的location是出现问题的try_files的配置,所以history模式受影响,hash模式不受影响,即history模式会丢参数,hash模式不丢参数。
想要了解更多的信息nginx配置导致301的信息,可以看一下我写的另一篇文章:nginx配置导致的301和丢参数的问题的关系
拓展
上面使用的是三级路径(ip后面跟了三层目录/vuecay/path1/path2,我这里暂且称为三级路径):
http://ip/vuecay/path1/path2?name=cay
通过测试发现二级及以上路径,在vue为history模式并且错误的try_files配置中会丢失参数,但是一级路径却不会丢失参数
vue的模式设置为history:
mode: 'history'
history模式丢参数的location的try_files的配置:
location /vuecay {
root html;
index index.html index.htm;
# 匹配history模式,histoty模式必须要配置,hash模式可以不用配置
#这里有两个坑:$uri/后面没有index.html,后面不会自动添加index.html,vuecay后面没有‘/’
try_files $uri $uri/ /vuecay;
}
测试的一级路径:
http://ip/vuecay?name=cay
访问截图:
nginx访问日志:
"GET /vuecay?name=cay HTTP/1.1" 301 162 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay --args:name=cay
"GET /vuecay/?name=cay HTTP/1.1" 200 583 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/index.html --args:name=cay
"GET /vuecay/js/chunk-vendors.a0183049.js HTTP/1.1" 200 46638 "http://ip/vuecay/?name=cay" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/chunk-vendors.a0183049.js --args:-
"GET /vuecay/js/app.a38bbab2.js HTTP/1.1" 200 1529 "http://ip/vuecay/?name=cay" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/app.a38bbab2.js --args:-
"GET /vuecay/js/app.a38bbab2.js.map HTTP/1.1" 200 19888 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/app.a38bbab2.js.map --args:-
"GET /vuecay/js/chunk-vendors.a0183049.js.map HTTP/1.1" 200 677730 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36" "-" --uri:/vuecay/js/chunk-vendors.a0183049.js.map --args:-
可以看出来,地址栏发生变化(vuecay多了“/”),参数未丢失,请求会发生301,这是因为vuecay后面没有‘/’,所以发生301。
可见一级路径在错误的配置下,发生了301,但是却没有丢失参数,但是如果是二级路径及以上则会丢失参数,感兴趣可以尝试。
小结
- try_files的错误配置会导致history模式下的请求的参数丢失,将try_files修改正确即可不丢失参数。
- hash模式不需要额外配置try_files,所以不会丢失参数。
- nginx配置的时候注意“/”,有“/” (目录下的资源,一般是index.html)和 无“/” (资源)是两种含义。
- try_files中的$uri/ 虽然带有“/”,但是后面默认不带index.html,所以最好自己添加index.html。
- 一级路径在vue是history模式,try_files配置有问题的情况下,不会丢失参数。
高亮的两条总结,是这次history请求丢参数的主要误区,大家一定要注意。如果大家测试的结果和我不同,欢迎一起讨论。
想要了解更多的信息nginx配置导致301的信息,可以看一下我写的另一篇文章:nginx配置导致的301和丢参数的问题的关系
附录:vue代码
我们构建简单的vue项目,使用路由,vue的相关代码如下。
Route.js
import VueRouter from "vue-router"
import HelloWorld1 from "./components/HelloWorld1"
import HelloWorld2 from "./components/HelloWorld2"
import HomeTest from "./components/HomeTest"
export default new VueRouter({
mode: 'hash',
base: '/vuecay/',
deep: true,
routes: [{
//一级目录需要添加‘/’
path: '/',
component: HomeTest,
//redirect: "/path1/path2",
children: [{
path: 'path1',
component: HelloWorld1,
children: [{
//二级目录不需要加‘/’
path: 'path2',
component: HelloWorld2
}
]
}
]
}
]
})
Vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
publicPath: '/vuecay/'
})
Main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router"
import router from '@/router'
Vue.config.productionTip = false
Vue.use(VueRouter)
new Vue({
render: h => h(App),
router
}).$mount('#app')
App.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
//import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
}
</script>
<style>
</style>
HomeTest.vue
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
//import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
}
</script>
<style>
</style>
HelloWorld1.vue
<template>
<div>
welcome to path1,{{name}},访问的路径的参数:{{argName}}
<div>
<router-view/>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld1',
data(){
return {
name: 'cay',
argName: ''
}
},
props: {
msg: String
},
created () {
console.log('path1:' + window.location.href)
console.log('path1:' + this.$route.query.name)
console.log(this.$route)
console.log(this.$router)
this.argName = this.$route.query.name
}
}
</script>
<style scoped>
</style>
HelloWorld2.vue
<template>
<div>
welcome to path2,{{name}},访问的路径的参数:{{argName}}
</div>
</template>
<script>
export default {
name: 'HelloWorld2',
data(){
return {
name: 'lucy',
argName: ''
}
},
props: {
msg: String
},
created () {
console.log('path2:' + window.location.href)
console.log('path2:' + this.$route.query.name)
console.log(this.$route)
console.log(this.$router)
this.argName = this.$route.query.name
//const x = { a: 8 };
//console.log(JSON.stringify(x))
}
}
</script>
<style scoped>
</style>
执行命令
npm run build
将编译后的文件部署到服务器上。部署的时候惨过一些坑后面会总结贴上链接。上面的步骤已经是排除坑之后的步骤了。
更多推荐
所有评论(0)