技术面‍:前端代码是如何与服务器交互的

前言: 本篇文章主要是想讲解 .html 文件和 .CSS 文件在实际开发中和后端服务器交互最后上线的基础原理。

面向的人群🆕:是刚入行不久,且目前只会写前端业务代码而不清楚整个工作流的前端新人。我会从 0 开始一步一步带你理解整个流程的底层逻辑是什么,希望你能跟着我一起做完今天的所有步骤。


一. 前期准备

  1. 为了能让更多的人明白这其中的原理,今天我们回归前端最原始的本质,抛开 VueReact 这些前端框架,只用最原始的 .js.css 文件开始今天的讲解。

  2. 你的电脑需要安装 node,因为会用到一些文件读写的操作。

  3. 创建一个文件夹,然后创建出下面两个文件,一个 index.html 文件和 server.js 文件。
    image.png

  4. index.html 文件如下,你也可以自己写喜欢的内容,但是如果懒得写,请 copy 我的代码

        <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><h1>JavaScript is the best language in the world!</h1></body>
    </html>
  5. 我相信每个前端开发的读者都,或多或少安装过下面这个插件 Live Server
    image.png
    实现的效果是将你编写的 .html文件直接在浏览器打开,可以帮我们极大提升开发体验,实现的效果如下图:
    1.gif

  6. 看起来很神奇对吧?其实 Live Server 实现的功能和我们今天要讲解的知识非常接近,让我们暂时先关闭它,然后准备实现一个自己的简易版 Live Server
    image.png

二. 什么是服务器

  1. 在此之前,我觉得很有必要先解释一下服务器这个概念,因为这个概念之前困扰我很久。

  2. 对于前端来讲,因为不像后端开发者一样需要日常跟服务器打交道,所以可能会觉得服务器是一个很高大上的东西,是一个我们前端开发人员触不可及的东西。包括我刚入行的时候,我也是这样想的,但随着工作阅历的不断增加,发现服务器是一个再普通不过的东西罢了。

  3. 我们从现实生活类比,服务器就好比一家超市。

    • 你去超市的目的是什么?
    • 答:购买日用品 ,那么此时你就是消费者,那么超市就是给你提供服务的地方对吧?在这种场景下,你充当的其实就是 客户端(client) 的角色,而超市就充当着服务器的角色。服务器并不一定只能提供单一的服务,就像超市提供了很多类型的柜台,有日用品,有肉类,有水果,这些不同的柜台充当着给你提供服务的角色,而超市是容纳这些服务运行的地方,这就是服务器服务之间的关系。

    2.jpeg

  4. 你还可以自己再类比所有日常生活中需要你花钱消费的地方。如饭店、宾馆、花店、网吧等等。它们都是为了满足你的需求,来为你提供这些需求的场所,它们都充当着 “服务器” 的角色。

  5. 让我们回到网络上面来,你完全可以把 “服务器” 和上面你类比现实世界所理解到的概念画等号。比如你今天想看视频,我们拿 B站举例, 那么B站 此时就是一个服务器,当你在地址栏输入 bilibili 后,你就相当于走进了 “视频分类” 柜台 ,它上面存放着各种各样的视频,B站 它现在提供了观看视频的一项服务给你。
    image.png

  6. 然后你看视频看累了,想看一看漫画,此时就变成了它提供 “漫画” 服务给你。
    image.png

  7. 还是有点抽象?让我们回到 Live Server。刚刚我们关闭了 Live Server,所以导致我们在浏览器里输入 localhost:5500 这个地址后,页面出现了访问错误。
    image.png

  8. 但是当我们打开 Live Server 的时候,我们发现页面又恢复了正常工作。
    3.gif

  9. 那么上面的步骤,我们就可以这样理解:

    • Live Server 运行的时候,我们的电脑给了我们一个可以使用浏览器访问本地 .html 文件的服务。这个服务的提供者就是 Live Server 这个程序。那么谁是服务器呢?没错,就是帮你运行 Live Server主机-----你的电脑

    • 当你关闭 Live Server 的时候,相当于你的电脑关闭了提供服务的程序,导致你失去了访问 .html 的能力。

  10. 通过上面的例子,不难发现,其实服务本质上是一段代码,而运行这段代码的容器被我们叫做了服务器

  11. 这里有一个十分重要的概念----端口号。也就是 Live Server 启动的 5500 这个数字。这个数字你可以暂时把它理解为,你的电脑(也就是服务器)给它找了一个唯一的服务窗口,这个窗口号是 5500。(想象一个政务大厅,里面不同的业务都开设在不同的窗口位置,即使此时没人访问,它也需要有工作人员坐在那里等待。)
    image.png

  12. 那么上面整个过程可以这样理解:

    • 😣 Live Server: “好烦,周一又要上班了。喂,服务器(你的电脑),5500 这个窗口还没人值班吧?没人的话我就先坐这了。”

    • 🧑‍🏫 你的电脑:“我看一下啊,哦,暂时没人用。那你坐这里吧,即使没人来,你也不能跑出去啊!”

  13. 聪明的你也许会想到,那如果 5500 窗口如果有人先占了怎么办?注意,这里服务器你的电脑)会自动安排你的程序到另外的端口号上提供服务(执行代码)。(如果你的程序中也支持这么做的话,不妨打开两个 vscode 自己尝试一下同时开启 live Server 看看会是什么效果。)

