zoukankan      html  css  js  c++  java
  • HTTP和前后端分离

    一、当用户在浏览器地址栏中输入网址,到看到页面,经历的步骤

    tips:hexo自己搭一个博客
    在这里插入图片描述

    1.解析输入的URL地址

    • 传输协议(把信息在客户端和服务器端进行传递,类似于快递小哥)

      • http 超文本传输协议(传输的内容除了文本,还有可能是其它类型:二进制编码、BASE64码、文件流等等)
      • https 比HTTP更加安全的传输协议(传输通道设置加密算法SSL),一般支付类网站都是HTTPS协议
      • ftp 资源上传协议,一般应用于把本地文件直接上传到服务器端
    • 域名 zhufengpeixun.cn

      • 一级域名 www.zhufengpeixun.cn
      • 二级域名 video.zhufengpeixun.cn
      • 三级域名 webG.video.zhufengpeixun.cn
      • 常用域名性质:.com国际 / .cn中国 / .gov政府 / .org官方 / .net系统 / .io博客 / .vip ...
    • 端口号 (根据端口号,找到当前服务器上指定的服务)

      • 0~65535之间
      • 不同协议有自己默认的端口号(也就是自己不用写,浏览器会帮我们加上)
        • http => 80
        • https => 443
        • ftp => 21
        • 除这几个在书写的时候可以省略,其余的不能省
    • 请求资源的路径和名称

      • /stu/index.html
        • 一般情况下,如果我们访问的是index.html等,可以省略不写(因为服务端一般会设置index.html为默认文档,当然可以自定义)
      • 伪URL
    • 问号传参部分 ?xxx=xxx

      • 客户端基于GET系列请求,把信息传递会服务器,一般都会基于问号传参的模式
      • 页面之间跳转,信息的一些通信也可以基于问号传参的方式(单页面中组件和组件跳转之间的信息通信,也可能基于问号传参)
      • 关于传递的内容需要进行编码处理(处理特殊字符和中文)
        • encodeURI / decodeURI
        • encodeURIComponent / decodeURIComponent
        • escape / unescape
        • ...
        • encodeURI / decodeURI:只能把空格和中文内容进行编码和解码,所以一般应用这种模式处理整个URL的编码
        • encodeURIComponent / decodeURIComponent:汇报所有的特殊字符和汉字都进行编码,一般不会整个URL编码,只会给传递的每一个参数值单独编码
        • escape / unescape:这种方式不一定所有的后台都有,所以一般只应用于客户端自己内部编码,例如:存储cookie信息,把存储的中文进行编码和解码;特殊符号也会被编码;
    • 设置哈希HASH #xxx

    2.DNS解析

    网站中,每发送一个TCP请求,都要进行DNS解析(一但当前域名解析过一次,浏览器一般会缓存解析记录,缓存时间一般在1分钟左右,后期发送的请求如果还是这个域名,则跳过解析步骤 =>这是一个性能优化点)

    真实项目中,一个大型网站,他要请求的资源是分散到不同的服务器上的(每一个服务器都有自己的一个域名解析)

    • WEB服务器(处理静态资源文件,例如:html/css/js等 的请求)
    • 数据服务器(处理数据请求)
    • 图片服务器 (处理图片请求)
    • 音视频服务器
    • ......
      这样导致,我们需要解析的DNS会有很多次

    优化技巧:DNS Prefetch 即 DNS 预获取
    让页面加载(尤其是后期资源的加载)更顺畅更快一些

    <meta http-equiv="x-dns-prefetch-control" content="on">
    <link rel="dns-prefetch" href="//static.360buyimg.com">
    <link rel="dns-prefetch" href="//misc.360buyimg.com">
    <link rel="dns-prefetch" href="//img10.360buyimg.com">
    <link rel="dns-prefetch" href="//img11.360buyimg.com">
    <link rel="dns-prefetch" href="//img12.360buyimg.com">
    

    3.基于TCP的三次握手,够建客户端和服务器端的连接通道

    只有建立好连接通道,才能基于HTTP等传输协议,实现客户端和服务器端的信息交互

    在这里插入图片描述

    4.发送HTTP请求

    基于HTTP等传输协议,客户端把一些信息传递给服务器

    • HTTP请求报文(所有客户端传递给服务器的内容,统称为请求报文)

      • 谷歌控制台NetWork中可以看到
      • 请求起始行
      • 请求首部(请求头)
      • 请求主体
    • 强缓存 和 协商缓存(性能优化:减少HTTP请求的次数)

      • 强缓存 ( Cache-Control 和 Expires )
      • 协商缓存 ( Last-Modified 和 Etag )

    5.服务器接受到请求,并进行处理,最后把信息返回给客户端

    • HTTP响应报文(所有服务器返回给客户端的内容)
      • 响应起始行
      • 响应首部(响应头)
        • date存储的是服务器的时间
        • ...
      • 响应主体
      • 服务器返回的时候是:先把响应头信息返回,然后继续返回响应主体中的内容(需要的信息大部分都是基于响应主体返回的)

    6.断开TCP链接通道 (四次挥手)

    在这里插入图片描述

    • 当客户端把请求信息发送给服务器的时候,就挥第一次手:客户端告诉服务器端,我已经把请求报文都给你了,你准备关闭吧
    • 第二次挥手:由服务器发起,告诉浏览器,我接收完请求报文,我准备关闭,你也准备吧;
    • 第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完毕,你准备关闭吧;
    • 第四次挥手:由浏览器发起,告诉服务器,我响应报文接收完毕,我准备关闭,你也准备吧;

    Connection: Keep-Alive 保持TCP不中断(性能优化点,减少每一次请求还需要重新建立链接通道的时间)

    7.客户端渲染服务器返回的结果

    二、前端性能优化点

    1. 减少HTTP请求的次数和大小

    • 合并压缩 webpack(代码比较少的情况下,尽可能使用内嵌式)
    • 雪碧图或者图片BASE64
    • 尽量使用字体图标
    • 对于动态获取的图片,采用图片懒加载(数据也做异步分批加载:开始只请求加载第一屏的数据,滑动到第几屏在加载这一屏的数据和图片)
      • 骨架屏技术(首屏内容由服务器渲染;再或者开始展示占位结构,客户端在单独获取数据渲染;)
    • 音视频取消预加载(播放的时候再去加载音视频文件,对于自动播放采取延迟播放的处理)
    • 服务器采用GZIP压缩

    2.建立缓存机制

    把一些请求回来的信息进行本地存储(缓存存储),在缓存有效期内,再次请求资源,直接从缓存中获取数据,而不是服务器上从新拉取

    • DNS预获取
    • 资源文件的强缓存和协商缓存(304)
    • 数据也可以做缓存(把从服务器获取的数据存储到本地:cookie/localStorage/redux/vuex等,设定期限,在期限内,直接从本地获取数据即可)
    • 离线存储(一般很少用)manifest
    • CDN区域分布式服务器开发部署(费钱 效果会非常的好)
    • ....

    3.代码上的优化

    • 减少DOM的重绘和回流
    • 在JS中尽量减少闭包的使用(内存优化)
    • 在JS中避免“嵌套循环”和“死循环”
    • 尽可能使用事件委托
    • 尽量减少CSS表达式的使用(expression)
    • CSS选择器解析规则是从右向左解析(基于less/sass开发的时候尽可能减少层级嵌套,目的是让选择器的前缀短一点) 【 a{} 和 .box a{}】
    • 尽可能实现JS的封装(低耦合高内聚),减少页面中的冗余代码
    • 在CSS导入的时候尽量减少使用@import导入式
    • 使用window.requestAnimationFrame(JS中的帧动画)代替传统的定时器动画(能用CSS3动画的绝对不用JS动画)
    • 减少递归的使用,避免死递归,避免由于递归导致的栈内存嵌套
    • 基于SCRIPT调取JS的时候,可已使用 defer或者async 来异步加载
      ……

    4.安全优化

    5.webpack上的优化

    三、AJAX基础知识

    AJAX:async javascript and xml 异步的JS和XML

    • XML(最早的时候,基于AJAX从服务器获取的数据一般都是XML格式数据,只不过现在基本上都是应用更小巧、更方便操作的JSON格式处理)

      • HTML 超文本标记语言
      • XHTML 严谨的HTML
      • XML 可扩展的标记语言(基于标签结构存储数据)
    • 异步的JS(基于AJAX实现局部刷新)

      • 服务器渲染(一般都是同步:全局刷新) 全靠服务器解析数据和界面,压力大
      • 客户端渲染(一般都是异步:局部刷新)
        在这里插入图片描述
        在这里插入图片描述

    发送AJAX请求有四步操作

    • 1.创建一个XHR对象

      • 不兼容XMLHttpRequest的浏览器使用ActiveXObject创建
    • 2.打开请求连接(配置请求信息)

      • xhr.open([METHOD],[URL],[ASYNC],[USER-NAME],[USE-PASS])
      • [METHOD]请求方式
      • GET系列:从服务器获取 POST系列:向服务器发送信息
      • [ASYNC]是否为异步请求,默认是true,也就是异步,设置为false代表当前请求任务为同步(项目中基本上都采用异步请求)
      • [USER-NAME],[USE-PASS] 向服务器发送请求所携带的用户名密码,只有在服务器设置了安全来宾账号的情况下需要(一般不用)
    • 3.监听请求状态,在不同状态中做不同的事情

    • 4.发送AJAX请求(AJAX任务开始,直到响应主体信息返回[AJAX状态为4]代表当前任务结束)

    GET系列 VS POST系列

    let xhr = new XMLHttpRequest;
    xhr.open('get', './data.json?lx=1&name=zhufeng');
    xhr.send();
    
    xhr = new XMLHttpRequest;
    xhr.open('post', './data.json');
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send('lx=1&name=zhufeng&obj=' + encodeURIComponent(JSON.stringify({
    	name: '哈哈'
    })));
    
    
    xhr = new XMLHttpRequest;
    xhr.open('post', './data.json');
    xhr.setRequestHeader('Content-Type', 'multipart/form-data');
    let formData = new FormData();
    formData.append('lx', 2);
    formData.append('name', 'zhufeng');
    formData.append('obj', {
    	name: '哈哈'
    });
    xhr.send(formData);
    
    • 传递给服务器的数据格式:

      • application/x-www-form-urlencoded:xxx=xxx&xxx=xxx (最常用的方式) 【字符串】
      • multipart/form-data (也很常用,例如:表单提交或者文件上传) 【对象】
      • raw (可以上传text、json、xml、html等格式的文本,富文本编辑器中的内容可以基于这种格式传递)
      • binary (上传二进制数据或者编码格式的数据)
    • GET系列 VS POST系列

      • 不管是哪一种请求方式,客户端都可以把信息传递给服务器,服务器也可以把信息返回给客户端,只不过GET偏向于拿(给的少拿的多),而POST偏向于给(给的多拿的少)
      • [GET系列]:GET / HEAD(只获取响应头的信息,不获取响应主体内容)/
        • DELETE(删除,一般代指删除服务器上指定的文件)
        • OPTIONS(试探性请求,在CROSS跨域请求中,所以正常请求发送前,先发送一个试探请求,验证是否可以和服务器正常的建立连接)
      • [POST系列]:POST / PUT(新增,一般代指向服务器中新增文件)
    • 基于GET向服务器发送请求,传递给服务器的方式:

      • 基于请求头传递给服务器(比如想把本地的Cookie信息传递给服务器)
      • 请求URL地址后面的问号传参(主要方式) xhr.open('get', './data.json?id=2&lx=0')
    • 基于POST向服务器发送请求,传递给服务器的方式:

      • 基于请求头传递给服务器
      • 基于请求主体,把信息传递给服务器(主要方式) xhr.open('post', './data.json'); xhr.send(data);

    get和post的区别

    • GET请求传递给服务器的信息有大小的限制(因为它是基于地址问号传参方式传递信息,而URL有长度的限制:IE浏览器只有2KB大小...);而POST请求理论上是没有大小限制的(实际操作中也都会给予限制);

    • GET请求相对POST请求来说不太安全,也是因为传参是基于地址栏问号传参,会被别人基于URL劫持的方式把信息获取到...所以真实项目中,涉及到安全的信息(例如:密码等)都是基于POST方式传递的(互联网面前人人都在裸奔,没有绝对的安全,我们需要更多的处理安全性)

    • GET请求容易产生缓存,原因还是因为GET是基于问号传参传递信息的,浏览器在每一次获取数据后,一般会缓存一下数据,下一次如果请求的地址和参数和上一次一样,浏览器直接获取缓存中的数据,所以我们基于GET发送请求,需要清除缓存的时候,一般都会在地址栏中添加一个随机数
      xhr.open('get', './data.json?lx=1&name=zhufeng&_='+Math.random())

    • AJAX状态码

      0 =>unset
      1 =>opened
      2 => headers_Received
      3 => loading
      4 => done

    let xhr = new XMLHttpRequest();
    xhr.open("get", "./data.json");
    // xhr.timeout = 100; 设置超时时间
    // xhr.withCredentials=true; 跨域资源共享中,允许携带资源凭证
    // xhr.abort() 强制中断AJAX请求
    // xhr.setRequestHeader() 设置请求头信息(记住:属性值不能是中文和特殊字符)
    xhr.setRequestHeader("name", encodeURIComponent("hello"));
    xhr.onreadystatechange = function () {
      let status = xhr.status,
        state = xhr.readyState,
        result = null;
      if (!/^(2|3)d{2}$/.test(status)) {
        // 错误处理
        return;
      }
      // AJAX状态码为2的时候,响应头信息回来了
      if (state === 2) {
        // 获取响应头信息
        console.log(xhr.getAllResponseHeaders());
        // console.log(xhr.getResponseHeader('date')); //=>获取的服务器日期是格林尼治时间 GMT(比北京时间晚了八个小时 北京时间:GMT+0800)
        console.log(new Date(xhr.getResponseHeader("date"))); //=>转换为北京时间
        return;
      }
      if (state === 4) {
        // 获取响应主体信息  responseText/responseType/responseXML
        result = xhr.response;
        console.log(result);
      }
    };
    xhr.send();
    /* SEND后:首先响应头信息回来  最后响应主体信息再回来 */
    

    HTTP状态码

    • 状态码:AJAX状态码 服务器返回的HTTP网络状态码(代表了服务器返回信息的状态)

      [2开头的基本都是代表成功]
      +200 OK 正常返回数据

      [3开头的一般也是成功了,只不过中间做了一些额外处理]

      • 301 Moved Permanently 永久性转移/重定向 一般应用于网站域名更换,访问老域名,永久都跳转到新的域名上
      • 302 Move Temporarily 临时转移
      • 307 Temporary Redirect 临时重定向 一般应用于服务器的负载均衡
      • 304 Not Modified 读取的是缓存中的数据 这个是客户端和服务器端共建的协商缓存(把不经常更新,请求过的资源文件做缓存,后期在访问这些资源直接走缓存数据,除非服务器端更新了此资源,或者客户端强制清缓存刷新等)

      [4开头的都是失败:失败的原因一般都是客户端的问题]

      • 400 Bad Request 请求参数错误
      • 401 Unauthorized 无权限访问
      • 404 Not Found 地址错误
      • 405 Method Not Allowed 当前请求的方式服务器不支持

      [5开头的都是失败:失败的原因一般都是服务器问题]

      • 500 Internal Server Error 未知服务器错误
      • 503 Service Unavailable 服务器超负荷

    常用的AJAX库(调用起来更方便、操作起来更简单):

    • 以JQ/ZEPTO为主的AJAX库(把AJAX四步操作进行封装、提供了JSONP跨域处理、对于一些常用操作[例如:GET/POST/表单序列化/参数处理等]进行封装处理)

    • 以AXIOS为主的AJAX库(不仅对AJAX进行封装,而且是基于PROMISE进行管理) [最常用的]

    • ES6中新增的内置类Fetch来完成HTTP数据请求(记住:FETCH不是AJAX,他是新的通讯方案;而且默认基于PROMISE进行管理) [很多公司已经开始尝试使用]

    • 跨域请求方案...

    AXIOS

    axios.request({
              // 请求的地址  baseURL:统一基本地址,一般是设置地址的前缀
              url: "./data.json",
              // 请求的方式
              method: "GET",
              // 设置请求头信息
              headers: {
                "Content-Type": "application/x-www-form-urlencoded",
              },
              // GET请求下,问号传参的信息
              params: {},
              // POST请求下,请求主体传参的信息
              data: {},
            })
            .then((result) => {
              // 从服务器获取的结果
              /*
               * config:你自己的配置信息
               * headers:响应头信息
               * request:原生的XHR AJAX对象
               * status:网络状态码
               * statusText
               * data:存储的是响应主体信息
               */
              console.log(result);
            });
    
    • 快捷请求的方法 axios.get/delete/head/post/put... 或者 axios.all
      .get([URL],[OPTIONS])
     axios.get("./data.json", {
            params: {
              lx: 0,
            },
            /* transformResponse: [function (data) {
    				// 把从服务器获取的请求主体信息进行处理,处理完在执行THEN操作
    			}] */
          });
    	  // .get([URL],[DATA],[OPTIONS])  [DATA]是基于请求主体传递的内容
    
     // axios基于请求主体传递给服务器的默认是JSON格式,如果想变为x-www-form-urlencoded格式还需要自己处理
           axios.post('./data.json', {
    			lx: 0,
    			name: 'zhufeng'
    		}, {
    			// 针对于POST系列请求,把传递给服务器请求主体内容进行处理(函数中返回的结果就是最后基于请求主体传递给服务器的内容)
    			transformRequest: [function (data) {
    				// xxx=xxx&xxx=xxx
    				let str = ``;
    				for (let key in data) {
    					if (!data.hasOwnProperty(key)) break;
    					str += `&${key}=${data[key]}`;
    				}
    				str = str.substring(1);
    				return str;
    			}],
    			headers: {
    				'Content-Type': 'application/x-www-form-urlencoded'
    			}
    		}); 
    
  • 相关阅读:
    03014_properties配置文件
    Python 文件I/O
    Python面向对象
    Python CGI编程
    Python正则表达式
    Python使用SMTP发送邮件
    python操作mysql数据库
    Python多线程
    python XML解析
    给傻瓜用的SP2010开发--第一部分--理解SP开发平台--第一章节--理解SP促销讨论(2)--追踪SP源头
  • 原文地址:https://www.cnblogs.com/smilestudio/p/13019272.html
Copyright © 2011-2022 走看看