打包后使用history模式打开白屏

545 阅读3分钟

问题

在项目中,我们打包之后如果用history模式打开index.html文件,会出现白屏的情况,但是切换为hash模式就不会出现白屏。那如何在history模式下解决白屏的问题呢? 为什么要对服务器做响应的配置呢?

辨析history & hash

hash

原理

hash模式是利用我们基础知识锚点 & window 监听 onhashchange 事件

锚点:当超链接的href值不是某个页面,而是使用hash值时,不会发生页面跳转。

vue-router 利用这个特点,再加上 window 可以监听 onhashchange 事件,在地址栏的hash值发生变化之后,切换不同组件进行渲染。这样一来,即使前端没有发送http请求,也能找到对应页面的代码进行按需加载。

history

原理

是基于 html5 提供的 history api 来实现的。 pushStatereplaceState

---> 在history中,页面刷新之后会出现404,因为刷新浏览器之后,是真实的向服务器发送一个http请求,所以要使用history模式,就需要服务端的支持。

---> 原因:利用history api,将url替换并且不刷新页面。也就是说,http并没有去请求服务器该路径下的资源,一旦刷新之后就会暴露这个问题,暴露出实际上不存在的“页面”,显示404

问题呈现

http://127.0.0.1:5500/host/ 当我们的url是主页面时,页面显示正常,但是当我们的url改为http://127.0.0.1:5500/host/home会显示404

history和hash模式下不同的处理方式

1、hash 模式下下,只将 hash 前面的部分当作地址,所以会向服务端重新请求http://127.0.0.1:5500/host/,服务端仍然会返回 index.html,此文件再下载引入的 js、css 等文件,然后根据地址栏中的 hash 值匹配路由,所以刷新之后,与刷新之前的页面内容是一致的(因为 hash 值没有变化)

--- 请求时,后面没有加上 #/home,因为浏览器认为hash值不是请求地址的一部分

2、history 模式下,会将地址栏中的地址全部看作请求地址,所以刷新后,会向服务端请求这个地址。而我们的前端项目下,只有一个 index.html 和一些 js、css、图片等文件,根本没有请求的资源,所以服务器就返回 404了。

找不到资源的原因

1、因为我们一般都是打包以后放在静态资源服务器中的,我们访问诸如 http://127.0.0.1:5500/host/ 这种形式的资源没问题,是因为,index.html 文件是真实的存在于 rootpath 文件夹中的,可以找到的,返回给前端的。 但是如果访问子路由 http://127.0.0.1:5500/host/login 进行登录操作,但是 login/index.html 文件并非真实存在的文件,其实我们需要的文件还是 host 目录中的 index.html 。

2、再者,如果我们需要 js 文件,比如登陆的时候请求的地址是 http://127.0.0.1:5500/host/login/js/dist.js 其实我们想要的文件,还是 host/js/ 目录中的 dist.js 文件而已。

前端路由其实是一种假象,只是用来蒙蔽使用者,无论用什么路由,访问的都是同一套静态资源。之所以展示的内容不同,只是因为代码里,根据不同的路由,对要显示的视图做了处理。

解决

需要后端的配合:

对服务器做一些手脚,将不存在的路径请求重定向到入口文件。

---> 也就是说,一旦匹配子路径,发现404了,直接将路径的子目录移除掉,返回根目录中对应的文件,也就是说,请求的是子目录,找不到,就返回根目录一级对应的资源文件。

---> 比如要找http://127.0.0.1:5500/host/login找不到,直接返回http://127.0.0.1:5500/host

后端配置

nginx

location /rootpath/ { 
    root html; 
    index index.html index.htm; 
    try_files $uri $uri/ /rootpath/index.html;
}

参考资料:

(35条消息) vue路由模式及 history 模式下服务端配置_vue history路由_巴山却话的博客-CSDN博客 (35条消息) 当使用 history 模式的前端路由时静态资源服务器配置详解_纯爱枫若情的博客-CSDN博客