ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Web开发实战笔记:从框架选型到部署安全的全栈经验

Web开发实战笔记:从框架选型到部署安全的全栈经验 做web开发这些年我手机上攒的笔记比代码行数还多。从大学时第一次用记事本写html页面到后来进公司带项目大量经验其实都沉淀在这些零散的“web笔记”里某个不起眼的报错、一次折腾半天的部署、一个让前端崩溃的缓存问题。这篇内容就是把其中最常被问到的几类整理出来当作一份个人实操笔记分享给同行。无论你是刚入行的web前端开发还是准备转后端、做全栈又或者是企业里负责web工程交付的工程师应该都能从中找到对自己有用的那一段。网上关于web开发的教程一搜一大把但碎片化的知识点看完就忘。真正有价值的是那些“连起来看”的经验技术选型怎么权衡、部署踩坑怎么定位、浏览器报错背后到底是什么逻辑、安全基线怎么落到日常开发里。我尽量把每类问题都写清楚“为什么这样处理”而不是只丢一段配置上去。1. 从零搭一个web项目先想清楚这几件事1.1 框架选型不是跟风是看团队和人很多人在开始一个web项目时第一反应是“哪个框架最火就选哪个”。我看过太多项目因为这个原因翻车团队里没人写过这类代码边学边写最后交付质量全靠加班撑。选型真正的逻辑应该是团队技术栈是否匹配、社区生态是否成熟、将来招人容不容易、出问题时能不能快速找到解决方案。前端方向上国内企业级web开发基本被Vue和React两分天下。Vue上手平滑中文资料多中小团队做后台管理系统很顺手React的函数组件和Hooks体系在现代前端里更“正统”配合TypeScript做中大型项目很稳。Angular用的人相对少但如果你要做的是一套长期演进的大型企业内部系统它内置的路由、表单校验、依赖注入确实能省不少基础设施的功夫。Flutter Web则是个特殊选项——它适合一个代码基同时覆盖移动端和Web端的小工具型产品但如果你的核心场景是内容型站点、需要强SEO就别硬上浏览器端第一次加载那包体积够喝一壶的。后端的选择逻辑同样如此。Java WebSpring Boot在企业级应用、银行政企类项目里仍然是绝对主力原因不是它写起来爽而是稳定性、供应链组件的成熟度和招人池的厚度都最高。Python Web这边Flask轻、自由适合快速原型和简单服务Django自带Admin后台和ORM写内容类系统效率极高FastAPI靠异步和自动生成API文档最近几年接手了很多新项目。我的建议是如果团队里有人能撑住Java的整套体系而业务又不涉及太多高并发实时流量Java比Python更容易长期维护反过来如果是做AI应用的外壳、内部小工具Python这套能快一个量级。1.2 开发环境的版本管理比IDE选型更重要IDE本身其实很个人化。后端用IntelliJ IDEA 2024版本创建web项目要么选Spring Initializr在线初始化要么本地的Maven骨架项目都很成熟前端用VS Code配几个插件也完全够用。真正让大家反复折腾的往往是开发环境本身的版本问题。一个很典型的场景公司里老的web项目用的是Node 14你新装的机器是Node 20一跑构建就报错或者干脆装依赖的时候直接卡死。类似的还有Java的JDK版本、Python的解释器版本。所以我的一个基本操作习惯是电脑上用一个版本管理器兜底。Node的nvm、Java的sdkman、Python的pyenv都可以这样切换项目不用反复卸载重装项目的.nvmrc、requirements.txt、pom.xml里写清版本新成员clone下来一条命令就能把环境还原。这比任何IDE选型都省时间。真实的团队协作里九成“我这能跑你那不能跑”的问题都是环境污染导致的而不是代码本身的问题。1.3 代码管理从第一天就要做别信“先写写再说”个人项目也一样哪怕只有你自己在写Git带来的价值也会在你第N天回滚时体现出来。SVN和Git的核心差异是分布式与集中式SVN有一个中心服务器历史记录都在服务器上离线基本没法完整操作Git本地就有一个完整仓库先提交、后推送分支合并的机制也远比SVN灵活。现在团队新项目几乎默认Git。有些人问“除了SVN还有什么web端的工具支持查看不同版本的”。这里的典型答案是Gitea和GitLab它们本质是Git的Web管理界面浏览器里能看到提交历史、分支对比、合并请求不需要在终端敲命令。如果你想要轻量、好部署Gitea非常合适一个二进制文件就能跑起来想要Code Review、CI/CD一体化用GitLab更完整。GitHub和国内的Gitee属于云端托管平台直接注册即可项目公开或私有不影响你用Git管理版本。一个容易忽略的点是不管是哪种web端工具提交信息都要有规范。我通常要求团队提交信息格式是type(scope): description比如fix(user): 修复手机号校验半年后再回去查问题效率会高很多。2. 浏览器端“玄学”问题其实背后都是有规律的2.1 service worker注册失败别再拍脑袋加代码你可能会在浏览器控制台看到类似这样的报错加载 web 视图时出错: Error: could not register service worker: InvalidStateError这个报错第一次见会很懵因为service worker看起来只是自己写的一小段代码报错信息却看不懂。拆开来看InvalidStateError通常指向三个原因当前页面不是安全上下文、注册路径和脚本路径的作用域不匹配、service worker脚本的响应不合法。安全上下文service worker只在HTTPS或者localhost下可用。你如果在HTTP的局域网或者线上环境调试一定注册失败。作用域不匹配navigator.serviceWorker.register(/sw.js)默认作用域是/如果你把脚本放到了/static/sw.js作用域就变成/static/页面路径不在这个范围内就炸。脚本响应不合法SW脚本必须有合法的MIME类型application/javascript并且不能带BOM头。很多构建工具会把SW脚本也做hash处理结果每次部署都注册一个新的旧的一个没注销控制台就会冒出各种奇怪的错误。我的排查习惯是先打开DevTools的Application面板看Service Workers部分是否显示了当前注册的脚本再确认网络面板里SW脚本的响应头和状态码浏览器不会在这个问题上跟你讲情面。2.2 WebGL上下文创建失败先禁用硬件加速试试Three.js玩家应该熟这句THREE.WebGLRenderer: A WebGL context could not be created. Reason: Web page ...意思是浏览器没能创建出WebGL上下文。绝大多数情况下不是代码问题而是运行环境的锅。远程桌面、虚拟机、老显卡驱动、浏览器设置禁用硬件加速都可能导致WebGL创建失败。网上有人建议你升级显卡驱动方向没错但对普通用户来说最有效的验证方式是浏览器设置里搜“硬件加速”关掉以后重启浏览器再跑一次。如果问题解决说明是驱动和浏览器的兼容问题如果还报错再用WebGL支持检测页面确认OpenGL和WebGL的状态。只有在确认是这一环节出错的情况下才值得去查Three.js初始化代码里的{ antialias: true }等参数——它们很少是主因。2.3 Flutter Web引擎启动慢多半是构建体积没控制住Flutter Web项目首次打开白屏时间长是社区里常聊的问题。它的渲染引擎CanvasKit体积很大加载慢非常正常。最快的处理办法是发布时开启--web-renderer html或根据版本改用canvaskit的延迟加载方式把引擎体积降下来其次是确保静态资源服务器开Gzip或Brotli压缩并配置好Cache-Control。还有一招是把Logo、启动页做成内联样式让用户先看到骨架页而不是对着白屏等。Flutter Web在复杂业务场景下的“首帧体验”确实拼不过传统前端这是技术基因决定的别把它当bug来调。2.4 那些“白屏”“白屏后没反应”的排查路径Google Web Designer运行白屏、某些Web IDE白屏、本地工具Web界面白屏看起来现象一样根因可能完全相反。我一般按“由近到远”排查第一步看浏览器控制台Console和Network面板有没有报错、哪个资源挂了第二步看是不是缓存——如果每次都要强制刷新才能显示新版那就是静态资源版本化没做好第三步看是不是跨域问题——接口跨域失败也会导致页面初始化卡住最后再考虑浏览器兼容性比如使用了太新的CSS或JS特性在老浏览器上无法解析。按这个顺序走下来绝大多数白屏问题都能在十分钟内定位。3. 部署这条路上nginx是绕不开的守门员3.1 同一个端口部署两个web系统配置逻辑其实很简单搜索里“nginx同一个端口部署两个web系统怎么配置”是个很高频的问题。现实场景往往是服务器只有一个公网IP80或443端口只能被一个程序监听但你有两个系统要对外提供服务。解决办法是把两个系统的入口统一交给nginx用location前缀或server_name域名做分流。最常见的做法是location前缀区分server { listen 80; server_name example.com; location /app1/ { proxy_pass http://127.0.0.1:8081/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /app2/ { proxy_pass http://127.0.0.1:8082/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这里要特别注意一个细节proxy_pass http://127.0.0.1:8081/末尾的斜杠和location /app1/配合会把/app1/api/login转发成/api/login。如果你的后端本身就是挂在根路径的这个写法没问题如果后端代码里写了统一前缀/app1你就得去掉斜杠否则会出现路径重复或404。使用location前缀方案还会遇到两个连锁问题。一是前端路由的history模式单页应用访问/app1/user刷新时nginx会去找/app1/user这个真实文件找不到就404必须在location里加try_files $uri $uri/ /app1/index.html;。二是后端Cookie的Path应用生成的Cookie默认Path是/那/app2接口也能带上/app1的Cookie容易串登录态所以应用里要把Cookie的Path改成自己的前缀。如果两个系统有各自的域名用server_name区分会更干净server { listen 80; server_name a.example.com; location / { proxy_pass http://127.0.0.1:8081; } } server { listen 80; server_name b.example.com; location / { proxy_pass http://127.0.0.1:8082; } }我部署过多次两种方案要提醒的是域名方案虽然清爽但需要你掌握DNS解析权并且用户要能记住两个域名前缀方案则要求后端或前端对路径前缀做统一适配。没有哪个方案绝对更好只有哪个更适合你的业务。3.2 Linux Web缓存的三个层级更新不及时就查这里“Linux web缓存”这个词范围很大实际常遇到的是三层浏览器缓存通过Cache-Control和ETag控制适合图片、CSS、JS这类静态资源。nginx层缓存proxy_cache可以把后端响应缓存下来适合接口结果比较稳定的场景。应用层缓存Redis适合热点数据和会话。遇到“页面更新了用户还是老内容”的问题我一般按顺序检查先看浏览器Network面板里的请求状态如果静态资源是304或直接走了memory cache那就是版本号没变给文件名加hash能解决如果是nginx层缓存要看配置的proxy_cache_key和缓存过期时间有没有覆盖对应URL最后才考虑是不是CDN缓存。CDN那层最容易忽略因为它在你的服务器前面回源策略和缓存规则都得你主动去配。3.3 web服务器安全别等被打了再补部署完web服务第一件事不是测试功能而是检查三个地方服务器版本和补丁、开放端口扫描、默认配置改动。nginx这类web服务器通常要隐藏版本号server_tokens off关闭不用的模块限制上传大小做好访问日志切割。万一出现异常扫描日志是最重要的证据。防火墙层面只开放必要端口数据库Redis这类服务千万别直接暴露到公网。4. 安全不是选修课从CTF入门到web安全常识4.1 为什么CTF选手都在“找flag”CTF Web解题也被称为夺旗赛核心形式很简单主办方在一个有漏洞的web应用里埋了一串字符串flag选手的任务是通过分析、利用web漏洞拿到它。搜索“ctf web解题 找flag夺旗赛”的人很多是刚接触CTF的新人第一次看到那种“给一个网站目标是拿到flag”的题都会愣住不知道该从哪入手。我个人的理解是CTF的web题并不是教你怎么做坏事而是用游戏化的方式检验你对web系统底层机制的理解程度。一道经典的SQL注入题你其实是在学“为什么参数化查询能防注入”一道XSS题你是在理解“为什么输出需要编码”和“为什么浏览器要有CSP这类安全策略”。所以我认为做CTF题对普通web开发者最好的收益不是“能打比赛”而是建立漏洞敏感性拿到一个Web系统你能本能地判断哪些地方是攻击面然后再针对性加固。如果你是新手我建议按这个顺序入门先搞懂HTTP协议请求头、响应头、Cookie、状态码再熟悉“输入-处理-输出”这条链路然后刷几套经典的web入门题集比如CTFHub的技能树边做边把每道题背后的漏洞原理写成笔记。这样比看一堆理论文档有效得多。4.2 普通开发者要守住的几条安全基线很多开发者觉得安全是安全工程师的事但实际上大多数web安全事故都源于开发阶段的疏漏。我自己在项目里会强制守住几条底线凡是用户输入的参数URL参数、Header、Body、上传文件一律做校验和过滤不能直接拼进SQL或HTML。所有数据库操作使用参数化查询或ORM不自己拼SQL字符串。开启CSP内容安全策略控制浏览器只能加载你允许来源的资源能挡掉一大半XSS。加密一定要用可靠的库和标准算法自己发明的“混淆”不是加密。密钥、口令绝对不能写进前端代码或Git仓库要用环境变量或专门的密钥管理服务。生产环境不要开放调试接口、不使用默认口令更不要预留“后门入口”哪怕你觉得自己只是临时加了个验证步骤。如果你负责的web项目上线前时间紧优先级我觉得应该这样排数据库注入和越权类漏洞必须重写修掉XSS类漏洞至少要做输出编码暴露的管理后台至少加访问控制日志泄露要处理。其他的安全项可以排期跟进。4.3 命令行工具和本地服务的“登录提示”别忽略搜索词里有一条“dsh web authentication required; reopen the url printed by dsh web.”以及一条“dsh web: opening the default browser; pass --no-open to disable”。这类提示其实很常见很多开发工具为了方便身份认证会在第一次使用时弹出一个本地URL让你在浏览器里完成登录授权。你的终端会打印出一个地址复制到浏览器打开、登录、授权然后回到终端里回车工具就拿到了令牌。这类流程的安全要点是确认URL确实是工具自己打印的通常指向127.0.0.1或localhost且端口随机而不是别人发给你的链接。如果终端里还出现“不是内部或外部命令”“command not found”这类提示通常不是认证的问题而是程序本身没装好或没加入PATH先检查安装步骤别对着认证流程折腾。还有一个小习惯这类本地认证端口用完就会关闭如果你在浏览器里看到“Connection reset”回终端重新执行一次命令让它再打印新URL即可不用慌。5. 局域网、远程访问和“工具链”这些杂症5.1 本地服务只能自己访问多半是监听地址的问题开发Web应用时经常遇到在电脑上启动了一个web服务比如内网的某个管理平台、opencode web这类工具的本地界面甚至你用命令行临时起的静态站点自己浏览器输localhost:端口能打开换到同一局域网的另一台电脑输入192.168.x.x:端口却打不开。大概率是服务默认只监听了127.0.0.1这个回环地址相当于“只对自己可见”。解决办法是把监听地址改成0.0.0.0表示所有网卡接口或具体局域网IP。不同工具的改法不太一样有的在启动参数里比如不少CLI工具支持--host 0.0.0.0或--server-ip有的是改配置文件里的bind字段还有的需要在环境变量里指定。改完之后从其他设备访问时要记得确认防火墙允许该端口入站。如果你在改完监听地址、防火墙也放行了之后仍然不通就用netstat或资源监视器确认服务到底在监听哪个IP和端口IP写错的话状态会直接体现。5.2 下载模型、安装插件卡住先检查网络与代理“inpaint web无法下载模型”这类工具性问题根子上基本都是网络连接或下载源问题。我的排查顺序是先确认网络是否通能正常访问外网并下载文件再看工具是否支持镜像源或手动放置模型文件最后考虑是不是代理工具干扰了本地下载请求。很多AI工具第一次运行需要拉取模型权重动辄几百兆一旦断线就可能出现“下载失败、重新运行又从头开始”的循环。比较好的习惯是提前查看工具文档里指定的模型缓存目录去官方源手动下载好后放到对应位置再启动应用一次就能过。5.3 桌面工具白屏、跨浏览器插件、Web端协作工具平时还会收到很多杂问题比如“ntko web chrome跨浏览器插件怎么下载”“obsidian web clipper怎么用”“figma design web组件库视频怎么看”。这类问题的共同点是你需要的不是一个技术方案而是一个“工具使用方法”。我会习惯先到官方帮助中心找答案而不是搜二手教程。浏览器插件类问题注意确认你用的是Chrome还是Edge这两家的扩展商店不是完全互通跨浏览器插件一般在应用官网都有直接的下载入口。Obsidian Web Clipper这类知识管理插件核心是让你在浏览网页时一键截取内容到笔记库前提是你先安装好对应桌面端或Web端服务再在扩展设置里授权。6. 测试与调试拉开普通开发者和靠谱开发者差距的地方6.1 Fiddler这类抓包工具Web端调试怎么用性价比最高Fiddler是经典的HTTP抓包调试工具很多人用它抓移动端包但它Web端的使用价值也很高你在浏览器页面里做的每个请求都能在这里看到完整请求头、响应头、Cookie、耗时。它的原理是在本机启动一个HTTP代理浏览器或系统流量经过代理时被记录和修改。Web端调试时最常用的三个功能断点修改请求在请求发送前拦截改参数再放行很方便做边界测试。AutoResponder把某个请求的响应直接指到本地文件前端可以脱离后端独立调试。组合请求Composer手工构造请求快速验证接口逻辑。用Fiddler抓HTTPS流量时需要先安装并信任它的根证书否则抓到的全是加密乱码。用完记得检查系统代理是否已经关闭否则可能出现“浏览器能上网但网络特别慢”或“其他软件报代理错误”的情况。6.2 从“全国大学生软件测试web”这类比赛聊测试素养有些高校会组织Web应用测试类竞赛比如全国大学生软件测试大赛的Web测试方向。它的题看起来复杂实际考核的就是两类能力功能测试设计和缺陷发现能力。说白了给你一个系统你要能设计测试用例并且真把bug找出来。这和平时项目里的测试没什么本质区别只是更讲究方法。我建议开发者在测试自己功能时也按几类方法来等价类划分把无限输入分成有效和无效的几类、边界值上限、下限、最小、最大、场景法把用户完整操作路径串起来、错误推测凭经验猜哪些地方容易出问题。很多人觉得自己写的功能测过了没问题其实只是把正常路径跑通了一遍边界和异常场景全都没覆盖上线后出问题不奇怪。所以测试思维不是测试岗位专属后端工程师、前端工程师都应该有。6.3 Web端实时视频、Web打印这类“冷门”需求笔记里也得有日常开发里还会有一些看起来冷门但高价值的Web场景。比如web端实时视频大致分三条路线WebRTC的延迟最低适合视频会议、直播连麦但服务器端带宽和信令复杂度高HLS兼容性好但延迟有几秒到十几秒适合直播观看场景FLV over HTTP在有低延迟需求的边缘场景常用但需要客户端装flv.js。选择路线的逻辑是先看你的业务对延迟的容忍度再看播放器兼容性最后才是服务端成本。“web页面pdf打印”也很典型。简单做法是直接调用window.print()用好浏览器的打印对话框配合media print样式隐藏页面干扰元素、调整页边距复杂一点的批量生成PDF场景可以用服务端的无头浏览器比如puppeteer把页面渲染成PDF。个人经验是前端打印方案适合“用户在自己浏览器打印”的场景可交互服务端方案适合“系统自动生成电子文件”的场景可批量但样式兼容坑不少。两条路线各有各的甜点位别混着用。7. 把笔记变成自己的武器库写了这么多我想强调的还是笔记本身的价值。再大的项目经验不沉淀下次遇到新坑还是从头摸。我的“web笔记”不是教科书式的手册而是由一个个具体问题积累起来的某个报错怎么解决、某个部署方案为什么选这个不选那个、某个安全项到底防的是什么。发现问题、记录原因、连点成线时间久了就成了自己的武器库。如果你还没有记录习惯我建议从今天开始遇到一个让你卡过半小时以上的问题就花五分钟写下来问题现象、排查过程、根因、解决方案、下次怎么避免。不用在乎文笔甚至不用结构化先把当下的经验和判断留住。等你一两个月后回看会发现这些笔记比很多付费课程都有用。这套方法在web开发里适用放在任何领域的项目里效果也都一样。
返回列表