三. 编写 server.js 文件

  1. 既然我们已经知道了,服务其实就是一段代码。那么我们就可以根据需求,去编写出这样的代码。其实我们的需求很简单,就是想让我的浏览器可以正常渲染我的 .html 文件。

  2. 这里我们需要从 node 中引入 http 模块,这个模块封装了一些可以让我们快速编写 http 服务器的方法。
    image.png

  3. 注意:这里我说了编写 “http 服务” 这个概念,结合我们上面对服务器的理解。这句话的完整含义应该是:

    node 提供的 http 模块,让我们可以快速在电脑上,编写一段代码程序。当我们的电脑运行这段程序的时候,我们的电脑可以提供 http 这样一项服务,此时浏览器可以通过使用 http 协议来和这个 http 服务程序进行通信。

  4. 然后我们调用 http 模块提供的 createServer 方法,具体用法在注释中写的很清楚了,不过多赘述。
    image.png

  5. 现在的你已经创建出了一个服务实例,它虽然还没有任何功能,但你已经可以告诉你的电脑,它现在可以被当作一个服务程序启动了。那么此时你还需要告诉电脑你想在那个窗口(端口) 去提供服务,这里我随便写了一个 7777,你可以选择一个任意你喜欢的数字。(注意,有些端口号是操作系统独享的,你不能占用,最好使用 5000-65535 范围内的数字) 然后使用 http_server.listen() 方法去向电脑申请这个端口号
    image.png

  6. 让我们在 http_server 的回调函数中,打印一些数据,来看看我们的服务是正常启动了。
    image.png

  7. 让我们在终端用 node 运行这个文件,你可以在控制台看到你的这段代码已经被你的电脑成功启动了。
    7.gif

  8. 可以看到,随着我用浏览器去访问这个在窗口 7777 提供的服务,我们回调函数监听到请求后成功打印了相对应的输出。

  9. 但是此时我们的浏览器好像呆呆的,没有展示任何信息。这是因为你这项服务现在还不够到位,你没有返回给浏览器任何信息。此时我们需要调去 response 身上的 end 函数。response.end()。这个函数第一个参数是你要告诉浏览器的数据,第二个参数也是一个回调函数,会在你返回给浏览器消息后被调用。那么我们就可以这样写:
    (这里别忘了需要 ctrl c,然后重新执行这个文件)
    image.png

  10. 你会看到虽然我们的服务成功打印了相应的输出,但是我们浏览器显示的却是乱码
    image.png
    image.png

  11. 这是因为你没告诉浏览器应该用什么格式去渲染这段数据,你可能会有疑问,浏览器这么笨吗?默认为 utf-8 不就行了?如果你能联想到这里,不得不给你点个赞👍,但是假如这段数据是图片视频呢,那不就乱套了吗?这里不卖关子,解决方法很简单,就是我们的服务在返回数据之前,告诉浏览器该如何展示我们的内容,怎么告诉?调用 response.writeHeader()设置相对应的 Content-type 即可。
    image.png
    现在的显示效果就符合我们的预期啦!
    image.png

四. 读取 html 文件

  1. 这里涉及到 node 的一些知识,不过不是本篇文章的重点,故不会做过多解释。

  2. 这里有两个重点,第一个就是引入 fs文件系统模块,它提供了一个方法叫做 readFileSync,这个函数是同步读取指定路径下的文件,默认返回值为 buffer 类型。
    image.png

  3. 当拿到这个 data 后,我们就可以返回给浏览器这个数据。此时你的浏览器应该已经正确渲染出这些内容了。
    image.png

