前端网络 webpack axios

228 阅读38分钟

01-初识Webpack打包过程

hs 7/26/2022

# 1. 初识Webpack打包工具

目前前端的开发现状

  • 模块化开发模式
  • 使用高级的特性加快开发效率
  • sass、less等方式优化css编写方式
  • 实时的监听文件的变化,自动刷新浏览器,提高开发效率
  • 项目开发完后,将代码进行压缩、合并以及其他相关的优化

Webpack到底是什么

  • Webpack 是一个模块打包器 (bundler),本身是一个工具
  • 在 Webpack 看来,前端所有的静态资源文件都是模块,如 JS / JSON / CSS / IMG / LESS / FONTS 等等,这些文件都会作为模块来处理。
  • Webpack 会根据模块之间的依赖关系,进行分析打包,生成最终的静态资源。
  • webpack的官方文档是webpack.js.org/
  • webpack的中文官方文档是webpack.docschina.org/

一个真实项目中用到的文件都有哪些

  • JavaScript的打包:

    • 将ES6转换成ES5的语法
    • TypeScript的处理,将其转换成JavaScript
  • CSS的处理:

    • CSS文件模块的加载、提取
    • Less、Sass等预处理器的处理
  • 资源文件img、font:

    • 图片img文件的加载
    • 字体font文件的加载
  • HTML资源的处理: -打包HTML资源文件

  • 处理vue项目的.vue文件;

  • 处理react项目的.jsx文件;

在webpack眼中,一切都是模块,webpack模块打包工具,webpack支持的模块有JS模块,CSS模块,VUE模块,PNG模块,JPG模块.....

# 2. Webpack的安装与零配置打包

Webpack的运行是依赖Node环境的,所以我们电脑上必须有Node环境

  • 需要先安装Node.js,并且同时会安装npm
  • 老师电脑上的node版本是v16.15.1,npm版本是8.11.0(务必保持一样)

安装

  • 在安装webpack时,我们需要同时安装webpack-cli
  • npm install webpack webpack-cli –g # 全局安装
  • npm install webpack webpack-cli –D # 局部安装

零配置打包

  • 默认情况下,不需要做任何配置,都可以打包
  • 通过webpack进行打包,之后通过 webpack 命令运行打包之后的代码
  • 当我们运行webpack时,webpack会查找当前目录下的 src/index.js作为入口
  • 生成一个dist文件夹,里面存放一个main.js的文件,就是我们打包之后的文件
  • 文件中的代码被压缩和丑化了
  • 如果有JS高级语法,webpack也是转化的,也就是默认情况下,webpack只能打包ES6之前的语法
  • 指定入口和出口 webpack --entry ./src/main.js --output-path ./build

依赖图

  • webpack在处理应用程序时,它会根据命令或者配置文件找到入口文件
  • 从入口开始,会生成一个 依赖关系图,这个依赖关系图会包含应用程序中所需的所有模块(比如.js文件、css文件、图片、字体等)
  • 然后遍历图结构,打包一个个模块(根据文件的不同使用不同的loader来解析)

# 3. 局部的webpack

前面我们直接执行webpack命令使用的是全局的webpack,如果希望使用局部的可以按照下面的步骤来操作。但是真实开发中,我们不会使用全局的webpack进行打包,我们都是在当前项目中安装webpack。操作步骤如下:

  • 第一步:通过 npm init 创建package.json文件
  • 第二步:安装局部的webpack npm install webpack webpack-cli -D
  • 第三步:使用局部的webpack npx webpack
  • 第四步:在package.json中创建scripts脚本,执行脚本打包即可 npm run build

# 4. Webpack配置文件

五个核心概念

  • Entry 入口

    • 入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点依赖的
  • Output 出口

    • Output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件
  • Loader 加载器

    • Webpack 默认只能处理 JS / JSON 文件,如果需要打包其他类型文件,就需要使用对应的 loader 进行处理。例如 css-loader,less-loader,file-loader 等等
    • Loader 本质是 JS 函数,接受源文件内容,返回转换后的结果
  • Plugins 插件

    • loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量
  • Mode 模式

    • Webpack 主要有两种工作模式,分别是 development 开发模式和 production 生产模式。

在通常情况下,webpack需要打包的项目是非常复杂的,零配置打包,并不能满足我们的要求,一般我们会在项目的根目录下,创建一个webpack.config.js文件,来作为webpack的配置文件。

当然我们也可以不叫webpack.config.js,如果不是webpack.config.js,那么在使用webpack命令时,必须指令webpack的配置文件

  • npx webpack --config wk.config.js
  • 项目中最常用的是在package.json文件中添加一个脚本,通过npm run build来打包就OK
  • 使用npm run build打出来的包,是直接生成到硬盘上的,叫硬盘打包。也就是说,项目开发完毕,需要使用npm run build在硬盘上打好包,把打好包的代码扔到服务器就OK了,服务器上不能放项目源码。
  • dist 产出代码 可以直接在浏览器中运行,最终项目上线,也是把dist扔到服务器上。

02-Webpack打包常见资源

hs 7/26/2022

# 1. 打包CSS

打包非JS文件,我们需要安装一个loader来处理此文件

  • 打包css时,可以将css文件也看成是一个模块,我们是通过import来加载这个模块的
  • 在加载这个模块时,webpack其实并不知道如何对其进行加载,我们必须制定对应的loader来完成这个功能
  • loader 可以用于对模块的源代码进行转换,对于加载css文件来说,我们需要一个可以读取css文件的loader
  • 使用css-loader来读取css文件,安装:npm install css-loader -D

css-loader的使用方案

  • 内联方式(了解),使用较少,不方便管理

    • 在引入的样式前加上使用的loader,并且使用!分割;
    • import "css-loader!../css/out.css"
  • 配置方式(重点掌握)

