Skip to content

从输入URL开始建立前端知识体系

前置内容 浏览器主要进程

浏览器是多进程的,主要分为:

  • 浏览器主进程:只有一个,主要控制页面的创建、销毁、网络资源管理、下载等。
  • 第三方插件进程:每一种类型的插件对应一个进程,仅当使用该插件时才创建。
  • GPU进程:最多一个,用于3D绘制等。
  • 浏览器渲染进程(浏览器内核):每个Tab页对应一个进程,互不影响。

第一部分 输入网址并解析

这里我们只考虑输入的是一个URL 结构字符串,如果是非 URL 结构的字符串,则会用浏览器默认的搜索引擎搜索该字符串。

URL的组成

URL 主要由 协议主机端口路径查询参数锚点6部分组成!

image-20220208100601463

解析URL

输入URL后,浏览器会解析出协议、主机、端口、路径等信息,并构造一个HTTP请求。

  1. 浏览器发送请求前,根据请求头的expirescache-control判断是否命中(包括是否过期)强缓存策略,如果命中,直接从缓存获取资源,并不会发送请求。如果没有命中,则进入下一步。
  2. 没有命中强缓存规则,浏览器会发送请求,根据请求头的If-Modified-SinceIf-None-Match判断是否命中协商缓存,如果命中,直接从缓存获取资源。如果没有命中,则进入下一步。
  3. 如果前两步都没有命中,则直接从服务端获取资源。

HSTS

由于安全隐患,会使用 HSTS 强制客户端使用 HTTPS 访问页面。详见:你所不知道的 HSTS。 当你的网站均采用 HTTPS,并符合它的安全规范,就可以申请加入 HSTS 列表,之后用户不加 HTTPS 协议再去访问你的网站,浏览器都会定向到 HTTPS。无论匹配到没有,都要开始 DNS 查询工作了。

浏览器缓存

强缓存

强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。强缓存又分为两种ExpiresCache-Control

image-20220208101012657

Expires
  • 版本:HTTP/1.0
  • 来源:存在于服务端返回的响应头中
  • 语法:Expires: Wed, 22 Nov 2019 08:41:00 GMT
  • 缺点:服务器的时间和浏览器的时间可能并不一致导致失效
Cache-Control
  • 版本:HTTP/1.1
  • 来源:响应头和请求头
  • 语法:Cache-Control:max-age=3600
  • 缺点:时间最终还是会失效
示例

新建server.js

js
// 转载的一些文章\从输入URL开始建立前端知识体系\server.js
const http = require('http')
const fs = require('fs')

http.createServer(function (request, response) {
    console.log('request come', request.url)

    if (request.url === '/') {
        const html = fs.readFileSync('test.html', 'utf8')
        response.writeHead(200, {
            'Content-Type': 'text/html'
        })
        response.end(html)
    }

    if (request.url === '/script.js') {
        response.writeHead(200, {
            'Content-Type': 'text/javascript',
            'Cache-Control': 'max-age=20,public' // 缓存20s 多个值用逗号分开
        })
        response.end('console.log("script loaded")')
    }
}).listen(8888)

console.log('server listening on 8888', 'http://localhost:8888')

新建test.html

html
<!-- 转载的一些文章\从输入URL开始建立前端知识体系\test.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

</body>
<script src="/script.js"></script>

</html>

启动服务

shell
node server.js

image-20220208103718384

在浏览器请求,http://localhost:8888/

image-20220208103916327

第一次请求script时,服务端在响应头上告诉这个结果需要缓存在本地,20s,'Cache-Control': 'max-age=20,public' // 缓存20s 多个值用逗号分开

刷新浏览器,第二次请求这个资源时,如果在20s以内,会从缓存中读取。

image-20220208104122160

image-20220208104139258

协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。

image-20220208104408179

模拟Last-Modified

新建server2.js

js
// 转载的一些文章\从输入URL开始建立前端知识体系\server.js
const http = require('http')
const fs = require('fs')
const path = require('path')

http.createServer(function (request, response) {
    console.log('request come', request.url)

    if (request.url === '/') {
        const html = fs.readFileSync('test2.html', 'utf8')
        response.writeHead(200, {
            'Content-Type': 'text/html'
        })
        response.end(html)
    }

    if (request.url === '/server2.js') {
        const filePath = path.join(__dirname, request.url); // 拼接当前脚本文件地址
        console.log(filePath, 'filePath~~');

        const stat = fs.statSync(filePath); // 获取当前脚本状态
        console.log(stat, 'stat~~~');

        const mtime = stat.mtime.toGMTString() // 文件的最后修改时间
        console.log(mtime, 'mtime~~~');

        const requestMtime = request.headers['if-modified-since']; // 来自浏览器传递的值
        console.log(requestMtime, 'requestMtime~~~');


        // 走协商缓存
        if (mtime === requestMtime) {
            response.statusCode = 304;
            response.end();
            return;
        }

        // 协商缓存失效,重新读取数据设置 Last-Modified 响应头
        console.log('协商缓存 Last-Modified 失效');
        response.writeHead(200, {
            'Content-Type': 'text/javascript',
            'Last-Modified': mtime,
        });

        const readStream = fs.createReadStream(filePath);
        readStream.pipe(response);
    }

}).listen(8888)

console.log('server listening on 8888', 'http://localhost:8888')

新建test2.html

html
<!-- 转载的一些文章\从输入URL开始建立前端知识体系\test.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

</body>
<script src="/server2.js"></script>

</html>

启动服务 node server2.js

参考

在浏览器输入 URL 回车之后发生了什么(超详细版)

从输入URL开始建立前端知识体系

你所不知道的 HSTS

从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系!

https://www.bilibili.com/video/BV17Q4y127We?spm_id_from=333.999.0.0

HTTP/3 explained

浏览器怎么查看发起的请求是http1.0还是http2.0