五. CSS 文件生效的原理

  1. 让我们在跟文件夹下生成一个 global.css 的文件。
    image.png

  2. 别忘了我们最初是如何引入 cssindex.html 的。
    image.png

  3. 这里有一个关键的知识点需要了解,我们打开 localhost:7777,其实是会向我们的服务发起三个请求的。其中,发送 index.html 是我们的主动行为,favicon.ico 这个请求是浏览器的默认行为,global.css 是由于我们的 index.html 携带了 \<link/> 标签,从而引起浏览器附带请求导致的。
    image.png

  4. 让我们打印一下 requesturl 参数信息,这里包含了浏览器请求资源的地址。
    image.png
    它对应了浏览器 request 字段的信息。
    image.png

  5. 刷新一下浏览器,你会看到控制台有以下三个输出,和我们上面的推测是符合的。注意,这里的根路径 / 路径之后会被我们替换为 index.html
    image.png

  6. 聪明的你可能已经发现了,我们浏览器其实已经请求了 global.css 但是样式好像没有正确的生效。那是因为 .css 文件没有设置正确的 mime 格式。被浏览器当成普通的文件格式处理了。
    image.png

  7. 这里我们就需要为 index.html.css 分别设置不同的 content-type 来让 css 文件生效。此时你的 http_server 的代码应该如下。

      const http_server = http.createServer((request, response) => {let file_path = ""; //1. 这里存放文件的真实路径let data = ""; //2. 这里准备存放文件的 buffer 数据let ext = ""; //3. 这里准存放文件的后缀名称if (request.url === "/") { //4. 如果请求路径是跟路径,那么替换为 index.htmlfile_path = "index.html";} else {file_path = request.url.replace("/", ""); //5. 否则的话,去掉路径前面的斜杠 '\'}data = fs.readFileSync(file_path);
    }  
    
  8. 这里最关键的后缀名如何获取呢?我们需要引入另一个模块 path。我们利用 path.extname 方法,将切割好的 file_path 传递为参数即可获取到正确的文件后缀名。
    image.png

  9. 之后为每次请求设置正确的类型即可。具体文件类型 mimecontent-type 的映射关系请参照:MDN提供的 MIME 对照表。
    image.png

  10. 此时我们可以看到,样式已经正确生效。
    image.png

六. 80 端口的含义

  1. 想必大家都知道 http 服务是跑在 80 端口这一前端常识的吧?其实它没什么特别的,它只不过是把端口申请在服务器的80窗口上而已,然后我们配合浏览器的默认行为—当没有指定明确端口号时,帮你自动填写为 80 端口。

  2. 我们来试验一下。
    image.png
    注意,此时我没有像之前一样输入 7777,但是浏览器却依然正确找到了我http-服务的位置,和我们对浏览器默认行为的猜想一致。
    33.gif

  3. 所以不要再死记硬背 80443 这两个数字了,它们只不过是你的后端搭档在代码程序里根据业务不同而写下的一个普通数字罢了。

  4. 为什么要这样做?如果每个 http-server 开发者,大家都用不同的端口号。那么你就需要不仅仅需要把它们的域名记下来,还要记住相对应的端口号。就像上面一样,你不觉得每次手动输入 7777 很麻烦吗?那么干脆大家和浏览器商量好,就用 80 这个端口,浏览器默认帮你填写就好了。

七. 源码

这里故意屏蔽了 favicon.ico 的请求,和文章整体内容关系不大。

const http = require("node:http"); //从 node 中引入 http 模块
const fs = require("node:fs"); //引入 fs 模块
const path = require("node:path");// 这个函数接收一个回调函数
// 1.第一个函数接收的是前端传递过来的 request 参数
// 2.第二个函数是要返回给浏览器的信息const http_server = http.createServer((request, response) => {let file_path = ""; //1. 这里存放文件的真实路径let data = ""; //2. 这里准备存放文件的 buffer 数据let ext = ""; //3. 这里准存放文件的后缀名称if (request.url === "/") {//4. 如果请求路径是跟路径,那么替换为 index.htmlfile_path = "index.html";} else {file_path = request.url.replace("/", ""); //5. 否则的话,去掉路径前面的斜杠 '\'}if (file_path !== "favicon.ico") {response.writeHeader = `Content-type:text/${ext}`;data = fs.readFileSync(file_path);ext = path.extname(file_path);}response.end(data);
});// 告诉你的电脑,你想用 7777 这个端口
http_server.listen("7777", () => {console.log("我提供的服务在 7777 窗口");
});

