CS Code
提醒:这篇文章主要讲的是如何把已经写好的本地网页,变成全世界互联网都能访问的网站,的一个过程,而不是如何开发前端 / 后端。
前言(一些碎碎念)
主要用于分享这么多年搭建网站的经验。
从初中开始第一次接触搭建网站到现在大二,踩了无数大大小小的坑,也算是在过程中学习吧。记得初中那会,在信息竞赛队的机房里,算法题做不出来,就想着写点别的东西,刚好另一个哥们在学前端,然后小学的时候我学过一点点前端(HTML、CSS、JS)和 Python,就想着做一个网站来玩,于是拼拼凑凑,一开始应该是用 Python Bottle 库搭建的一个简易小网站,然后越写越多,轻量型的 Bottle 没办法实现很多东西,就开始尝试用 Flask,继续堆史山,最后到初三毕业堆成了最开始的 skyzhou.top,具体代码已经开源到 Github(skyzhou_top)。
当时学了很多东西,看着自己写的东西能被全世界所有人用浏览器直接访问,觉得真的很有意思。但实际上也是遇到了非常非常多的问题。最主要的问题就是服务器和公网 IP,我记得是那会有个阿里云服务器的学生优惠,一年只需要一百出头就可以拿下,但那会还不懂备案的事情,只知道初二的时候有人给我打电话说我的服务器没有备案怎么怎么了,但我只能跟他说我未成年搞不了这些东西。我把网站绑定到服务器上之后,因为服务器和域名都没有备案,80 端口只要开就是秒封,然后其他端口,那会阿里云疑似是一天扫一次然后封端口,我就写了个批处理每天重启一次后端,就这样使用 skyzhou.top:8023 用了两年。
这个小网站虽然堆了史山,但是其实塞了很多很多我和那位哥们的想法在里面,现在想来初中生能有这么多想法也不容易啊(),现在还记得比较清的,一个是 chatroom 聊天室,第一次学习使用 socket 前后端交互,我写后端,他写前端,就这样做了一个聊天室,而且还支持用户系统。当时在一次初中的计算机课上有人宣传了一波然后一下子涌入了三十多个用户同时在线聊得热火朝天,那个场面我到现在还历历在目难以忘怀。还有一个就是当时想做一个浏览器里面的梯子浏览器,就是我服务器翻了墙然后我这个网站就像一个浏览器,可以输入域名,通过服务器后台读到翻墙后访问的内容,再传回用户这里组装成网页。这个东西让前端哥们做了好久,但最后还是因为 JS、CSS 难以处理等问题失败了,最好的样子我记得是真的在网站上访问了 google.com,但是没有很好的 JS 来支持搜索功能。
中考结束,我跟那哥们考上了不同的高中,之后也再没合作做过网站了,旧 skyzhou.top 的故事就到此结束了。
但我在高中打完 NOIP2022 之后,又想着开始做网站了,那会在编程社遇到了两个好哥们,其实也都是同班同学,一个哥们(富哥)有一台闲置的电脑,里面甚至有空闲的 GTX1050TI 显卡,另一位哥们会写点代码,也想一起做个网站学习一下,于是就有了 Smartlearn 项目。这个项目由一个 cnsml.com:10000 作为主网站,做了账号系统、云盘系统和一些小游戏等等。除了主站之外,我们还尝试了 Code Server、JellyFin、论坛、邮箱系统等各种各样的小玩意,其中,Code Server 和 JellyFin 我是比较满意的,用了挺多次。
这个项目和他的名称一样,旨在让我们三个学到网页开发的相关知识,这也是我第一次这样系统全面的接触服务器、Linux(Debian)、Flask、SQL、Nginx 等等知识,对于高中一周只有一个小时社团课+周末一点点时间折腾的东西,已经不赖了。其实从这个时候开始,已经对简单的服务器和网站架构有所了解,但是也只是停留在自己玩的过家家阶段,还有很多深入的信息安全知识以及代码规范知识没有学习到。也是这个时候让我意识到,写这种简单的网站或许不是什么很难的事情,但是想把它稳定运行下去,不出现问题以及能防御住全世界的攻击,其实还是有点难的。
然后高三了,一整年应该都没写什么东西,就让 Smartlearn 一直这样跑着,也正是这个时候,第一批大语言模型开始有热度,那时候简单试了一下但也没有深入去搞。
上大学之后,终于又有时间来写网站了,第一件想到的事就是买回来 skyzhou.top 这个域名,然后在大一上到大一下的寒假,在宿舍一两周时间把这个博客给基础版给搓出来了。这也是我第一次接触 Github Page 以及 Hexo 生成 Blog,也是从这个时候开始记录大学的一些事情,我觉得这种记录是有必要而且很有意义的。而且我作为比较宅的人,大部分时间都窝在宿舍懒得出门,平时最多也就和同学在微信 qq 上聊聊天,真正有内容的思想输出其实会比较少,我也想通过博客这种方式来不断输出自己,让大脑活跃思考起来。高中及以前,大部分的输出都是作文写作,其实只是在固定框架下带着镣铐跳舞,并不是很好。
当然,现在除了 skyzhou.top 之外,我还维护了几个其他的小网站(子域名),基本都是一些小型 Web 应用,在此不多展开。
在大学期间做网站,还得特别感谢 cgluWxh 等同学给予我的无限支持。
常见的架构
其实,搭建网站并不是一个很困难的事情,尤其是熟悉了流程之后,其实并没有很多需要思考的地方,而且可以做到廉价、高效。最关键的是如何选择这个架构和工具,这里的工具包括但不限于服务商、服务器、硬件软件等相关的东西。
下面这个图是一个最简单最基础的网站架构,我会对每一个展开来讲,所有内容基于我本身的理解和经验,如有误差和错误请谅解!
浏览器
浏览器本身就是一个渲染前端代码的工具,可以把各种各样的内容按照对应的格式和位置排列,给用户展示。首推当然是 Google 的 Chrome 浏览器,多端同步、使用方便、扩展应用都是远超世界上其他浏览器的,当然常见的还有 Apple 的 Safari、Microsoft 的 IE 和 Edge(内核与 Chrome 一样),Linux 的 Firefox,在 Linux 电脑上有些人会选择直接装 Chromium。
注意:不同的浏览器底层渲染逻辑不一样,其实经常会出现各种各样的适配问题,以及在不同设备上也有不同的问题。热知识 iPhone 手机的 Chrome 其实也是 Safari 内核,具体原因不展开。
域名
域名就是形如 google.com, skyzhou.top 这种的字符串,由主域名和域名服务商组成。对于内地用户来说,一般会从腾讯云或者阿里云这种云服务商购买域名,但是在这里买的域名通常是要实名认证+备案的(备案其实主要针对服务器)。我一般用的是 NameSilo 来购买域名,价格实惠,不容易被背刺(这里要注意有些域名服务商会有什么首年特别便宜,但是之后续费特别贵的情况),关键是可以支付宝支付,不用实名认证,直接接入 DNS 解析服务商即可。
DNS 解析
Domain Name System 简称 DNS,即域名系统。大家需要理解在互联网上传输我们用的地址是 IP 地址而不是域名,DNS 解析就是把域名转换成 IP 地址的过程。这里我们最常用的服务商是 Cloudflare,他可以做到在全世界大部分地方都有 10ms 以内的延迟,而且相对来说特别稳定(虽然前段时间炸过一次),是现代互联网的网络服务商基石。
公网 IP 以及 80/443 端口
这个就是内地管得最严格的东西,或许也是大部分网站站长最头疼的东西。简单来说,中国内地的公网 IP 不够用,加上某些特殊原因,实行严格的公网 IP 管控。正常家用默认是没有公网 IP 的,可以花大价钱买公网 IP 专线但也是动态的。大部分人买云服务器就是为了这个公网 IP,但是阿里云和腾讯云等内地的服务器受法律要求是要备案的。有公网 IP 意味着,全世界基本上就可以直接通过这个 IP 访问到端口所展示的内容。
80/443 端口实际上分别对应的是 http/https 协议,也就是互联网传输内容的基层协议,http 是裸露不加密的,https 是加密的(现在基本都要求全部用 https)。内地的服务器原则上只有备案才能使用域名解析出来的 80/433 端口,其他端口有些服务商也会禁用,但自己申请的公网 IP 不会。
在浏览器里面,80/443 端口一般是隐藏的,比如这个网址:http://skyzhou.top,实际上是http://skyzhou.top:80,但是其他端口就不能被隐藏,比如 http://skyzhou.top:8023 这种。
关于备案:目前个人备案还极其麻烦,有着非常繁杂的法律流程,最主要的是还会限制网站的内容,比如这个个人博客甚至不允许有评论区,以及有些文章也不能发表,我个人是反对这个事情的(甚至有些事会直接找上你来)。
服务器
我认为,服务器提供商的选择至关重要,会直接影响网站开发体验以及用户使用网站的体验。一般来说,正常的做法是租云服务器,它直接拥有公网 IP,然后所有服务都在上面跑。但实际上,我们也可以使用自己的本地实体服务器,好处也有很多(比如不用续费,就在手边),但是这样就要考虑公网 IP 问题和网络安全问题。
内地的服务器是需要备案的,常见的比如在阿里云或者腾讯云买的广州、杭州、北京、上海等地的服务器。但是,香港是不需要备案的,公网 IP 的 80 / 443 端口随便用。
Nginx 反代
Nginx 的核心作用其实是隐藏后端服务器,他可以将访问的公网 IP 端口与本地服务器开的内网 IP 以及端口连接起来。而且,可以支持将不同子域名的公网 IP:80 端口映射到内网 IP 的其他端口!
子域名,即形如
*.skyzhou.top一类的,我们一般还是在公网会暴露它的 80 端口,但可以通过 Nginx 反代到内网的其他端口。
IP 和端口
形象来说,IP 就是你的设备 / 服务器在互联网 / 局域网上的地址,就像一栋公寓,然后端口就是公寓里的窗口(房间),用于展示和传递内容。IP(这里都默认 IPv4)的格式是 *.*.*.*,每一个 * 的是一个范围 0-255 的数字。端口就是一个 0-65535 的数字。为了访问到你这个公寓里的房间,IP 和端口都是必要的,比如 1.1.4.5:14 这样子。
后端 / 前端
这里就是代码层面的东西了,简单来说,前端用于给用户展示能看到的内容,常用的有 HTML, CSS, Javascript 等语言来编写,通过前面那一堆过程,从服务器传递到用户的浏览器解析,展示出来。后端更多是用于前端和服务器之间的交互,比如前端要登录,把账号密码传给后端,后端这边查服务器的数据库,然后再将结果返回给前端,常用的有 Python, Java 等。前端的代码是基本上公开的,浏览器需要拿来解析,而后端的代码是不公开的,而且一般就是用于开这个网页服务。
关于内容,这个其实没什么,就是这个网站他所传递的东西或者功能,一般来说网站都是功能性的,比如博客、论坛、搜索引擎、AI 对话等,大部分人做网站,要么是为了给用户提供服务,要么就是展示自己所想要公开出来的内容。得益于现代互联网的发展,网站所能传递的内容形式几乎是无限的,我正在用的 VSCode,大家天天刷的一些软件 / APP,很多本质上就是网页套壳,是高度成熟的技术。浏览器渲染可以做到文字、图片、音频、视频、简单的游戏等,已经完全够用了,而且兼容性非常强。
我目前使用的架构
我从初一开始就在探索各种各样的做网站方法,认为有两点极度重要:
- 自己开发方便
- 用户访问流畅
看上去很简单的两件事,实际上真正上手做才会发现,没那么好做😭
首先是开发方便,最方便的开发肯定是在自己的个人电脑上,但是,上面也说过了,内地是不会随便提供公网 IP 的,自己开发完之后的服务没法直接展示给用户。而且,网页服务需要一台一年 365 天,每天 24 小时不关机的电脑(也就是服务器),个人电脑一般不会这样做。
我之前都是买各种云服务器,写完小项目(或者干脆直接在上面改)之后 scp 也好,git 也好,挪到云服务器上去跑。这个时候又会出现问题,比如内地的服务器网速快,ssh 连上去之后体验很好,但没有备案就没有 80 / 443 端口,非内地服务器不用备案但是,ssh 访问以及用户访问体验奇烂(延迟高、卡、丢包),这又不得不提到我们内地小的可怜的国际带宽。
探索了这么多之后,结合我现在只能在大学宿舍开发的场景,个人认为比较好的框架如下
这个架构是我目前使用体验最好的一个,无需备案,80 / 443 端口开放,价格实惠,开发方便,访问速度极快,而且相对稳定。
Namesilo & Cloudflare
买域名用 Namesilo,基本上大部分域名都有首年优惠,虽然是海外域名网站但是可以直接使用支付宝支付,无需实名,非常方便。Namesilo 买完域名之后选择 DNS 解析服务器,去 Cloudflare 开一个这个域名的免费服务,填写 DNS 服务器名称,然后就挂载到 Cloudflare 服务器上了,这个在海外接近光速,在内地也很稳定很快了,免费服务已经绰绰有余。
上图分别为 Namesilo 和 Cloudflare
阿里云香港服务器
然后就是核心出装,阿里云香港服务器,直接选轻量应用服务器,有内地 BGP 加速,30 人民币左右一个月,价格适中,而且在这里仅用作公网 IP 和 80 / 443 端口的使用,已经是我能找到无需备案且内地访问无痛的最实惠服务器了,说实话这种在国内可能算是有点钻空子,但他确实合法且好用。这个阿里云香港云服务器其实一直有,但是我之前没注意到这个,基本都在用没什么内地加速的香港服或者其他海外服,效果都很一般,自己 ssh 都卡的要死,但这个有内地加速那就完全不一样了。