loader配置

  • module.rules中允许我们配置多个loader
  • 配置形式管理loader,方便后期的维护,同时也让你对各个Loader有一个全局的概览
  • test属性:用于对 resource(资源)进行匹配的,通常会设置成正则表达式
  • use属性:对应的值时一个数组
  • use: [ 'css-loader' ])是 loader 属性的简写方式(如:use: [ { loader: 'css-loader'} ]

认识style-loader

通过css-loader来加载css文件了, 但是发现这个css在我们的代码中并没有生效(页面没有效果),因为css-loader只是负责将.css文件进行解析,并不会将解析之后的css插入到页面中,我们希望再完成插入style的操作,那么我们还需要另外一个loader,就是style-loader

  • 安装style-loader npm install style-loader -D

配置style-loader

  • 在配置文件中,添加style-loader
  • 因为loader的执行顺序是从右向左(或者说从下到上,或者说从后到前的),所以我们需要将style-loader写到css-loader的前面
  • 重新执行编译npm run build,可以发现打包后的css已经生效了

# 2. 打包Less

在我们开发中,我们可能会使用less、sass、stylus的预处理器来编写css样式,效率会更高

less-loader处理 less文件

  • less-loader需要使用less工具来转化less
  • 安装:npm i less less-loader -D
  • 使用less-loader,来自动使用less工具转换less到css

# 3. PostCSS工具

什么是PostCSS呢

  • PostCSS是一个通过JavaScript来转换样式的工具
  • 这个工具可以帮助我们进行一些CSS的转换和适配,比如自动添加浏览器前缀、css样式的重置
  • 实现这些功能,我们需要借助于PostCSS对应的插件

使用PostCSS

  • 第一步:查找PostCSS在构建工具中的扩展,比如webpack中的postcss-loader
  • 第二步:选择可以添加你需要的PostCSS相关的插件

在webpack中使用postcss就是使用postcss-loader来处理的

  • 安装postcss-loader npm install postcss-loader -D
  • 修改加载css的loader,postcss需要有对应的插件才会起效果,所以我们需要配置它的plugin
  • 安装添加前缀的插件 npm install autoprefixer -D

单独配置文件管理

  • 在根目录下创建postcss.config.js
  • 将这些配置信息放到一个单独的文件中进行管理

postcss-preset-env

  • 在配置postcss-loader时,我们配置插件并不需要使用autoprefixer
  • postcss-preset-env也是一个postcss的插件,将一些现代的CSS特性,转成大多数浏览器认识的CSS,并且会根据目标浏览器或者运行时环境添加所需的polyfill
  • 会自动帮助我们添加autoprefixer(所以相当于已经内置了autoprefixer)
  • 安装:npm install postcss-preset-env -D

# 4. 打包图片

  • 在webpack5之前,加载这些资源我们需要使用一些loader,比如raw-loader 、url-loader、file-loader
  • 在webpack5开始,我们可以直接使用资源模块类型(asset module type),来替代上面的这些loader

资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader

  • asset/resource 发送一个单独的文件并导出 URL,之前通过使用 file-loader 实现;
  • asset/inline 导出一个资源的 data URI,之前通过使用 url-loader 实现;
  • asset/source 导出资源的源代码,之前通过使用 raw-loader 实现
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择,之前通过使用 url-loader,并且配置资源体积限制实现

asset module type的使用

  • 加载图片,我们可以使用下面的方式:
{
    test:/.(png|svg|jpg|jpeg|gif)$/i,
    type:"asset/resource"
}

自定义文件的输出路径和文件名

  • 方式一:修改output,添加assetModuleFilename属性;
  • 方式二:在Rule中,添加一个generator属性,并且设置filename;

最常用的placeholder

  • [ext]: 处理文件的扩展名
  • [name]:处理文件的名称;
  • [hash]:文件的内容,使用MD4的散列函数处理,生成的一个128位的hash值(32个十六进制)

# 5. 资源模块类型的limit

开发中将小的图片进行转换,大的图片直接使用图片

  • 因为小的图片转换base64之后可以和页面一起被请求,减少不必要的请求过程;
  • 大的图片也进行转换,反而会影响页面的请求速度

实现步骤

  • 步骤一:将type修改为asset;
  • 步骤二:添加一个parser属性,并且制定dataUrl的条件,添加maxSize属性;

# 6. babel打包JS高级语法

  • 开发中,我们想要使用ES6+的语法,想要使用TypeScript,开发React项目,它们都是离不开Babel的;
  • 学习Babel对于我们前端开发来说,非常重要

Babel到底是什么

  • Babel是一个工具链,主要用于旧浏览器或者环境中将ECMAScript 2015+代码转换为向后兼容版本的JavaScript;
  • 包括:语法转换、源代码转换等;

Babel命令行使用

  • babel本身可以作为一个独立的工具(和postcss一样),可以单独使用
  • 在命令行尝试使用babel,需要安装如下库
  • @babel/core:babel的核心代码,必须安装, @babel/cli:可以让我们在命令行使用babel
  • npm install @babel/cli @babel/core -D
  • 使用babel来处理我们的源代码
  • npx babel src --out-dir dist

插件的使用

  • 转换箭头函数,那么我们就可以使用箭头函数转换相关的插件
  • npm install @babel/plugin-transform-arrow-functions -D
  • npx babel src --out-dir dist --plugins=@babel/plugin-transform-arrow-functions

let/const转成var

  • 使用 plugin-transform-block-scoping 来进行转化
  • npm install @babel/plugin-transform-block-scoping -D
  • npx babel src --out-dir dist --plugins=@babel/plugin-transform-block-scoping,@babel/plugin-transform-arrow-functions

Babel的预设preset

  • 如果要转换的内容过多,一个个设置是比较麻烦的,我们可以使用预设(preset)
  • 预设说白了,就是插件的集合
  • 安装:npm install @babel/preset-env -D
  • 使用:npx babel src --out-dir dist --presets=@babel/preset-env

babel-loader

  • 在实际开发中,我们通常会在构建工具中通过配置babel来对其进行使用的,比如在webpack中
  • 安装依赖:npm install babel-loader -D (之前已经安装了@babel/core,那么不需要再次安装)
  • 配置规则,在加载js文件时,使用我们的babel

babel-preset

  • 一个个去安装使用插件,那么需要手动来管理大量的babel插件,我们可以直接给webpack提供一个preset,webpack会根据我们的预设来加载对应的插件列表,并且将其传递给babel。
  • 常见的预设有三个:env,react,TypeScript
  • 安装preset-env:npm install @babel/preset-env

# 7. 打包vue代码

要使用vue,需要安装vue

  • npm i vue@next

安装vue-loader, @vue/compiler-sfc

  • npm i vue-loader
  • npm i @vue/compiler-sfc

03-Webpack常见插件

hs 7/26/2022

# 1. 什么是Plugin

Webpack的另一个核心是Plugin

  • Loader是用于特定的模块类型进行转换
  • Plugin可以用于执行更加广泛的任务,比如打包优化、资源管理、环境变量注入等

# 2. CleanWebpackPlugin

每次修改了一些配置,重新打包时,都需要手动删除dist文件夹,可以借助于一个插件来帮助我们完成,这个插件就是CleanWebpackPlugin

  • 安装:npm install clean-webpack-plugin -D

# 3. HtmlWebpackPlugin

  • 我们的HTML文件是编写在根目录下的,而最终打包的dist文件夹中是没有index.html文件的
  • 使用HtmlWebpackPlugin,可以生成一个html文件,并将打包后的js插件到html中
  • 使用HtmlWebpackPlugin,也可以根据模拟生成一个html文件,并将打包后的js插件到html中
  • 安装:npm install html-webpack-plugin -D

在配置HtmlWebpackPlugin时,我们可以添加如下配置

  • template:指定我们要使用的模块所在的路径;
  • title:在进行htmlWebpackPlugin.options.title读取时,就会读到该信息;

# 4. DefinePlugin的介绍

在引入资源时,代码如下:

  • 使用到一个BASE_URL的常量,但是我们并没有设置过这个常量值
  • 这个时候我们可以使用DefinePlugin插件

DefinePlugin的使用

  • DefinePlugin允许在编译时创建配置的全局常量,是一个webpack内置的插件(不需要单独安装)
  • 编译template就可以正确的编译了,会读取到BASE_URL的值

# 5. Mode配置

Mode配置选项,可以告知webpack使用相应模式的内置优化

  • 默认值是production(什么都不设置的情况下)
  • 可选值有:'none' | 'development' | 'production';

Mode配置代表更多

04-搭建本地服务器

hs 7/26/2022

# 1. 为什么要搭建本地服务器

目前我们开发的代码,运行方式

  • npm run build,打包代码,直接双击运行
  • 通过live server或者直接通过浏览器,打开index.html代码

这个过程经常操作会影响我们的开发效率,我们希望可以做到,当文件发生变化时,可以自动的完成 编译 和 展示

# 2. webpack-dev-server

webpack-dev-server 在编译之后不会写入到任何输出文件,而是将 bundle 文件保留在内存中

  • 说白了,就是在内存中打包,使用了一个库叫memfs(memory-fs webpack自己写的)
  • 安装本地开发服务器,安装:npm install webpack-dev-server -D

两个配置

  • 在webpack.config.js中配置devServer
  • 在package.json中配置serve命令

host设置主机地址

  • 默认值是localhost
  • localhost:本质上是一个域名,通常情况下会被解析成127.0.0.1;
  • 127.0.0.1:回环地址(Loop Back Address),表达的意思其实是我们主机自己发出去的包,直接被自己接收;

port、open、compress

  • port设置监听的端口,默认情况下是8080
  • open是否打开浏览器,默认值是false,设置为true会打开浏览器;
  • compress是否为静态文件开启gzip compression,默认值是false,可以设置为true;

# 3. Proxy(后面回头学习)

proxy是我们开发中非常常用的一个配置选项,它的目的设置代理来解决跨域访问的问题:

常见配置

  • target:表示的是代理到的目标地址,比如 /api-hy/moment会被代理到 http://localhost:8888/api-hy/moment;
  • pathRewrite:默认情况下,我们的 /api-hy 也会被写入到URL中,如果希望删除,可以使用pathRewrite;
  • secure:默认情况下不接收转发到https的服务器上,如果希望支持,可以设置为false;
  • changeOrigin:它表示是否更新代理后请求的headers中host地址;

# 4. historyApiFallback(后面回头学习)

historyApiFallback是开发中一个非常常见的属性,它主要的作用是解决SPA页面在路由跳转之后,进行页面刷新时,返回404的错误

  • boolean值:默认是false,如果设置为true,那么在刷新时,返回404错误时,会自动返回 index.html 的内容;
  • object类型的值,可以配置rewrites属性,可以配置from来匹配路径,决定要跳转到哪一个页面;

事实上devServer中实现historyApiFallback功能是通过connect-history-api-fallback库的

# 5. 区分开发环境

目前所有的webpack配置信息都是放到一个配置文件中的:webpack.config.js

  • 当配置越来越多时,这个文件会变得越来越不容易维护
  • 并且某些配置是在开发环境需要使用的,某些配置是在生成环境需要使用的,当然某些配置是在开发和生成环境都会使用的
  • 最好对配置进行划分,方便我们维护和管理;

如何区分

  • 方案一:编写两个不同的配置文件,开发和生成时,分别加载不同的配置文件即可
  • 方式二:使用相同的一个入口配置文件,通过设置参数来区分它们;

创建三个文件:

  • webpack.comm.conf.js
  • webpack.dev.conf.js
  • webpack.prod.conf.js

01-前端网络理论

hs 7/25/2022

# 1. 客户端和服务器

客户端: Client 客户所使用的电脑中安装的应用程序。 服务端: Server 存放网页,客户端程序,数据处理程序,数据库的电脑。

客户端(网页浏览器、网络爬虫或者其它的工具)作用

  • 发起一个HTTP请求到服务器上指定端口(默认端口为80)
  • 我们称这个客户端为用户代理程序(user agent)

服务端作用

  • 响应的服务器上存储着一些资源,比如HTML文件和图像
  • 我们称这个响应服务器为源服务器(origin server)

# 2. 一切要从URI说起

URI

  • Uniform Resource Identifier 统一资源标识符,用来唯一标识一个资源

URL

  • Uniform Resource Locator 统一资源定位符,用来唯一标识一个资源
  • URL也可以用来标识一个资源,而且它还可以指明如何定位资源

URN

  • Uniform Resource Name 统一资源命名 通过名字表示资源

URL肯定是一个URI,URI并不一定是URL,也有可能是URN,URL与URN是URI的子集

  • 你要找WC这个人,WC就是一个URI,URI没有寻找资源的方式
  • 家庭住址 => URL 定位
  • 姓名+身份证号 => URN

对于我们来说,最重要的是URL,它的作用

  • 资源标识
  • 有定位资源的功能
  • 指明了获取资源所采用的协议

URL格式

  • 协议名称 + 主机名称 + 端口号 + 路径 + 文件 + 查询所需的字符串 + HASH
  • http:// baidu.com :80 /01/index.html ?a=1&b=2 #abc
  • scheme:// host port path filename ?query hash

# 3. BS架构和CS架构

BS架构

  • Browser/Server(浏览器/服务器), 利用浏览器去呈现界面,浏览器提供浏览器所需要的数据
  • 优点:无需安装客户端软件,只需要有浏览器,无需升级客户端。
  • 缺点:浏览器的兼容性可能有问题,功能性相对弱一点,安全性弱,交互性弱。

CS架构

  • Client/Server 将应用程序放到一个软件中,可以是Android也可以是iOS,服务器给客户端软件提供它需要的数据。
  • 优点:界面丰富,交互性强,响应速度快,安全性强。
  • 缺点:开发成本高,需要下载安装,维护成本高,升级麻烦。

# 4. 购买云服务器和域名

服务器分类

  • 实体服务器:自己购买服务器。
  • 云服务器:阿里云,华为云,JD云....

域名分类

  • 通用类

    • .com 工商金融企业
    • .com.cn 公司
    • .gov 政府
    • .net 提供互联网网络服务机构
    • .org 各类组织机构
    • .edu 教育机制
  • 国家地区分类

    • .cn 中国
    • .ca 加拿大
    • .uk 英国
    • .jp 日本
  • 域名级别

    • 顶级域名(一级域名) baiu.com 一般我们买的是一级域名,在一级域名下可以配 置N个二级域名
    • 二级域名 zhidao.baidu.com image.baidu.com wenku.baidu.com tieba.baidu.com
    • 三级域名 sport.news.baidu.com
    • www.baidu.com 也是所谓的二级域名

www: world Wide Web 万维网

  • Internet,叫因特网。这个因特网中提供非常多的服务,如www网页服务,ftp文件传输服务,E-mail电子邮件服务,Telnet远程登录服务...,www是浏览器访问网页的服务,所以说,很早之前,所有的网站主页域名前面都会加上www。后来,可以配置二域名和三级域名,不同的域名,就可以对应不同的业务,而业务处理任务会分配到不同的服务器,所以,不再需要使用www来标注主页了。但是加上www,已经成为一种习惯了,所以现在,很多网站都还会做DNS解析www,说到底还是尊重用户习惯。国外的网站基本上都不会使用www。

# 5. DNS解析

DNS:Domain Name Server(域名服务器)

  • 作用:域名与对应的IP转化的服务器
  • DNS中保存了一张域名与对应的IP地址的表,一个域名对应一个IP地址,一个IP地址可以对应多个域名
  • 说白了,根据域名,通过DNS解析就可以得到一个IP 地址。就可以找到对应的服务器

# 6. IP地址和端口号

IP:Internet Protocol Address 互联网协议地址 IP地址

  • 作用:分配给用户上网使用的互联网协议
  • 分类:IPv4 IPv6

根据IP地址,就可以找到对应的服务器,服务器上可以提供N种服务器,你需要哪种服务呢?就需要根据端口号,来区分你需要哪种服务。\

  • 端口号范围:065535 01024是系统使用的 1025~65535之间
  • 知名端口号:http协议下:80 https协议下:443 mysql: 3306 FTP协议下:20 21...

# 7. TCP连接

TCP:transmission Control Protocol 传输控制协议

  • 特点:在收发数据之前,必须建立可靠的连接。TCP就是可靠连接。UDP不可靠连接。
  • 建立连接基础:三次握手
  • 应用场景:HTTP请求(HTTP请求就是基于TCP的),FTP文件传输,邮件发送
  • 优点:速度慢,稳定,重传机制
  • 缺点:效率低,占用资源,容易被攻击

TCP 三次握手理解 (双方确认)(非常重要,面试必问)

  • TCP是一个端到端的 可靠 面相连接的协议
  • HTTP基于传输层TCP协议不用担心数据传输的各种问题(当发生错误时,可以重传)
  • 根据IP,找到对应的服务器,发起TCP的三次握手
为什么要3次握手:

我们假定第一次发送的请求,  因为网络延迟很慢才到达服务端,然后客户端以为这服务器居然不理睬我,然后默默的关闭的等待连接的请求,走开了(好比追女神);但事实呢?女神(服务器)是因为各种各样的原因,很晚才看到,然后说我接受你了, 同意你的要求咱们两结婚吧!但是,A早已经远走高飞,这个请求A完全不会收到(在第二次握手,服务端打开连接,等待客户端的响应),那么女生呢,以为对方收到了,就会一直等待,这样B的资源就会被浪费的(创建连接的时候,空间浪费以及端口消耗);而三次握手, 就不会发生,服务端同意连接了,但是A缺一直没有下一步的动作,导致资源浪费;

关闭TCP连接四次挥手的理解 (客气挽留)

  • 不能直接一次性断开连接(双方知晓), 万一还有什么数据没有传完, 造成数据的丢失!

为什么要4次挥手:

这和有礼貌的好友道别一样:(a:客户端 b:服务端) 1、一开始A想要回家离开,但是呢?怕B还有事情要交代,那么呢?只好先向B打招呼,我要走了,请求停止交谈(请求断开连接),(此时,a到B的连接没有断开,依旧可以进行通信); 2、同意A的请求,说好的,但是我这里可能还有一些话(数据)没说完。我检查看看, 你等等, 等我说完你再走。 3、B确实没啥要补充的了,就告知你我可以撤了 4、A说好的,知道了,88;(B得知A走开了,关闭了自己的连接 )

总结三次握手和四次挥手

建立连接 => 三次握手 (双方确认)
    (1) 服务器啊, 我是浏览器, 我要和你建立连接
    (2) 服务器看到了, 好的, 那么建立连接吧, 我准备好了, 你确定吗?
    (3) 浏览器: 是的, 我确定!
    连接就建立成功,三次握手 = 连接的发起 + 双方的确认

断开连接 => 四次挥手 (客气挽留)
    (1) 一方A发起断开连接的消息
    (2) 另一方B会确认收到断开的需求, 但是会要求等一等, 确认是否数据传输完毕
    (3) B当确认完之后, 确实数据都传完了, 告知A, 连接可以断开了
    (4) A确认收到消息, 告知B, 我要走了

# 8. HTTP的概念(掌握)

HTTP:HyperText Transfer Protocol 超文本传输协议

  • 客户端和与服务器之间传递数据的规范
  • HTTP请求:按照HTTP协议(规则),由客户端(浏览器)向服务器发出请求
  • HTTP响应:按照HTTP协议(规则),由服务器给出响应

HTTPS: HyperText Transfer Protocol Secure 超文本传输安全协议。

  • HTTP的安全版本(安全的基础是SSL/TLS)
  • SSL: Secure Sockets Layer 安全套接层
  • TLS:transport Layer Security 传输层安全
  • 说白了,就是为了网络通信提供的一种安全协议,对网络连接进行加密

HTTP和HTTPS的区别

  • HTTP是不安全 HTTPS可以防止攻击
  • HTTP协议传输的内容是明文,直接在TCP连接上传递,客户端和服务器都无法验证对方的身份
  • HTTPS协议的传输内容都是被SSL/TLS加密,且运行在SSL/TLS,SSL/TLS运行在TCP连接上,所以传递的数据是安全

# 9. HTTP报文(背会)

HTTP是基于TCP通信协议来传递数据。通过一个可靠的连接来交换信息。在交换信息之前,客户端和服务器之间需要有规则。

HTTP通信包含两部分

  • HTTP请求 Request
  • HTTP响应 Response

在HTTP请求和HTTP响应中,都包含了HTTP报文,报文也是一块数据,在客户端与服务器之间发送的数据块。这些报文也是在客户端与服务器之间流行。所以HTTP报文也叫报文流。

HTTP请求报文组成部分

  • 对报文进行描述的起始行
  • HTTP各种头(header),也叫http报文头,不同的头含义是不一样的
  • 请求体(请求正文)(可选的),就是客户端给服务器的数据

HTTP响应报文组成部分

  • 响应行(起始行) HTTP/1.0 200表示状态码 OK叫状态描述符
  • 响应头 header
  • 响应体 服务器给客户端响应的数据

# 10. HTTP协议版本(掌握)

HTTP/0.9

  1. 仅支持GET请求
  2. 仅能请求HTML资源
  3. 发布于1991年

HTTP/1.0

  1. 增加了POST请求和HEAD请求
  2. 支持多种数据格式的请求和访问
  3. 添加了缓存的功能
  4. 增加了状态码,内容编码
  5. 浏览器的每次请求都需要与服务器建立一个TCP连接,请求处理完成后立即断开TCP连接,每次建立连接增加了性能损耗
  6. 也就是说早期的HTTP1.0是不支持长连接(持久化连接)的,只支持串行连接
  7. 后期的HTTP1.0添加了Connection:keep-alive字段,开始支持持久化连接
  8. 发布于1996年

HTTP/1.1(目前使用最广泛的版本)

  1. 采用持久连接(Connection: keep-alive),多个请求可以共用同一个TCP连接
  2. 增加PUT/PATC/OPTION/DELETE等请求方式
  3. 增加了host字段,指定服务器域名
  4. 增加了100状态码,支持只发送头信息
  5. 支持内容传递,只传递一部分和文件断点继传
  6. 发布于1997年;

HTTP/2.0

  1. 增加了双工模式 客户端同时发送N个请求,服务器同时处理N个请求
  2. 服务器推送 服务器可以主动推送数据给客户端
  3. 发布于2015年

# 11. HTTP的请求方式

GET:GET 方法请求一个指定资源的表示形式,使用 GET 的请求应该只被用于获取数据。
HEAD:HEAD 方法请求一个与 GET 请求的响应相同的响应,但没有响应体。比如在准备下载一个文件前,先获取文件的大小,再决定是否进行下载;
POST:POST 方法用于将实体提交到指定的资源。
PUT:PUT 方法用请求有效载荷(payload)替换目标资源的所有当前表示;
DELETE:DELETE 方法删除指定的资源;
PATCH:PATCH 方法用于对资源应部分修改;
CONNECT:CONNECT 方法建立一个到目标资源标识的服务器的隧道,通常用在代理服务器,网页开发很少用到。
TRACE:TRACE 方法沿着到目标资源的路径执行一个消息环回测试。\

在开发中使用最多的是GET、POST请求

GET,POST,PUT,DELETE就是CRUD,就是增删改查。

  • 说是这么说,4种不同的请求方式只是为了清楚不同的请求目的,但是并不代表用post就一定要修改数据,用get并不一定代码去获取数据。

GET和POST

  • GET主要是用来获取数据
  • GET也可以传递数据给服务器,通过查询字符串,就是在URL中把数据扔给服务器
  • POST可以对数据进行添加,删除,修改,数据是放在FormData

GET和POST区别(面试题)

  • post更安全:get请求是把数据放在url,每个人都可以看到,相对来说,不安全。
  • get请求,数据放在url,url的长度是有限,get请求传递给服务器的数据大小是有限的
  • post请求,传递给服务器的数据理论上来说是无限的
  • get请求只能发送ASCII字符数据,post请求能发送更多的数据类型
  • post比get速度慢,post接收数据之前会先将请求头发送给服务器确认,然后发送数据
  • get请求会进行数据缓存,post没有

GET过程

  1. 第三次握手,浏览器确认并发送请求头和数据
  2. 服务器返回200 OK响应

POST过程

  1. 第三次握手,浏览器确认并发送post请求头
  2. 服务器返回状态码100后,continue响应
  3. 浏览器开始扔数据到服务器
  4. 服务器返回200 OK响应

# 12. Request Header

在request对象的header中也包含很多有用的信息,客户端会默认传递过来一些信息

content-type是这次请求携带的数据的类型

  • application/x-www-form-urlencoded:表示数据被编码成以 '&' 分隔的键 - 值对,同时以 '=' 分隔键和值
  • application/json:表示是一个json类型;
  • text/plain:表示是文本类型;
  • application/xml:表示是xml类型;
  • multipart/form-data:表示是上传文件;

content-length

  • 文件的大小长度

keep-alive

  • http是基于TCP协议的,但是通常在进行一次请求和响应结束后会立刻中断

  • 在http1.0中,如果想要继续保持连接

    • 浏览器需要在请求头中添加 connection: keep-alive
    • 服务器需要在响应头中添加 connection:keey-alive
    • 当客户端再次放请求时,就会使用同一个连接,直接一方中断连接
  • 在http1.1中,所有连接默认是 connection: keep-alive的

    • 不同的Web服务器会有不同的保持 keep-alive的时间
    • Node中默认是5s中

accept-encoding

  • 告知服务器,客户端支持的文件压缩格式,比如js文件可以使用gzip编码,对应 .gz文件

accept

  • 告知服务器,客户端可接受文件的格式类型

user-agent

  • 客户端相关的信息

# 13. Response Header

响应的header中包括一些服务器给客户端的信息

# 14. Response响应状态码

  • Http状态码(Http Status Code)是用来表示Http响应状态的数字代码
  • Http状态码非常多,可以根据不同的情况,给客户端返回不同的状态码
  • MDN响应码解析地址:developer.mozilla.org/zh-CN/docs/…

# 15. 同源策略(掌握)

同源策略:Same Origin Policy SOP 是浏览器的策略

  • 同源策略(Same-Origin Policy)最早由 Netscape 公司提出,是浏览器的一种安全策略
  • 规定:只允许两个页面有相同的源时,一个页面才可以去访问另一个页面中的数据。
  • 源:说白了,就是指域名 相同的源指的是有相同的域名
  • 换句话说,jd.com不能去获取taobao.com下面的数据


有一个这样的域名:www.wangcai.com\

总结

  • 源:协议 + 域名 + 端口
  • 同源:相同的协议 && 相同域名 && 相同的端口
  • 不同源:不同的协议 || 不同的域名 || 不同的端口

不受同源策略的限制

  • 资源的引入 如:img标签的src link标签的href script标签的src
  • 页面中的超连接 a标签中的href
  • 表单的提交
  • 重定向页面

01-原生Ajax

hs 7/25/2022

# 1. 原生Ajax

AJAX: 全称为Asynchronous Javascript And XML,就是异步的 JS 和 XML

  • 它可以使用 JSON,XML,HTML 和 text 文本等格式发送和接收数据
  • AJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式

Ajax发送请求的经典步骤

  • 第一步:创建网络请求的AJAX对象(使用XMLHttpRequest)
  • 第二步:监听XMLHttpRequest对象状态的变化,或者监听onload事件(请求完成时触发)
  • 第三步:配置网络请求(通过open方法)
  • 第四步:发送send网络请求

httpbin.org (是一个专门提供:免费测试http服务的网站)

<script>
    // 1.创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()

    // 2.监听状态的改变
    xhr.onreadystatechange = function() {
        if (xhr.readyState !== XMLHttpRequest.DONE) return

        console.log(xhr.response)
    }

    // 3.配置请求open
    xhr.open("get", "http://httpbin.org/get")

    // 4.发送请求(浏览器帮助发送对应请求)
    xhr.send()
</script>

# 2. XMLHttpRequest的state(状态)

在一次网络请求中看到状态发生了很多次变化,这是因为对于一次请求来说包括如下的状态

  • 0       UNSENT       代理被创建,但尚未调用 open() 方法。
  • 1       OPENED       open() 方法已经被调用。
  • 2       HEADERS_RECEIVED       send() 方法已经被调用,并且头部和状态已经可获得。
  • 3       LOADING       下载中, responseText 属性已经包含部分数据。
  • 4       DONE       下载操作已完成。

注意

  • 这个状态并非是HTTP的相应状态,而是记录的XMLHttpRequest对象的状态变化
  • http响应状态通过status获取

# 3. XMLHttpRequest其他事件监听

除了onreadystatechange还有其他的事件可以监听

  • loadstart:请求开始
  • progress: 一个响应数据包到达,此时整个 response body 都在 response 中
  • abort:调用 xhr.abort() 取消了请求
  • error:发生连接错误,例如,域错误。不会发生诸如 404 这类的 HTTP 错误
  • load:请求成功完成,我们也可以使用load来获取数据
  • timeout:由于请求超时而取消了该请求(仅发生在设置了 timeout 的情况下)
  • loadend:在 load,error,timeout 或 abort 之后触发
<script>
    const xhr = new XMLHttpRequest()
    // onload监听数据加载完成
    xhr.onload = function() {
        console.log("onload")
    }
    xhr.open("get", "http://httpbin.org/get")
    xhr.send()
</script>

# 4. 响应数据和响应类型

XMLHttpRequest response 属性返回响应的正文内容

  • 返回的类型取决于responseType的属性设置
  • 通过responseType可以设置获取数据的类型
  • 早期通常服务器返回的数据是普通的文本和XML,所以我们通常会通过responseText、 responseXML来获取响应结果
  • 目前服务器基本返回的都是json数据,直接设置为json即可
 <script>
     const xhr = new XMLHttpRequest()

     xhr.onload = function() {
         // const resJSON = JSON.parse(xhr.response)
         console.log(xhr.response)
         // console.log(xhr.responseText)
         // console.log(xhr.responseXML)
     }

     // 3.告知xhr获取到的数据的类型
     xhr.responseType = "json"
     // xhr.responseType = "xml"

     // 4.配置网络请求
     // 4.1.json类型的接口
     xhr.open("get", "https://httpbin.org/json")
     // 4.2.text类型的接口
     // xhr.open("get", "https://httpbin.org/robots.txt")
     // 4.3.xml类型的接口
     // xhr.open("get", "https://httpbin.org/xml")

     // 5.发送网络请求
     xhr.send()
 </script>

# 5. 响应的状态status

  • XMLHttpRequest的state是用于记录xhr对象本身的状态变化,并非针对于HTTP的网络请求状态
  • 如果我们希望获取HTTP响应的网络状态,可以通过status和statusText来获取

测试接口

# 6. GET/POST请求传递参数

在开发中,我们使用最多的是GET和POST请求,在发送请求的过程中,我们也可以传递给服务器数据

常见的传递给服务器数据的方式有如下几种

  • 方式一:GET请求的query参数
  • 方式二:POST请求 x-www-form-urlencoded 格式
  • 方式三:POST请求 FormData 格式
  • 方式四:POST请求 JSON 格式
<body>
    <form class="info">
        <input type="text" name="username">
        <input type="password" name="password">
    </form>
    <button class="send">发送请求</button>
    <script>
        const formEl = document.querySelector(".info")
        const sendBtn = document.querySelector(".send")
        sendBtn.onclick = function() {
            // 创建xhr对象
            const xhr = new XMLHttpRequest()

            // 监听数据响应
            xhr.onload = function() {
                console.log(xhr.response)
            }

            // 配置请求
            xhr.responseType = "json"

            // 1.传递参数方式一: get -> query
            // xhr.open("get", "http://httpbin.org/get?cityId=404100&keyWord=天河公园")

            // 2.传递参数方式二: post -> urlencoded
            // xhr.open("post", "http://httpbin.org/post")
            // // 发送请求(请求体body)
            // xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
            // xhr.send("name=wc&age=18&address=BJ")

            // 3.传递参数方式三: post -> formdata
            // xhr.open("post", "http://httpbin.org/post")
            // // formElement对象转成FormData对象
            // const formData = new FormData(formEl)
            // xhr.send(formData)

            // 4.传递参数方式四: post -> json
            xhr.open("post", "http://httpbin.org/post")
            xhr.setRequestHeader("Content-type", "application/json")
            xhr.send(JSON.stringify({
                name: "wc",
                age: 18,
                height: 1.88
            }))
        }
    </script>
</body>

# 7. 延迟时间timeout和取消请求

在网络请求的过程中,为了避免过长的时间服务器无法返回数据,通常我们会为请求设置一个超时时间:timeout

  • 当达到超时时间后依然没有获取到数据,那么这个请求会自动被取消掉
  • 默认值为0,表示没有设置超时时间
<button>取消请求</button>
<script>
    // 1.创建XMLHttpRequest对象
    const xhr = new XMLHttpRequest()

    // 2.监听状态的改变
    xhr.onreadystatechange = function() {
        if (xhr.readyState !== XMLHttpRequest.DONE) return

        console.log(xhr.response)
    }

    // 3.配置请求open
    xhr.open("get", "http://httpbin.org/delay/5")

    // 4.发送请求(浏览器帮助发送对应请求)
    xhr.send()

    // 5.设置超时时间
    xhr.timeout = 3000;
    xhr.ontimeout = function() {
        console.log("Ajax request timeout");
    };

    // 6.手动取消结果
    const cancelBtn = document.querySelector("button")
    cancelBtn.onclick = function() {
        xhr.abort()
    }
</script>

# 8. XMLHttpRequest文件上传

文件上传是开发中经常遇到的需求,比如头像上传、照片等

  • 要想真正理解文件上传,必须了解服务器如何处理上传的文件信息;
<body>
    <input class="file" type="file">
    <button class="upload">上传文件</button>
    <script>
        const uploadBtn = document.querySelector(".upload")
        uploadBtn.onclick = function() {
            const xhr = new XMLHttpRequest()
            xhr.onload = function() {
                console.log(xhr.response)
            }

            xhr.onprogress = function(event) {
                console.log(event)
            }

            xhr.responseType = "json"
            xhr.open("post", "文件上传接口")

            const fileEl = document.querySelector(".file")
            const file = fileEl.files[0]

            const formData = new FormData()
            formData.append("avatar", file)

            xhr.send(formData)
        }
    </script>
</body>
# 02-axios

*hs* *7/29/2022*

## [#](https://tubie.gitee.io/fe-blog/network/ajax/02.html#_1-初识axios) 1. 初识axios

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2f8442b918a3489ab6d0f76ad982b0a4~tplv-k3u1fbpfcp-zoom-1.image)

