diff --git a/douyin/http-cache.md b/douyin/http-cache.md index c0aec1f..0da2949 100644 --- a/douyin/http-cache.md +++ b/douyin/http-cache.md @@ -15,3 +15,11 @@ max-age 可设置强缓存时间周期,在该周期内,将直接从客户端 它每次发送请求时,需要进行缓存新鲜度校验,如果资源过旧,将直接从响应中获取,否则从客户端缓存中进行获取。 新鲜度校验,通过请求头 If-None-Match 与响应头 ETag 进行对比,或者请求头 If-Modified-Since 与响应头 Last-Modifed 进行对比。 + +一般来说,我们对经构建工具打包后,带有 hash 的资源进行一年的强缓存。 + +而对不带 hash 的资源进行协商缓存控制,注意协商缓存需配置 Cache-Control 为 max-age=0,或者 no-cache。 + +否则一个没有设置 Cache-Control 的静态资源,将会根据 Date 与 Last-Modified,计算出强缓存时间。 + +我们可以通过谷歌浏览器中开发者工具中的网络面板,查看其 Javascript、CSS 等资源的响应头,来确认是否配置了正确的缓存策略。 diff --git a/douyin/minify.md b/douyin/minify.md index e2ac289..e6a4479 100644 --- a/douyin/minify.md +++ b/douyin/minify.md @@ -39,6 +39,16 @@ function f(a,b){return a+b}console.log(f(3,4)) console.log(7) ``` +terser 是 js 中专业的代码压缩工具,在 webpack 中可使用 `terser-webpack-plugin` 进行代码压缩。 + +我们可以在 Terser REPL 中在线尝试压缩代码。 + +哦对,在测试环境中用以调试随便打的 console.log,出现在生产环境中是不不太好。 + +很多同学也将去除生产环境中的 console.log 写在简历上。 + +这仅仅需要对 terser 添加一个配置项 drop_console 即可完成。 + ## 纯文字 大家好,我是山月。 @@ -58,3 +68,13 @@ console.log(7) 我们开启代码压缩的神奇魔法,在编译期对代码进行预计算。 经优化,代码最终仅有 14 个字节。 + +terser 是 js 中专业的代码压缩工具,在 webpack 中可使用 terser-webpack-plugin 进行代码压缩。 + +我们可以在 Terser REPL 中在线尝试压缩代码。 + +哦对,在测试环境中用以调试随便打的 console.log,出现在生产环境中是不不太好。 + +很多同学也将去除生产环境中的 console.log 写在简历上。 + +这仅仅需要对 terser 添加一个配置项 drop_console 即可完成。 diff --git a/frontend-engineering/deploy/ci-env.md b/frontend-engineering/deploy/ci-env.md index 2e6a11e..9a6536f 100644 --- a/frontend-engineering/deploy/ci-env.md +++ b/frontend-engineering/deploy/ci-env.md @@ -110,6 +110,8 @@ $ CI=true npm run test $ CI=true npm run build ``` +::: v-pre + ## 写段 CI 验证下 CI 中的环境变量 ![](https://cdn.jsdelivr.net/gh/shfshanyue/assets/2022-01-11/clipboard-9125.9b3a8e.webp) @@ -158,3 +160,5 @@ jobs: ## 小结 关于 CI 中的环境变量介绍就到此了,下篇文章将介绍功能分支的 Preview。 + +::: \ No newline at end of file diff --git a/frontend-engineering/deploy/simple-intro.md b/frontend-engineering/deploy/simple-intro.md index d5c117f..0e78f90 100644 --- a/frontend-engineering/deploy/simple-intro.md +++ b/frontend-engineering/deploy/simple-intro.md @@ -1,10 +1,14 @@ -# 关于前端部署的简单理解 +# 手写最简静态资源服务器 在所有人入门编程及学习更多编程语言时,敲下的第一行代码是: 输出 `hello, world`。 -初学如何部署前端,如同学习编程一样,第一步先根据最简单页面进行部署。 +``` js +console.log('hello, world') +``` + +初学部署前端,如同学习编程一样,第一步先根据最简单页面进行部署。 -比如本系列专栏,先部署一个最简单 HTML 如下所示,只有几行代码,我称它为**hello 版前端应用**。 +比如本系列专栏,先部署一个最简单 HTML 如下所示,只有几行代码,无任何 CSS/Javascript 代码,我称它为**hello 版前端应用**。 ``` html @@ -21,11 +25,20 @@ > PS: 本文以 [simple-deploy](https://github.com/shfshanyue/simple-deploy) 仓库作为实践 +我们将带着两个疑问,一步一步了解前端部署: + +1. 如何手写一个简单的静态资源服务器用以部署前端 +1. 为何需要 nginx、docker 等工具辅助前端部署 + ## HTTP 报文 -部署可看做对 HTTP 资源的服务,或者说,是对 HTTP 请求报文的响应。我们写一段服务器代码用以返回 HTML,便完成了对前端的部署。 +HTTP 是在互联网中进行数据交互的协议,你可从互联网中拿到文档、图片、音频及视频各种资源。 + +而最简部署可看做,你向服务器发送一个获取 HTML 资源的请求,而服务端将响应一段 HTML 资源。我们在请求资源的过程中将发送一段请求报文(Request Message),而服务端返回的 HTML 资源为响应报文(Response Message)。 -以下是对*hello版前端应用*的一段简单的 HTTP 请求及响应报文。 +我们写一段服务器代码,在 HTTP 响应报文中设置响应体为 HTML,便完成了对前端的部署。 + +以下是对**hello版前端应用**的真实的 HTTP 请求及响应报文。 > 通过 `curl -vvv localhost:3000` 可获得报文信息。 @@ -54,13 +67,34 @@ Keep-Alive: timeout=5 ``` +以下是对**hello版前端应用**的 HTTP 请求及响应报文的图文表示 + ![](https://cdn.jsdelivr.net/gh/shfshanyue/assets/2022-02-24/simple-deploy.67a117.webp) -## 一段简单的服务器部署代码 +好,那接下来我们写一段服务器代码,用以响应 HTML。 + +## 手写简单静态资源服务器: 响应字符串 + +作为前端,以我们最为熟悉的 Node 为例,写一段最简单的前端部署服务。该服务监听本地的 3000 端口,并在响应体返回我们的**hello 版前端应用**。 + +为求简单,我们直接将**hello 版前端应用**以字符串的形式进行响应。 -作为前端,以我们最为熟悉的 Node 为例,写一段最简单的前端部署服务。 +在 Node 中写服务端最重要的内置模块(`builtinModule`)为 [node:http](https://nodejs.org/api/http.html),通过 `node:` 前缀,可指明其为内置模块,被称作 `Protocol Import`。从而避免了 node 内置模块与第三方模块的命名冲突。 -该服务监听本地的 3000 端口,并返回我们的*hello 版前端应用*。 +``` js +const http = require('node:http') +``` + +通过 `http.createServer` 可对外提供 HTTP 服务,而 `res.end()` 可设置 HTTP 报文的响应体。以下是一段 hello 版本的 nodejs 服务。 + +``` js +const server = http.createServer((req, res) => res.end('hello, world')) +server.listen(3000, () => { + console.log('Listening 3000') +}) +``` + +我们将**hello 版前端应用**以字符串的方式在代码中进行维护,并通过 `res.end()` 设置其为响应报文的响应体。最终代码如下。 > PS: 该段服务器 nodejs 代码位于 [simple-deploy/server.js](https://github.com/shfshanyue/simple-deploy/blob/master/server.js) @@ -84,19 +118,36 @@ server.listen(3000, () => { }) ``` -启动服务,并在浏览器端打开 `localhost:3000`,可看见 `hello, shanyue`。 +通过 `node server.js` 启动服务,成功运行。 + +``` bash +$ node server.js +Listening 3000 +``` + +启动服务后,在浏览器端打开 `localhost:3000`,可查看到响应头及响应体 `hello, shanyue`。 ![](https://cdn.jsdelivr.net/gh/shfshanyue/assets/2021-12-31/clipboard-3621.529aef.webp) **恭喜你,部署成功!** -但是前端静态资源总是以文件的形式出现,我们对代码进一步优化。 +但是前端静态资源总是以文件的形式出现,我们需对代码进一步优化。 -## 一段稍微复杂的服务器代码: 文件系统 +## 手写简单静态资源服务器: 响应文件 + +当然,部署前端作为**纯静态资源**,需要我们使用文件系统(file system)去读取资源并将数据返回。 + +在代码中,html 以前以字符串形式进行维护,现在将其置于文件系统中的 `index.html` 中,并通过 nodejs 中文件系统读取文件的相关 API `fs.readFileSync('./index.html')` 进行获取文件内容,代码如下。 + +``` js +// fs 为内置模块, +const fs = require('node:fs') -当然,部署前端作为**纯静态资源**,需要我们使用文件系统(fs)去读取资源并将数据返回。 +// 通过 fs.readFileSync 可读取文件内容 +const html = fs.readFileSync('./index.html') +``` -在代码中,html 以前是个字符串,现在通过 nodejs 文件系统读取文件的相关 API `fs.readFileSync('./index.html')` 进行获取,代码如下。 +我们将**hello 版前端应用**以文件系统的方式进行维护,并通过 `res.end()` 设置其为响应报文的响应体。最终代码如下。 > PS: 该段服务器 nodejs 代码位于 [simple-deploy/server-fs.js](https://github.com/shfshanyue/simple-deploy/blob/master/server-fs.js) @@ -113,9 +164,16 @@ server.listen(3000, () => { }) ``` -当然,对于前端这类纯静态资源,**自己写代码无论从开发效率还是性能而言都是极差的**。 +接下来启动代码,成功运行。 + +``` bash +$ node server-fs.js +Listening 3000 +``` + +当然,对于前端这类纯静态资源,**自己写代码无论从开发效率还是性能而言都是极差的**,这也是我们为何要求助于专业工具 nginx 之类进行静态资源服务的原因所在。 -比如将文件系统修改为 `ReadStream` 的形式将会提升该静态服务器的性能,代码如下。 +比如将文件系统修改为 `ReadStream` 的形式进行响应将会提升该静态服务器的性能,代码如下。 ```js const server = http.createServer((req, res) => { @@ -130,58 +188,62 @@ const server = http.createServer((req, res) => { $ npx serve . ``` -在 create-react-app 构建成功后,它会提示使用 `serve` 进行部署。 +`serve` 是 `next.js` 的母公司 `vercel` 开发的一款静态资源服务器。作为前端久负盛名的静态服务器,广泛应用在现代前端开发中,如在 `create-react-app` 构建成功后,它会提示使用 `serve` 进行部署。本地环境而言,还是 [serve](https://github.com/vercel/serve) 要方便很多啊。 ![Creact React APP 构建后,提示使用 serve 进行部署](https://cdn.jsdelivr.net/gh/shfshanyue/assets/2021-12-31/clipboard-3980.619061.webp) **然而,Javascript 的性能毕竟有限,使用 `nginx` 作为静态资源服务器拥有更高的性能。** -但是对于本地环境而言,还是 [serve](https://github.com/vercel/serve) 要方便很多啊。 - ## 部署的简单理解 -那什么是部署呢,为什么说你刚才部署成功? +通过以上两个最简服务的成功运行,可以使我们更加深入的了解前端部署。我们再回头看,什么是部署呢,为什么说你刚才部署成功? + +假设此时你有一台拥有公共 IP 地址的服务器,在这台服务器使用 `nodejs` 运行刚才的代码,则外网的人可通过 `IP:3000` 访问该页面。那这可理解为部署,使得所有人都可以访问。 -假设此时你有一台拥有公共 IP 地址的服务器,在这台服务器使用 `nodejs` 运行刚才的代码,则外网的人可通过 `IP:3000` 访问该页面。 +假设你将该服务器作为你的工作环境,通过 `npm start` 运行代码并通过,所有人都可访问他,即可视为部署成功。看来你离所有人都可访问的部署只差一台拥有公共 IP 的服务器。 -那这可理解为部署,使得所有人都可以访问。 +实际上,有极少数小微企业在生产环境中就是直接 ssh 进生产环境服务器,并通过 `npm start` 部署成功后,通过 IP 与端口号的方式进行访问。当然通过 IP 地址访问的项目一般也非公开项目,如果公开使用域名的话,则用 nginx 配置域名加一层反向代理。 -假设你将该服务器作为你的工作环境,通过 `npm run start` 运行代码并通过,所有人都可访问他,部署成功。看来你离所有人都可访问的部署只差一台拥有公共 IP 的服务器。 +**不管怎么说,你现在已经可以通过裸机(宿主机)部署一个简单的前端应用了。** -不管怎么说,你现在已经可以通过裸机(宿主机)部署一个简单的前端应用了。 +## 关于部署的更多疑问解答 -## 一些疑问 +我们现在已经可以在本地跑起服务了,但是在生产环境部署为什么还需要 nginx,甚至 docker 呢? -*问: 那既然通过 `npm start` 可以启动服务并暴露端口对外提供五福,那为什么还需要 nginx 呢?* +接下来,我回应一些关于前端部署的更多疑问。 -**你需要管理诸多服务(比如A网站、B网站),通过 nginx 进行路由转发至不同的服务,这也就是反向代理**,另外 nginx 还可以提供 TLS、HTTP2 等功能。 +*一问: 那既然通过 `npm start` 可以启动服务并暴露端口对外提供服务,那为什么还需要 nginx 呢?* + +**你需要管理诸多服务(比如A网站、B网站),通过 nginx 进行路由转发至不同的服务,这也就是反向代理**,另外 TLS、GZIP、HTTP2 等诸多功能,也需要使用 nginx 进行配置。 当然,如果你不介意别人通过端口号去访问你的应用,不用 nginx 等反向代理器也是可以的。 ![反向代理](https://cdn.jsdelivr.net/gh/shfshanyue/assets/2022-02-24/Nginx.632fa5.webp) -*问: 我确实不介意别人通过 IP:Port 的方式来访问我的应用,那在服务器可以 npm run dev 部署吗?* +*二问: 我确实不介意别人通过 IP:Port 的方式来访问我的应用,那在服务器可以 npm run dev 部署吗?* -可以,但是非常不推荐。`npm run dev` 往往需要监听文件变更并重启服务,此处需要消耗较大的内存及CPU等性能。 +**可以,但是非常不推荐**。`npm run dev` 往往需要监听文件变更并重启服务,此处需要消耗较大的内存及CPU等性能。 针对 Typescript 写的后端服务器,不推荐在服务器中直接使用 `ts-node` 而需要事先编译的理由同样如此。 当然,如果你也不介意性能问题也是可以的。 -*问: 那为什么需要 Docker 部署?* +*三问: 那为什么需要 Docker 部署?* 用以隔离环境。 -假设你有三个后端服务,分别用 Java、Go、Node 编写,你需要在服务器分别安装三者的环境,非常麻烦。 +假设你有三个后端服务,分别用 Java、Go、Node 编写,你需要在服务器分别安装三者的环境,才能运行所有语言编写的代码,这对于开发者而言非常麻烦。 -假设你有三个 Node 服务,分别用 node10、node12、node14 编写,你需要在服务器分别安装三个版本 nodejs,非常麻烦。 +假设你有三个 Node 服务,分别用 node10、node12、node14 编写,你需要在服务器分别安装三个版本 nodejs 才能运行各个版本 nodejs 编写的代码,对于开发者而言也非常麻烦。 -而有了 Docker,就没有这种问题。 +而有了 Docker,就没有这种问题,它可单独提供某种语言的运行环境,并同时与宿主机隔离起来。 对于前端而言,此时你可以通过由自己在项目中单独维护 `nginx.conf` 进行一些 nginx 的配置,大大提升前端的自由性和灵活度,而无需通过运维或者后端来进行。 ## 小结 -本篇文章介绍了了一些对于前端部署的简单介绍,并使用 nodejs 写了两段代码用以提供静态服务,来加深理解。 +本篇文章介绍了了一些对于前端部署的简单介绍,并使用 nodejs 写了两段代码用以提供静态服务,加深对前端部署的理解。虽然我们可自写代码对前端静态资源进行部署,但从功能性与性能而讲,都是远不如专业工具的。 + +在本文章,将应用在本地或者宿主机进行成功运行,但是现代流行的前端部署方案,都是使用 docker 对前端进行部署。 而在下篇文章中,我们将介绍如何使用 Docker 将仅有十几行代码的 **hello 版前端应用** 跑起来。 diff --git a/post/10000.md b/post/10000.md new file mode 100644 index 0000000..8c2bb9c --- /dev/null +++ b/post/10000.md @@ -0,0 +1,23 @@ +哔哩哔哩粉丝突破一万,前端面试重启! + +大家好,我是山月。 + +就在今天愚人节的凌晨零点零三分,我的哔哩哔哩粉丝数达到了一万。从截图可以看出,十二月底打破千粉大关,三个月增长了九千粉丝。 + +![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9c17b5054a9d4287aaa8c8f2a1975d10~tplv-k3u1fbpfcp-watermark.image?) + +接下来,准备了一些一分钟即可讲完的前端小知识,将被我放在合集《前端一分钟》。 + +![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/015e1bc474d044c393c320c0a224b10f~tplv-k3u1fbpfcp-watermark.image?) + +我在三月份上半月的朋友圈宣布暂时停止模拟面试一段落。但是,由于得到了珠峰架构的独家赞助,模拟面试得以继续。关于珠峰架构的这个 logo,将会在我模拟面试时挂在直播间右下角。 + +![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/48cb3b182a884a17b455af769ee55645~tplv-k3u1fbpfcp-watermark.image?) + +我的模拟面试一个月将会进行十次,感兴趣的同学可以添加我的微信 `shanyue-bot` 来报名了,如果报名超过十个,将会做进一步筛选。 + +如果不会写简历,可以在我的公众号后来回复简历二字,获取我简单做的简历内容模板。 + +哦对,我昨天刚在院里种了两排蜀葵,希望能发芽。 + +![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0ab5bdbfdb12497384309e431ad0396b~tplv-k3u1fbpfcp-watermark.image?) \ No newline at end of file diff --git a/post/gitee.md b/post/gitee.md new file mode 100644 index 0000000..4caaf61 --- /dev/null +++ b/post/gitee.md @@ -0,0 +1,85 @@ +# 突发Gitee 防盗链,图片在外站打不开 + +今天下午,群内及朋友圈内有小伙伴反映: **Gitee 图床中的图片打不开** + +![image.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2c0d911e47404cbaac02349ffbb187c0~tplv-k3u1fbpfcp-watermark.image?) + +在本文中,我以 `https://gitee.com/Topcvan/js-notes-img/raw/master/%E5%AE%8F%E4%BB%BB%E5%8A%A1%E9%98%9F%E5%88%97.png` 这个图片为例,重现下事发过程。 + +## 防盗链 + +我一想,这肯定是突加了防盗链,来看一看防盗链的原理: + +**Referer 指当前请求页面的来源页面的地址,用以判断当前页面的访问源。图片防盗链通过判断 `Referer` 是否目标网站而对图片替换为禁止标志的图片。** + +> Referer 实际上是单词 `referrer` 的错误拼写 + +比如,这次 gitee 事件中,gitee 网站上所有图片加载时,浏览器会默认给图片添加上一个请求头: `referer: https://gitee.com/`。而在其它网站,携带的 referer 请求头字段并非 gitee 的网站,则会返回一个占位符图片。 + +**但是,一般来说,防盗链图片在浏览器图片能够直接打开,因为在浏览器直接打开,不会携带 `referer` 请求头字段,防盗链配置会对此放行。** + +如果是这样,如果在个人网站上,可**通过 [Referrer Policy](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Referrer-Policy) 配置所有图片请求时不带 `Referer` 请求头字段来跨过防盗链设置**。 + +![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/786b24bc83c04aefae5add24c47e9416~tplv-k3u1fbpfcp-watermark.image?) + +``` html + +``` + +为此,我专门做了两个网页,根据已经设置了防盗链的 mdnice 网址图片,对照了一番: + ++ 添加了该头,成功绕过了防盗链设置: https://vercel-api.shanyue.vercel.app/referrer ++ 没添加该头,图片被 403 禁止访问: https://vercel-api.shanyue.vercel.app/referrer/forbidden.html + +![403](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6b5f4a7261ee4920b22b58ca6a21ee61~tplv-k3u1fbpfcp-watermark.image?) + +哦对,此时打开两个网址的时候,记得**在浏览器控制台禁止缓存**:(PS: 加一个 Vary: referer 禁止这类问题多好) + +![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0f8eae6bab49447ea9bbb6d2474ec6c3~tplv-k3u1fbpfcp-watermark.image?) + +然而,这对于 gitee 却没有用! + +## gitee 的防盗链措施 + +但是,gitee 设置的防盗链措施更为严格: + +**在 gitee 中的图片,如果没有携带 referer 也会进行防盗链处理** + +为此,我根据 `referer` 字段做了一个对照试验。 + +通过 cURL **直接请求图片地址,无任何内容返回**: + +``` bash +$ curl 'https://gitee.com/Topcvan/js-notes-img/raw/master/%E5%AE%8F%E4%BB%BB%E5%8A%A1%E9%98%9F%E5%88%97.png' \ + --compressed +``` + +通过 cURL 直接请求图片地址,并**携带上 `referer` 字段,有内容并正确返回**: + +``` bash +$ curl 'https://gitee.com/Topcvan/js-notes-img/raw/master/%E5%AE%8F%E4%BB%BB%E5%8A%A1%E9%98%9F%E5%88%97.png' \ + -H 'Referer: https://gitee.com/' \ + --compressed +Warning: Binary output can mess up your terminal. Use "--output -" to tell +Warning: curl to output it to your terminal anyway, or consider "--output +Warning: " to save to a file. +``` + +截图如下: + +![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a7961f75f84a418289caeed5b4f6ed95~tplv-k3u1fbpfcp-watermark.image?) + +直接在官网中替换某个 img 的 src 为个人的 gitee 图片地址,正常打开: + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b4d1324afd4d4a45967786314224abba~tplv-k3u1fbpfcp-watermark.image?) + +## 评价 + +按理来说,防盗链也是为了避免网站中图片等资源被大量盗用,而造成极大的一笔服务器费用。但是 gitee 拥有更好的做法: + +1. 提前一个月进行通知,平滑过渡,也不会造成如此之大的反响 +2. 防盗链策略过于严格,在浏览器都无法直接打开图片 + +**哪怕像掘金这样,在右下角加一个自己的水印呢!** + +![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e1d2ec87380447d080ab974e3e37ce06~tplv-k3u1fbpfcp-watermark.image?) diff --git a/post/oc.md b/post/oc.md new file mode 100644 index 0000000..b086de1 --- /dev/null +++ b/post/oc.md @@ -0,0 +1,70 @@ +大家好,我是山月。 + +昨天有一位同学私信我说,通过我在哔哩哔哩的模拟面试系列视频拿到了字节跳动的 **OC**。 + +我一想,`OC` 是什么意思,我一肚子狐疑,但又不好说我不知道让别人觉得我孤陋寡闻。都来感谢我了,肯定是个好事,我先恭喜恭喜总不会有错的。 + +事后,我查了一下万能的百度! + +![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/32cfc830a5974555a50bd559acc34045~tplv-k3u1fbpfcp-watermark.image?) + +啥都没有,肯定是我搜索姿势有问题,程序员要用 Google 搜索! + +![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aa8fba25f8334afdaffeb4783672e354~tplv-k3u1fbpfcp-watermark.image?) + +好吧,还是啥都没有。 + +我猜测估计和 offer 有关,那我就和 offer 关键词一起进行搜索。 + +![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/95acdf7132ba44b1a44e0260e3fa2692~tplv-k3u1fbpfcp-watermark.image?) + +这下终于有了线索。顺藤摸瓜,在 [HC、JD、OC 是啥...求职、工作过程中可能遇到的英文缩略语整理](https://zhuanlan.zhihu.com/p/149051616) 我找到了它的最终释义! + +> OC (Offer Call),当企业决定录用你时,会打电话发 Offer,并询问你是否接受。一般 OC 也称为「开奖」。 + +大概就是口头 offer 的意思吧。 + +除此之外,还有 + ++ HC (Head Count),招聘名额 ++ JD(Job Description),工作职责描述 ++ BG(Business Group),事业群。如微信事业群,WeiXin Group,简称WXG ++ BU(Business Unit),业务线 ++ PR(Public Relationship),公关 ++ PM(Product Manager/Project Manager),产品经理或项目经理 ++ OD (Outsourcing Dispatcher),外包,比如华为的外包 + +曾几何时,我对这些互联网专业术语一窍不通,而现在已了然在胸。 + +今天的互联网黑话,你学会了吗?你对这些英文单词缩写词汇怎么看呢? + +![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a441e120c25e41b6b7f1775f954f518f~tplv-k3u1fbpfcp-watermark.image?) + +英文缩写学会了,那就再看看一些中文词汇吧! + +二字动词: + +复盘,赋能,沉淀,倒逼,落地,串联,协同,反晡,兼容,包装,重组,履约,晌应,量化,发力,布局,联动,细分,梳理,输出,加速,共建,支撑,融合,聚合,集成,对齐,对标,对焦,抓手,拆解,拉通,抽象,摸索,提炼,打通,打透,吃透,迁移,分发,分层,分装,穿梭,辐射,围绕,复用,渗透,扩展,开拓。 + +二字名词: + +漏斗,中台,闭环,打法,拉通,纽带,矩阵,刺激,规模,场景,聚焦,维度,格局,形态,生态,话术,体系,认知,玩法,体感,感知,调性,心智,战役,合力,心力。 + + + + +--- + +更多关于山月的文章: + +1. [我的专栏《前端工程化三十八讲》免费发布了,附视频讲解、代码示例](https://mp.weixin.qq.com/s/u4-AzPc7bmwi2f6oUCBNmQ) +1. [三分钟讲解什么是 corejs](https://mp.weixin.qq.com/s/ATM1Je1cYkJa6v6cgRD9rA) +1. [Javascript 体积优化时的代码压缩原理是什么](https://mp.weixin.qq.com/s/BcryGbaFLs4R-c8fFE3p5Q) +1. [简述 Javascript 的模块化方案](https://mp.weixin.qq.com/s/F-U4YP42QY9n1GSsTzX34w) +1. [什么是 CICD](https://mp.weixin.qq.com/s/fzBYqEp1sB-iAEiTlOQ9WA) + +--- + +欢迎扫码添加山月的微信,备注进群,加入山月的前端面试交流群: + + diff --git a/post/processon.md b/post/processon.md new file mode 100644 index 0000000..b2c465a --- /dev/null +++ b/post/processon.md @@ -0,0 +1,23 @@ +# 你们都在用什么思维导图软件画图? + +大家好,我是山月。 + +我在之前做了一个关于前端面试题的网站,[大厂面试每日一题](https://q.shanyue.tech/)。 + +![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9a849a881d994ce580727ec53a8de894~tplv-k3u1fbpfcp-watermark.image?) + +同时,计划将其中的高频面试题,构建成**前端面试路线图**,并绘制成思维导图,供广大网友参考。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/915f4ed9bf824612bcb18938be747ded~tplv-k3u1fbpfcp-watermark.image?) + +于是,我调研了诸多思维导图软件,xmind、processon、语雀等等。最终决定使用了 processon 作为目标工具,因为它组织方便,也不像 xmind 那样需要收费。 + +你们用哪一款思维导图软件呢? + +以下是我最近刚使用 [processon](https://processon.com/?utm_source=hulianwang) 做的两个思维导图,后续对前端面试的所有思维导图补全一下。 + +![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ab822a8909934cc08de2b55a5e58e99d~tplv-k3u1fbpfcp-watermark.image?) + +对 processon 感兴趣的可以在以下地址尝试一下: + + \ No newline at end of file diff --git a/post/zero-to-learn-node.md b/post/zero-to-learn-node.md index c8867c4..ad00e7b 100644 --- a/post/zero-to-learn-node.md +++ b/post/zero-to-learn-node.md @@ -1,9 +1,109 @@ -## Node +# 零基础可操作的 Node 入门学习指南 -## 插曲: glob +1. 如何开始学习 Node? +2. Node 有哪些重要的内置模块需要重点学习? +3. 哪些源码可以推荐阅读? +4. 有没有路线图(Roadmap)可以进行系统学习? -## 插曲: braces +## 如何开始学习 Node? + +**根据公司的需求学习 node.js,在需求中进行学习,时间充分,成长快,事半功倍。** + +我们来看一看 nodejs 扮演的最重要的两个角色: + +1. 前端工具链 +2. Server + +而对于前端,接触最多的便是基于 Node 的前端工具,比如 webpack、rollup、vite、eslint、prettier、create-react-app、create-vue 等。因此这里先说下**前端工具链**这部分。 + +而这部分,最容易在工作中获得需求,如**构建一个脚手架**,也容易作为自己的 KPI/OKR。通过此,可获得 node 关于 **文件系统**、**终端操作** 一系列知识。 + +如果业务中不需要构建一个脚手架,那也有诸多的场景需要写一个脚本,其中涉及最多的也是文件系统。 + +比如,在详细了解并完成一个脚手架后,你至少可以了解一个问题? + +**如何判断文件是否存在?** + +再往下看,你会发现有很多关于文件系统的第三方包,他们是做什么的? + ++ [mkdirp](https://github.com/isaacs/node-mkdirp#readme): 什么是 `mkdir -p`,你自己实现会如何实现,如何设计 API?(当然这个在 node 10+ 已经原生实现,不过你仍然可以看看源码的实现) ++ [fs-extra](https://npm.devtool.tech/fs-extra): 你会发现很多脚手架都使用了 `fs-extra`,它又比原生的 `fs` 多了什么功能呢? ++ [fs-events](https://npm.devtool.tech/fsevents): 为什么不使用原生的 `fs.watch` 监听文件变化呢,监听文件变化的底层操作系统原理又是什么呢? ++ [graceful-fs](https://npm.devtool.tech/graceful-fs): 它为什么比原生的 `fs` 更加友好 (graceful) + + +继续深入,你会发现,一个东西叫 Glob,一个叫 Braces,它们又是啥?最后你发现,原来它们和语言无关,在终端就可以直接使用。 + +### glob + ++ `ls -lah *.js` + +### braces + Set: `{x,y,z}` + Sequence: `{1..10}` + Step: `{1..10..2}` + +## Node 有哪些重要的内置模块需要重点学习? + +好吧,假设这个大前提是,**我想要使用 Node 作为服务器端来使用,那我应该重点学习哪些重要模块?** + +那最重要的一个就是: + ++ `http` + +非常重要但是不那么紧急的有: + ++ `stream` ++ `buffer` ++ `net` + +这几个模块十分重要,但是学习起来非常枯燥。可参照我的示例代码 [node-native](https://github.com/shfshanyue/node-examples/tree/master/node-native) 进行学习。 + +最终也可以思考一个问题? + +**我需要考虑多少边界条件才能正确读取到 Request Body 呢?** 可以参考 [raw-body](https://github.com/stream-utils/raw-body) + +## 哪些源码可以推荐阅读? + ++ [lru-cache](https://github.com/isaacs/node-lru-cache): LRU Cache,前端及服务端框架中的常用依赖。 ++ [tsdx](https://github.com/formium/tsdx): 零配置的 npm 库开发利器,与 CRA 相似,不过它主要面向库开发者而非业务开发者,了解它是如何提供零配置功能,看懂默认配置做了那些优化,并了解它的所有工具链 (prettier、eslint、size、bundleanalyzer、rollup、typescript、storybook)。 ++ [create-react-app](https://github.com/facebook/create-react-app): React 最广泛的脚手架,读懂三点。一,如何生成脚手架;二,如何实现 eject;三,了解 cra 的所有重要依赖,读懂默认 webpack 配置。 ++ [axios](https://github.com/axios/axios): 请求库,了解它是如何封装源码且如何实现拦截器的。 ++ [koa](https://github.com/koajs/koa) ++ [body-parser](https://github.com/stream-utils/raw-body): express 甚至是大部分服务端框架所依赖的用以解析 body 的库 ++ [next](https://github.com/vercel/next.js) ++ [ws](https://github.com/websockets/ws): 了解 websocket 是如何构造 Frame 并发送数据的 (在此之前可阅读 node/http 源码) ++ [apollo-server](https://github.com/apollographql/apollo-server): GraphQL 框架,值得一看 ++ [node](https://github.com/nodejs/node): 最难的放到最后边 + +还有一些细节可以实现下: + ++ native http server ++ native http client ++ trie router ++ mustable ++ stream pipeline (nodejs): https://github.com/mafintosh/pump + +## 有没有线路图可以推荐下 + +目前关于 node 的学习路线图还不太有,我粗略总结一下,过几天做一个路线图出来: + +1. 了解 node.js 可以做什么 +2. 学习 node.js 的 http 模块,并了解一些简单的 HTTP Header 及状态码 +3. 学习 node.js 的 stream 并且了解如何最简单形式的读取 Request Body +4. 学习 node.js 的一个框架,比如 express、koa、fastify、nest +5. 学习 node.js 框架如何写中间件,并了解其 Context +6. 学习 node.js 的路由,了解两种,一种基于正则,一种基于前缀树 +7. 使用 docker 在本地搭建一个 postgres/redis,学习简单的数据库和 redis +8. 使用 sequelize 了解如何操作数据库 +9. 使用 node.js 写一个真正但简单的服务,比如成语接龙 +10. 日志设计,接入数据 +11. 部署 +12. 异常与报警设计 +13. 性能分析与调试 + +学习结束后可以根据面试进行系统训练: + ++ https://github.com/ElemeFE/node-interview: 关于 node 的面试合集 ++ https://github.com/goldbergyoni/nodebestpractices: ✅ The Node.js best practices list (February 2022) \ No newline at end of file diff --git a/test/mock.md b/test/mock.md new file mode 100644 index 0000000..dfe881f --- /dev/null +++ b/test/mock.md @@ -0,0 +1,134 @@ +# Mock 神器 Apifox + +大家好呀,我是一名苦逼的前端开发工程师,为啥苦逼呢,这不,项目下周就要上线了,但是后端还没给我接口,没有接口我就无法调试,工作停滞不前,我也只能坐着干着急。 + +我报告给了我的老板山哥: **老板,这后端不靠谱啊,都快上线了,接口还没出来**。 + +山哥回道,**别着急呀,这不有 Mock 吗**? + +**Mock,什么是 Mock 啊?**我一脸狐疑,问向山哥。 + +山哥慢条斯理说,就是**前端自己启动一个 HTTP 服务,模拟后端接口的数据,这样就无需等待后端接口开发完成了,不会因为后端开发延误而阻塞你的工作进程了**。 + +嗯,真是个不错的注意,我仿佛发现了新大陆!以后再也不用受后端拖累了,心里暗暗开心,但转念一想不对啊,时间不够啊! + +我又沮丧了下来,转头向山哥说道: **Mock 好是好,但是时间不够了啊,我重新启动一个 Mock HTTP Server,也要花不少时间呀**。 + +山哥见我开了窍,又忙不迭地说: **咱们团队不是用的 Apifox 管理 API 吗,只需要点下按钮,就可以自动 Mock!** + +一键 Mock 数据,这么简单,那应该怎么使用 Apifox 自动 Mock 呢? + +山哥接下来,缓缓道来。 + +## 使用 Apifox 智能 Mock + +Apifox,API 文档、API 调试、API Mock、API 自动化测试集成于一体的强大工具,可以在 [Apifox官网](https://www.apifox.cn/?utm_source=shanyue-question) 直接下载,在 Windows、Linux、Mac 下都可以使用。 + +![](https://files.mdnice.com/user/5840/2dea171d-ab32-42c2-89a9-ddac0993a046.png) + +下载成功后,可打开其中的**示例项目**,是一个关于宠物店的项目。打开宠物店的项目,可以在每个标签页看到四个标签: 文档、修改文档、运行、高级 Mock。 + +![](https://files.mdnice.com/user/5840/f9276d5a-59e4-4afb-ae44-3c33c80ca565.png) + +我们先看下这个**查询宠物详情**的接口,其请求接口为 `/pet/{petId}`,而响应数据为 `code` 与 `data`,`data` 是一个 `Pet` 的一个自定义数据类型。 + +![](https://files.mdnice.com/user/5840/7c0c7ba9-37cd-4052-b98a-bbed63258993.png) + +在数据模型选项卡中,可以看到 `Pet` 这个自定义数据类型,其中有两个字段为 `id`、`name` 和 `photoUrls`。 + +![](https://files.mdnice.com/user/5840/ff4c39ab-c0e7-4770-93c1-e66cd383971e.png) + +在我们的本地是肯定没有宠物店的这个项目和接口的,那我们现在就可以使用一键 Mock 服务,请求 Mock 出来的宠物店数据,非常方便! + +切换环境为**Mock服务**,此时地址栏前缀为 `http://127.0.0.1:4523/mock/533840`,点击运行按钮发送请求,见证奇迹的时刻到了,数据正确返回! + +![](https://files.mdnice.com/user/5840/68e12984-e582-44e0-8b8b-e48a466bf412.png) + +在项目中进行 Mock 时,使用 `http://127.0.0.1:4523/mock/533840` 代替后端的 API 前缀即可,特别好用是不是! + +但这仅仅是 Apifox 强大的只能 Mock 下的冰山一角! + +**假设,我们有一个用户接口,它有一个字段 email 期待返回邮箱格式的数据,一个字段 phone 期待返回手机格式的数据,一个字段 avatar 期待返回一个头像,而这在 Apifox 下都可以零配置完成!** + +![](https://files.mdnice.com/user/5840/32d23cf9-b399-42ef-8664-0a43a8616c2c.png) + +这就是,Apifox 强大的智能 Mock 规则: **你需要做的仅仅是定义 API 接口文档中的响应数据,接下来一键 Mock 服务,全部只能工作都交给 Apifox 的智能 Mock 来完成**。 + +在 Apifox 内部,当接口响应的数据字段未配置 mock 规则时,系统会自动使用智能 Mock 规则来生成数据,以实现使用时零配置即可 mock 出非常人性化的数据。根据项目设置、功能设置、智能 Mock 设置即可打开默认配置。 + +![](https://files.mdnice.com/user/5840/7a2aa8ec-5b09-4dc1-a38b-9b1b0964ca76.png) + +除此之外,Apifox 还可以根据高级设置,对字段进一步的限制,如 + +1. 字符串长度限定,及正则限定 +1. 数字最大最小的限定 +1. 枚举类型 + +![](https://files.mdnice.com/user/5840/e8147b2e-6657-48d0-bab4-6d3ccaa1895b.png) + +举一个示例,宠物售卖状态总共有三种:在售、待上架、已售。我们可以通过高级设置的枚举类型来完成,如下图所示: + +![](https://files.mdnice.com/user/5840/5bc61733-a91b-491d-a8c1-29c13a1ccafd.png) + +![](https://files.mdnice.com/user/5840/3c5db58a-add3-4e50-84c5-778c9f557a64.png) + +## 使用 Apifox 自定义 Mock + +在 Apifox 自动 Mock 非常方便,但我们需要自定义 Mock 功能,在上个接口中,宠物有一个字段是 `name`,表示宠物的名字,我们可不可以将宠物的名字仅仅定位为两个字符。 + +我们在 Apifox 数据模型设置中找到该宠物的数据模型,并配置其 `name` 字段。 + +![](https://files.mdnice.com/user/5840/adbe46af-c005-4d85-b0fb-c4eed92ade8e.png) + +`@cword(3)` 是[Apifox 的 Mock 语法](https://www.apifox.cn/help/app/mock/mock-rules/),完全兼容 Mock.js(数据占位符方式),并扩展了一些 Mock.js 没有的语法(如国内手机号 @phone)。 + +![](https://files.mdnice.com/user/5840/69d8e813-62c2-4f11-80be-431b77216584.png) + +如现有 Mock 语法无法满足需求,建议使用 正则表达式 `@regexp` 来实现灵活的定制。正则表达式基本能满足各种特殊场景的需求。 + +![](https://files.mdnice.com/user/5840/90098d40-a7f8-4a08-8872-f3238bd35cd8.png) + +而我们将宠物的名字限制为两个字符,即可使用: `@cword(2)` 替代。 + +## Apifox 的高级 Mock + +Apifox 的智能 Mock 与自定义 Mock 已经足够强大,但是他的功能远不止于此。我们尽管可以使用自定义 Mock 对数据进行每个字段更为精细的模拟,但远远无法满足复杂业务的多样性。 + +以以上**查询宠物详情**的接口为例,难免有记录不存在的示例,此时接口响应为完全不同的数据类型。此时,我们可以使用 Apifox 的高级 Mock 用以模拟数据。 + +![](https://files.mdnice.com/user/5840/e694b02c-ef90-4aa4-9d0e-1ef89d9d9caa.png) + +当我们查询宠物的 ID 为3时,返回不存在数据的相应格式,同时设置状态码为 404。 + +![](https://files.mdnice.com/user/5840/f8bc471d-ec66-4ba5-adf6-9844036a5b83.png) + +为了满足业务的多样性,我们还可以使用基于模板的高级 Mock 功能与 Apifox 的 Mock 语法相结合。这里使用了 Javascript 的 [nunjucks](https://github.com/mozilla/nunjucks) 模板语法,可以生成你想生成的任意数据。 + +![](https://files.mdnice.com/user/5840/d3759afb-8586-4c42-82f0-f7f5be4d44dc.png) + + +## 小结 + +今天关于 Apifox 强大的 Mock 功能就介绍到了这里,除了这些功能外,它还有以下更强大的功能: + +1. 接口设计:Apifox 接口文档遵循 OpenApi 3.0 (原 Swagger)、JSON Schema 规范的同时,提供了非常好用的 可视化文档管理功能,零学习成本,非常高效。并且支持在线分享接口文档。 +1. 数据模型:可复用的数据结构,定义接口 返回数据结构及 请求参数数据结构(仅 JSON 和 XML 模式)时可直接引用。支持模型直接嵌套引用,直接 JSON/XML 智能导入,支持 oneOf、allOf 等高级组合模式。 +1. 接口调试:Postman 有的功能,比如环境变量、前置/后置脚本、Cookie/Session 全局共享 等功能,Apifox 都有,并且比 Postman 更高效好用。接口运行完之后点击 保存为用例按钮,即可生成 接口用例,后续可直接运行接口用例,无需再输入参数,非常方便。自定义脚本 100% 兼容 Postman 语法,并且支持运行 javascript、java、python、php、js、BeanShell、go、shell、ruby、lua 等各种语言代码。 +1. 接口用例:通常一个接口会有多种情况用例,比如 参数正确用例、 参数错误用例、 数据为空用例、 不同数据状态用例等等。运行接口用例时会自动校验数据正确性,用接口用例来调试接口非常高效。 +1. 接口数据 Mock:内置 Mock.js 规则引擎,非常方便 mock 出各种数据,并且可以在定义数据结构的同时写好 mock 规则。支持添加“期望”,根据请求参数返回不同 mock 数据。最重要的是 Apifox 零配置 即可 Mock 出非常人性化的数据,具体在本文后面介绍。 +1. 数据库操作:支持读取数据库数据,作为接口请求参数使用。支持读取数据库数据,用来校验(断言)接口请求是否成功。 +1. 接口自动化测试:提供接口集合测试,可以通过选择接口(或接口用例)快速创建测试集。目前接口自动化测试更多功能还在开发中,敬请期待!目标是:JMeter 有的功能基本都会有,并且要更好用。 +1. 快捷调试:类似 Postman 的接口调试方式,主要用途为临时调试一些 无需文档化的接口,无需提前定义接口即可快速调试。 +1. 代码生成:根据接口及数据数据模型定义,系统自动生成 接口请求代码、 前端业务代码及 后端业务代码。 +1. 团队协作:Apifox 天生就是为团队协作而生的,接口云端实时同步更新,成熟的 团队/项目/成员权限管理,满足各类企业的需求。 + +你是不蠢蠢欲动也想下载尝试一下呢? + ++ 客户端下载地址:https://www.apifox.cn/ ++ API Hub网页版地址:https://www.apifox.cn/apihub/ + +大家可前往下载体验一波~ + +如果有什么疑问,也可以进Apifox官方交流群和官方工作人员讨论交流。 + +![](https://mmbiz.qpic.cn/mmbiz_png/nRXib819UwN10LkP959TE1FKNEC1nw0wBdw2ZWQLr2M1Lq3WHP4VzMMvzaJGvpCIXp9qEtPbDqhttFC9HgwHE0g/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1)