您的位置: 游戏资讯 > 手游攻略

哔哩哔哩-B站,哔哩哔哩早期页面

来源:头条 浏览:0 2022-12-26 17:08:01

过去的开发模型采用以后端为中心的MVC体系结构方式。 具体来说,每次项目评审时,前后端都要先约定一起接口,然后分别进行开发,开发完成后,前端向后端提供页面,后端需要配置并返回数据。 基于这种开发模式,导致了总工作量的增加,同时沟通和协调成本的消耗也非常显著。

前后端分离

哔哩哔哩-B站,哔哩哔哩早期页面

为了摆脱这种过于依赖前后端的情况,(其实前端也不想每次修改和发布时都发布到后端,后端也不想每次前端只改变标题时就发布,影响服务器的稳定性)

前后端分离、最基本的2个模式有可能有中间层也有可能没有中间层。

第一,如果没有web中间层的话很简单。 提供放置在静态资源机器上的html模板。 html模板引用了所需的js和css。 访问页面时,将此静态模板返回给用户,然后运行js并在浏览器中通过ajax向api请求数据以呈现页面。

(前后端分离)

二是有节点中间层。 2009年,随着node的横向进入,将前端逐渐推向了后端。 有了node,JavaScript可以做更多的事情。

B站在最初进行前后端分离时,也确实是用第一种方法进行的。 现在仍然有https://www.bilibili.com/account/history (可以显示网页的源代码)等页面。 对于不需要seo的页面来说,是个好方法。 前端开发完成后,用webpack将对应的js和css打包并上传到cdn,将参考webpack打包的对应资源的html文件上传到专用的静态机器,进行运行时配置路由后端同学提供对应的api接口即可。 前后端分开维护,自己按自己的节奏行走,降低了页面和服务的结合度

这种方式确实是一种可以立即进行前后端分离的方法。 我们花了一段时间,在pc端使用vue进行重构,在移动端的H5端使用react进行重构。 虽然进度很快,但慢慢地也出现了弊端。

对于第一个屏幕,第一个屏幕有一个白色屏幕,因为他要等待资源加载完成才能进行渲染。 如果是单页的话还好,spa APP的话加载时间会变长,白屏的时间会严重影响用户的体验。 此外,由于国内搜索公司与spa APP不兼容,客户端呈现对seo很不友好,因此有seo需求的页面需要服务最终呈现。

(B站首页,右模块进行服务渲染,左模块未进行服务渲染) )。

那么,依赖node进行服务最终渲染被提上了日程。

选型

首先进行node框架的选定。 市面上有三种主流框架。 hapi express koa,还有一些是打包的、定制的框架。 例如,eggjs等。

我从一开始就排除了eggjs。 第一,eggjs非常强大,有很多功能,所以有一些完全不能用。 因此,他将处于或重或轻的水平。 第二,eggjs对我来说是黑匣子,如果有什么问题,需要很长时间才能解决。 (但是,有很多借鉴eggjs的地方。 果然很强)

而且剩下的三个框架,express的使用方法比较简单,文档也很多,很全面,所以选择了express。 (之后也重构了==! )

然后是前端框架的选定。 前端框架的主流有很多,所以我用react和vue,比如ng r v。 他们有可以前后同源的优势。 不需要写两个同样的逻辑,太棒了。

(同构逻辑大概是这样吧)

以前,前后端分离的时候,是在pc上用vue重新构建的,所以当然,这次的服务终端渲染也是在vue上构建并使用vue ssr。 (这也为我后来的想法埋下了伏笔)