**axios是什么?**

-   前端最流行的ajax请求库
-   react/vue官方都推荐使用axios发ajax请求
-   文档: https://github.com/axios/axios

**功能特点**

-   基于xhr + promise的异步ajax请求库
-   浏览器端/node端都可以使用
-   支持 Promise API
-   拦截请求和响应
-   转换请求和响应数据
-   支持请求取消
-   批量发送多个请求

**axios请求方式**

-   axios(config): 通用/最本质的发任意类型请求的方式
-   axios(url[, config]): 可以只指定url发get请求
-   axios.request(config): 等同于axios(config)
-   axios.get(url[, config]): 发get请求
-   axios.delete(url[, config]): 发delete请求
-   axios.post(url[, data, config]): 发post请求
-   axios.put(url[, data, config]): 发put请求
-   axios.defaults.xxx: 请求的默认全局配置
-   axios.interceptors.request.use(): 添加请求拦截器
-   axios.interceptors.response.use(): 添加响应拦截器
-   axios.create(config): 创建一个新的axios(它没有下面的功能)
-   axios. Cancel(): 用于创建取消请求的错误对象
-   axios. CancelToken(): 用于创建取消请求的token对象
-   axios.isCancel(): 是否是一个取消请求的错误
-   axios.all(promises): 用于批量执行多个异步请求
-   axios.spread(): 用来指定接收所有成功数据的回调函数的方法

