冷静一下心情:
问题: 最近有一批项目是uni-app 开发的,外包团队给的源码部署后出现了图片资源无法访问等现象
解决方案:这个涉及到前台和服务器之间的配置, 除了配置,代码上也需要调整,下面给出单站点和多站点访问的设置
1. 单站点访问
- 我们先了解一下 uni-app 的配置文件[
manifest.json
]
{
"name" : "******",
"appid" : "****",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
"debug" : false,
/* 5+App特有相关 */
"app-plus" : {
"usingComponents" : true,
"nvueCompiler" : "uni-app",
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* 模块配置 */
"modules" : {},
/* 应用发布信息 */
"distribute" : {
/* android打包配置 */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios打包配置 */
"ios" : {},
/* SDK配置 */
"sdkConfigs" : {}
}
},
/* 快应用特有相关 */
"quickapp" : {},
/* 小程序特有相关 */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"h5" : {
"title" : "--------",
"router" : {
"mode" : "hash",
"base" : "/" // 注意此处的base 并不是给访问的路由增加前缀的 和下面的publicPath 要区分开
},
"publicPath" : "/" // 此处的单站点直接设置为 `/` 就行
}
}
- 我们把H5 这一部分抽离出来进行配置
"h5" : {
"title" : "--------",
"router" : {
"mode" : "hash",
"base" : "/"
},
"publicPath" : "/" // 注意是 yarn build:h5 才会使用这个路径
}
-
uni-app 配置文件我们看过了,看下什么是单站点访问
- 比如: 我们设置的域名为:
https://h5.example.com
访问的路径是我们打包后的dist/build/h5/index.html
, 这种情况我们 配置文件设置成"base : "/"
, 同时"publicPath": "/"
- 比如: 我们设置的域名为:
配置文件完成了,那么代码里面的该怎么去写呢
<view class="detail_title" @click="pulldown(index)">
<img src="static/bill_icon_water@2x.png" class="detail_type"/>
{{items.ln_policy_title}}
<img src="static/bill_icon_pulldown_pressed@2x.png" class="detail_jian" :class="{xuan:index == indexa&&detail == true}" />
</view>
- 不要问我static 目录放在放在那里,连接看向这里 uni-app 开发规范
- 最终访问资源的路径为:
https://h5.example.com/static/bill_icon_pulldown_pressed@2x.png
, 这个路径是根据domain 地址加上 配置文件的 base 生成的,能解决掉资源丢失的问题 - 可能有人会问 为什么不用
@/static/image.png
这种形式,经过查阅文档发现,这种方案是可行的,也是我自己推荐的,但是我们如果图片过大,这种在执行npm build:h5
指令后,有些大图并不能转成base64 还是无法解析
,所以方案你们可以根据场景去使用 - 【新增加的】 由于uni-app 不建议我们重写vue.config.js 那么 大图模式下 我们采用
src="/static/img/logo.png"
,此时需要检查项目 src 目录下manifest.json 文件里面的H5 的 router base 配置和 publicPath 配置保持统一,这样方便测试和正式环境都能正确识别路径 【重要
、重要
、重要
】 - 单站点不涉及服务器内容,所以后台提供什么,你们就按照什么格式进行打包就行
2. nginx 多站点 h5 访问时部署
-
多站点是什么意思
- 简单来说就是一台nginx 上面配置了多个二级地址供外面访问,比如 之前我们 访问
https://h5.example.com
, 现在可能需要访问https://h5.example.com/pay
、https://h5.example.com/notice
、https://h5.example.com/work
等等这些带有sub-path 的访问 - 这个时候我们先把配置弄好
"h5" : { "title" : "物业公告", "router" : { "mode" : "hash", "base" : "/notice/" 此处填写当前sub-path 对应的路径 此处可改成 pay or notice or word }, "publicPath" : "./" 此处注意一点, 需要设置成 `./` 此处用于生成index.html 引用JS文件位置 }
- Vue 页面内针对 static 目录下的文件访问, 参考单站点的写法
- 前端修改的地方不是很多,下面看服务器对多站点的解析
- 简单来说就是一台nginx 上面配置了多个二级地址供外面访问,比如 之前我们 访问
server {
listen 80;
server_name h5.example.com;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/h5.example.com/;
#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
#SSL-END
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
#error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END
#PHP-INFO-START PHP引用配置,可以注释或修改
include enable-php-73.conf;
#PHP-INFO-END
#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/h5.example.com.conf;
#REWRITE-END
#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
location /graphql-file {
proxy_pass https://www.example.com/graphql-file;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 代理访问
location /graphql {
proxy_pass https://www.example.com/graphql;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ^~ /pay {
index index.html index.htm;
autoindex on;
alias /www/wwwroot/h5.example.comfrontend/pay/dist/build/h5;
}
location ^~ /notice {
index index.html index.htm;
autoindex on;
alias /www/wwwroot/h5.example.com/notice/dist/build/h5;
}
location ^~ /work {
index index.html index.htm;
autoindex on;
alias /www/wwwroot/h5.example.com/work/dist/build/h5;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log off;
access_log /dev/null;
}
location ~ .*\.(js|css)?$
{
expires 12h;
error_log off;
access_log /dev/null;
}
location / {
try_files $uri $uri/ /index.html;
}
access_log /www/wwwlogs/access.log;
error_log /www/wwwlogs/error.log;
}
服务器配置完毕,我们需要针对 nginx 执行
nginx -t
来检测 ,检测通过 执行nginx -s reload
多站点的配置到这里我们就完成了
3. 前后端分离的针对跨域的设置
- 比如前端访问
https://h5.example.com
, 里面API 调用的是https://api.h5.example.com
,访问时前端会出现一个 options 的请求, 此时,我们最简单的办法就是在nginx 里面设置个uri 拦截
location ^~ /api {
proxy_pass https://api.h5.example.com/api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
- 注意H5内部的改动,前端此时的request 请求的baseUrl 还是访问
http://example.com
4. 总结:
针对以上两种方案,我们都是在生产环境直接上用的, 开发环境这样配置也是没什么影响的哦
-
本地如何设置成多环境的呢
- 本地新建一个 json 文件
env.example.json
- 本地新建一个 json 文件
- Mac 环境 执行
cp env.example.json env.json
, Wins 环境copy env.example.json env.json
或者 手动拷贝一份,名字改成 env.json
- Mac 环境 执行
- 将env.json 文件添加到 .gitignore 文件中 并在代码中使用的地方进行引用
- 文件内容为:
{ "env" : "production", "base_url": "http://h5.example.com", "city": "shanghai", "map_url": "https://api.map.baidu.com/geocoder/v2/?ak=ak", "callback_url": "'call_url'" }
- 注意一点 uni-app 内 等价webpack 的文件是 vue.config.js 具体是否能用需要看uni-app 文档哦
- 如果有不对的地方,大佬尽情指教,联系方式:
me@raybon.vip
- 如果有不对的地方,大佬尽情指教,联系方式:
标注 新增加的,是自己测试中发现的一个加载问题
说个问题, uni-app 内部如果加载的静态资源图片大于 8192 字节 时,采用 / 方式加载, 如果是 小于这个数值 采用 @ 符号进行处理
,
具体可查看 先关文档 【webpack url-loader】
url-loader
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
}
}
以上是在处理 uni-app 时候的一个兼容问题