X
返回

Nginx打包Vue项目部署

文章信息:
  • 分类:服务器部署
  • 阅读量:6129
  • 创建时间:2022-04-09
  • 更新时间:2年前

准备工作

准备一台服务器:

我用的是华为云的云耀云服务器,系统用的是 Ubuntu,linux 系统操作上基本类似

Nginx 安装和启动:

安装 Nginx

sudo apt-get install nginx

启动

sudo service nginx start

启动后,正常情况下,直接访问 http://服务器 ip 或者域名地址就可以看到 Nginx 的服务器默认页面,如果访问不到,可能是服务器的 80 端口没对外开放,在服务器安全组配置一下 80 端口即可

Nginx 配置:

查看 nginx 的配置,linux 系统下的配置文件通常会存放在/etc 目录下,nginx 的配置文件就在/etc/nginx 文件夹,打开文件

vi /etc/nginx/sites-available/default

nginx 可以有多个配置文件,通常我们配置 nginx 也是修改这个文件

默认情况下,nginx 代理的根目录是/var/www/html,输入 http://服务器 ip 会访问这个文件夹下的文件,会根据 index 的配置值来找默认访问的文件,比如 index.html、index.htm 之类。
我们可以更改 root 的值来修改 nginx 服务代理的文件夹:

  1. 创建文件夹
    在服务器目录里面找个地方创建文件夹(这个根据个人喜欢存放)
mkdir /web

这里我是在服务器根目录下创建了一个叫 web 的目录
2. 修改 Nginx 配置里面的 root

  1. 在目录下创建 html 文件
echo 'myNginx config' > /web/index.html
  1. 检查 Nginx 配置是否正确
sudo nginx -t 检查nginx配置是否正确

出现successful就证明配置是正确的

  1. 重启 Nginx 加载配置
sudo nginx -s reload
再次访问页面的时候发现内容已经变成我们创建的web目录下的html文件了

Vue项目打包同步文件到远程服务器

  1. 打包
    默认情况下,使用vue-cli创建的项目,package.json里的script应该已经配置了build指令,直接执行yarn build 或者 npm run build即可。
  2. 同步到远程服务器
    我们使用nginx部署Vue项目,实质上就是将Vue项目打包后的内容同步到nginx指向的文件夹。之前的步骤已经介绍了怎样配置nginx指向我们创建的文件夹,剩下的问题就是怎么把打包好的文件同步到服务器上指定的文件夹里,比如同步到之前步骤中创建的/www。
    同步文件可以在git-bash或者powershell使用scp指令,如果是linux环境开发,还可以使用rsync指令:
scp -r dist/* root@服务器公网Ip:/web
或
rsync -r dist/* root@服务器公网Ip:/web

为了方便,可以在package.json脚本中加一个push命令

"scripts": {
    "build": "vite build",
    "push": "npm run build && scp -r dist/* root@服务器公网Ip:/web"
  },

这样就可以直接执行yarn push 或者npm run push直接发布了, 访问一下,原来打开的页面变成了你新部署上去的vue页面

非域名根路径发布

有时候我们会在同一台服务器上部署多个项目,那么我们会创建多个文件夹去区分不同的项目。我们刚刚Nginx默认指向的是web/目录,那么当我们访问地址的时候默认是查找这个目录的下的index.html,那么当我们想要部署不同的项目时需要修改nginx配置以及Vue打包配置

  1. Nginx配置
    只需要添加一条location规则,分配访问路径和指定访问文件夹。我们可以把/admin指向新创建创建的/vue3文件夹,这里因为文件夹名称和访问路径不一致,需要用到alias这个配置:
location /admin {
    alias /vue3;
}

如果文件夹名称与访问路径一致都为admin,那这里可以用root来配置:

location /admin {
    root /;
}

注意:这里要将/admin配置放到/之前,意味着在路由进入的时候,会优先匹配/admin。如果根路径/下的项目有子路由/admin,那http://xxxx/admin只会访问到/vue3里的项目,而不会访问该子路由。

  1. 项目配置
    为了解决打包后资源路径不对的问题,需要重新在项目配置引用路径
    vite配置:
// vite.config.ts
base: '/admin/'

webpack:

// vue.config.js
publicPath: '/admin/'

如果不进行项目配置,直接发布访问会出现JS、CSS等资源找不到导致页面空白的问题,该问题原因是资源引用路径不对,页面审查元素可以看到,页面引用的js都是从根路径下引用的:

该问题原因是资源引用路径不对,页面审查元素可以看到,页面引用的js都是从根路径下引用的:

查看打包后的文件结构,可以看到static资源文件是与index.html处于同级别的

  • vite的base或者webpack的publicPath配置为./, 打包后资源引用路径为相对路径:

  • vite的base或者webpack的publicPath配置为./admin,打包后资源相对路径为从域名根目录开始的绝对路径: 更新nginx配置,发布后即可正常访问啦。
  1. 绝对路径引用的静态资源找不到的问题
    因为在打包过程中,public下的静态资源都不会被webpack处理,我们需要通过绝对路径来引用它们。当项目部署到非域名根路径上时,这点非常头疼,你需要在每个引用的URL前面加上process.env.BASE_URL(该值即对应上文配置的publicPath),以使得资源能被正常访问到。我们可以在main.js把这个变量值绑定到Vue.prototype,这样每个Vue组件都可以使用它:
    Vue.prototype.$pb = process.env.BASE_URL
    在模板中使用:
<img :src="`${$pb}static/logo.png`">

然而,更加头疼并且没有良好解决方案的问题是在组件style部分使用public文件夹下的静态资源:
如果需要使用图片等作为背景图片等,尽量使用内联方式使用吧,像在模板中使用一样。
如果需要引入样式文件,则在index.html中使用插值方式引入吧。
关于静态资源的问题,vue-cli的推荐是尽量将资源作为你的模块依赖图的一部分导入(即放到assets中,使用相对路径引用),避免该问题的同时也带来其它好处:

history模式部署

默认情况下,Vue项目使用的是hash路由模式,就是URL中会包含一个#号的这种形式。#号以及之后的内容是路由地址的hash部分。
正常情况下,当浏览器地址栏地址改变,浏览器会重新加载页面,而如果是hash部分修改的话,则不会,这就是前端路由的原理,允许根据不同的路由页面局部更新而不刷新整个页面。
H5新增了history的pushState接口,也允许前端操作改变路由地址但是不触发页面刷新,history模式即利用这一接口来实现。因此使用history模式可以去掉路由中的#号。

  1. 项目配置
export const route = createRouter({
  history: createWebHistory('/admin'),
  routes: routes as unknown as RouteRecordRaw[],
});

我这里是vue-route4的配置,其他版本请直接查看文档

  1. Nginx配置
    对于history模式,假设项目部署到域名下的/admin目录,访问http://xxx/admin/login的时候,服务器会去找/admin指向的目录下的login子目录或文件,很显然因为是单页面应用,并不会存在a这个目录或者文件,就会导致404错误。
    我们要配置nginx让这种情况下,服务器能够返回单页应用的index.html,然后剩下的路由解析的事情就交给前端来完成即可。
location /admin {
    root /;
    try_files $uri $uri/ /admin/index.html;
}

评论/留言