我们在本地开发前端时,一般是执行 npm run serve
启动项目,控制台打印出如下日志:
App running at:
- Local: http://localhost:7007/
- Network: http://192.168.0.105:7007/
怀着愉快的心情访问链接 http://localhost:7007/,浏览器也按我们预期显示了项目的主页面。
当你不小心手误,访问链接时多敲了几个按键,链接变成这样:http://localhost:7007/asdf,一个回车,woc??,这怎么还能显示主页?!!你很确定项目没有一个名为 ‘/asdf’ 的路由,这也能行?开始反复尝试,试试访问 http://localhost:7007/qwer、http://localhost:7007/666666666666666666666…无一例外,访问任何路径都会显示主页面。这就很神奇了。(一肚子内心戏hhha~)
回到正题,为什么访问vue项目的任何路径都能打开主页面?
要回答这个问题,首先要知道本地执行 npm run serve
时,到底干了什么。参考:浅析npm run serve命令
直接上总结: npm run serve
其实是在本地启动了个 webpack-dev-server
服务器。
不知道你发现没有,当我们打包部署到nginx时也会出现这个现象,nginx.conf的配置一般如下:
location / {
root html;
try_files $uri $uri/ /index.html;
}
通过对nginx配置的调试,发现是 try_files指令实现了这个能力,它支持当获取不到任何文件时,将所有请求重定向到某个路径上去。上述配置最终会重定向到/index.html。具体细节可参考:Nginx try_files指令
知道了nginx也有这种情况,而且这个能力是通过一个内部的try_files指令配置实现,我不禁在想,webpack-dev-server可以说就好比nginx,那应该也会有类似的配置吧。
基于这个思路,我进行了一系列的探索。
- 既然说到配置,那从项目的
vue.config.js
配置入手,我们发现 devServer 会作用于 webpack-dev-server,继续深入devServer
; - https://cli.vuejs.org/zh/config/#devserver
文档提到 devServer 支持所有 webpack-dev-server 的选项配置。继续深入webpack-dev-server
的选项; - https://webpack.docschina.org/configuration/dev-server/
重点关注静态资源的配置部分,一圈看下来,我发现staticOptions
这个选项很可疑!它用于支持静态文件的高级选项。继续深入; - https://webpack.docschina.org/configuration/dev-server/#staticOptions
文档提到staticOptions会用于Express框架中的express.static API,所以可配置项自然就是express.static
支持的值,继续深入 - http://expressjs.com/en/4x/api.html#express.static
看了文档中相关的几个选项,我其实关注到了fallthrough
,仅凭参数的定义是这样的:Let client errors fall-through as unhandled requests, otherwise forward a client error.,直译就是:让客户端错误作为未处理的请求发生,否则转发客户端错误。 - 多次调试,得出结论。
我测试了各种配置,一步步调试…
皇天不负有心人,真让我试了出来!主角就是 fallthrough
配置项。
当devServer.staticOptions.fallthrough
为true
时,访问子路径会自动重定向到主页面!
当devServer.staticOptions.fallthrough
为false
时,访问子路径会报错!
直接上示例:
项目访问地址:http://localhost:7007/
当我配置了 devServer.staticOptions.fallthrough
= true
启动时,访问子路径会自动重定向到主页面!
当我配置 devServer.staticOptions.fallthrough
= false
启动时,访问子路径会报错!
总结
问:为什么访问vue项目的任何路径都能打开主页面?
答:因为 devServer.staticOptions.fallthrough
配置项,该配置默认为 true
。当它为true
时,访问子路径会自动重定向到主页面;当它为false
时,访问子路径会报错!
在vue.config.js中实际配置长这样:
module.exports = {
...
devServer: {
staticOptions: {
fallthrough: false
},
...
}
reference:
浅析npm run serve命令
vue.config.js 官方文档
Webpack DevServer 官方文档
https://webpack.js.org/configuration/dev-server/#staticoptions
http://expressjs.com/en/4x/api.html#express.static