无题
运行和管理容器容器是基于容器技术所建立和运行的轻量级应用运行环境,它是 Docker 封装和管理应用程序或微服务的“集装箱”。在 Docker 中,容器算是最核心的部分了,掌握容器的操作也是 Docker 中最基础的技能了。在这一节中,我们会深入了解容器,展示关于容器的操作。
容器的创建和启动在了解容器的各项操作之前,我们再来回顾一下之前我们所提及的容器状态流转。
在这幅图中,我们可以看到,Docker 容器的生命周期里分为五种状态,其分别代表着:
Created:容器已经被创建,容器所需的相关资源已经准备就绪,但容器中的程序还未处于运行状态。
Running:容器正在运行,也就是容器中的应用正在运行。
Paused:容器已暂停,表示容器中的所有程序都处于暂停 ( 不是停止 ) 状态。
Stopped:容器处于停止状态,占用的资源和沙盒环境都依然存在,只是容器中的应用程序均已停止。
Deleted:容器已删除,相关占用的资源及存储在 Docker 中的管理信息也都已释放和移除。
创建容器当我们选择好镜像以后,就可以通过 docker create 这个命令来创建容器了。
123$ ...
无题
镜像与容器镜像和容器作为 Docker 里最基础的概念,我们很有必要了解 Docker 对它们的很多定义以及其他与它们有关的知识。在这一小节里,我们就专门针对镜像与容器两个概念展开,细致的梳理与这两者有关的概念和定义。
Docker 镜像如果进行形象的表述,我们可以将 Docker 镜像理解为包含应用程序以及其相关依赖的一个基础文件系统,在 Docker 容器启动的过程中,它以只读的方式被用于创建容器的运行环境。
从另一个角度看,在之前的小节里我们讲到了,Docker 镜像其实是由基于 UnionFS 文件系统的一组镜像层依次挂载而得,而每个镜像层包含的其实是对上一镜像层的修改,这些修改其实是发生在容器运行的过程中的。所以,我们也可以反过来理解,镜像是对容器运行环境进行持久化存储的结果。
深入镜像实现与其他虚拟机的镜像管理不同,Docker 将镜像管理纳入到了自身设计之中,也就是说,所有的 Docker 镜像都是按照 Docker 所设定的逻辑打包的,也是受到 Docker Engine 所控制的。
这么说起来也许还不够具体,让我们来做一个比较。我们常见的虚拟机镜像,通常是由热心的提供 ...
无题
网页加载后,浏览器会解析 html、执行 js、渲染 css,这些工作都是在 Event Loop 里完成的,理解了 Event Loop 就能理解网页的运行流程。
但很多人对 Event Loop 的理解只是停留在概念层面,并没看过真实的 Event Loop 是怎样的。
其实在 Performance 工具里就可以看到,今天我们一起来看一下:
首先我们需要一个网页,我这里用的是 react 测试 fiber 用的网页:
https://claudiopro.github.io/react-fiber-vs-stack-demo/fiber.html
点击 Performance 面板的 reload,录制 3 s 的数据:
其中 Main 这部分就是网页的主线程,也就是执行 Event Loop 的部分:
这块区域包含了所有 task 执行的流程,每个 task 的调用栈,因为像燃烧的火焰,所以也叫做火焰图。
鼠标划到想看的部分,向下拖动,就可以放大那个区域:
左右上下拖动可以调整看的位置:
展示的信息中很多种颜色,这些颜色代表着不同的含义:
灰色就代表宏任务 task: ...
无题
Chrome DevTools 的 Performance 工具是性能分析和优化的利器,因为它可以记录每一段代码的耗时,进而分析出性能瓶颈,然后做针对性的优化。
这么强大的工具肯定是要好好掌握的,今天我们就来做一个性能优化的案例来快速上手 Performance 吧。
性能分析首先,我们准备这样一段代码:
123456789101112131415161718192021222324252627282930313233343536<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>worker performance optimization</title></head><body> <script> function a() { b(); } functio ...
无题
用 Performance 工具分析网页的时候,你可能会看到 FP、DCL、FCP、L、LCP 这些东西:
勾选 web vitals 的话,还能看到具体的时间:
这是什么呢?
这叫做 web vitals,网页性能指标,这其中还有 3 个核心的,叫做 web core vitals。
我们分别来看下它们的含义:
Web VitalsTTFB (首字节到达)Time To First Byte,从开始加载网页到接收到第一个字节的网页内容之间的耗时,用来衡量网页加载体验。
可以通过 performance api 计算出来:
12const { responseStart, requestStart } = performance.timingconst TTFB = responseStart - requestStart
或者通过 PerformanceObserver api:
123456789101112new PerformanceObserver((entryList) => { const entries = entry ...
无题
很多前端都喜欢用 console.log 调试,先不谈调试效率怎么样,首先 console.log 有个致命的问题:会导致内存泄漏。
为什么这么说呢?
用 Performance 和 Memory 工具分析下就知道了。
我们准备这样一段代码:
一个按钮,点击之后创建一个数组,执行一些计算。
很常见的逻辑。
我们最后加了一个 console.log 打印了下这个数组。
起个静态服务:
浏览器访问:
点击 performance 下的垃圾回收按钮,手动触发一次 GC:
勾选 Memory,然后开始录制,点击 3 次按钮,再执行一次 GC:
你会发现内存是这样的:
内存占用有三次增长,因为我们点击三次按钮的时候会创建 3 次大数组。
但是最后我们手动 GC 之后并没有回落下去,也就是这个大数组没有被回收。
按理来说,代码执行完,那用的内存就要被释放,然后再执行别的代码,结果这段代码执行完之后大数组依然占据着内存,这样别的代码再执行的时候可用内存就少了。
这就是发生了内存泄漏,也就是代码执行完了不释放内存的流氓行为。
有同学说,只是这么一点内存问题不大呀,反正可用内存还很多。
但如 ...
无题
上节通过 Performance 和 Memory 工具证明了打开 devtools 的时候 console.log 会有内存泄漏。
有 console.log 的时候,内存是这样的:
去掉之后是这样的:
我们得出结论,console.log 会导致内存泄漏。
这点没错。
但很多同学会有疑问,是不是因为打开 devtools 才有内存泄漏,不打开就不会呢?
不打开 devtools 怎么确定内存泄漏问题呢?
看下内存大小就知道了。
通过 performance.memory.totalJSHeapSize 是可以拿到堆内存大小的。
我们通过分析 console.log 的代码执行后的堆内存大小变化就行。
也就是这样:
123456789101112131415161718192021222324252627<!DOCTYPE html><html lang="en"><body> <button id="btn">点我</button> <div id=" ...
无题
大家应该接触过图层的概念,可能是在一些设计软件里面,其实网页里也有图层。
用 Performance 分析页面运行流程的时候,你可能会主线程发现这样的任务:
回流、重绘、绘制,然后再合并图层。
下面还有 Compositor 线程,专门用来合并图层:
说明网页前面的绘制是在绘制在不同的图层上的。
为什么一个网页要分为不同的图层呢?
页面中的不同部分,重绘频率是不一样的,比如 video、canvas、动画这种就要高频重绘,而且现代浏览器都支持通过 GPU 做计算来加速渲染(硬件加速),怎么综合高频重绘和低频重绘、CPU 渲染和 GPU 渲染呢?
答案就是分成不同的图层,每个图层单独做自己的绘制,最后由 Compositor 线程把它们合并到一起。
那什么样式会新建图层呢?
大家可能听过用 3D transform 会新建图层,用 will-change 会新建图层等等,但是是否真的新建了图层心里并没底。
其实这个也是有工具可以分析的,就是 Layers 工具。
在 more tools 里开启 Layers:
就可以看到所有的图层,就是被黑框框出的那些:
选中某一个图层后,会展 ...
无题
Chrome DevTools 有很多有用的小功能,这节就专门梳理一下这个:
reply XHR当你想重新发送一次 XHR 请求的时候,不用刷新页面,直接点击 replay XHR 即可:
请求定位到源码当你想知道某个请求是在哪里发的,可以打开 Network 面板,在每个网络请求的 initiator 部分可以看到发请求代码的调用栈,点击可以快速定位到对应代码。
元素定位到创建的源码当你想知道某个元素的创建流程,可以通过 Elements 面板选中某个元素,点击 Stack Trace,就会展示出元素创建流程的调用栈。这可以帮你理清前端框架的运行流程。
这个功能是实验性的,需要手动开启下:在 settings 的 expriments 功能里,勾选 “Capture node creation stacks”。
group by folder网页加载的文件默认是按照域名和目录组织的,找文件时一层层找起来比较麻烦。
这时候可以切换为平铺的,会按照 js、css、图片的顺序列出来,找某个文件就容易多了:
Network 自定义展示列Network 是可以修改展示的列的,比如我勾 ...
无题
很多同学不知道为什么要用 debugger 来调试,console.log 不行么?
还有,会用 debugger 了,还是有很多代码看不懂,如何调试复杂源码呢?
这篇文章就来讲一下为什么要用这些调试工具:
console.log vs Debugger相信绝大多数同学使用 console.log 调试的,把想看的变量值打印在控制台。
这样能满足需求,但是遇到对象的打印就不行了。
比如我想看 webpack 源码里的 compilation 对象的值,我打印了一下:
但你会发现对象的值也是对象的时候不会展开,而是打印一个 [Object] [Array] 这种字符串。
更致命的是打印的太长会超过缓冲区的大小,terminal 里会显示不全:
而你用 debugger 来跑,在这里打个断点来看就没这些问题了:
有的同学可能会说,那打印一个简单的值的时候用 console.log 还是很方便呀。
比如这样:
真的么?
那还不如用 logpoint:
代码执行到这里就会打印:
而且没有污染代码,用 console.log 的话调试完之后这个 console 不也得删掉么?
但是 ...
