宝塔面板部署前后端分离项目踩到的坑
宝塔面板部署前后端分离项目项目踩到的坑
项目模式采用了前后端分离的模式。前端是使用iview前端框架,使用的是iview-admin框架。后台使用的是thinkPHP5的PHP框架。
跨域是通过后台解决的。
1.部署后台项目
首先打开宝塔面板输入账号和密码进行登陆。宝塔面板默认安装的目录是在/www下,网站根目录则是/www/wwwroot。安装宝塔面板时已经默认生成好了面板访问地址、用户名和账号。
所以我们上传的项目基本存放在/www/wwwroot下。在此之前,我们需要创建好后台项目需要用到的数据库。
1.1创建数据库
选择数据库,点击添加数据库按钮
在弹出数据库添加表单中填写类似如下信息
默认会生成一个这个数据库指定的用户和用户密码,这个基本上没什么用户只是数据库权限问题。在tp项目中直接配置的数据库全局用户root也可以正常访问这个数据库。
1.2上传代码文件
上传项目源代码文件目录
点击文件,首先需要新建一个目录来存放项目前端和后台文件。例如这里新建了2020JianKongServer这个目录
点击进入2020JianKongServer目录,点击上传按钮,选择上传目录,就可以将整个项目源代码文件上传
这里上传好了后台代码文件夹
接下来,我们还需要对项目中的数据库配置改换为服务器数据库的配置
打开TP项目数据配置文件(/www/wwwroot/2020JianKongServer/admin/application)database.php文件,双击文件进行编辑,配置如下
1.3创建站点
然后创建站点,其实相当于配置web服务器的虚拟机。选择网站,创建站点让外界能访问后台接口
然后TP项目还需要配置站点伪静态,点击设置按钮
在弹出的设置弹窗中,选择伪静态,点击选择下拉框,可以看到有thinkPHP选项,选中该选项,
之后就会在文本域中输入配置信息。点击保存即可
千万不要忘记重启站点
1.4验证部署是否成功
验证后台项目是否正常访问,在浏览器中输入站点地址进行访问
如果出现如下结果,则说名接口可以正常访问
后台接口出入安全考虑,可以对其进行进行安全组设置。
2.部署前端项目
2.1打包项目代码
打包前需要将src/config/index.js中的将请求后台的路径进行修改
baseUrl: {
dev: 'https://produce.com/',
pro: 'http://XXXXX:9003'
},
打开命令行终端,在项目路径下执行命令npm run build进行打包。
打包成功之后项目中多出dist目录。这个目录可以自定义命名。
2.2上传代码文件
将打包生成的文件夹(默认生成的是dist文件夹)上传到服务器中。上传步骤和部署后台项目一致。
2.3创建站点
选择网站,创建站点让外界能访问项目界面
由于vue项目的路由模式如果是history的话,需要web服务器进行相应的配置,否则刷新界面的时候将会报404的错误。这里的web服务器是Nginx。宝塔面板中的Nginx配置文件在/www/server/nginx/conf中
打开nginx.conf文件,可以看到里面导入宝塔面板Nginx所有的.conf后缀的文件配置
...
server
{
listen 888;
server_name phpmyadmin;
index index.html index.htm index.php;
root /www/server/phpmyadmin;
location ~ /tmp/ {
return 403;
}
#error_page 404 /404.html;
include enable-php.conf;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 12h;
}
location ~ /\.
{
deny all;
}
access_log /www/wwwlogs/access.log;
}
include /www/server/panel/vhost/nginx/*.conf;
}
在这种情况下,所以应该在宝塔面板中修改相应站点的配置。
将配置内容拉倒最下方,将
location / {
try_files $uri $uri/ /index.html;
}
加入到配置内容中
点击保存即可,千万别忘记重启站点,否则配置将不会起效。这样就解决刷新报错404的问题。
2.4验证部署是否成功
在浏览器中输入站点进行访问到正常系统界面,则说明部署成功。
2.5遇到问题
1.报错XMLHttpRequest:对预检请求的响应未通过访问控制检查: 没有HTTP正常状态
报错如下:
Access to XMLHttpRequest at http://xxx.xxx from origin 'http://localhost:8000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
刚开始以为是跨域问题,然后在本地访问服务器上接口的时候又没有报跨域问题,在本地又是可以正常请求的,但是部署服务器上就是不行报错,在network里面打开报错的接口login。返回的结果说是后台不存在login模块(由于测试部署直接没有写登陆模块)。然后终于想到引起问题的原因了,首先说本地为何成功?由于登陆是请求后台登陆的接口已经被mock拦截了返回了token和登陆用户信息,但是打包之后,mock模块将不起作用了。所以登陆操作将请求后台接口,然而后台没有做登陆模块的接口,所以报错500的错误。那么如何跳过登陆呢,
捋一下前端的登陆思路,在不要发起对后台登陆接口的操作。
这里看一下router中的index,js
...
router.beforeEach((to, from, next) => {
iView.LoadingBar.start()
const token = getToken()
// console.log("路由跳转钱",token,to.name)
if (!token && to.name !== LOGIN_PAGE_NAME) {
// 未登录且要跳转的页面不是登录页
next({
name: LOGIN_PAGE_NAME // 跳转到登录页
})
} else if (!token && to.name === LOGIN_PAGE_NAME) {
// 未登陆且要跳转的页面是登录页
next() // 跳转
} else if (token && to.name === LOGIN_PAGE_NAME) {
// 已登录且要跳转的页面是登录页
next({
name: homeName // 跳转到homeName页
})
} else {
if (store.state.user.hasGetInfo) {
turnTo(to, store.state.user.access, next)
} else {
store.dispatch('getUserInfo').then(user => {
// 拉取用户信息,通过用户权限和跳转的页面的name来判断是否有权限访问;access必须是一个数组,如:['super_admin'] ['super_admin', 'admin']
turnTo(to, user.access, next)
}).catch(() => {
setToken('')
next({
name: 'login'
})
})
}
}
})
...
以看出router每次跳转前都需要进行验证是否登陆操作。
然后登陆操作用到了store里面的方法,然后是在store的module里面的user,js中
那么需要对handleLogin、handleLogOut、getUserInfo等进行修改,修改如下:
// 登录
handleLogin ({ commit }, { userName, password }) {
userName = userName.trim()
return new Promise((resolve, reject) => {
commit('setToken', 'super_admin')
resolve()
})
},
// 退出登录
handleLogOut ({ state, commit }) {
return new Promise((resolve, reject) => {
// 如果你的退出登录无需请求接口,则可以直接使用下面三行代码而无需使用logout调用接口
commit('setToken', '')
commit('setAccess', [])
resolve()
})
},
// 获取用户相关信息
getUserInfo ({ state, commit }) {
return new Promise((resolve, reject) => {
try {
//根据mock中返回的用户信息来修改
const USER_MAP = {
super_admin: {
name: 'super_admin',
user_id: '1',
access: ['super_admin', 'admin'],
token: 'super_admin',
avatar: 'https://file.iviewui.com/dist/a0e88e83800f138b94d2414621bd9704.png'
},
admin: {
name: 'admin',
user_id: '2',
access: ['admin'],
token: 'admin',
avatar: 'https://avatars0.githubusercontent.com/u/20942571?s=460&v=4'
}
}
const data = USER_MAP[state.token];
commit('setAvatar', data.avatar)
commit('setUserName', data.name)
commit('setUserId', data.user_id)
commit('setAccess', data.access)
commit('setHasGetInfo', true)
resolve(data)
} catch (error) {
reject(error)
}
})
},
则再次打包进行部署之后,这样的问题就没了。