Caddy
Caddy 是一个比较新的反代工具,功能类似 Nginx 但是相比之下使用极度容易,而且自带 https 签名和续签,无需用 CertBot 之类的工具自己签,用一次之后就爱不释手。
下面是一个比较简单的 CaddyFile 配置,比 Nginx 配置要简单得多,要加子域名只需要继续往下写就好了。
1 | :80 { |
frp
frp 内网穿透是 Github 上的一个开源项目,其利用简单的 p2p 连接,能将局域网(内网)的端口直接映射到具有公网 IP 的服务器上,这个功能是实现高速开发的关键步骤,通过这个我们在自己的本地服务器上跑服务,然后云服务器只做转发。其源码仓库就是下面这个链接,直接去 Release 下载对应版本即可使用。
对于我的 frp 来说,云服务器(即服务器)和本地服务器(即客户端)需要都下载 frp,然后写不同的配置文件来使用。
服务器
先使用
1 | nano frps.toml |
来编辑服务端的配置文件,一般来说只需要写 bindPort(frp端口) 和 auth.token(密钥) 即可,然后再使用
1 | ./frps -c frps.toml |
启动服务端的 frp。
客户端
先使用
1 | nano frps.toml |
来编辑客户端的配置文件,大概格式如下
1 | serverAddr = "" # 云服务器的公网 IP |
然后再使用
1 | ./frpc -c frpc.toml |
启动客户端的 frp。
本地服务器
本地服务器通常比云服务器性能强大且实惠很多,不会到期,不需要续费,而且在手边很有安心感。像我先现在这个 CPU 强、内存大、硬盘空间大,体验都是远比云服务器要好的。况且不跑重型服务的话,一个 ubuntu 服务器一直开着几乎耗不了什么电费。
我自己宿舍里放着的小服务器😋
前端 / 后端
前端 / 后端并不是我这篇文章想讲的重点,但我可以分享,我自己用最多的后端是 Python Flask,我觉得写起来非常顺手而且容易扩展,能实现的功能也很多。前端我还是用 HTML,CSS,JS 比较多(有点古法),而且现在 AI 兴起之后,其实大部分前端都是 AI 写的,因为这个东西手写的话比较费时费力,而 AI 能在几秒钟内给一个效果还可以的前端。
总结
写网站其实不难,难的是让它在公网稳定运行,并且在各种限制和环境下找到一个平衡点。