SSR (server side render)服务端渲染,是指由服务侧(server side)完成页面的DOM结构拼接,然后发送到浏览器,为其绑定状态与事件,成为完全可交互页面的过程。
CSR(client side render)客户端渲染,是指由客户端(client side)JS完成页面和数据的拼接,生成DOM结构再交由浏览器渲染成页面的过程。
DNS 查找数据缓存服务中是否缓存过当前域名信息,有则直接返回;
否则,会进行 DNS 解析返回域名对应的 IP 和端口号,
如果没有指定端口号,http 默认 80 端口,https 默认 443。
DNS协议属于应用层协议,一般是运行在UDP协议之上,使用53端口。
无状态是指服务端无状态是指服务端不会存储每次的会话信息,对于客户端每次发送的请求,都认为它是一个新的请求,上一次会话和下一次会话没有联系。
用SSL/TLS对数据进行加密和解密
SSL的全称是Secure Sockets Layer,即安全 套接 层协议
TLS的全称是Transport Layer Security,即安全 传输 层协议
HTTP标头
在隔开一段时间之后发送几次没有数据内容的网络请求来判断当前连接是不是应该继续保留。
可能会造成大量的无用途连接,白白占用系统资源
如果将资源的最后修改日期Last-Modified<=If-Modified-Since,会 304(Not Modified)
使用了该头部,即为条件请求,若请求标识符==资源的当前标识符,则304
If-None-Match: "d41d8cd98f00b204e9800998ecf8427e"
Content-Length: 123
text/plain:纯文本文件,例如 .txt 文件。
text/html:HTML 文档,用于网页。
text/css:层叠样式表文件,控制网页的样式。
text/xml:XML 数据。
Accept-Encoding: gzip, deflate
Origin: https://www.example.com
Accept-Language: en-US,en;q=0.5
(例如 cookies、HTTP 认证(用户名和密码)等)
Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
session_id=abcd123; Path=/; HttpOnly
Server: Apache/2.4.29 (Ubuntu)
Location: https://www.example.com/new-page
Content-Disposition: attachment; filename="document.pdf"
缓存:
Cache-Control+max-age(HTTP/1.1)>
Expires(
HTTP/1.0)
1.0->1.1(一次传输多个文件,默认Connection: keep-alive)
http1.x解析基于文本,
http2.0采用二进制格式,新增特性 多路复用、header压缩、服务端推送(静态html资源)
HTTP/2和HTTP/3,主要支持 并发处理 和 减少延迟 方面。
服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
//响应拦截器
if (error.response && error.response.status === 302) {
if (window.location.host === 'expenseexternal.xx.cn') {
window.location.href = 'https:///passport-cloud.xxx.cn/login?service=' + encodeURIComponent(window.location.href)
}
}
表示客户端发送了一个带有条件的请求(通常If-Modified-Since或
If-None-Match
)
>
Expires(
1.0)
状态码为灰色的请求则代表使用了强制缓存,请求对应的Size值则代表该缓存存放的位置,分别为from memory cache 和 from disk cache。
如果设成 .example.com,那么子域名 a.example.com 和 b.example.com 都可以使用.example.com 的 cookie;反之不可以。
会话性cookie仅保存在客户端内存中,并在隐私浏览模式中用户关闭 整个 浏览器时失效;
(会话恢复/恢复上次打开的标签页,导致浏览器保留会话信息,包括Session Cookie
迫使服务器为 session 设置了一个失效时间,
当距离客户端上一次使用 session 的时间超过这个失效时间时,
服务器就认为客户端已经停止了活动,才会把 session 删除以节省存储空间)
持久性Cookie会保存在用户的硬盘中(txt ),直至生存期到或用户直接在网页中单击“注销”等按钮结束会话时才会失效
Max-Age:失效时间(单位秒)
为负数,该 cookie 为临时 cookie ,关闭浏览器即失效,
如果为 0,表示删除该 cookie 。默认为 -1。
如果 Max-Age 和 Expires 同时存在,以 Max-Age 为准。
一个站点可以包含多个网页,例如个人博客
"顶级导航" 指的是从一个站点的一个URL跳转到另一个站点的URL,通常是通过点击链接或输入网址来实现的。
删除:expires=new Date(0)
new Date(0)
:970年1月1日UTC时间,0代表的是 Unix 时间戳的起始时间
document.cookie = ‘cookieName=; expires=${new Date(0)}; path=/;’;
基本刷新只是从本地硬盘中重新拿取数据到浏览器
http://www.example.com/user?token=xxx
WebStorage
localStorage
localStorage.setItem('uname','zwq')
localStorage.getItem('uname')
localStorage.key(0)
localStorage.removeItem('uname')
localStorage.clear()
sessionStorage
IndexDB
(运行在浏览器的非关系型数据库) 前端/后端路由
位置:
导航方式:
SEO(搜索引擎优化):
,
当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成。
web worker 是运行在后台的 JavaScript,独立于其他脚本,不会影响页面的性能。
Web Worker 线程无法直接访问 DOM(文档对象模型)元素、操作页面内容,也不能访问浏览器的 Window 和 Document 对象。这是为了防止 Web Worker 影响主页面的交互
index.js:
创建分线程
var w =new webwork('work.js')//创建 Web Worker 对象
向子线程发送数据
w.postmesage('数据')
work.js:
onmessage = function(ev) {
console.log(ev);//接受主线程发送过来的ev.data数据
this.postMessage('数据')//通过 postmesage('数据') 向主线程发送数据
}
通过w.onmessage=function(ev){ev.data} ev.data 接受 a 的值.
w.terminate();//终止 Web Worker
// 在浏览器中,根据其Content-Type头信息,自动转换数据
axios.get('/api/data').then(response => {
// response.data 将是一个JavaScript对象
});
// 在Node.js中手动设置响应数据类型
axios.get('/api/data', { responseType: 'json' }).then(response => {
// response.data 将是一个JavaScript对象
});
window.fetch(url, { method: 'get'}) //fetch() 返回响应的promise
// 第一个then 设置请求的格式
.then(res => return res.json()) // 第一层then返回的是:响应的报文对象
.then((data) => { //第二层:如果想要使用第一层的数据,必须把数据序列化
res.json() 返回的对象是一个 Promise对象再进行then()
}).catch(e => console.log("Oops, error", e))
//什么都不输出
new Promise(()=>{}).then(()=>{
console.log("then")
}).finally(()=>{
console.log("finally")
})
allSettled()
:多个不依赖于彼此成功完成的异步任务时,或者:想知道每个 promise 的结果时all
:当异步操作之间不存在结果的依赖时,all中的所有方法是一同执行的const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');//setTimeout(function[, delay, arg1, arg2, ...]);
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// Expected output: Array [3, 42, "foo"]
catch方法返回的promise实例会被promise.reslove()包裹,这样传进promise.all的数据都是resolved状态的。
let p1 = Promise.resolve(1)
let p2 = Promise.resolve(2)
let p3 = Promise.resolve(3)
let p4 = Promise.resolve(4)
let p5 = Promise.reject("error")
let arr = [p1,p2,p3,p4,p5];
let all = Promise.all(arr.map((promise)=>promise.catch((e)=>{console.log("错误信息"+e)})))
all.then(res=>{console.log(res)}).catch(err=>console.log(err));
Promise.resolve(a)
.then(b => {
// do something
})
.then(c => {
// do something
})
//等价于
async () => {
const a = await Promise.resolve(a);
const b = await Promise.resolve(b);
const c = await Promise.resolve(c);
}
async
关键字+函数async function asyncFunc() {
try {
await new Promise(function (resolve, reject) {
throw "Some error"; // 或者 reject("Some error")
});
} catch (err) {
console.log(err);
// 会输出 Some error
}
}
asyncFunc();
Event Loop执行
setTimeout(_ => console.log(5))
new Promise(resolve => {
resolve()
console.log(1)
}).then(_ => {
console.log(3)
}).finally(_=>{
console.log(4)
})
console.log(2)
// 1 2 3 4 5
http://example.com/page?param1=value1¶m2=value2#section1
JSONP(JSON With Padding)是利用跨域
因为是动态创建script标签,所以它只支持get请求,不支持post请求
正向代理主要是用来解决访问限制问题;
反向代理则是提供负载均衡、安全防护等作用。
前端应用运行在 http://localhost:3000
,跨域访问后端 API ,它运行在 http://localhost:8000
server {
#HTTP 协议来监听请求,应该使用 listen 80;
listen 80;
server_name localhost;
location /api {
proxy_pass http://localhost:8000;
# 允许来自前端应用的跨域请求
add_header 'Access-Control-Allow-Origin' 'http://localhost:3000';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
# 支持 OPTIONS 请求,用于预检请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'http://localhost:3000';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
# 响应预检请求,直接返回 204 No Content
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
}
}
const configStatic = {
proxy: {
'/test': {
target: 'http://www.xx.cn',// 设置目标服务器的地址
changeOrigin: true,
pathRewrite: {
'^/test': '/'
}
}
}
module.exports = configStatic
预检请求是指浏览器在发送跨域请求之前,会先发送一个 OPTIONS 请求,用于询问服务器是否接受实际的请求。
预检请求主要用于对复杂请求(例如包含自定义请求头或使用非简单标头字段的请求)进行安全验证。
条件2:除了被允许的自定义请求头(例如:X-PINGOTHER),请求头仅包含一些简单标头字段,如:Accept、Accept-Language、Content-Language、Content-Type,Range。
其中Content-Type 的值仅限于下列三者之一:
原理:
包装成简单请求,以躲过预检查。但是有些客户端或者代理还是会预检查
安全:
浏览器对于 JSON 响应的默认处理机制是自动将其解析为 JavaScript 对象。
当浏览器接收到响应时,如果响应的 Content-Type 是 application/json 或没有指定 Content-Type,浏览器会自动将响应体解析为 JSON, JavaScript 对象,如果是恶意代码可能会被执行,导致安全漏洞或攻击。
通过将 JSON 响应伪装成 text/plain 类型,可以避免浏览器将响应自动解析为 JavaScript 对象的默认行为。
这样一来,JavaScript 代码需要手动对响应进行解析,确保数据的安全性和正确性。这种伪装可以提供额外的安全层,防止对于响应的自动解析可能带来的安全风险。
//请求头
GET /example HTTP/1.1
Host: example.com
Accept: text/plain
//响应头
HTTP/1.1 200 OK
Content-Type: text/plain
//响应体
{"foo": "bar"}
跨源资源共享(CORS) - HTTP | MDN
Cross-Origin Resource Sharing (CORS) - HTTP | MDN
HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信
WebSocket 和 HTTP 都是应用层协议,都基于 TCP 协议。
WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了
原生WebSocket API使用起来不太方便
Socket.io
,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。
本地文件socket.html向localhost:3000
发生数据和接受数据:
// socket.html
// server.js
let express = require('express');
let app = express();
let WebSocket = require('ws');//记得安装ws
let wss = new WebSocket.Server({port:3000});
wss.on('connection',function(ws) {
ws.on('message', function (data) {
console.log(data);
ws.send('我不爱你')
});
})
解决:
解决:添加验证码、使用token
解决:表单输入时通过正则表达式将一些特殊字符进行转换
解决: