首页 前端知识 解决一些搭建与部署网站时可能遇到的问题

解决一些搭建与部署网站时可能遇到的问题

2024-09-01 00:09:18 前端知识 前端哥 553 803 我要收藏

前言

        假期里与团队搭了一个小网站,网站主题是青岛旅游检索。网站集成地展示了青岛的角角落落,我们对其分成了几大类进行信息展示,包括“著名景点”“美食体验”和“驻青高校”,每一大类下面又有许多分支,信息收集较为全面。除了信息展示功能,我们还提供了用户搜索、旅游路线个性定制、自由路线规划等交互性较强的功能。这次项目是我们对网站搭建的初次尝试,会有很多不足,但也不枉十几天的努力。

        在这个项目中我负责的部分是前端网页制作和服务器部署,搭建网站的整个过程并不轻松,中间会遇到很多问题,但最终也一一解决了。因此这里我对网站搭建与部署中可能遇到的问题进行归纳总结,希望对更多正在探究的码者有帮助。

网站地址

        我们网站的地址是:http://qdtourism.top/

        如果感兴趣可以移步瞧瞧、试试功能,但是我只买了一年的云服务器和域名,过了明年这个时间段应该就访问不了了。

        额卖完瓜之后就该上干货了,下面我将只针对前端网页制作部分与服务器部署部分中所遇到的问题及解决方法进行列举。(但我这里不会再说html和css怎么写,一般是基于网站结构与样式已经搭好的基础上,针对进一步调试的时候会出现的问题)

一、前端网页制作部分

        1、不同电脑中样式显示不同

        初步搭好网站后,在保证网页样式在我自己的电脑中已经用css调好的基础上,我把网页代码发给其他人打开,会发现只要不是跟我一样的电脑,打开的网页中个别元素(如图片)的样式排版都会很乱,乱得各有千秋。在排查之后最终发现本质问题:不同电脑分辨率一般不同,而我对图片等元素的位置设置是固定设置(position:fixed)或绝对设置(position:absolute),是定位模式的问题导致了不同分辨率的窗口中元素显示的问题。

        首先我对css位置参数(position)的几种模式加以解析与区分:

        static:这是所有html元素的默认定位值(不设置即默认)。元素按照正常的文档流进行排列,不会受到top、bottom、left、right的影响。

        relative:相对定位是指元素相对于它在文档流中的原始位置进行定位。无论偏移多少,它都会在文档流中保留空间,不影响其他元素的定位。

        fixed:固定定位是相对于浏览器窗口来定位的,即使页面滚动,它也会固定在相应的位置。使用fixed定位的元素不会保留在文档流中的位置,会被其他内容覆盖。

        absolute:绝对定位则是相对于最近的已定位父元素来定位的。如果元素没有已定位的父元素,那么它的位置相对于<html>元素。绝对定位的元素同样不会在文档流中保留位置。

        sticky:粘性定位是基于用户的滚动位置来定位的。在页面滚动到一定程度时,它会像固定定位一样保持在特定位置;否则,它的行为与相对定位相同。

        可以看到,fixed模式是明确会受视口分辨率影响的,当窗口大小变化时,使用fixed定位的元素的位置也会随之变化。而absolute定位是相对于最近父元素定位的,如果父元素的大小或位置因窗口尺寸变化而改变,那么子元素的定位也会受到影响。因此使用这两种定位都有无法适应全部视口的问题。

        解决方法:改变元素定位模式。可以用相对定位relative,也可以使任何元素(无论是文字还是图片)都只适应文档流,即用默认的静态定位static。这主要是因为这两种定位方式都是顺应文档流的。下面是一个使用相对定位的例子:

/* 路线生成按钮设置 */
.route_button{
    background-color: #f2f7f8; 
    border: 2.5px solid #1e4b6a;
    color: rgb(12, 63, 84);
    padding: 10px 20px; 
    text-align: center;
    display: inline-block;
    font-size: 16px;
    margin: 4px 2px;
    position: relative;
    right: -500px; 
    bottom: 50px; 
    cursor: pointer; 
  }
.route_button:hover{ 
    background:#e6ebec;
}

        2、一些网页功能实现的参考

        以下所有功能都是基于javascript、DOM操作以及对数组的处理来实现的。

        1)选择功能

        实现方法:使用JavaScript脚本语言、通过DOM操作和对数组的处理实现一个具有去重功能的选项显示逻辑,使网页与用户有一个选择交互。

        实现逻辑:首先获取用户所选选项,再进行去重处理(创建一个空数组来存储不重复的用户选项,遍历所有选项并检查它们是否已选中且未被添加到数组中,以确保选项的唯一性。),最后通过DOM操作将已有选项与新选选项对比合并,更新显示(获取当前已显示的选项,并根据是否是第一次显示来更新显示的内容。如果是第一次,直接显示选出的选项;如果不是,将现有显示的选项与新选出的选项进行对比和合并,然后更新显示。)。

        代码:我们的自由路线规划页面共有三处选择功能的体现,即对起点、途经点、终点的选择,下面仅展示起点选择功能,另两处代码大同小异:

// 选择当前位置
function showCurrentPoint(){
    // 维护一个去重数组,将用户选项不重复地显示在页面上
    var select=document.getElementById("destinations");
    var selectedPoint=[];
    for(var i=0; i<select.options.length; i++){
        if(select.options[i].selected && !selectedPoint.includes(select.options[i].value)){
            selectedPoint.push(select.options[i].value);
        }
    }
    var currentSelection=document.getElementById("selectedPoint").innerHTML;
    if(currentSelection==="当前位置:"){
        document.getElementById("selectedPoint").innerHTML="当前位置:"+selectedPoint.join("<br>");
    }else{
        var newSelection=currentSelection.split("<br>");
        var updatedPoint=[];
        for(var j=0; j<newSelection.length; j++){
            if(!selectedPoint.includes(newSelection[j])){
                updatedPoint.push(newSelection[j]);
            }
        }    
       document.getElementById("selectedPoint").innerHTML=updatedPoint.concat(selectedPoint).join("<br>");
   }

   // 打印数组
   console.log('Updated Selection:', updatedPoint);

   // 转化为json格式
   var jsonData=JSON.stringify(updatedPoint);
   console.log('Json data:', jsonData);
}

       当然,在html结构中也需要加入选项和选项框,例如:

<select id="destinations" multiple onchange="showCurrentPoint()">
    <option value="a">a</option>
    <option value="b">b</option>
                ...
</select>

        2)删除键设置

        实现方法:使用JavaScript脚本语言、通过DOM操作和对数组的处理实现删除功能。

        实现逻辑:将已选选项与待删除选项分别存入两个数组(下面的代码中,selectId表示用户选中的待删除选项ID,displayId表示已选选项ID),将两个数组进行对比,将不存在于待删除选项数组中的元素存入新数组,并将新数组显示,从而实现更新显示。

        代码:删除键javascript脚本代码:

// 删除按钮设置
function deleteOption(selectId, displayId) {
    var select = document.getElementById(selectId);
    var selectedOptions = [];
    for (var i = 0; i < select.options.length; i++) {
        if (select.options[i].selected) {
            selectedOptions.push(select.options[i].value);
        }
    }
    var currentSelection = document.getElementById(displayId).innerHTML;
    var newSelection = currentSelection.split("<br>");
    var updatedSelection = [];
    for (var j = 0; j < newSelection.length; j++) {
        if (!selectedOptions.includes(newSelection[j])) {
            updatedSelection.push(newSelection[j]);
        }
    }
    document.getElementById(displayId).innerHTML = updatedSelection.join("<br>");
}

        当然,相应地在html结构代码中也要设置删除按钮:

<button class="delete_button" onclick="deleteOption('destinations', 'selectedPoint')">删除</button>

        3)搜索框设置

        实现方法:使用JavaScript脚本语言、通过DOM操作和对数组的处理实现搜索框智能匹配。

        实现逻辑:首先获取用户输入的关键字,遍历所有选项尝试与关键字进行匹配,通过匹配结果更新选项的状态,不匹配则隐藏。并且会固定“确定选项”供用户确认,主要作用是将用户所选的最后一个元素添加至数组中。下面代码中的selectId代表下拉框元素ID,searchBoxId则表示用户输入的关键字ID。

        代码:搜索框设置javascript脚本代码:

// 搜索设置
function filterOptions(selectId, searchBoxId) {
    var select = document.getElementById(selectId);
    var searchBox = document.getElementById(searchBoxId);
    var filter = searchBox.value.toUpperCase();
    var options = select.options;

    for (var i = 0; i < options.length; i++) {
        var option = options[i];
        if (option.value.toUpperCase().indexOf(filter) > -1 || filter === "") {
            option.style.display = "";
        } else {
            option.style.display = "none";
        }
    }

    // 确保“确定”选项始终可见
    for (var j = 0; j < options.length; j++) {
        if (options[j].value === "确定") {
            options[j].style.display = "";
            break;
        }
    }
}

        当然,在下面的html结构中也要设置供用户输入的搜索框:

<input type="text" id="searchBox" onkeyup="filterOptions('destinations', 'searchBox')" placeholder="请输入你想搜索的起点">

二、服务器部署部分

        1、服务器选用说明

        本次项目中我们选购的云服务器是华为云Flexus L实例,选购的数据库是rds云数据库,部署工具是CodeArts IDE,其中python代码部署工具是PyCharm Professional。因此以下所有对网页在服务器中的部署问题都是针对华为云产品的。

        2、服务器镜像的选用

        在购买服务器时一定会涉及应用镜像与系统镜像的选用,但是很多人会忽略这一点(对我就忽略了),会直接“确认”到底,根本不看购买时他让你选择什么,这样你的镜像就会默认选用应用镜像WordPress。但是在进入WordPress之后会发现它并不支持文件夹的传输,也不支持css/html文件的直接传输,我也并没有找到可用的扩展。也就是说你几乎只能在WordPress现有的工具中重新制作网页。这显然不是我们想要的部署。

        解决方法:重新选用镜像。

        1)点击进入华为云控制台

        2)点击进入你的云服务器(实例)

        3)点击实例右下角的三个点,选中“切换镜像”

        4)选择“系统镜像”,将镜像切换至系统镜像Ubuntu 22.04。然后根据提示逐步完成镜像切换、关机重启服务器即可。(不要选应用镜像,直接选系统镜像!)

        经过以上操作就能成功切换镜像了。接下来就是如何将你的整个项目直接远程传输至服务器的问题了。

        3、远程传输文件至服务器

        要将本地文件上传至服务器,一开始尝试在华为云控制台中连接服务器远程终端,直接将文件拖拽至服务器文件管理器中,但是终端不支持多文件的一次性拖拽,如果要将整个网页项目的文件一个个拖进去工作量太大,根本不现实,这种方法行不通。

        所以只能通过第三方文件传输工具。

        一开始会先想到通过搭建ftp服务器进行文件传输,但是最后由于电脑远程设置的报错未解决,这条路没走下去。但不得不说,搭建ftp服务器步骤多、配置杂、错误率高,且并不是非常智能好用,因此不建议用ftp传文件。

        这里推荐用华为云推出的资源访问工具CodeArts IDE,只需要与自己的云服务器建立远程连接即可在CodeArts IDE的远程文件管理器中任意调用终端,上传或下载文件夹、多文件。下面是下载与建立远程连接的步骤:

        1)下载

        首先打开华为云控制台选中你的实例,点击“远程登录”。

        使用CloudShell登录服务器后,在登录界面的左上方就可以找到下载的入口。

        下载即可。

        2)建立远程连接

        下载完成后进入CodeArts IDE,点击左上角“远程连接”,选择“新建远程连接”

        或者直接点击右侧“会话管理”中的“新建远程连接”。

        然后你需要填写建立连接的相关信息:

        这里的“主机地址”填你的弹性公网IP;用户名填服务器用户名,一般是root;密码与你在控制台“远程登录”时的密码相同。其他信息可以不填。填好后点击“连接”即可将这里的远程文件管理器与你的服务器实现连接了。

        建立连接后你就能看到服务器的文件管理器了,然后就能任意上传与下载你的项目了。

        到这里文件传输的问题就解决了。

        4、网站在服务器上的部署

        除了文件传输的部分,还需要在服务器中安装web服务器软件,建议直接在服务器终端安装Apache,命令也比较简单:

//安装命令
sudo apt-get update
sudo apt-get install -y apache2

//启动命令
sudo systemctl start apache2

        完成后就会在根目录下出现/var/www/html路径,然后在html文件夹中上传自己的项目即完成部署。此时用任一电脑进入任意浏览器,在网址栏输入你的弹性公网IP即可看到你部署的网站了。

        如果不在配置中改动默认首页,那么网站打开时的默认首页是index.html,如果你想更改你的默认首页,那么进入CodeArts IDE,点击远程搜索(左上角放大镜图标),在远程文件搜索框中输入dir.conf,在弹出的几个文件中点击etc/apache2/mods-available路径下的dir.conf文件。具体操作如下图:

        进入配置文件后将DirectoryIndex后的html文件名改成你想设置为默认首页的html文件即可。

        到这里服务器部署部分的解析就全部结束了。

三、前后端通信部分

        1、本地的前后端通信

        问题描述:本地路径下的前后端通信会出现同源策略安全机制(CORS协议)阻止问题,也就是类似下面的报错:(图片源:https://segmentfault.com/a/1190000022506474#item-3)

        解决方法:经多方法尝试,最终还是基于flask解决,在后端python文件引入flask模块中的request和make_response库,加入请求处理函数after_request,在函数中加入请求头,引入访问源(允许任何源访问)、请求方法(”POST,GET,OPTIONS”)、请求头(“Content-Type”)三个字段。最后在代码尾段加入一个打开文件的操作,用于在请求头相应、代码运行后读取生成的html文件,并将其内容作为http响应返回前端,从而实现前后端通信。如以下代码(设置请求头和http相应):

 

            

        在html文件中则要建立http请求对象(xhr),将需要从前端传输给后端的数据用json格式通过xhr对象发送给后端,例如下面的代码:

        这样就可以成功解决cors协议阻止的问题,成功实现前后端通信。

        2、服务器上的前后端通信

        1)服务器中python程序后台挂载问题

        问题描述:既然要在网站上保证网站功能的实时可用性,则前后端通信的模块就要实时建立且可用,实时通信的前提是后端flask服务器需要在后台时刻挂载运行,因此要解决的就是python程序后台挂载问题。

        解决方法:尝试过cron作业和systemd服务都无法解决,最后是用PyCharm本地编辑器同步至服务器+Anaconda环境实现的。首先在服务器上配置Anaconda环境,然后在PyCharm中添加SSH解释器,将其与服务器解释器远程连接后将python代码直接部署在服务器中。最后在Anaconda创建的虚拟环境中运行nohup命令,使程序在后台挂载。

        上面只是将步骤大致概括了一下,更详细更具体的操作步骤可参考另一大佬的博客:

云服务器上运行python程序(PyCharm本地编辑同步服务器+Anaconda)挂载跑实验详细教程_可以跑pycharm代码的云服务器-CSDN博客

        在终端输入的nohup挂载命令中的.py文件和.log文件路径要改为在文件管理器中的绝对路径。

        经过上面的步骤就可以实现python程序后台挂载了。

        2)网络拒绝与超时问题

        问题描述:在解决以上问题后在服务器上尝试前后端通信仍然会出现 net::ERR_CONNECTION_TIMIED_OUT 网络超时问题和 net:: CONNECTION_REFUSED 拒绝连接问题。

        解决方法:经过对访问IP、端口、防火墙等问题的层层排查,最后发现是端口未开放的问题,解决方法是在服务器控制台添加对应端口的安全组规则,将该端口开放即可。

        安全组配置举例:例如在我的代码里前后端通信的端口是7777,就要在安全组中开放7777端口。配置方法如下:

        首先同样进入华为云控制台,点击进入“安全组”。

        选择需配置的安全组,点击进入配置“入方向规则”。

        点击“添加规则”,添加需开放的端口的安全组规则即可。

        配置格式如下:

        相应端口开放后就不会出现网络拒绝与网络超时的问题了,服务器上的前后端通信也就可以成功实现了。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/17370.html
评论
发布的文章

Spring MVC-JSON

2024-06-02 09:06:53

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!