diff --git a/.vuepress/header.json b/.vuepress/header.json index 73b90a41..b0c7e59a 100644 --- a/.vuepress/header.json +++ b/.vuepress/header.json @@ -220,11 +220,23 @@ ], [ "http/330", - "如何避免 CDN 为 PC 端缓存移动端页面" + "如何避免 CDN 为 PC 端缓存移动端页面⭐️" ], [ "http/360", "在 node 端如何向服务器上传文件" + ], + [ + "http/363", + "什么情况下会发送 OPTIONS 请求⭐️" + ], + [ + "http/364", + "CORS 如果需要指定多个域名怎么办⭐️" + ], + [ + "http/366", + "既然 cors 配置可以做跨域控制,那可以防止 CSRF 攻击吗 ⭐️" ] ] }, @@ -370,7 +382,7 @@ ], [ "network/135", - "ssh 的原理是什么" + "ssh 的原理是什么⭐️" ], [ "network/174", @@ -387,6 +399,10 @@ [ "network/184", "tcp 中 time_wait 堆积过多会有什么问题,为什么它超时时间这么长" + ], + [ + "network/365", + "localhost 与 127.0.0.1 有什么区别⭐️" ] ] }, @@ -856,6 +872,14 @@ [ "server/353", "如何实现一个 timeout 的中间件" + ], + [ + "server/363", + "什么情况下会发送 OPTIONS 请求⭐️" + ], + [ + "server/368", + "如何获取当前系统中的在线用户数 (并发用户数)⭐️" ] ] }, @@ -938,7 +962,7 @@ ], [ "css/179", - "如何使用 css 写一个有 3D 效果的立方体" + "如何使用 css 写一个有 3D 效果的立方体⭐️" ], [ "css/185", @@ -970,7 +994,7 @@ ], [ "css/308", - "如何实现左右固定,中间自适应布局" + "如何实现左右固定,中间自适应布局⭐️" ], [ "css/309", @@ -978,7 +1002,7 @@ ], [ "css/311", - "简述下 css specificity" + "简述下 css specificity⭐️" ], [ "css/317", @@ -1018,7 +1042,11 @@ ], [ "css/342", - "伪类与伪元素有什么区别" + "伪类与伪元素有什么区别⭐️" + ], + [ + "css/369", + "css 如何匹配前N个子元素及最后N个子元素⭐️" ] ] }, @@ -1047,6 +1075,10 @@ "dom/215", "input 中监听值的变化是在监听什么事件⭐️" ], + [ + "dom/269", + "CSP 是干什么用的了⭐️" + ], [ "dom/286", "prefetch 与 preload 的区别是什么⭐️" @@ -1058,6 +1090,10 @@ [ "dom/315", "在浏览器中如何监听剪切板中内容⭐️" + ], + [ + "dom/367", + "js 动画和 css 动画那个性能比较好" ] ] }, @@ -1259,7 +1295,7 @@ ], [ "js/361", - "js 如何全部替代一个子串为另一个子串" + "js 如何全部替代一个子串为另一个子串⭐️" ] ] }, @@ -1634,7 +1670,7 @@ ], [ "前端工程化/192", - "什么是 Open Graph 协议,用来做什么" + "什么是 Open Graph 协议,用来做什么⭐️" ], [ "前端工程化/193", @@ -1915,6 +1951,10 @@ [ "open/264", "当一个排期五天的任务需要在两天后上线如何解决" + ], + [ + "open/340", + "你做前端有多少时间花在写 css 上" ] ] } diff --git a/Readme.md b/Readme.md index 5a540d01..c9302b39 100644 --- a/Readme.md +++ b/Readme.md @@ -27,6 +27,12 @@ ### [DevOps](https://q.shanyue.tech/devops/) ### [开放式问题](https://q.shanyue.tech/open/) +## 大厂内推 + ++ [阿里-供应链平台事业部-前端-校招/社招](https://q.shanyue.tech/infer/ali-ascp.html) ++ [字节-视频架构组-前端-社招](https://q.shanyue.tech/infer/toutiao-media-arch.html) ++ [腾讯-CSIG智慧零售-前端-社招](https://q.shanyue.tech/infer/tencent-csig.html) + ## 大厂面经 ### 阿里 @@ -53,12 +59,6 @@ 更多面经请转至 [大厂面经大全](https://q.shanyue.tech/interviews/fe.html) -## 大厂内推 - -+ [阿里-供应链平台事业部-前端-校招/社招](https://q.shanyue.tech/infer/ali-ascp.html) -+ [字节-视频架构组-前端-社招](https://q.shanyue.tech/infer/toutiao-media-arch.html) -+ [腾讯-CSIG智慧零售-前端-社招](https://q.shanyue.tech/infer/tencent-csig.html) - ## 大厂内推与大厂面经推送 关注公众号【互联网大厂招聘】,将持续推送大厂的面试经验与大厂的内推,直达招聘负责人或团队负责人 @@ -67,7 +67,7 @@ -如果你想在网站及公众号上发布招聘,请添加我的微信 `shanyue-94`,我将与你在以下几个方面进行讨论,并共同拟定模拟面试题在我公众号上发布招聘信息 +如果你想在网站及公众号上发布招聘,请添加我的微信 `shanyue94`,我将与你在以下几个方面进行讨论,并共同拟定模拟面试题在我公众号上发布招聘信息 1. 业务描述,及其业务发展与前景 1. 职位描述,及其技术侧重于偏向 diff --git a/base/Readme.md b/base/Readme.md index 0a928a5c..8bef2b9a 100644 --- a/base/Readme.md +++ b/base/Readme.md @@ -90,4 +90,8 @@ + [【Q329】什么是一致性哈希,可以解决什么问题](data-structure/332.html) + [【Q343】如何查找地图中某个点两公里内的餐厅](data-structure/346.html) + [【Q344】如何列出所有已合并到 master 的分支并删除](git/347.html) -+ [【Q356】在 node 端如何向服务器上传文件](http/360.html) \ No newline at end of file ++ [【Q356】在 node 端如何向服务器上传文件](http/360.html) ++ [【Q358】什么情况下会发送 OPTIONS 请求](http/363.html) ++ [【Q359】CORS 如果需要指定多个域名怎么办](http/364.html) ++ [【Q360】localhost 与 127.0.0.1 有什么区别](network/365.html) ++ [【Q361】既然 cors 配置可以做跨域控制,那可以防止 CSRF 攻击吗 ](http/366.html) \ No newline at end of file diff --git a/base/http/328.md b/base/http/328.md index 71a9f21e..5d515fb7 100644 --- a/base/http/328.md +++ b/base/http/328.md @@ -12,9 +12,9 @@ - `Access-Control-Allow-Origin` - `Access-Control-Allow-Methods` -- `Access-Control-Expose-Headers` - `Access-Control-Allow-Headers` -- `Access-Control-Max-Age` - `Access-Control-Allow-Credentials` +- `Access-Control-Expose-Headers` +- `Access-Control-Max-Age` 关于如何写一个 `cors` 的中间件可以参考 [koajs/cors](https://github.com/koajs/cors) \ No newline at end of file diff --git a/base/http/330.md b/base/http/330.md index 117322fb..4ea1d2ea 100644 --- a/base/http/330.md +++ b/base/http/330.md @@ -6,5 +6,47 @@ 欢迎在 Issue 中交流与讨论: [Issue 330](https://github.com/shfshanyue/Daily-Question/issues/330) ::: +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +如果 PC 端和移动端是一套代码则不会出现这个问题。**这个问题出现在 PC 端和移动端是两套代码,却共用一个域名。** + +使用 `nginx` 配置如下,根据 UA 判断是否移动端,而走不同的逻辑 (判断UA是否移动端容易出问题) + +``` conf +location / { + // 默认 PC 端 + root /usr/local/website/web; + + # 判断 UA,访问移动端 + if ( $http_user_agent ~* "(Android|webOS|iPhone|iPad|BlackBerry)" ){ + root /usr/local/website/mobile; + } + + index index.html index.htm; +} +``` + +解决方案通常使用 `Vary` 响应头,来控制 CDN 对不同请求头的缓存。 + +**此处可以使用 `Vary: User-Agent` ,代表如果 User-Agent 不一样,则重新发起请求,而非从缓存中读取页面** + +``` txt +Vary: User-Agent +``` + +当然,`User-Agent` 实在过多,此时缓存失效就会过多。 + +## 简答 + +使用 `Vary: User-Agent`,根据 UA 进行缓存。 + +``` txt +Vary: User-Agent +``` +但最好不要出现这种情况,PC 端和移动端如果是两套代码,建议用两个域名,理由如下 +1. `nginx` 判断是否移动端容易出错 +1. 对缓存不友好 diff --git a/base/http/363.md b/base/http/363.md new file mode 100644 index 00000000..a794b355 --- /dev/null +++ b/base/http/363.md @@ -0,0 +1,16 @@ +# 什么情况下会发送 OPTIONS 请求 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 363](https://github.com/shfshanyue/Daily-Question/issues/363) +::: + +::: tip Author +回答者: [hedongxiaoshimei](https://github.com/hedongxiaoshimei) +::: + +[搬运地址](https://blog.csdn.net/kahhy/article/details/81563063) +1:请求的方法不是GET/HEAD/POST +2:POST请求的Content-Type 异常 +3:请求设置了自定义的header字段 diff --git a/base/http/364.md b/base/http/364.md new file mode 100644 index 00000000..bdf27b4d --- /dev/null +++ b/base/http/364.md @@ -0,0 +1,91 @@ +# CORS 如果需要指定多个域名怎么办 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 364](https://github.com/shfshanyue/Daily-Question/issues/364) +::: + +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +`CORS` 通过控制 `Access-Control-Allow-Origin` 控制哪些域名可以共享资源,取值如下 + +``` bash +Access-Control-Allow-Origin: | * +``` + +其中 `*` 代表所有域名,`origin` 代表指定特定域名,那如何设置多个域名了? + +此时需要通过代码实现,**根据请求头中的 `Origin` 来设置响应头 `Access-Control-Allow-Origin`**,那 Origin 又是什么东西? + +## 请求头: Origin + +并不是所有请求都会自动带上 `Origin`,在浏览器中带 `Origin` 的逻辑如下 + +1. 如果存在跨域,则带上 `Origin`,值为当前域名 +1. 如果不存在跨域,则不带 `Origin` + +逻辑理清楚后,关于服务器中对于 `Access-Control-Allow-Origin` 设置多域名的逻辑也很清晰了 + +1. 如果请求头不带有 `Origin`,证明未跨域,则不作任何处理 +1. 如果请求头带有 `Origin`,证明跨域,根据 `Origin` 设置相应的 `Access-Control-Allow-Origin: ` + +使用伪代码实现如下: + +``` js +// 获取 Origin 请求头 +const requestOrigin = ctx.get('Origin'); + +// 如果没有,则跳过 +if (!requestOrigin) { + return await next(); +} + +// 设置响应头 +ctx.set('Access-Control-Allow-Origin', requestOrigin) +``` + +## Vary: Origin + +此时可以给多个域名控制 CORS,但此时假设有两个域名访问 `static.shanyue.tech` 的跨域资源 + +1. `foo.shanyue.tech`,响应头中返回 `Access-Control-Allow-Origin: foo.shanyue.tech` +1. `bar.shanyue.tech`,响应头中返回 `Access-Control-Allow-Origin: bar.shanyue.tech` + +看起来一切正常,但如果中间有缓存怎么办? + +1. `foo.shanyue.tech`,响应头中返回 `Access-Control-Allow-Origin: foo.shanyue.tech`,被 CDN 缓存 +1. **`bar.shanyue.tech`,因由缓存,响应头中返回 `Access-Control-Allow-Origin: foo.shanyue.tech`,跨域出现问题** + +此时,`Vary: Origin` 就上场了,代表为不同的 `Origin` 缓存不同的资源 + +## 总结 (简要答案) + +CORS 如何指定多个域名? + +**根据请求头中的 `Origin` 来设置响应头 `Access-Control-Allow-Origin`**,思路如下 + +1. 总是设置 `Vary: Origin`,避免 CDN 缓存破坏 CORS 配置 +1. 如果请求头不带有 `Origin`,证明未跨域,则不作任何处理 +1. 如果请求头带有 `Origin`,证明浏览器访问跨域,根据 `Origin` 设置相应的 `Access-Control-Allow-Origin: ` + +使用伪代码实现如下 + +``` js +// 获取 Origin 请求头 +const requestOrigin = ctx.get('Origin'); + +ctx.set('Vary', 'Origin') + +// 如果没有,则跳过 +if (!requestOrigin) { + return await next(); +} + +// 设置响应头 +ctx.set('Access-Control-Allow-Origin', requestOrigin) +``` + +> 相关问题:[如何避免 CDN 为 PC 端缓存移动端页面](https://github.com/shfshanyue/Daily-Question/issues/330) \ No newline at end of file diff --git a/base/http/366.md b/base/http/366.md new file mode 100644 index 00000000..8b8b82d0 --- /dev/null +++ b/base/http/366.md @@ -0,0 +1,16 @@ +# 既然 cors 配置可以做跨域控制,那可以防止 CSRF 攻击吗 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 366](https://github.com/shfshanyue/Daily-Question/issues/366) +::: + +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +**对 CORS 一点用也没有** + +1. **`form` 提交不通过 `CORS` 检测**,你可以在本地进行测试 +1. 即使通过 `xhr` 及 `fetch` 进行提交被 CORS 拦住,**但是对于简单请求而言,请求仍被发送**,已造成了攻击 diff --git a/base/http/Readme.md b/base/http/Readme.md index ffa7abd2..d0fe64d3 100644 --- a/base/http/Readme.md +++ b/base/http/Readme.md @@ -31,4 +31,7 @@ + [【Q301】base64 由哪64个字符构成](303.html) + [【Q325】关于 cors 的响应头有哪些](328.html) + [【Q327】如何避免 CDN 为 PC 端缓存移动端页面](330.html) -+ [【Q356】在 node 端如何向服务器上传文件](360.html) \ No newline at end of file ++ [【Q356】在 node 端如何向服务器上传文件](360.html) ++ [【Q358】什么情况下会发送 OPTIONS 请求](363.html) ++ [【Q359】CORS 如果需要指定多个域名怎么办](364.html) ++ [【Q361】既然 cors 配置可以做跨域控制,那可以防止 CSRF 攻击吗 ](366.html) \ No newline at end of file diff --git a/base/linux/4.md b/base/linux/4.md index b1d18be7..6b841672 100644 --- a/base/linux/4.md +++ b/base/linux/4.md @@ -38,6 +38,20 @@ Linux 3.10.0-957.21.3.el7.x86_64 (shanyue) 11/04/19 _x86_64_ 20:47:41 0 3506 0.00 0.00 139940 6984 0.18 vim ``` -当然,也可以使用万能的 `htop` 命令 +`pidstat` 是属于 `sysstat` 下的 linux 性能工具,但在 mac 中,如何定位内存的变化?此时可以使用万能的 `top/htop` -参考: [linux 各项监控指标小记](https://shanyue.tech/op/linux-monitor) \ No newline at end of file + ``` bash + $ htop -p 31796 + ``` + +![image](https://user-images.githubusercontent.com/13389461/86353210-7b210080-bc99-11ea-9885-8e5ca1b909b5.png) + +## 总结 + +简而言之,有以下三个命令 + +1. `pidstat -r` +1. `htop/top -p` +1. `ps -O rss -p` + +关于更多指标的监控可以参考我的文章: [linux 各项监控指标小记](https://shanyue.tech/op/linux-monitor.html) \ No newline at end of file diff --git a/base/linux/71.md b/base/linux/71.md index d1dccbdc..fd9deb46 100644 --- a/base/linux/71.md +++ b/base/linux/71.md @@ -10,12 +10,36 @@ 回答者: [shfshanyue](https://github.com/shfshanyue) ::: -使用 `sed` 或者 `head`/`tail`,以要输出第100行为例 +通常使用 `sed` 命令打印特定行,如 +``` bash +# -n: 按特定格式打印 +# 100p: 指打印第一百行 +$ sed -n 100p Readme.md ``` -sed -n 100p Readme.md -head -100 Readme.md | tail -1 +但 `sed` 打印的本领,远不止于此,除了打印特定行,还可以打印一段范围的行,如 + +``` bash +# 打印文件中第 100-120 行 +$ sed -n 100,120p Readme.md + +# 打印文件中第 100-120 行 +$ sed -n 100,+20p Readme.md +``` + +还有一种本办法,`head`/`tail` 的组合命令,以要输出第100行为例 + +``` bash +# 输出前100行,再通过 pipe,输出最后一行 +$ head -100 Readme.md | tail -1 ``` -关于 `sed` 更多的用法可以参考我的文章: [sed 命令详解及示例](https://shanyue.tech/op/linux-sed.html#sed-%E5%91%BD%E4%BB%A4%E8%AF%A6%E8%A7%A3) \ No newline at end of file +关于 `sed` 更多的用法可以参考我的文章: [sed 命令详解及示例](https://shanyue.tech/op/linux-sed.html) + +## 总结 + +两种方法 + +1. `sed -n 100p Readme.md` +1. `head -100 Readme.md | tail -1` \ No newline at end of file diff --git a/base/network/135.md b/base/network/135.md index ef837298..c1854bc2 100644 --- a/base/network/135.md +++ b/base/network/135.md @@ -6,5 +6,8 @@ 欢迎在 Issue 中交流与讨论: [Issue 135](https://github.com/shfshanyue/Daily-Question/issues/135) ::: +::: tip Author +回答者: [hedongxiaoshimei](https://github.com/hedongxiaoshimei) +::: - +搬运 [图解SSH原理](https://www.jianshu.com/p/33461b619d53) \ No newline at end of file diff --git a/base/network/365.md b/base/network/365.md new file mode 100644 index 00000000..74592bfe --- /dev/null +++ b/base/network/365.md @@ -0,0 +1,15 @@ +# localhost 与 127.0.0.1 有什么区别 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 365](https://github.com/shfshanyue/Daily-Question/issues/365) +::: + +::: tip Author +回答者: [hedongxiaoshimei](https://github.com/hedongxiaoshimei) +::: + +localhost 可以更改后指向其它地址。 +127.0.0.1 是约定的本机IP。 +类似互联网中域名与服务器IP的关系。 \ No newline at end of file diff --git a/base/network/Readme.md b/base/network/Readme.md index 9da64743..64f4d7e4 100644 --- a/base/network/Readme.md +++ b/base/network/Readme.md @@ -11,4 +11,5 @@ + [【Q173】简述 UDP socket 建立的过程](174.html) + [【Q174】TCP 三次握手发生在 socket 建立的哪一步](175.html) + [【Q182】简述 TCP 的四次挥手,三次挥手可以吗](183.html) -+ [【Q183】tcp 中 time_wait 堆积过多会有什么问题,为什么它超时时间这么长](184.html) \ No newline at end of file ++ [【Q183】tcp 中 time_wait 堆积过多会有什么问题,为什么它超时时间这么长](184.html) ++ [【Q360】localhost 与 127.0.0.1 有什么区别](365.html) \ No newline at end of file diff --git a/fe/Readme.md b/fe/Readme.md index 1d6d891e..32182360 100644 --- a/fe/Readme.md +++ b/fe/Readme.md @@ -109,7 +109,7 @@ + [【Q264】当 Node 应用发生 gc 时,如何监控](node/266.html) + [【Q265】Node 应用中如何查看 gc 的日志](node/267.html) + [【Q266】bind 与 call/apply 的区别是什么](js/268.html) -+ [【Q267】CSP 是干什么用的了](js/269.html) ++ [【Q267】CSP 是干什么用的了](dom/269.html) + [【Q268】你如何看待 serverless](前端工程化/270.html) + [【Q269】什么是 XSS 攻击,如何避免](前端工程化/271.html) + [【Q271】react hooks 的原理是什么](react/273.html) @@ -163,4 +163,6 @@ + [【Q354】在 node 中如何判断一个对象是 stream](node/357.html) + [【Q355】什么是 Iterable 对象,与 Array 有什么区别](js/358.html) + [【Q356】在 node 端如何向服务器上传文件](node/360.html) -+ [【Q357】js 如何全部替代一个子串为另一个子串](js/361.html) \ No newline at end of file ++ [【Q357】js 如何全部替代一个子串为另一个子串](js/361.html) ++ [【Q362】js 动画和 css 动画那个性能比较好](dom/367.html) ++ [【Q364】css 如何匹配前N个子元素及最后N个子元素](css/369.html) \ No newline at end of file diff --git a/fe/css/179.md b/fe/css/179.md index ed8699fb..89701f31 100644 --- a/fe/css/179.md +++ b/fe/css/179.md @@ -6,5 +6,89 @@ 欢迎在 Issue 中交流与讨论: [Issue 179](https://github.com/shfshanyue/Daily-Question/issues/179) ::: +::: tip Author +回答者: [lihan1k](https://github.com/lihan1k) +::: + +`
+
1
+
2
+
3
+
4
+
5
+
6
+
` +`* { + margin: 0; + padding: 0; +} + +body { + perspective: none; + perspective-origin: 50% 50%; +} + +.warp { + width: 500px; + height: 500px; + margin: 100px auto; + + position: relative; + + transform-style: preserve-3d; + + transform: rotateX(45deg) rotateY(45deg); + + animation: play 5s linear infinite; +} + +.box { + width: 200px; + height: 200px; + border: 2px solid #ccc; + + text-align: center; + line-height: 200px; + font-size: 150px; + font-weight: bold; + color: #fff; + + position: absolute; + top: 150px; + left: 150px; +} + +.box1 { + background: rgba(135,135,135,.3); + transform: rotateY(90deg) translateZ(100px); +} + +.box2 { + background: rgba(135,0,255,.3); + transform: rotateY(90deg) translateZ(-100px); +} + +.box3 { + background: rgba(255,125,125,.3); + transform: rotateX(90deg) translateZ(-100px); +} + +.box4 { + background: rgba(125,255,125,.3); + transform: rotateX(90deg) translateZ(100px); +} + +.box5 { + background: rgba(30,150,189,.3); + transform: translateZ(100px); +} +.box6 { + background: rgba(169,150,189,.3); + transform: translateZ(-100px); +} +@keyframes play { + from{ transform: rotateX(0) rotateY(0) rotateZ(0);} + to {transform: rotateX(360deg) rotateY(180deg) rotateZ(90deg);} +}` \ No newline at end of file diff --git a/fe/css/18.md b/fe/css/18.md index 6b8eca21..1da84367 100644 --- a/fe/css/18.md +++ b/fe/css/18.md @@ -7,27 +7,61 @@ ::: ::: tip Author -回答者: [zhaochongzi](https://github.com/zhaochongzi) +回答者: [shfshanyue](https://github.com/shfshanyue) ::: -css--- - .box{ - width:100%;; - height:100%; - display:flex; - } - .one{ - width:300px; - height:300px; - background-color: #afa; - } - .two{ - flex:1; - height:300px; - background-color: #ae5aca; - } -html---- -
-
12312313
-
123
-
\ No newline at end of file +使用 `flex` 布局,左侧 `300px`,右侧 `flex-grow: 1`。`pug` 代码及 `css` 代码示例如下 + +``` pug +.container + .left + .main +``` + +``` css +.container { + display: flex; +} + +.left { + flex-basis: 300px; +} + +.main { + flex-grow: 1; +} +``` + +此处看起来比较圆满了,其实还有一个缺陷: **如果 .main 区域过大挤压 .left 区域怎么办**,此时还需要加一个禁止挤压 + +``` css +.left { + flex-basis: 300px; + flex-shrink: 0; +} +``` + +## 总结 + +使用 `flex` 进行如下布局 + +``` pug +.container + .left + .main +``` + +``` css +.container { + display: flex; +} + +.left { + flex-basis: 300px; + flex-shrink: 0; +} + +.main { + flex-grow: 1; +} +``` \ No newline at end of file diff --git a/fe/css/308.md b/fe/css/308.md index a8b2787c..590514ab 100644 --- a/fe/css/308.md +++ b/fe/css/308.md @@ -6,5 +6,36 @@ 欢迎在 Issue 中交流与讨论: [Issue 308](https://github.com/shfshanyue/Daily-Question/issues/308) ::: +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +可以参考 [【Q017】css 如何实现左侧固定300px,右侧自适应的布局](https://github.com/shfshanyue/Daily-Question/issues/18) + + +``` pug +.container + .left + .main + .right +``` + +``` css +.container { + display: flex; +} + +.left { + flex-basis: 300px; + flex-shrink: 0; +} +.right { + flex-basis: 300px; + flex-shrink: 0; +} +.main { + flex-grow: 1; +} +``` \ No newline at end of file diff --git a/fe/css/309.md b/fe/css/309.md index c3fc7689..7518bc08 100644 --- a/fe/css/309.md +++ b/fe/css/309.md @@ -10,7 +10,12 @@ 回答者: [shfshanyue](https://github.com/shfshanyue) ::: -通过 `css3` 中选择器 `:nth-child` 来实现 +通过 `css3` 中伪类 `:nth-child` 来实现。其中 `:nth-child(an+b)` 匹配下标 `{ an + b; n = 0, 1, 2, ...} ` 且结果为整数的子元素 + ++ `nth-child(2n)`/`nth-child(even)`: 双行样式 ++ `nth-child(2n+1)`/`nth-child(odd)`: 单行样式 + +其中 `tr` 在表格中代表行,实现表格中单双行样式就很简单了: ``` css tr:nth-child(2n) { @@ -21,4 +26,9 @@ tr:nth-child(2n) { tr:nth-child(2n+1) { background-color: blue; } -``` \ No newline at end of file +``` + +同理: + +1. 如何匹配最前三个子元素: `:nth-child(-n+3)` +1. 如何匹配最后三个子元素: `:nth-last-child(-n+3)` \ No newline at end of file diff --git a/fe/css/311.md b/fe/css/311.md index 0e469ef3..3770e2e3 100644 --- a/fe/css/311.md +++ b/fe/css/311.md @@ -6,5 +6,18 @@ 欢迎在 Issue 中交流与讨论: [Issue 311](https://github.com/shfshanyue/Daily-Question/issues/311) ::: +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +`css specificity` 即 css 中关于选择器的权重,以下三种类型的选择器依次下降 + +1. `id` 选择器,如 `#app` +1. `class`、`attribute` 与 `pseudo-classes` 选择器,如 `.header`、`[type="radio"]` 与 `:hover` +1. `type` 标签选择器,如 `h1` 和 `p` + +其中通配符选择器 `*`,组合选择器 `+ ~ >`,否定伪类选择器 `:not()` 对优先级无影响 +另有内联样式 `
` 及 `!important`(最高) 具有更高的权重 +> [`:not` 的优先级影响 - codepen](https://codepen.io/shanyue/pen/dyGQqBe) 可以看出 `:not` 对选择器的优先级无任何影响 \ No newline at end of file diff --git a/fe/css/342.md b/fe/css/342.md index 7f8671fa..6ed8417f 100644 --- a/fe/css/342.md +++ b/fe/css/342.md @@ -6,5 +6,11 @@ 欢迎在 Issue 中交流与讨论: [Issue 342](https://github.com/shfshanyue/Daily-Question/issues/342) ::: +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: +1. 伪类使用单冒号,而伪元素使用双冒号。如 `:hover` 是伪类,`::before` 是伪元素 +1 伪元素会在文档流生成一个新的元素,并且可以使用 `content` 属性设置内容 +参考 \ No newline at end of file diff --git a/fe/css/369.md b/fe/css/369.md new file mode 100644 index 00000000..538acebd --- /dev/null +++ b/fe/css/369.md @@ -0,0 +1,16 @@ +# css 如何匹配前N个子元素及最后N个子元素 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 369](https://github.com/shfshanyue/Daily-Question/issues/369) +::: + +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +见 [【Q307】如何实现表格单双行条纹样式](https://github.com/shfshanyue/Daily-Question/issues/309) + ++ 如何匹配最前三个子元素: `:nth-child(-n+3)` ++ 如何匹配最后三个子元素: `:nth-last-child(-n+3)` \ No newline at end of file diff --git a/fe/css/Readme.md b/fe/css/Readme.md index 15fba346..2280cd02 100644 --- a/fe/css/Readme.md +++ b/fe/css/Readme.md @@ -23,4 +23,5 @@ + [【Q335】什么是层叠上下文 (stacking contect),谈谈对它的理解](338.html) + [【Q336】你用 css 实现过什么不错的效果](339.html) + [【Q337】你做前端有多少时间花在写 css 上](340.html) -+ [【Q339】伪类与伪元素有什么区别](342.html) \ No newline at end of file ++ [【Q339】伪类与伪元素有什么区别](342.html) ++ [【Q364】css 如何匹配前N个子元素及最后N个子元素](369.html) \ No newline at end of file diff --git a/fe/dom/269.md b/fe/dom/269.md new file mode 100644 index 00000000..6958ca21 --- /dev/null +++ b/fe/dom/269.md @@ -0,0 +1,17 @@ +# CSP 是干什么用的了 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 269](https://github.com/shfshanyue/Daily-Question/issues/269) +::: + +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +`CSP` 可以最大限度地防止 `XSS` 攻击,它只允许加载指定的脚本及样式等,通过 http 的响应头 `Content Security Policy` 控制。 + +如果网站必须加载内联脚本 (inline script) ,则可以提供一个 `nonce` 才能执行脚本,这样攻击者无法注入脚本进行攻击。 + +可参考阮一峰 [Content Security Policy 入门教程](http://www.ruanyifeng.com/blog/2016/09/csp.html) \ No newline at end of file diff --git a/fe/dom/367.md b/fe/dom/367.md new file mode 100644 index 00000000..e5457156 --- /dev/null +++ b/fe/dom/367.md @@ -0,0 +1,10 @@ +# js 动画和 css 动画那个性能比较好 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 367](https://github.com/shfshanyue/Daily-Question/issues/367) +::: + + + diff --git a/fe/dom/Readme.md b/fe/dom/Readme.md index 64c2a606..948a81cc 100644 --- a/fe/dom/Readme.md +++ b/fe/dom/Readme.md @@ -3,6 +3,8 @@ + [【Q161】如何删除一个 cookie](162.html) + [【Q210】如何判断当前环境时移动端还是PC端](211.html) + [【Q214】input 中监听值的变化是在监听什么事件](215.html) ++ [【Q267】CSP 是干什么用的了](269.html) + [【Q284】prefetch 与 preload 的区别是什么](286.html) + [【Q311】当 cookie 没有设置 maxage 时,cookie 会存在多久](313.html) -+ [【Q313】在浏览器中如何监听剪切板中内容](315.html) \ No newline at end of file ++ [【Q313】在浏览器中如何监听剪切板中内容](315.html) ++ [【Q362】js 动画和 css 动画那个性能比较好](367.html) \ No newline at end of file diff --git a/fe/js/149.md b/fe/js/149.md index 48280bed..bf9101c7 100644 --- a/fe/js/149.md +++ b/fe/js/149.md @@ -22,8 +22,22 @@ console.log(JSON.stringify(obj)) 回答者: [shfshanyue](https://github.com/shfshanyue) ::: +> ``` js +> const obj = { +> a: 3, +> b: 4, +> c: null, +> d: undefined, +> get e () {} +> } +> ``` +> +> console.log(JSON.stringify(obj)) +> +> 输出什么? + ``` js {"a":3,"b":4,"c":null} ``` -对重中的 `null`,`function` 将在 `JSON.stringify` 时会忽略掉 \ No newline at end of file +对其中的 `undefined`,`function` 将在 `JSON.stringify` 时会忽略掉 \ No newline at end of file diff --git a/fe/js/269.md b/fe/js/269.md index c7fc9e39..6958ca21 100644 --- a/fe/js/269.md +++ b/fe/js/269.md @@ -7,7 +7,11 @@ ::: ::: tip Author -回答者: [DoubleRayWang](https://github.com/DoubleRayWang) +回答者: [shfshanyue](https://github.com/shfshanyue) ::: -http://www.ruanyifeng.com/blog/2016/09/csp.html \ No newline at end of file +`CSP` 可以最大限度地防止 `XSS` 攻击,它只允许加载指定的脚本及样式等,通过 http 的响应头 `Content Security Policy` 控制。 + +如果网站必须加载内联脚本 (inline script) ,则可以提供一个 `nonce` 才能执行脚本,这样攻击者无法注入脚本进行攻击。 + +可参考阮一峰 [Content Security Policy 入门教程](http://www.ruanyifeng.com/blog/2016/09/csp.html) \ No newline at end of file diff --git a/fe/js/28.md b/fe/js/28.md index 35ffeb35..62b59bac 100644 --- a/fe/js/28.md +++ b/fe/js/28.md @@ -12,4 +12,63 @@ 回答者: [shfshanyue](https://github.com/shfshanyue) ::: -[fingerprintjs2](https://github.com/Valve/fingerprintjs2) \ No newline at end of file +由于不同的系统显卡绘制 `canvas` 时渲染参数、抗锯齿等算法不同,因此绘制成图片数据的 `CRC` 校验也不一样。 + +``` js +function getCanvasFp () { + const canvas = document.getElementById('canvas') + const ctx = canvas.getContext('2d') + ctx.font = '14px Arial' + ctx.fillStyle = '#ccc' + ctx.fillText('hello, shanyue', 2, 2) + return canvas.toDataURL('image/jpeg') +} +``` + +因此根据 `canvas` 可以获取浏览器指纹信息。 + +1. 绘制 `canvas`,获取 `base64` 的 dataurl +1. 对 dataurl 这个字符串进行 `md5` 摘要计算,得到指纹信息 + +但是对于常见的需求就有成熟的解决方案,若在生产环境使用,可以使用以下库 + ++ [fingerprintjs2](https://github.com/Valve/fingerprintjs2) + +它依据以下信息,获取到浏览器指纹信息,**而这些信息,则成为 `component`** + +1. `canvas` +1. `webgl` +1. `UserAgent` +1. `AudioContext` +1. 对新式 API 的支持程度等 + +``` js +requestIdleCallback(function () { + Fingerprint2.get((components) => { + const values = components.map((component) => component.value) + const fp = Fingerprint2.x64hash128(values.join(''), 31) + }) +}) +``` + +在 `fingerprintjs2` 中,对于 `component` 也有分类 + ++ [browser independent component](https://github.com/Valve/fingerprintjs2/wiki/Browser-independent-components):有些 `component` 同一设备跨浏览器也可以得到相同的值,有些独立浏览器,得到不同的值 ++ [stable component](https://github.com/Valve/fingerprintjs2/wiki/Stable-components): 有些 `component` 刷新后值就会发生变化,称为不稳定组件 + +在实际业务中,可根据业务选择合适的组件 + +``` js +const options = { + excludes: {userAgent: true, language: true} +} +``` + +## 简答 + +根据 `canvas` 可以获取浏览器指纹信息 + +1. 绘制 `canvas`,获取 `base64` 的 dataurl +1. 对 dataurl 这个字符串进行 `md5` 摘要计算,得到指纹信息 + +若在生产环境使用,可以使用 [fingerprintjs2](https://github.com/Valve/fingerprintjs2),根据业务需求,如单设备是否可跨浏览器,以此选择合适的 `component` \ No newline at end of file diff --git a/fe/js/3.md b/fe/js/3.md index c8beca46..7df2c42b 100644 --- a/fe/js/3.md +++ b/fe/js/3.md @@ -7,63 +7,57 @@ ::: ::: tip Author -回答者: [xiaoai7904](https://github.com/xiaoai7904) +回答者: [shfshanyue](https://github.com/shfshanyue) ::: -#### 防抖(debounce) -触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间 - -##### 示例代码 -```javascript - // 防抖函数 - function debounce(fn, wait) { - let timer; - return function() { - let _this = this; - let args = arguments; - if(timer) { clearTimeout(timer) } - timer = setTimeout(function(){ - fn.apply(_this, args) - }, wait); - } - } - // 使用 - window.onresize = debounce(function() {console.log('resize')}, 500) +## 防抖 (debounce) + +防抖,顾名思义,防止抖动,以免把一次事件误认为多次,敲键盘就是一个每天都会接触到的防抖操作。 + +想要了解一个概念,必先了解概念所应用的场景。在 JS 这个世界中,有哪些防抖的场景呢 + +1. 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖 +1. 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖 +1. 文本编辑器实时保存,当无任何更改操作一秒后进行保存 + +代码如下,可以看出来**防抖重在清零 `clearTimeout(timer)`** + +``` js +function debounce (f, wait) { + let timer + return (...args) => { + clearTimeout(timer) + timer = setTimeout(() => { + f(...args) + }, wait) + } +} ``` -#### 节流(throttle) -高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率 -##### 示例代码 - -```javascript - // 方式1: 使用时间戳 - function throttle1(fn, wait) { - let time = 0; - return function() { - let _this = this; - let args = arguments; - let now = Date.now() - if(now - time > wait) { - fn.apply(_this, args); - time = now; - } - } - } - // 方式2: 使用定时器 - function thorttle2(fn, wait) { - let timer; - return function () { - let _this = this; - let args = arguments; - - if(!timer) { - timer = setTimeout(function(){ - timer = null; - fn.apply(_this, args) - }, wait) - } - } - } +## 节流 (throttle) + +节流,顾名思义,控制水的流量。控制事件发生的频率,如控制为1s发生一次,甚至1分钟发生一次。与服务端(server)及网关(gateway)控制的限流 (Rate Limit) 类似。 + +1. `scroll` 事件,每隔一秒计算一次位置信息等 +1. 浏览器播放事件,每个一秒计算一次进度信息等 +1. input 框实时搜索并发送请求展示下拉列表,没隔一秒发送一次请求 (也可做防抖) + +代码如下,可以看出来**节流重在开关锁 `timer=null`** + +``` js +function throttle (f, wait) { + let timer + return (...args) => { + if (timer) { return } + timer = setTimeout(() => { + f(...args) + timer = null + }, wait) + } +} ``` -上面`节流`和`防抖`实现方式比较简单,但是已经可以满足日常使用,如果想更近一步了解可以查看[underscore](https://www.bootcss.com/p/underscore/)和[lodash](https://www.lodashjs.com/docs/latest)文档中`debounce`和`thorttle` \ No newline at end of file +## 总结 (简要答案) + ++ 防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 `clearTimeout` ++ 节流:控制流量,单位时间内事件只能触发一次,如果服务器端的限流即 Rate Limit。代码实现重在开锁关锁 `timer=timeout; timer=null` \ No newline at end of file diff --git a/fe/js/361.md b/fe/js/361.md index c968a53d..ff49ea87 100644 --- a/fe/js/361.md +++ b/fe/js/361.md @@ -1,10 +1,55 @@ # js 如何全部替代一个子串为另一个子串 - +::: tip 更多描述 + 假设有一个字符串 `hello. hello. hello. ` 需要替换为 `AAA`,即把 `hello. ` 替换为 `A` +::: ::: tip Issue 欢迎在 Issue 中交流与讨论: [Issue 361](https://github.com/shfshanyue/Daily-Question/issues/361) ::: +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +如果需要全量替换字符串,可以使用 `String.prototype.replace(re, replacer)`,其中正则表达式需要开启 `global` flag + +``` js +const s = 'foo foo foo' +s.replce(/foo/g, 'bar') +``` + +那如题中,**是否可以使用正则表达式来替代子串** + +答:**不可以,因为使用子串构建正则时,有可能有特殊字符,就有可能出现问题**,如下 + +``` js +// 期待结果: 'AhelloX hello3 ' +> 'hello. helloX hello3 '.replace(new RegExp('hello. ', 'g'), 'A') +< "AAA" +``` + +而在 `javascript` 中替换子串只能使用一种巧妙的办法:`str.split('foo').join('bar')` + +``` js +> 'hello. hello. hello. '.split('hello. ').join('A') +< "AAA" +``` + +真是一个巧(笨)妙(拙)的办法啊!!!!!**大概 TC39 也意识到了一个问题,于是出了一个新的 API**,在 `ESNext` 中 + +``` js +String.prototype.replaceAll() + +'aabbcc'.replaceAll('b', '.'); +// 'aa..cc' +``` + +详细文档在 [String.prototype.replaceAll](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll) + +## 总结(及直接答案) +两种办法 ++ `str.split('foo').join('bar')` ++ `str.replaceAll('foo', 'bar')`,在 `ESNext` 中,目前支持性不好 \ No newline at end of file diff --git "a/fe/\345\211\215\347\253\257\345\267\245\347\250\213\345\214\226/192.md" "b/fe/\345\211\215\347\253\257\345\267\245\347\250\213\345\214\226/192.md" index 2a37600f..f7143a31 100644 --- "a/fe/\345\211\215\347\253\257\345\267\245\347\250\213\345\214\226/192.md" +++ "b/fe/\345\211\215\347\253\257\345\267\245\347\250\213\345\214\226/192.md" @@ -6,5 +6,41 @@ 欢迎在 Issue 中交流与讨论: [Issue 192](https://github.com/shfshanyue/Daily-Question/issues/192) ::: +::: tip Author +回答者: [grace-shi](https://github.com/grace-shi) +::: + +Open Graph 协议可以让任何一个网页集成到社交图谱中。例如,facebook就是一种社交图谱(social graph)。 +一旦一个网页按照该协议进行集成,这个网页就像是社交图谱的一个节点,例如,你的网页集成了open graph协议, +按照协议加入了网页的标题,描述以及图片信息等等,那么你在facebook中分享这个网页的时候,facebook就会按照 +你定义的内容来展示这个网页。 + +这个协议其实很简单,主要是通过在html中加入一些元数据(meta)标签来实现,例如 +在head中加入meta标签,property是以og(open graph)开头, 后面跟着具体属性,content里面是属性的值, +下面这段描述的就是一个类型为 video.movie,标题为 The rock,以及url和图片信息。这个例子就可以当做是 +为 https://www.imdb.com/title/tt0117500/ 实现了Open Graph协议、 + +``` + + +The Rock (1996) + + + + +... + +... + +``` +结论: +这个协议主要是Facebook提出来的,为了更好的展示用户分享的网页的内容,实现这个协议,有助于SEO优化,告诉google该网页有哪些内容,以及关键词等。 +可以快速实现Open Graph协议的工具有: +Wordpress的SEO plugin +使用Facebook的Facebook Page功能 + +Reference: +1. The Open Graph Protocol https://ogp.me/ +2. Open Graph Protocol for Facebook Explained with Examples https://www.optimizesmart.com/how-to-use-open-graph-protocol/ \ No newline at end of file diff --git a/open/Readme.md b/open/Readme.md index 9ebf30c6..46f62008 100644 --- a/open/Readme.md +++ b/open/Readme.md @@ -15,4 +15,5 @@ + [【Q225】你相比去年,有哪些成长](open/226.html) + [【Q227】你如何看待996](open/228.html) + [【Q231】你周末都喜欢做些什么](open/232.html) -+ [【Q262】当一个排期五天的任务需要在两天后上线如何解决](open/264.html) \ No newline at end of file ++ [【Q262】当一个排期五天的任务需要在两天后上线如何解决](open/264.html) ++ [【Q337】你做前端有多少时间花在写 css 上](open/340.html) \ No newline at end of file diff --git a/open/open/340.md b/open/open/340.md new file mode 100644 index 00000000..b21981dd --- /dev/null +++ b/open/open/340.md @@ -0,0 +1,10 @@ +# 你做前端有多少时间花在写 css 上 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 340](https://github.com/shfshanyue/Daily-Question/issues/340) +::: + + + diff --git a/open/open/Readme.md b/open/open/Readme.md index 5fabcfda..dc0f9831 100644 --- a/open/open/Readme.md +++ b/open/open/Readme.md @@ -15,4 +15,5 @@ + [【Q225】你相比去年,有哪些成长](226.html) + [【Q227】你如何看待996](228.html) + [【Q231】你周末都喜欢做些什么](232.html) -+ [【Q262】当一个排期五天的任务需要在两天后上线如何解决](264.html) \ No newline at end of file ++ [【Q262】当一个排期五天的任务需要在两天后上线如何解决](264.html) ++ [【Q337】你做前端有多少时间花在写 css 上](340.html) \ No newline at end of file diff --git a/server/Readme.md b/server/Readme.md index cfeedf34..1a96b3e0 100644 --- a/server/Readme.md +++ b/server/Readme.md @@ -79,4 +79,6 @@ + [【Q342】`A, B` 复合索引时,`A=? and B=?` 与 `B=? and A=?` 效果是否一致](db/345.html) + [【Q345】postgres 中 Index Scan 与 Index Only Scan 有何区别](db/348.html) + [【Q346】Sentry 中 `withScope`,`configureScope` 与 直接 setTags 有何区别](micro-service/349.html) -+ [【Q350】如何实现一个 timeout 的中间件](micro-service/353.html) \ No newline at end of file ++ [【Q350】如何实现一个 timeout 的中间件](micro-service/353.html) ++ [【Q358】什么情况下会发送 OPTIONS 请求](server/363.html) ++ [【Q363】如何获取当前系统中的在线用户数 (并发用户数)](server/368.html) \ No newline at end of file diff --git a/server/server/288.md b/server/server/288.md index 1b0de0e3..f1bfb04c 100644 --- a/server/server/288.md +++ b/server/server/288.md @@ -10,7 +10,14 @@ 回答者: [shfshanyue](https://github.com/shfshanyue) ::: -如果有 `x-forwarded-for` 的请求头,则取其中的第一个 IP,否则取建立连接 socket 的 remoteAddr +**如果有 `x-forwarded-for` 的请求头,则取其中的第一个 IP,否则取建立连接 socket 的 remoteAddr。** + +而 `x-forwarded-for` 基本已成为了基于 proxy 的标准HTTP头,格式如下,可见第一个 IP 代表其真实的 IP,可以参考 MDN [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For) + +``` js +X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178 +X-Forwarded-For: , , +``` 以下是 `koa` 获取 IP 的方法 @@ -33,4 +40,6 @@ } return this[IP]; }, -``` \ No newline at end of file +``` + +参见源码: \ No newline at end of file diff --git a/server/server/328.md b/server/server/328.md index 71a9f21e..5d515fb7 100644 --- a/server/server/328.md +++ b/server/server/328.md @@ -12,9 +12,9 @@ - `Access-Control-Allow-Origin` - `Access-Control-Allow-Methods` -- `Access-Control-Expose-Headers` - `Access-Control-Allow-Headers` -- `Access-Control-Max-Age` - `Access-Control-Allow-Credentials` +- `Access-Control-Expose-Headers` +- `Access-Control-Max-Age` 关于如何写一个 `cors` 的中间件可以参考 [koajs/cors](https://github.com/koajs/cors) \ No newline at end of file diff --git a/server/server/363.md b/server/server/363.md new file mode 100644 index 00000000..a794b355 --- /dev/null +++ b/server/server/363.md @@ -0,0 +1,16 @@ +# 什么情况下会发送 OPTIONS 请求 + + + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 363](https://github.com/shfshanyue/Daily-Question/issues/363) +::: + +::: tip Author +回答者: [hedongxiaoshimei](https://github.com/hedongxiaoshimei) +::: + +[搬运地址](https://blog.csdn.net/kahhy/article/details/81563063) +1:请求的方法不是GET/HEAD/POST +2:POST请求的Content-Type 异常 +3:请求设置了自定义的header字段 diff --git a/server/server/368.md b/server/server/368.md new file mode 100644 index 00000000..0e750c2d --- /dev/null +++ b/server/server/368.md @@ -0,0 +1,16 @@ +# 如何获取当前系统中的在线用户数 (并发用户数) + +::: tip 更多描述 + 一些 SaaS 系统基于 Pricing 的考虑,会限制团队人数及同时在线数,如何实现 +::: + +::: tip Issue + 欢迎在 Issue 中交流与讨论: [Issue 368](https://github.com/shfshanyue/Daily-Question/issues/368) +::: + +::: tip Author +回答者: [shfshanyue](https://github.com/shfshanyue) +::: + +> 一些 SaaS 系统基于 Pricing 的考虑,会限制团队人数及同时在线数,如何实现 + diff --git a/server/server/Readme.md b/server/server/Readme.md index 4a4d70b9..2483eef5 100644 --- a/server/server/Readme.md +++ b/server/server/Readme.md @@ -16,4 +16,6 @@ + [【Q260】如何实现单点登录](262.html) + [【Q286】在服务端应用中如何获得客户端 IP](288.html) + [【Q325】关于 cors 的响应头有哪些](328.html) -+ [【Q350】如何实现一个 timeout 的中间件](353.html) \ No newline at end of file ++ [【Q350】如何实现一个 timeout 的中间件](353.html) ++ [【Q358】什么情况下会发送 OPTIONS 请求](363.html) ++ [【Q363】如何获取当前系统中的在线用户数 (并发用户数)](368.html) \ No newline at end of file diff --git a/weekly/Readme.md b/weekly/Readme.md index 615ffaef..258502c9 100644 --- a/weekly/Readme.md +++ b/weekly/Readme.md @@ -265,7 +265,7 @@ + [【Q264】当 Node 应用发生 gc 时,如何监控](../fe/node/266.html) + [【Q265】Node 应用中如何查看 gc 的日志](../fe/node/267.html) + [【Q266】bind 与 call/apply 的区别是什么](../fe/js/268.html) -+ [【Q267】CSP 是干什么用的了](../fe/js/269.html) ++ [【Q267】CSP 是干什么用的了](../fe/dom/269.html) + [【Q268】你如何看待 serverless](../fe/前端工程化/270.html) + [【Q269】什么是 XSS 攻击,如何避免](../fe/前端工程化/271.html) + [【Q270】一张员工表,一个字段代表它的上级,如何查询该员工的所有上级](../server/db/272.html) @@ -355,4 +355,11 @@ + [【Q354】在 node 中如何判断一个对象是 stream](../fe/node/357.html) + [【Q355】什么是 Iterable 对象,与 Array 有什么区别](../fe/js/358.html) + [【Q356】在 node 端如何向服务器上传文件](../base/http/360.html) -+ [【Q357】js 如何全部替代一个子串为另一个子串](../fe/js/361.html) \ No newline at end of file ++ [【Q357】js 如何全部替代一个子串为另一个子串](../fe/js/361.html) ++ [【Q358】什么情况下会发送 OPTIONS 请求](../base/http/363.html) ++ [【Q359】CORS 如果需要指定多个域名怎么办](../base/http/364.html) ++ [【Q360】localhost 与 127.0.0.1 有什么区别](../base/network/365.html) ++ [【Q361】既然 cors 配置可以做跨域控制,那可以防止 CSRF 攻击吗 ](../base/http/366.html) ++ [【Q362】js 动画和 css 动画那个性能比较好](../fe/dom/367.html) ++ [【Q363】如何获取当前系统中的在线用户数 (并发用户数)](../server/server/368.html) ++ [【Q364】css 如何匹配前N个子元素及最后N个子元素](../fe/css/369.html) \ No newline at end of file