飞道软件工厂

插件式开发

新建web页面

项目新建完成以后,我们已经有了一个初始的首页(src/pages/pg001),但是往往一个系统中不会只有这么一个页面,那么,如果我们如何新建一个页面呢?原则上讲,手动创建页面也是可以的,但是我们的开发助手可以帮助我们快速创建一个新的空白页面。

1. 页面渲染的时序

  1. 用户通过点击超链接等动作通过浏览器(像在微信中,也同样是内嵌限一个浏览器内核)发出到服务器的GET请求,请求地址为http(s)://xxx.
  2. web服务器接收到该请求,组织好html字符串,返回到客户端。这一步可以是读取本地html文件,也可以是服务器使用动态数据对页面进行渲染,之后生成完整的html。
  3. 浏览器接收到html,进行解析,编译为dom树,结合css,最终展示出来。
  4. 有些页面还会在html初次下载渲染之后再次向服务器发出请求,获取到服务器返回的数据之后再次对页面进行局部渲染操作。
  5. 在html页面中,还会有一些用户交互,这些用户交互也有可能会向服务器再次发出http请求,访问某个服务。

2. web页面的分类

我们根据上面的页面渲染的时序对页面的渲染过程进行分析,从而对web页面进行分类。

在上述时序中的最后一步,客户端有没有用户的交互动作并不影响页面初始渲染的逻辑,因此上我们在页面初始化渲染时不需要考虑这一步。

在2步的过程中,如果有数据的处理,往往其渲染速度不如静态html效果好,因为静态html只有一个读取文件的操作(甚至如果文件在内存当中,连磁盘读取都不需要,直接把内存数据返回给请求的客户端即可)。所以,为了使得我们的应用的页面响应速度更快,在其它硬件条件一样的情况下,我们要尽可能使其为“静态的”。这样,客户端浏览器在请求这个页面的时候,就可以几乎无延迟地将页面内容传送给发出请求的浏览器。像新闻资讯这样的页面最适合生成静态的页面了,因为这些内容几乎是不会修改的,虽然有些内容可能存在数据修改的可能,但即使是修改后也无须即时向用户呈现,允许有时间延迟。这样的页面我们可以将其直接生成静态的html部署在服务器上是最为合适的。

当然有些情况使得这些页面“不可能”是静态的。比如用户的个人信息页,必须根据用户当前的个人信息进行渲染,况且还要校验用户的权限,再比如购物车页面,都太容易做成静态页面,因为它对数据非常敏感,一旦数据发生变化,那么所有请求终端来说,这些被展示出来的内容都要发生变化,不允许有延迟的情况,如果有延迟,用户就会以为对数据的修改未及时生效,这是不能被容忍的。

而还有一些页面,虽然其内容不一定是可以提前生成静态的html文件,但也不能使用上面时序中讲的第4步的方法进行页面的渲染,这是因为这些页面使像百度这样的网络爬虫可以及时爬取到正确的内容,网络爬虫往往不会在请求完html页面后再次执行页面中的js使其进行第二次“渲染”。这就要求我们要在服务器端就完成该页面的渲染工作。这会损失一些服务器的运行效率,但却可以使网络爬虫爬到我们希望它爬到的内容。另外,这种服务器渲染的做法,虽然加重了服务器的压力,但同时也减轻了客户端浏览器的压力,因其无须第二次(时序第4步)向服务器请求,这降低了客户端用户看到首屏展示等待的时间(客户端发出二次请求渲染必须要等到html以及其引用的js文件下载完成后方可进行,不能同时进行)。这对于网络条件差,电脑(也可能是手机)性能差的用户来说更加友好。

  1. 预生成静态页面

    提前将内容生成为html文件,放在服务器上,客户端请求时直接读取html文件。

  2. 服务器渲染页面

    在服务器上对页面进行取数渲染,这是有限制的,因为在服务器上并不能完成所有浏览器能做的事情,比如读取localstorage等。

  3. 浏览器端渲染,但初始数据在服务器生成基础html时跟随html共同带到浏览器端,浏览器端不需再次发出请求,直接使用这些数据完成渲染。

  4. 纯浏览器端渲染

    这种渲染方式是现在主流的动态页面的渲染方式,因为前后端分离的开发方式使得服务端渲染结合浏览器渲染这种复杂多变的渲染方式变得非常难以实现,前后端沟通成本过高,一般小企业小公司没有成本完成这些事。这是全栈开发的一个非常大的优势,前后端分离的开发方式永远无法比拟。

3. 回到实战

3.1. 客户端渲染页面实例

新建一个页面,我们在打开一个web项目之后,使用代码助手,新建一个页面(快捷键为alt+p):

add client side render page

在这个页面中,开发人员就可以进行页面的开发了。这是一个客户端渲染的示例,即其没有服务器端渲染的部分。

3.2. 服务器端渲染页面实例

接起来我们来添加一个静态服务器渲染的示例,这样的页面就可以被网络爬虫爬到哦

add ssr page

在这个示例中,在获取数据时模拟了异步取数的示例。

3.3. 静态页面实例

我们模拟一个学生信息页面,所设我们有三个学生:张三李四王五,他们三个人的id分别是001,002,003.

user info

注意,在上例中,事实上会有两个错误:

  1. Async arrow function 'getStaticProps' has no 'await' expression.
  2. Async arrow function 'getStaticPaths' has no 'await' expression.

这其实是同一种错误,意思是说,在两个函数中我没有使用await关键字,事实上这是因为我这个示例纯粹是示例而已,里面没有异步操作,在实际的开发过程中几乎不会遇到这样的情况,如果真有,也有办法解决,只是异步函数的一种用法,这里不再过度讲解。

4. 全部匹配的静态页面

在某些情况下,可能我们需要有一个统一的方法来匹配请求地址。比如说多个产品中的某个商品,请求地址为http(s)://xxx/$productid/$id.甚至请求的层级都不是固定的情况。这样的页面也是支持的,但鉴于这种场景并不多见,所以这里暂不讲解,如确有需求再另行补上。

5. 示例代码

示例代码在https://github.com/mm-works/p000024,有需要的老师请自取。