无题
上节我们把 chrome devtools frontend 跑起来,然后连上自己做的 CDP backend,实现了 network 面板、element 面板的对接,明白了 Chrome DevTools 的运行原理。
那我们能基于已有的 backend,自己实现 frontend 么?
当然也是可以的。
我们通过命令行的方式把 chrome 跑起来,通过 remote-debugging-port 指定 backend 的端口(这是 mac 下的 chrome 路径,windows 下的话大家自己找一下):
1/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
然后我们自己通过 WebSocket 客户端连上就可以了。
当然自己实现 CDP 的交互还是挺麻烦的,chrome 给提供了一个工具包 chrome-remote-interface,内部实现了和 CDP backend 的 WebSocket 通信,我们只需要调用它的 api 即可:
12 ...
无题
前面我们通过 npm 下载过 chrome devtools frontend 的代码:
1npm install chrome-devtools-frontend@1.0.672485
但是那个是比较老的版本,不需要 build。
如果想用新版本的 chrome devtools frontend,就需要下载源码自己 build 了。
这节我们一起来编译下 chrome devtools frontend 源码,并且做下修改,生成新的 chrome devtools。
下载 depot_toolschrome devtools frontend 有一套自己的工具链,我们先把这套工具链下载下来。
从 google code 下载即可(需要科学上网):
1git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
它有很多命令,我们要把它夹到环境变量里,这样就能直接用了:
1export PATH=/本地的路径/depot_tools:$PATH
我们会用到这个工具链的 fetch/gn ...
无题
Puppeteer 是一个网页的自动化测试工具,它支持写一些 JS 脚本来控制浏览器执行一些行为,可以用来跑测试用例,或者用来做爬虫。
它的脚本类似这样:
123456789101112131415161718192021222324const puppeteer = require('puppeteer');const fs = require('fs/promises');(async () => { const browser = await puppeteer.launch({ headless: false }); const page = await browser.newPage(); await page.goto('https://baidu.com'); const $input = await page.$('#kw'); await $input.type('guangguangguang'); const ...
无题
上一节我们实现了 Chromium 的自动下载,这节把 Chromium 跑起来,实现远程控制。
你是否好奇过 Puppeteer 的远程控制是怎么实现的呢?
其实也是基于 Chrome DevTools Protocol,它是 chrome devtools 和 chromium 通信的协议,chrome devtools 用它来获取 chromium 的一些信息,并且还可以控制 chromium 来做一些事情。
在 chrome devtools 里打开 Protocol Monitor,就可以看到 CDP 的数据:
chrome devtools 里展示的数据,控制浏览器执行一些行为,都是通过这个实现的,Puppeteer 也同样是基于这个。
在 CDP 的文档可以看到协议的详细描述:
它是分为不同的域的,比如 Page、Browser、Network 等,分区来管理不同的协议。
比如 Page.navigate 可以让页面导航到某个 url:
Page.close 可以关闭页面
Browser.close 可以关闭浏览器
Puppeteer 就是基于这些来远程控制 ...
无题
中后台系统表单比较多,每次调试都要填一堆东西,而且项目需要登录,经常需要来一遍登录流程,再填写表单来调试。这个流程还是比较繁琐的。
于是我在想,自动化测试工具 puppeteer 是可以通过脚本来自动执行浏览器操作的,能不能调试的时候让 puppeteer 帮我自动做了页面操作的一些流程呢?
我试了一下还真可以,用 puppeteer 来自动执行脚本,并且过程中还可以打断点调试,调试体验简直不要太爽。
这节就来分享下。
首先,react 项目是通过 vscode debugger 来调试的:
在 .vscode > launch.json 的调试配置文件里新增一个 chrome 类型的调试配置,输入调试的 url。
然后点击 debug 启动:
执行到代码中的断点就会在 vscode 里断住:
这样就可以在 vscode 里断点调试 react 项目了。
但登录还是比较麻烦的,用户名密码我经常忘,而且登录之后还要填一些表单,也很麻烦。
这时候我想到了 puppeteer。
它是可以自动执行脚本的。
比如这样一段脚本:
1234567891011121314151617181 ...
无题
异步代码的执行顺序是前端面试必问的面试题,它主要考察对 Event Loop、宏微任务以及它们执行顺序的理解。
这类问题新手比较容易困惑,老手一不注意也容易掉坑里。
那理清这类问题,有没有什么好的办法呢?
还真有,就是通过 Performance 工具。
Performance 是 Chrome DevTools 内置的用来分析代码执行耗时的工具,它会记录每个函数、每个宏微任务的耗时,并且会把超过 50ms 的长任务标红,这样开发者就可以针对性的优化。
比如这就是一个长任务:
优化 js 运行性能的目标就是消除它。
但是今天我们不是用它来分析代码性能,而是用它来看宏微任务的执行情况。
我们准备这样一段代码:
12345678910111213141516171819202122<!DOCTYPE html><html lang="en"> <body> <script> Promise.resolve().then(() => { console.log('p ...
无题
代码运行的时候,我们想看到它的运行细节,这就需要调试。
我们平时会用各种调试工具: Chrome DevTools、VSCode Debugger、Vue/React DevTools 等。
这些调试工具都有 4 要素:frontend、backend、调试协议、信道。
同一个 backend 可以对接不同的 frontend,所以我们可以用 Chrome DevTools 或者 VSCode Debugger 来调试 Node.js 或者网页代码。它们只是不同的 frontend。
我们学习了用 VSCode Debugger 来调试网页,包括 Vue、React 项目,还有 Vue、React 源码。
还学习了用 VSCode Debugger 调试 Node.js 代码和 npm scripts,我们调试了 babel 源码、nest.js 项目和源码、typescript 源码、eslint 源码、patch-package 源码等。
因为代码一般会经过编译再运行,而我们想直接调试源码,这时候就需要 sourcemap 了。
我们学习了 sourcemap 的结构和如 ...
无题
为容器配置网络在互联网时代,网络已经成为绝大多数应用进行数据交换的主要通道,Docker 作为集群部署的利器,在网络支持上也下了许多功夫。功能丰富和强大,并不代表使用复杂,在 Docker 的封装下,我们依然可以通过命令和参数轻松的为容器制定不同的网络方案。在这一节中,我们就来了解 Docker 的网络部分。
容器网络在之前介绍 Docker 核心组成的时候,我们已经简单谈到了容器网络的相关知识。容器网络实质上也是由 Docker 为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、IP 协议栈、端口套接字、IP 路由表、防火墙等等与网络相关的模块。
还是回归上面这幅之前展示过的关于 Docker 网络的图片。在 Docker 网络中,有三个比较核心的概念,也就是:**沙盒 ( Sandbox )、网络 ( Network )、端点 ( Endpoint )**。
沙盒提供了容器的虚拟网络栈,也就是之前所提到的端口套接字、IP 路由表、防火墙等的内容。其实现隔离了容器网络与宿主机网络,形成了完全独立的容器网络环境。
网络可以理 ...
无题
从镜像仓库获得镜像之前我们说到了,Docker 与其他虚拟化软件的一处不同就是将镜像管理纳入到了功能之中。实现虚拟化只是程序能够无缝移植的一部分,而有了镜像管理,就真正取代了我们在移植过程中的繁琐操作。利用 Docker 的镜像管理功能,我们可以很方便的通过网络传输和分享镜像,并保障镜像内容的一致性。所以,了解 Docker 的镜像管理方法可以算是掌握 Docker 的第一步。
镜像仓库在之前的小节里,我们已经提到过 Docker 里集中存放镜像的一个概念,也就是镜像仓库。
如果说我们把镜像的结构用 Git 项目的结构做类比,那么镜像仓库就可以看似 GitLab、GitHub 等的托管平台,只不过 Docker 的镜像仓库托管的不是代码项目,而是镜像。
当然,存储镜像并不是镜像仓库最值得炫耀的功能,其最大的作用是实现了 Docker 镜像的分发。借助镜像仓库,我们得到了一个镜像的中转站,我们可以将开发环境上所使用的镜像推送至镜像仓库,并在测试或生产环境上拉取到它们,而这个过程仅需要几个命令,甚至自动化完成。
获取镜像虽然有很多种方式将镜像引入到 Docker 之中,但我们最为常用的获 ...
无题
管理和存储数据数据是应用程序重要的产出,所以很好的管理和存储数据,是对应用程序劳动结果的尊重。特别是在大数据时代,所有的数据都是重要的资产,保护好数据是每个开发者必须掌握的技能。我们知道,在 Docker 里,容器运行的文件系统处于沙盒环境中,与外界其实是隔离的,那么我们又要如何在 Docker 中合理的通过文件与外界进行数据交换呢?在这一小节中,我们就来介绍 Docker 中与文件数据有关的内容。
数据管理实现方式Docker 容器中的文件系统于我们这些开发使用者来说,虽然有很多优势,但也有很多弊端,其中显著的两点就是:
沙盒文件系统是跟随容器生命周期所创建和移除的,数据无法直接被持久化存储。
由于容器隔离,我们很难从容器外部获得或操作容器内部文件中的数据。
当然,Docker 很好的解决了这些问题,这主要还是归功于 Docker 容器文件系统是基于 UnionFS。由于 UnionFS 支持挂载不同类型的文件系统到统一的目录结构中,所以我们只需要将宿主操作系统中,文件系统里的文件或目录挂载到容器中,便能够让容器内外共享这个文件。
由于通过这种方式可以互通容器内外的文件,那么文件 ...
