Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
shfshanyue committed Mar 23, 2022
1 parent 954088b commit 3c1ab9f
Show file tree
Hide file tree
Showing 5 changed files with 393 additions and 35 deletions.
20 changes: 20 additions & 0 deletions douyin/minify.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 即可完成。

## 纯文字

大家好,我是山月。
Expand All @@ -58,3 +68,13 @@ console.log(7)
我们开启代码压缩的神奇魔法,在编译期对代码进行预计算。

经优化,代码最终仅有 14 个字节。

terser 是 js 中专业的代码压缩工具,在 webpack 中可使用 terser-webpack-plugin 进行代码压缩。

我们可以在 Terser REPL 中在线尝试压缩代码。

哦对,在测试环境中用以调试随便打的 console.log,出现在生产环境中是不不太好。

很多同学也将去除生产环境中的 console.log 写在简历上。

这仅仅需要对 terser 添加一个配置项 drop_console 即可完成。
126 changes: 94 additions & 32 deletions frontend-engineering/deploy/simple-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@

在所有人入门编程及学习更多编程语言时,敲下的第一行代码是: 输出 `hello, world`

初学如何部署前端,如同学习编程一样,第一步先根据最简单页面进行部署。
``` js
console.log('hello, world')
```

初学部署前端,如同学习编程一样,第一步先根据最简单页面进行部署。

比如本系列专栏,先部署一个最简单 HTML 如下所示,只有几行代码,我称它为**hello 版前端应用**
比如本系列专栏,先部署一个最简单 HTML 如下所示,只有几行代码,无任何 CSS/Javascript 代码,我称它为**hello 版前端应用**

``` html
<!DOCTYPE html>
Expand All @@ -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` 可获得报文信息。
Expand Down Expand Up @@ -54,13 +67,34 @@ Keep-Alive: timeout=5
</html>
```

以下是对**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)
Expand All @@ -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)
Expand All @@ -113,9 +164,16 @@ server.listen(3000, () => {
})
```

当然,对于前端这类纯静态资源,**自己写代码无论从开发效率还是性能而言都是极差的**
接下来启动代码,成功运行。

``` bash
$ node server-fs.js
Listening 3000
```

当然,对于前端这类纯静态资源,**自己写代码无论从开发效率还是性能而言都是极差的**,这也是我们为何要求助于专业工具 nginx 之类进行静态资源服务的原因所在。

比如将文件系统修改为 `ReadStream` 的形式将会提升该静态服务器的性能,代码如下。
比如将文件系统修改为 `ReadStream` 的形式进行响应将会提升该静态服务器的性能,代码如下。

```js
const server = http.createServer((req, res) => {
Expand All @@ -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 版前端应用** 跑起来。
70 changes: 70 additions & 0 deletions post/oc.md
Original file line number Diff line number Diff line change
@@ -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)

---

欢迎扫码添加山月的微信,备注进群,加入山月的前端面试交流群:

<img src="https://mmbiz.qpic.cn/sz_mmbiz_jpg/po6IxVbAMcS4QYxdQhORMWcjreiaYqVWcdhNcSuZt1GgMsmnDga1duWzdbxYKFFK5fAjvG1IeILYVT3JIWo1eOg/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" width="50%"></img>
Loading

0 comments on commit 3c1ab9f

Please sign in to comment.