**常见的配置选项**

-   请求地址      url: '/user'
-   请求类型      method: 'get'
-   根求路径      baseURL: 'http://www.mt.com/api'
-   请求前的数据处理      transformRequest:function(data){}
-   请求后的数据处理      transformResponse: function(data){}
-   自定义的请求头      headers:{'x-Requested-With':'XMLHttpRequest'}
-   URL查询对象      params:{ id: 12 }
-   查询对象序列化函数      paramsSerializer: function(params){ }
-   request body      data: { key: 'aa'}
-   超时设置      timeout: 1000

**1. 发送request请求**

axios.request({ url: "httpbin.org/get", method: "get" }).then(res => { console.log("res:", res.data) })


**2. 发送get请求**

axios.get(http://httpbin.org/get?id=123456).then(res => { console.log("res:", res) })

axios.get("httpbin.org/get", { params: { id: 123456 } }).then(res => { console.log("res:", res.data.lrc) })


**3. 发送post请求**

axios.post("httpbin.org/post", { name: "wc", password: 123456 }).then(res => { console.log("res", res.data) })

axios.post("httpbin.org/post", { data: { name: "wc", password: 123456 } }).then(res => { console.log("res", res.data) })


**4. 其它**

// 定义baseURL const baseURL = "httpbin.org"

// 给axios实例配置公共的基础配置 axios.defaults.baseURL = baseURL axios.defaults.timeout = 10000 axios.defaults.headers = {}

// 1.get axios.get("/get").then(res => { console.log("res:", res.data) })

// 2.axios发送多个请求 axios.all([ axios.get("httpbin.org/get"), axios.get("httpbin.org/post") ]).then(res => { console.log("res:", res) })


## [#](https://tubie.gitee.io/fe-blog/network/ajax/02.html#_2-axios的创建实例) 2. axios的创建实例

**为什么要创建axios的实例呢**

-   当我们从axios模块中导入对象时, 使用的实例是默认的实例
-   当给该实例设置一些默认配置时, 这些配置就被固定下来了
-   但是后续开发中, 某些配置可能会不太一样
-   比如某些请求需要使用特定的baseURL或者timeout等
-   这个时候, 我们就可以创建新的实例, 并且传入属于该实例的配置信息

**面试题**

-   需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一样, 如何处理
-   解决: 创建2个新axios, 每个都有自己特有的配置, 分别应用到不同要求的接口请求中

**注意点**

-   根据指定配置创建一个新的axios, 也就就每个新axios都有自己的配置
-   新axios只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的

// axios默认库提供给我们的实例对象 axios.get("httpbin.org/get")

// 创建其他的实例发送网络请求 const instance1 = axios.create({ baseURL: "httpbin.org", timeout: 6000, headers: {} })

instance1.get("/get", { params: { id: 123456 } }).then(res => { console.log("res:", res.data) })

const instance2 = axios.create({ baseURL: "httpbin.org", timeout: 10000, headers: {} })


## [#](https://tubie.gitee.io/fe-blog/network/ajax/02.html#_3-请求和响应拦截器) 3. 请求和响应拦截器

**axios的也可以设置拦截器:拦截每次请求和响应**

-   axios.interceptors.request.use(请求成功拦截, 请求失败拦截)
-   axios.interceptors.response.use(响应成功拦截, 响应失败拦截)

拦截器 发送请求 ```

面试题:拦截器函数/ajax请求/请求的回调函数的调用顺序

  • 说明: 调用axios()并不是立即发送ajax请求, 而是需要经历一个较长的流程
  • 流程: 请求拦截器2 => 请求拦截器1 => 发ajax请求 => 响应拦截器1 => 响应拦截器2 => 请求的回调
  • 注意: 此流程是通过promise串连起来的, 请求拦截器传递的是config, 响应拦截器传递的是response

# 4. 取消请求

基本流程

  • 配置cancelToken对象
  • 缓存用于取消请求的cancel函数
  • 在后面特定时机调用cancel函数取消请求
  • 在错误回调中判断如果error是cancel, 做相应处理

实现功能:点击按钮, 取消某个正在请求中的请求

  • 在请求一个接口前, 取消前面一个未完成的请求
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.26.1/axios.js"></script>
</head>

<body>
    <button>发送请求</button>
    <button>取消请求</button>
    <script>
        //获取按钮  代码片段
        let btns = document.querySelectorAll('button');
        //声明外部变量
        let cancel;

        // 绑定事件
        btns[0].onclick = async function() {
            let result = await axios('http://127.0.0.1:8090/test', {
                //2.设置cancelToken属性
                cancelToken: new axios.CancelToken((c) => {
                    cancel = c;
                })
            });
            console.log(result);
        }
        // 取消上面的请求
        cancel();
    </script>
</body>

</html>

# 5. Axios二次封装

功能点

  1. 统一进行请求配置: 基础路径/超时时间等
  2. 请求过程中loading提示
  3. 请求可能需要携带token数据
  4. 请求成功的value不再是response, 而是response.data
  5. 请求失败/出错统一进行处理, 每个请求可以不用单独处理
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Axios二次封装</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/nprogress/0.2.0/nprogress.css">
</head>
<body>
    <div>
        <button onclick="getUsers()">获取用户列表</button>
        <button onclick="getRepos()">获取仓库列表</button>
    </div>
    <!-- 
      测试接口1: https://api.github.com/search/repositories?q=v&sort=stars
      测试接口1: https://api.github.com/search/users?q=v
    -->
    <!--
      1). 统一进行请求配置: 基础路径/超时时间等
      2). 请求过程中loading提示
      3). 请求可能需要携带token数据
      4). 请求成功的value不再是response, 而是response.data
      5). 请求失败/出错统一进行处理, 每个请求可以不用单独处理
    -->

    <script src="https://cdn.bootcss.com/axios/0.19.0/axios.js"></script>
    <script src="https://cdn.bootcss.com/nprogress/0.2.0/nprogress.js"></script>
    <script>
        const instance = axios.create({
            baseURL: 'https://api.github.com',
            timeout: 15000
        })

        instance.interceptors.request.use(config => {
            NProgress.start()
            // 从local中读取前面保存的token数据
            const token = localStorage.getItem('token_key') || 'xxxxx'
            if (token) {
                config.headers['token'] = token // 请求头的名称为后台接口指定
            }

            return config
        })

        instance.interceptors.response.use(
            response => {
                NProgress.done()
                return response.data
            },
            error => {
                NProgress.done()
                alert('请求出错了', error)
                return error
            }
        )
    </script>

    <script>
        function getUsers() {
            instance.get('/search/users', {
                params: {
                    q: 'v'
                }
            }).then(result => {
                console.table(result.items)
            })
        }

        function getRepos() {
            instance.get('/search/repositories', {
                params: {
                    q: 'v',
                    sort: 'stars'
                }
            }).then(result => {
                console.table(result.items)
            })
        }
    </script>
</body>

</html>