一、简介
- 闲来无事,刷刷Github,这样一句话一下吸引到了我。
- “一个真实可怕的异步web谈天,前端不运用任何JS。”
- 看看作用图
- 看作用还挺不错的,如同真的能谈天!
- 尽管这如同并没有什么意义…但最使我好奇的几个点是:没有js,那么这个谈天室是怎样完结的呢?音讯怎样传递?为啥不让键盘直接输入文字呢?(奥秘度=3;)
二、浅看
- 翻开源码浅浅预览一下
- 能够看到目录结构非常简短,而且没有任何html类型文件和js类型文件,项目主体语言是Ruby,而且运用了Redis作为数据库。
- 那么咱们现在能够猜测:逻辑是写在Ruby里边的、谈天信息是经过Redis传递的。(奥秘度–;)
- 具体怎样搞,一会再揭晓。
三、本地复现
- 依据README.md的提示,咱们首要需求准备好Ruby和Redis环境。(环境装置这儿就不多赘述了,大约便是下载装置包或者绿色版压缩包之后装置到本地、配置环境变量、运转环境,当然能够运用虚拟机或Docker进行装置)
- 我是在Windows上进行复现的,所以需求下载RubyInstaller和Redis-x64-5.0.14.1.zip。
- 装置好之后,发动完环境。咱们的目光就转向了源码,Ruby的包办理东西叫做Gem(可能许多同学不了解Ruby所以在这儿阐明一下),在源码目录中有一个叫做Gemfile的文件,这个文件便是用来办理项目所需求的Gem包的。在Gemfile文件中咱们能够看见项目依赖于Rack、Puma、Redis、Faker等包,你可能对他们不熟悉,但不要紧,这些和原理无关,咱们只需求知道这些包是用来干什么的就行了。Rack和Puma能够完结http服务、Redis是数据库、Faker是用来生成假数据的。咱们直接控制台cd到项目目录,然后咱们上来便是一条指令:
bundle install
,这条指令会依据Gemfile文件中的内容自动装置所需求的包(网速你懂的,假如批量装置指令一直失利能够运用gem install xxx的指令逐一装置),装置完之后咱们就能够运转项目了。 - 最终执行
bundle exec puma
运用Puma发动项目,然后翻开浏览器拜访http://localhost:9292
,就能够看到作用了。 - 演示视频:www.bilibili.com/video/BV17e…
四、原理解析
- 在咱们翻开Web页面的时分,一定会发现一个现象!便是这几个界面加载的圈圈一直在转,如同从来没有中止加载一样。而且,分明在文件中没有任何html文件,也烘托出来了界面(这其实并不奇特)。
- 首要来看一下没有html文件就能烘托出来界面的问题,这个问题其实很简单。咱们平常拜访的页面被称为超文本,超文本从服务器发送到用户页面纷歧定是html文件,能够是其他类型文件,也能够是写死的包含一系列标签的字符串(这种用法在物联网芯片编程中很常见),由于本质上浏览器向服务地址发送http恳求得到的呼应数据只要是浏览器能读懂的呼应头、呼应行、呼应体就能够顺利的被烘托。咱们要做到让浏览器只要能辨认出来就行了,所以这儿的界面其实便是一个写死的标签字符串拼接起来的。
- 咱们去项目中唯一一个rb文件查找页面中的标志性信息
- 一目了然!实际上这个开源项目中便是搭建了一个http服务器,而且在/恳求途径下建立呼应处理和呼应内容(运用的技能是上文中说到的Rack+Puma),而且呼应内容是咱们看见的界面,就这么简单。
- 那项目是怎样完结通信的呢?在哪触发了办法?值得咱们留意的点在于输入字母的时分,咱们是经过点击屏幕上的字母按钮输入文字,隐秘其实就在这个按钮里边。
- 当咱们点击按钮的时分,竟然会呈现网络恳求!而且是途径有规律的网络恳求!界面也同时会跟着改动!
- 让咱们先将现在的信息收拾一下:页面在不停加载、只要CSS文件、点击按钮会触发网络恳求
- CSS怎样发恳求?这是一个很有意思的问题,很难想,可是在平常开发中却非常常用!非常常见!常用到有图片的地方,每次换图片都得调用一次网络恳求。这么说你还没懂的话,我可就直说了!
- 能够直接经过设置CSS的background-image特点来建议网络恳求,这个特点的值能够是一个图片的url,也能够是一个base64编码的图片字符串。当这个地址是一个可恳求途径的时分,浏览器就会向对应地址建议恳求获得背景图片!而且!CSS中的伪类选择器active能够知道咱们点击了按钮!然后转化款式!(奥秘度–;)。可是浏览器不会重复加载一个图画两次的,想想咱们在做网页验证码的时分是怎样做的?加时刻戳?对!便是这样!可是这儿咱们不能调用js内置时刻对象来发生时刻戳了,要整点纷歧样的了!
- 既然发恳求的问题解决了(尽管计划可行,可是现在来说每个按钮只能用一次,由于浏览器不会重复恳求图片),咱们先来看看怎样接收数据。
- 传统的完结动态网页的办法是运用js发恳求,拿到返回值之后运用js依据返回值去操作DOM元素,可是现在这个项目中作者标题写的只能用CSS来完结谈天室(尽管真的有点标题党,由于后端服务器里边也有许多逻辑),但还是坚决不能呈现js文件的!那这个项目的页面是怎样拿数据更新界面的呢?
- 要完结改动界面还不用CSS,怎样办?恐怖如斯!可是咱们再来看看现在收拾的信息都有啥(当时奥秘度=1)
- 现在信息:页面在不停加载、只要CSS文件(√)、点击按钮会触发网络恳求(√)
- 现在发送网络恳求的问题解决了,第二和第三个信息就用完了,还剩余俩信息了,咱们先来看看第一个信息:页面在不停加载。
- 有趣的工作来了!咱们在浏览器中翻开开发者东西,然后刷新页面,然后在Network中找到咱们的恳求,然后点击Preview,然后咱们就会发现…
- 留意!恳求尚未完结!而且离谱的是页面翻开多久,这个恳求就恳求多久。
- 想改动页面,除了咱们运用代码操作DOM。还有一种经常运用,可是咱们好像从来没有细心研讨过的办法,那便是——加载页面!
- 这儿开源软件的作者运用了一种能够说是非常极客的手法,让页面永远无法完结加载,并不断经过加载的数据流向页面中增加东西(留意:只能增加),听起来挺离谱的,但这样的确能够!
- 经过在恳求头中加入Transfer-Encoding: chunked,能够让浏览器在完结加载之前开始呈现页面。(奥秘度–;)
- 至此,一切隐秘都解开了!(当时奥秘度=0)
- 现在是填坑时刻了。可能你很好奇,分明只能增加东西不能删去东西(假如直接都想通了就当我没说),不能删掉旧的按钮或者删去旧的款式,那怎样完结每次点击按钮的时分发送不同的恳求呢?其实只要细心就会发现一件很绝的工作,div标签会越点越多!
- 每点击一次按钮,就会多一整套按键,而且老一套按钮会被完全躲藏。这是能够经过增加页面内容完结的,由于存在着能够躲藏控件的特点,而且款式是能够覆盖的。
- 至于谈天的功能,在这儿其实无足轻重。恳求和呼应都是运用Ruby的Web结构处理的,咱们知道谈天的音讯是存在Redis的,谈天室中的所有人存在一个set类型变量中,用来办理在线状况。音讯列表放在一个List类型中,用来共享音讯。咱们运用Redis可视化东西检查一下Redis中的数据就很简单看懂了。
五、难点
六、相关代码
- 收藏夹:github.com/stars/tyza6…
- 项目地址:github.com/kkuchta/css…
- 演示视频:www.bilibili.com/video/BV17e…
- Redis:github.com/tporadowski…
- Ruby:www.ruby-lang.org/ja/
七、总结
- 这个项目虽小,可是非常精悍,里边运用的技巧和思路都是非常值得学习的,期望大家能够喜欢。
- 感谢您能耐心看完这篇文章,假如有什么问题,欢迎在谈论区留言,我会尽快回复。
- 假如您觉得写的还不错,欢迎关注、点赞、分享、订阅、Star,您的点赞是我写作的动力!