先选一个简单的页面做样本吧。 使用tag页面吧。 (被上帝选中的孩子( https://www.bilibili.com/tag/3503159 ) ) ) )。

开发

目录结构

- client【客户端代码同种代码】

- build【构建相关】

- PC 【pc端vue项目】

- package.json

- config

- config.local.js【本地开发配置】

- dist【构建目录装载资源目录】

- server【服务器端代码】

-控制器【控制器】

-电脑

- route.js

- core [核心代码库]

- service [方法库]

-视图

- PC [vue构建后文件]

- tag.html [生成后模板]

- tag.json [构建后的bundle]

- manifest.json

- apps.js [启动项目]

最初设计时,客户端代码和服务器端代码位于同一个git库中,client包含vue的代码和webpack的包逻辑。 服务器上是服务器端的代码,使用的是类mvc结构。

Client内的vue的开发代码是参考vue ssr官方给出的例子制作的,使用createBundleRender方法

const { createbundlerenderer }=require ( vue-server-renderer ) )

const renderer=createbundlerenderer (服务器绑定,{

. } )

配置的推荐配置(参考: https://SSR.vue js.org/zh/build-config.html ) )。

简单来说,它提供了两个条目: entry-client.js。 一个主要是客户端执行条目,打包的是客户端引用代码集合manifest,另一个打包entry-server.js的是服务器端执行逻辑,集成在bundle.json中然后传达给上面的createBundleRender方法就可以了

server文件夹中的逻辑非常简单,core中包含启动项目的某些express核心代码的路由注册等逻辑。 有趣的是,我们的路由参考了eggjs的路由注册方式,使用了稍微修改和结构化的方式

配置优于代码,它将访问地址与相应的控制器相关联。

这里还有一个过滤器其实是在运行controller之前注册middlewares优先运行的。

我忽略了压力测试。 压力测试以后再说吧。

在线部署

在线部署是使用docker进行的。 配置为1C 4G配置,使用两个实例运行。 (到目前为止的镜像逻辑的构筑等不具体介绍)

此后,每天的访问量约为100W,服务器性能稳定。 在那期间,发生了故障。 也就是说,这里的一个状态与用户的登录状态有关,所以在服务器端请求接口时,需要带着cookie进行请求。 到时候忘记加了再加的话,这有点弊端很麻烦。

调用vuesssr时必须将其带到context中。 然后,需要在asyncData方法中一个接一个地传递,最后用action得到并送到api。

现在让我们再看一次tag页面。

ssr html

(我带来了不错的数据)

重建

其实不久,大约三个月吧。 node的版本迅速上升。 从7.6版开始,节点支持async/await语法糖。 不需要使用yield和*函数。 这样的话,koa对于await/async的支持是最好的。 我们果断地放弃了express,选择了koa2。

其实除了koa2支持async之外,还有一个原因就是我们koa是洋葱式的执行方式,所以我之前说过了,只有控制器的预处理,没有后处理。 像这样,我可以很容易地执行前后处理。 Koa的执行效率也优于express

正如我之前说的,选择vue为后面的重构埋下伏笔的就是这里

首先,我访问了部署中心进行项目。 部署中心是做什么用的? 记录脚本的版本号。 这样,配置中心就可以轻松控制前端页面使用的脚本版本。 更改脚本的版本号不需要重新启动和更新服务。

然后,我篡改了vue的打包组件,带来了与他打包的文件相对应的版本号(版本号为hash值)。

现在,vue前端的逻辑将更新,只需从配置中心分发到服务器端,而无需重新启动服务,就可以使用哪个版本的vue构建生成器。 一举两得。

主机设置

图中的conf是配置中心,我们的server与conf进行了长时间的连接,当conf的配置被更新时通知服务器,服务器拉动新的bundle和manifest进行渲染。 Ok太棒了

全民SSR

重构结束后,让我们再访问一个项目

主页,好的,让我们做主页吧

首页和tag页面

其实几乎一样。 没有什么特别的地方。 唯一不同的是量很大。 一天可能有1000W的访问量。 那么,在CDN的上面添加缓存,在服务器的上面也添加缓存。 破费( perfect )! ~

服务器端的缓存在文件中落地。 在收到第一个请求时渲染完成后,可以在本地写入文件,然后在下次访问时直接使用此本地文件进行渲染,而无需再次渲染。 之后,在有效期内进行控制。

在这里发现了问题。 这意味着每次更新都打包tag和index,但必须单独打包每个项目,然后单独更新。 可以通过参数控制打包哪个吗? 好的。 首先重写webpack.config.js,合并公共部分,私人分多次用package.json写

每次这样更新项目时,只需打包对应的项目即可,在访问了很多项目后,打包和开发时的热加载不会变慢。

由于访问了两层缓存,首页在线时,我们将服务从两个docker实例扩展到了六个。 ( docker扩展真的很方便。 )多亏了缓存的优点,服务器没有压力

当然首页不是像说的那样,这么随意就在线了,降级方案是必要的,降级方案多亏了vue的强大

Vue在浏览器端进行检查。 ( data-server-render=true ) ),是否在服务器端进行了渲染。 如果没有在服务器端进行渲染,客户端将再次执行逻辑进行渲染。 这样,我们在重新打包时,只需保留原始客户机渲染的index.html即可。 当然,您也应该在重新客户端执行时执行asyncData中的方法。 不这样做的话,数据会不足哦。 So easy~

接下来的一级分区和二级分区也分别被访问,虽然中途出现了一些问题,但最后一切都顺利解决了。 以后有机会的话,就其中遇到的问题再写一篇文章吧。

重建

我们的项目正在有序地从原来的静态页面客户端过渡到呈现、服务最终呈现,同时我们也在内部进行这个促销。 几个兄弟部门也因为面临我们以前的seo问题,或者想让最初的画面更快等理由,很乐意使用我们制作的车轮。 但是,我们的项目暂时没有普及性。 兄弟部门要使用,只能复制我们的库,然后删除业务逻辑,添加自己的逻辑。 成本很高。 另外,如果这边更新了什么,他们就需要手动同步,很麻烦。

我们花了一点时间。 首先,取出core核心库,与日志中心连接方式、配置中心连接方式等几种通用方法一起,制作npm包并发布在公司内部的npm源代码上,使client独立于库之外开发时不过度依赖node server .配置中心使项目支离破碎,但最终通过配置中心集中于同一服务,回到了前后端分离。 但是,不仅是前后端分离,前端独立开发的同事也带来了服务端渲染,一举两得。 设计体系结构图:

分割

顺便说一下,我们开发了两个脚手架,轻松地创建了项目,并添加了webpack配置和package.json配置

这样分割的话,项目会很干净。 前端开发前端的vue项目,服务端有npm包,便于升级和维护。 node服务也不需要一直重新启动,可以根据配置更新逻辑和热更新。

结束后,许多兄弟部门也开始访问。

压力测试

因为每个公司的情况都不一样,所以通过组件缓存、页面缓存等可以达到优化的目的,达到承载项目流量的标准。 这里说的情况是没有任何缓存时的冲压结果。

我们进行过几次不同级别的压力测量。 毕竟,性能需要满足要求。 我记得当时出版样品在线的时候,VUE在2.3.x的性能不太好。 VUE是基于虚拟DOM(vnode )实现的,是一个CPU密集型项目,压力测量时CPU很快达到100%,TPS很低,所以页面上添加的项目比较复杂,嵌套多的话,1C4G的

我看到了很多将vuessr与字符串模板进行比较的文章,他们的比较和demo一样简单,vue没有组件嵌套,性能比较可能确实相似,但是页面的复杂性上升了,组件嵌套

例如,我们的首页一、二级分区每天命中node的量和文章的量差不多,但文章用的是首页三分之一的机器。 机器的cpu和内存使用量相同。 因为文章项目使用的是字符串模板。

总结

在整个过程中,需要前端学生、后端学生的共同努力,后端api学生原本直接结合模板输出数据的方式都需要转变为api接口,这是前后端分离的基础。 对于基础设施,可以逐步发展完善。 像我们最初构建的时候一样,构建的配置文件的所有版本号都必须手动放置在配置中心,这很费时间,容易出错。 渐渐地,配置中心开放了api接口,使我们的访问变得方便,顺利地实现了配置同步的自动化。 上线的时候马上公开就可以了。

在用node做中间层的过程中,也遇到过内存泄漏、性能瓶颈等问题。 以后有机会的话,再写文章介绍吧。 在这一年里,B站发展很快,前端也有意识地在意前端的性能,把页面做得更好、更快。

从未停下脚步,我们还在路上!

和平精英体验服官网「V3.02」IOS版

和平精英体验服官网「V3.02」IOS版

  • 分类:资讯阅读
  • 大小:17MB
  • 语言:简体中文
  • 版本:V3.02