八. 总结

  1. 首先我们要对服务器有清晰的认知,任何一个设备都可以当作一个服务器,你的手机,你的笔记本,你的台式机,一个大型的存储计算机,都可以被叫做服务器。

  2. 所谓的服务就是跑在服务器上的一段普通代码程序而已。当代码运行起来后,服务器需要为这个服务分配一个唯一端口号,其它应用可以访问这个端口来接受你提供的服务。

  3. 有些服务并不是要公开为别人使用的,查看你的任务管理器或活动监视器。你的电脑开启了这么多服务,它们占用着不同的端口,而这些服务有的是只为操作系统提供的,并不对普通用户提供任何服务。
    image.png

  4. 我们的前端代码,不管是 .vue.tsx.ts 等等文件,最后都会被打包为原始的 htmlcssjs 文件,因为浏览器只认识这些内容。(不信你去看看有 content-type: vue 这种 mime 类型吗?)然后后端会部署一个 http-server 程序,让它跑在一个专属服务器上执行这段程序,通过我们上面讲解的内容来传递给 80 或者其他任何端口上,等待别人访问。

  5. 你在实际开发中使用的 npm run dev 后,你的前端代码呈现在浏览器上,其底层的原理和上面无异,不过是开发工具帮你将上面步骤封装的功能更加完善和便捷而已。
    image.png

  6. 本文中对于 server.js 对创建服务器的流程做了最大化的精简,来确保读者能够适应服务这个概念。在实际开发中,公司真正的后端服务开发绝不是这么简单。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/16586.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大规模敏捷SA(Leading SAFe)证书是什么意思?如何报名,含金量高吗?

大规模敏捷SA(Leading SAFe)证书是什么意思&#xff1f; 常规的敏捷框架适用于中小型项目团队&#xff0c;而且不具有扩展性。基于常规的敏捷框架&#xff0c;SAFe定义了一个可扩展的敏捷框架模型&#xff0c;它适用于大型团队的合作开发&#xff0c;可以提高团队之间的协作性…

【再探】设计模式—职责链模式、命令模式及迭代器模式

行为型设计模式研究系统在运行时对象之间的交互&#xff0c;进一步明确对象的职责。有职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式及访问模式共11种。 1 职责链模式 需求&#xff1a;1) 请求能被多…

如何使用golang自带工具对代码进行覆盖率测试

在 Go 语言中&#xff0c;测试代码覆盖率通常使用 go test 命令结合 -cover 和 -coverprofile 1. 基本代码覆盖率报告 在项目目录下运行以下命令 go test -cover这将在控制台输出一个代码覆盖率的百分比。但是&#xff0c;这种方式不会保存覆盖率数据&#xff08;可以指定目…

反对加征关税,特斯拉上海厂传减产20% | 百能云芯

特斯拉公司首席执行官马斯克近日在公开场合表达了对美国计划对中国电动车加征关税的反对立场&#xff0c;强调特斯拉不支持任何扭曲市场的举措。据知情人士透露&#xff0c;特斯拉上海工厂正计划在今年第二季度至少削减Model Y车型的产量20%&#xff0c;以应对市场需求的变化。…

C#读取.sql文件并执行文件中的sql脚本

有些时候我们需要在程序中编写读取sql脚本文件并执行这些sql语句&#xff0c;但是我们在有些时候会遇到读出来的sql语句不能执行&#xff0c;其实不能执行并不是你的sql脚本文件有错误&#xff0c;而是去执行sql语句的时候&#xff0c;C#代码里面执行sql语句的代码对sql里面的一…

低代码与人工智能:改变软件开发的未来

引言 在当今快速发展的科技时代&#xff0c;软件开发行业也在不断地创新和演进。其中&#xff0c;低代码开发和人工智能技术是两个备受关注的领域&#xff0c;低代码开发通过简化开发流程和降低编码难度&#xff0c;使得软件开发变得更加高效和便捷&#xff0c;而人工智能技术…

正宇软件:引领数字人大新纪元,开启甘肃人大代表履职新篇章

在数字化强国的主旋律之下&#xff0c;政府工作的数字化、智能化转型已成为提升治理效能、增强人民满意度的关键一环。在这个大背景下&#xff0c;正宇软件技术开发有限公司以其卓越的技术实力和丰富的行业经验&#xff0c;成为了政府信息化建设的杰出代表。甘肃省人大代表履职…

基于 Wireshark 分析 TCP 协议

一、TCP 协议 TCP&#xff08;Transmission Control Protocol&#xff09;是一种面向连接的、可靠的传输层协议。它在网络通信中扮演着重要的角色&#xff0c;用于保证数据的可靠传输。 TCP协议的特点如下&#xff1a; 1. 面向连接&#xff1a;在通信前需要先建立连接&#x…

