Vue 项目打包并部署到 GitHub 为 demo
本文最后更新于:2024年10月27日 凌晨
一文搞清楚 Vue 项目打包并部署到 GitHub 为 demo 的整个流程
目标:将打包好的 Vue2 | Vue3 项目部署到 github pages 用作项目 demo
我将尽可能的讲述打包前后可能遇到的绝大部分问题和原因,希望能有所帮助。
打包前的问题
打包其实实际上不会碰到什么大问题,我们讨论的问题实际是打包之后想要将打包结果也就是静态页面进行部署而发生的问题:
- 白屏问题
- 刷新 404 问题
- 跨域问题
但要想讨论上述问题,我们得研究好打包前的配置问题,也就是为什么会出现上述问题?
请求地址配置问题
首先我这里默认你的项目中二次封装了 axios
并配置了 base
请求基地址(别告诉我请求地址是 localhost 哈),那么你的请求配置方法可能是:
- 主动暴露 base
或者你是这样配置的(环境为 Vue3+vite):
- 配置 proxy 转发
如果你并没有在二次封装 axios 的过程中暴露具体请求地址,而是配置了 proxy 进行代理转发,你的 proxy 配置可能是:
配置 proxy 的开发环境下,只要请求匹配到 /api
就会把请求转发到 target
并且将 /dev
删除,浏览器请求为(假设你的项目运行在 8088 端口):http://localhost:8088/dev/api/end-point
,实际请求为:http://your.domain.com/api/end-point
proxy 的缺点
这两者在开发环境进行请求都没有问题,都能完成任务,但是一旦进行了打包,脚手架环境消失,这第 2 种配置方法就失效了,请求会只剩下 /dev/api/end-point
这种形式。
可能你会问:玩呢?这怎么发请求,我明明还是见到浏览器发出请求了啊,只不过失败了。
是的,/dev/api/end-point
这种形式的确不能正常发请求,不过浏览器会在只给出如 /dev/api/end-point
的形式的请求时,自动在前面拼接上下文环境,比如在本地测试项目,浏览器就会自动拼接上 http://localhost:8088
使得最终形式为:http://localhost:8088/dev/api/end-point
。不过变成这种情况的话,基本也就无法部署了(本地部署除外),因为你已经失去了脚手架的 proxy 环境,不过你依然可以在 Vue 项目的同系统环境下使用 Nginx(类似 Nginx 的也行)尝试进行监听和转发,也就是反向代理。详情请见下节中的 history 使用。
那么第 1 种配置方法会在打包之后发生什么问题吗?不会,它可以正常工作(除非请求地址是 localhost,如果为 localhost 则会引起跨域问题)。
Js 引入地址配置问题
如果说请求地址影响着数据显示问题,那么 js 引入地址影响的是打包后的页面白屏问题。
这个问题基本上就是打包后的文件引入问题,我们应当将导出后的 js 等文件的引入地址配置为相对地址。
在 vite 或 vue-cli 中 应当配置 如下:
对于 vue2 的 vue-cli,官方文档中不推荐直接配置
output.publicPath
而是始终使用 **publicPath
**
这将使得打包后的 index.html
页面的 js 引入地址为相对地址,看起来就像这样:
请注意结果为 css/app.363852d2.css
而非 /js/app.5bd045ab.js
解决打包后的白屏问题
出现白屏问题,白屏分为:
- 跨域造成的
- js 未正确引入造成的:没有配置成相对路径,详见 js 配置
- 其他……
解决跨域问题
相关链接:什么是跨域问题?
其实也谈不上解决,毕竟这个问题不是真正的跨域问题,真正的跨域问题只靠前端不靠服务器是不可能解决的。
一般这种情况下的跨域问题主要是打包后的文件是以 file 协议进行读取的,而 file 协议不像 http (s) 协议支持跨域,所以控制台 CROS 跨域报错
解决方案参考:vite 打包本地文件,file 类型 URL 引发跨域等问题探讨
但我不太推荐上面的解决方案,因为利用 Nginx(或其他网络服务器)的反向代理就够了。
详情见 history 使用
其他
诚然,我不可能见过所有的白屏问题,所以欢迎探讨。
解决打包后的刷新 404 问题
为什么会出现有基本结构但是我刷新就报 404 错误呢?
这个问题的发生满足以下条件:
配置了默认访问或
/
访问重定向到某具体路由页面,如/home
配置了路由模式为不带
#
符号的history
历史模式
为什么说满足以上条件就会触发这个问题呢?
这是因为当你第一次访问项目,你的访问地址可能是:http://localhost:8088
或者 http://localhost:8088/
而因为你的项目满足第一条,所以你的项目自动重定向到了你指定的某个具体路由页面,比如:http://localhost:8088/home
如果你按照上述方式访问,这个时候为第一次访问,是没有任何问题的,js 正常加载,页面正常显示。一旦当你刷新之后,访问地址就变成了 http://localhost:8088/home
这是什么地址?浏览器会认为 /home
是一个后端路由地址将其携带到后端服务器:” 嘿哥们,你这儿有这样一个路由地址吗?“,然而后端实际上没有这样一个路由能匹配,于是就造成了 404 not found
的结果。
那为什么别人做的网站 / 项目不会这样呢?当然是因为别人已经配置过了,没有经过正确配置之前,人人都一样的。
那是不是 Hash 哈希模式就可以呢?是的,hash 模式可以解决这个问题。
这是因为设置为 hash 模式后,如果有 http://your.domain.com/#/homepage
这样一个地址,那么其中的#/homepage
就是 hash
值,hash
值只在客户端(如浏览器)中使用,是不会带给服务器的,所以使用 hash
模式时,不存在刷新 404
问题。
怎么使用 history 模式
我不想出现 404 错误,我也不想使用 Hash 模式,我该怎么使用 history
模式来让网站变得更优雅呢?
思路:让服务器那边在收到未配置的 GET
路由时,都返回 index.html
即可。
什么意思呢?如果浏览器将这样一个后端不认识的路由真的带给了服务器,那么服务器就把 index.html
塞回去,index.html
回去了意味着它所引入的 js 就工作了,js 工作了那么前端路由就活过来了,于是就可以正确处理路由地址了,404 not found
问题也就迎刃而解了。
这也是为什么某些文章中使用 Nginx 配置里有 try_files $uri $uri/ /index.html;
存在了。
换句话说,如果你是本地部署使用 Nginx,它可以解决你的刷新 404 问题,并且,Nginx 也能解决打包后 proxy
失效带来的请求问题,配置 conf/nginx.conf
如下:
- 请注意 Nginx 的根目录最好不要是 C 盘,防止权限不足
相关链接:Nginx 下载
GitHub Pages 上的 history 路由模式可行性
我的看法
相信看过上面你已经想到了:我能不能对部署在 GItHub 上的 demo 也这样配置?
我只能说,我没试过,但我觉得不行:因为 Nginx 和 demo 不在同一个系统环境。
上述配置能成的根本原因是:在前端将路由也带来的情况下,Nginx 进行监听并匹配成功,然后将 index.html
进行返回。
这里的重点在于,Nginx 要能成功监听到项目的根地址,但对于部署到 GitHub 上的 demo 来说,浏览器会直接向 GitHub Pages 请求资源,而 GitHub Pages 只支持静态文件托管,它是没有针对 history
模式的服务端配置的。
而且,我总不可能将 Nginx 也部署到 GitHub 上吧?
一个可能的方法
不过,ChatGPT 有一个它的解决办法:在 dist
打包目录内中加入一个 404.html
页面用于手动返回 index.html
我无法验证该方法的可行性,因为我已经将我的 pages
给我生成的域名用来部署了 hexo
博客,我的所有其他仓库的 pages
项目都是在该域名下,这导致我的 demo 无法使用该方法,我也就无法验证了。
相关链接:GitHub Pages 部署 hexo 静态博客 -Fluid 主题
我参考的那篇文章找不到了……
一个可能需要的配置参考
别忘了给你的 Nginx
服务器加上 ssl监听
并正确转发请求(什么是 ssl 证书?),因为 GItHub 的网络环境是 https 的,如果你发送 http 请求,浏览器将会进行拦截。
可自行搜索需要的免费 ssl 证书签发厂家,如果你的远程服务器没有域名,那么你需要的 ssl 证书为 ip 证书,我使用的正是这种类型,可以搜索:zerossl
我的 Nginx
配置示例如下:
我的 demo 使用的数据来自 Strapi(什么是 Strapi?),我将该无头 CMS 部署到了和 Nginx 同一系统环境之下,于是有了上述配置。
部署到 GitHub Pages
可选配置
终于到了激动人心的部署时刻,在打包之前请根据上文做好自己项目的配置,除此之外还有一个配置对于 vite 打包的项目可选:
添加上述 build
配置项,将会将打包后的 dist 目录按类型分 css
、js
、img
文件夹。当然只是可选,非必须。
Github 部署
好了,请将项目 build
打包为一个 dist
文件夹。然后按照以下步骤进行部署:
转到 GitHub 创建一个新的仓库(已有仓库跳第二步),填写
Repository name
仓库名并将仓库设为Public
公开就可以了,其他不用设置,点击Create repository
创建仓库即可。复制仓库的 ssh 链接(我没有用过 git 进行远程仓库绑定),例如:
找到本地刚新鲜打包的
dist
文件夹,进入文件夹中,目录结构应该为:在
dist
文件夹内,执行 git 仓库初始化添加所有文件到暂存区,并执行
commit
提交
注:vite
打包的项目可能会存在以_
下划线开头的js
文件,而GitHub Pages
可能忽略该文件,导致项目 demo 无法找到文件报 404 错误,请检查你的 dist 文件夹下的 asset 目录中是否存在上述文件。如果确实存在,请在dist
目录下创建一个空文件以禁用 GitHub Pages 的 Jekyll 默认处理行为,文件名为:.nojekyll
参考文章:github pages 不能识别下划线开头的文件绑定远程仓库
你可以将该分支(我的默认初始化分支为 main)先 push 推送出去,已有仓库的可以跳到 8
创建孤立的空分支
gh-pages
用于推送推送代码到
gh-pages
分支用于部署静态页面转到 GitHub 仓库页,请切换仓库分支为
gh-pages
并等待GitHub
的check
操作:GitHub 的 check 操作完成后,点击仓库
Settings
设置项,然后在左侧侧边栏选择Pages
,点击构建好的链接或者右边的Visit site
即可。
小白篇到此,完结撒花🎉🎉🎉
有更多需求可以自行探索,相信你已经入门了。