vite vue-router history 打包,页面空白问题解决方案

前端使用vite + vue-router@4,部署是用nginx

背景

vue-router的hash模式逃不掉url后面的#号,想要去掉#时,我们就得考虑使用histtory模式

vue-router@4创建history模式路由,大致代码如下👇

	const router = createRouter({
	    history: createWebHistory(),
	})

问题

前端通过history打包部署后会发现刷新404了,这个问题设计到hash和history的区别了

  • hash模式 简单来说,它是基于浏览器的锚点实现的,#号后的url变化不会向服务器发送请求
  • history模式 url的变化都会向服务器发送一个请求,如果服务器没有做处理,对应的url找不到对应的资源返回,那么就会页面404

前端打包文件中(一般情况下)只包含了一个index.html文件和其他如js、css等资源文件,所以当history模式的url变化时,在服务器上找不到与之对应的资源,就会404了。

说的有点抽象,给大家举个例子:

同一个页面的url,hash模式是http://www.abc.com/#/home,那么访问后到服务器时#号后面的内容是不会发送到服务器的,那么就是访问/根目录,/后面没有内容,就会默认访问index.html页面,打的包中正好有index.html文件,那么就一点问题也没有。但如果是history模式,此时的url为http://www.abc.com/home,那么这个url代表的意思就是(服务端没做其他操作的前提下)访问服务器根目录下的home目录下的index.html文件,但我们知道正常打的包根本就没有这个home目录,那就理所当然的404了

解决办法

vue-router官网上所说

要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的
 index.html 相同的页面

在nginx做如下配置

	location / {
	  try_files $uri $uri/ /index.html;
	}

这里用到了try_files配置,简单说下它的作用:它首先匹配url有没有对应的资源(即上面的 u r i ),如果有则返回;如果没有,则继续查找 u r l 目录下(即上面的 uri),如果有则返回;如果没有,则继续查找url目录下(即上面的 uri),如果有则返回;如果没有,则继续查找url目录下(即上面的uri/)有没有默认的index.html文件,如果还没有,最后返回根目录下的index.html(即上面的/index.html)。其实在这里,我们想要的就是让它无脑返回根目录下的index.html(因为我们只有这个可访问文件)

这个时候,我们把打的包扔到nginx根目录下,并且加上如上配置,访问如http://www.abc.com/home页面就一切正常了。

至此部署到服务器的根目录就OK了~!

新的问题

如果部署在二级目录下,刷新依然会404,那么问题在哪呢?

把网页部署在/wj目录下(下文出现的所有newpage指的都是这个二级目录名称),并把前端打的包扔在了服务器上的/newpage目录下,期望访问http://www.abc.com/newpage/home能正常访问,那么按照经验,我们把nginx的配置修改成如下:

	# nginx 修改后配置
	location /newpage {
	  try_files $uri $uri/ /newpage/index.html;
	}

nginx -s reload 后你会发现一个新问题

html文件其实正常返回了,但是资源文件都404了,检查资源文件的请求路径,发现根本没有请求到真实的资源地址,因为我们的资源文件都是在/newpage目录下,图中请求的是根目录下的资源文件,那当然没有了。

新的解决办法

聪明的小伙伴对vite的中的base进行修改 官网配置链接

所以我们将vite.config.js的配置修改成如下

	// vite.config.js
	{
		base: '/newpage/'
	    // 其他代码省略
	}

再重新打包部署,你会发现 ,资源找到了 ,所有的请求全部200 ,但是又有新的问题出现了,页面白屏,这百思不得其解。

仔细分析一下,我们访问的路径是带newpage的,但是vue-router定义的路由其实不带路径,此时聪明的你就又会想到vue-router也有一个配置 官网配置链接没错,所以我们修改对应配置如下

	const router = createRouter({
	    history: createWebHistory('/newpage/')
	})

重新打包上传,你会发现一切正常,非常完美,大功告成!🎇🎇🎇

不同环境的打包

不同环境的打包怎么办?手动改一次代码打包一次?不可能也不应该吧。

我们要能根据不同环境切换不同的base,这里采用的方式是使用 vite环境变量和模式来切换,具体方式如下:

创建 3 个.env文件,分别为.env.dev(测试环境), .env.development(开发环境), .env.production(生产环境)

	# .env.dev
	VITE_BASE_URL=/
	# .env.development
	VITE_BASE_URL=/newpage/
	# .env.production
	VITE_BASE_URL=/newpage/

定义了不同环境时的环境变量,那么只要在vue-router和vite config对应位置使用环境变量替换原来的固定值即可

	const router = createRouter({
	    // 这里由原来的 '/newpage/' 固定值改为import.meta.env.VITE_BASE_URL替换
	    history: createWebHistory(import.meta.env.VITE_BASE_URL)
	})
 

vite.config.js中略有不同,大致代码如下:

	import { defineConfig, loadEnv } from 'vite'
	
	export default ({ mode }) => {
		// 使用loadEnv获取环境变量
	    const env = loadEnv(mode, process.cwd())
	    const BASE_URL = env.VITE_BASE_URL
	
	    return defineConfig({
	        base: BASE_URL, // 使用loadEnv获取VITE_BASE_URL替换原来的固定值 '/wj/'
	        // ...省略其他代码
	    })
	}
 

修改package.json文件,自定义不同环境的打包命令,这里就不做介绍了

总结

总结一下history模式部署时需要改动的地方

  • 如果是部署在根目录下,只需要改nginx配置即可,前端配置无需修改
  • 如果是部署在二级目录下(如部署在/newpage目录),修改内容如下
    • nginx配置
    • vue-router配置
    • vite.config配置

此致遍大功搞成了!!!

### 配置 Vue Router 为了在 Vite 项目中配置和使用 `vue-router` 进行路由管理,需遵循特定步骤来确保一切正常工作。 #### 添加依赖项 对于基于 ViteVue 项目而言,可以通过包管理工具安装所需的 `vue-router` 版本。如果采用的是 `pnpm` ,那么可以在项目的根目录执行命令 `pnpm add vue-router@4` 来获取最新版本的 `vue-router` [^1];而若是偏好于 `npm` 则应通过 `npm install vue-router` 完成相同操作 [^2]。 #### 设置路由模块 创建一个新的 JavaScript 文件用于定义应用程序中的路由逻辑。通常情况下是在源码(`src`)文件夹内建立名为 `router` 或者直接命名为 `router.js` 的子文件夹及其下的 JS 文件。此文件里会引入必要的 API 函数并声明应用内的路径映射关系: ```javascript // src/router/index.js or src/router.js import { createRouter, createWebHashHistory } from 'vue-router'; const routes = [ { path: '/home', component: () => import('../views/HomeView.vue') }, { path: '/about', component: () => import('../views/AboutView.vue') } ]; const router = createRouter({ history: createWebHashHistory(), routes, }); export default router; ``` 上述代码片段展示了如何利用懒加载的方式导入组件以及设置基础的历史模式为哈希历史 (`createWebHashHistory`) 。这有助于提高首次加载性能的同时保持 URL 地址栏友好性 [^4]。 #### 应用程序入口处注册路由器实例 最后一步就是在主应用程序文件 (通常是 `main.js`) 中引用之前创建好的路由对象,并将其挂载至 Vue 实例上以便在整个应用范围内生效: ```javascript // main.js import { createApp } from 'vue'; import App from './App.vue'; import router from './router'; createApp(App).use(router).mount('#app'); ``` 值得注意的是,在模板文件如 `App.vue` 中应当包含 `<router-view></router-view>` 标签以作为占位符让不同页面的内容能够被渲染出来 [^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值