Hunyuan-DiT环境搭建推理测试

引子 最近鹅厂竟然开源了一个多模态的大模型&#xff0c;之前分享福报厂的多模态视觉大模型&#xff08;Qwen-VL环境搭建&推理测试-CSDN博客&#xff09;感兴趣的可以移步。鹅厂开源的&#xff0c;我还是头一回部署。好的&#xff0c;那就让我们看看这个多模态视觉大模型有…

强化学习,第 3 部分:蒙特卡罗方法

文章目录 一、介绍二、关于此文章三、无模型方法与基于模型的方法四、V函数估计4.1 基本概念4.2 V-功能 五、Q 函数估计5.1 V函数概念5.2 优势5.3 Q函数 六、勘探与勘探的权衡七、结论 一、介绍 从赌场到人工智能&#xff1a;揭示蒙特卡罗方法在复杂环境中的强大功能    强化…

zstd库数据压缩与解压缩

在 Visual Studio 2019 中使用 C 的 zstd 库进行数据压缩与解压缩 在今天的博客中&#xff0c;我们将探讨如何在 Visual Studio 2019 中使用 zstd 库进行高效的数据压缩和解压缩。zstd&#xff08;也称为 Zstandard 或 zstd&#xff09;是由 Facebook 开发的开源压缩库&#x…

动手学深度学习22 池化层

动手学深度学习22 池化层 1. 池化层2. 实现3. QA 课本&#xff1a; https://zh-v2.d2l.ai/chapter_convolutional-neural-networks/pooling.html 视频&#xff1a; https://www.bilibili.com/video/BV1EV411j7nX/?spm_id_fromautoNext&vd_sourceeb04c9a33e87ceba9c9a2e5f0…

关于单元测试

关于单元测试的一些总结&#xff1a;

【408真题】2009-17

“接”是针对题目进行必要的分析&#xff0c;比较简略&#xff1b; “化”是对题目中所涉及到的知识点进行详细解释&#xff1b; “发”是对此题型的解题套路总结&#xff0c;并结合历年真题或者典型例题进行运用。 涉及到的知识全部来源于王道各科教材&#xff08;2025版&…

618值得买的东西有哪些?买什么最划算?超全品类大清单总结

平日里让许多人心动不已的收藏加购好物&#xff0c;是否常常因为价格昂贵而让人望而却步&#xff1f;然而&#xff0c;618活动期间的到来&#xff0c;恰恰为我们提供了一个难得的购物盛宴&#xff01;相信在第一波活动中&#xff0c;许多消费者已经跃跃欲试&#xff0c;开始享受…

SuperSocket 自定义AppServer、AppSession、CommandBase

1、预期效果如下图。 2、自定义AppServer&#xff0c;代码如下。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SuperSocket.SocketBase; using SuperSocket.SocketBase.Config;namespace Co…

做抖音电商,可以没有货源和经验,但不能没有耐心

我是王路飞。 在抖音做电商这件事&#xff0c;不需要怀疑其可行性。 经过四五年的发展&#xff0c;平台和商家已经证明了抖音电商的前景&#xff0c;它就是我们普通人做抖音最适合的一个渠道。 想在抖音做电商的&#xff0c;再给你们一个经验之谈&#xff0c;你可以没有货源…

基于 Spring Boot 博客系统开发(十一)

基于 Spring Boot 博客系统开发&#xff08;十一&#xff09; 本系统是简易的个人博客系统开发&#xff0c;为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。&#x1f33f;&#x1f33f;&#x1f33f; 基于 Spring Boot 博客系统开发&#xff08;十&#xff09;&#x…

云上聚智——移动云云服务器进行后端的搭建及部署

什么是移动云 移动云是指将移动设备和云计算技术相结合&#xff0c;为移动应用提供强大的计算和存储能力的服务模式。传统的移动应用通常在本地设备上进行计算和存储&#xff0c;而移动云将这些任务转移到云端进行处理。通过移动云&#xff0c;移动设备可以利用云端的高性能计算…

基于Python+flask+echarts的气象数据采集与分析系统,可实现lstm算法进行预测

背景 基于PythonFlaskEcharts的气象数据采集与分析系统结合了强大的数据处理能力和可视化展示技术&#xff0c;旨在实现对气象数据的实时采集、存储和分析。通过Python编程语言实现数据采集模块&#xff0c;利用Flask框架搭建后端系统&#xff0c;实现数据处理、存储和分析功能…