根據官網的說法,cdp(Chrome DevTools Protocol) 容許咱們檢測,調試Chromium, Chrome 和其餘基於 Blink的 瀏覽器. 這個協議被普遍使用. 其中最著名的是 Chrome DevTools 和 puppeteer,協議的api也由這個團隊維護。html
若是在瀏覽器中,當你打開devtools時,其實你已經在使用cdp了,只是感知不深罷了,一種辦法能夠更直觀的感知cdp,就是打開devtools的devtools,具體操做以下:git
ctrl+shift+i
,就能夠打開開發者工具的開發者工具了(禁止套娃),能夠看到開發者工具的url是devtools://devtools/bundled/xxx.html?xx
,如今在新打開的開發者工具的console裏面,輸入下面的代碼:let Main = await import('./main/main.js'); Main.MainImpl.sendOverProtocol('Runtime.evaluate', {expression: 'alert (12345)'});
這時網頁會alert 12345,你會發現平時在控制檯簡單的代碼執行,實際上是經過cdp遠程調用網頁的js引擎去執行再返回結果的。github
除此以外,protocol monitor也能夠幫助咱們更直觀的理解cdp。web
當一個頁面暴露出它的remote debugging port時,咱們就能夠藉助cdp來對這個網頁進行remote debugging了。因爲cdp是藉助websocket實現的,因此,在一切開始以前,有兩個url是比較重要的
http://localhost:[port]/json/list
http://localhost:[port]/json/version
這兩個url,可讓咱們拿到網頁的websocket url,json/list返回的數據相似於:chrome
[ { description: "", devtoolsFrontendUrl: "/devtools/inspector.html?ws=localhost:8080/devtools/page/a31c4d5c-b0df-48e8-8dcc-7c98964e2ebe", id: "a31c4d5c-b0df-48e8-8dcc-7c98964e2ebe", title: "", type: "page", url: "xxx://xxx", webSocketDebuggerUrl: "ws://localhost:8080/devtools/page/a31c4d5c-b0df-48e8-8dcc-7c98964e2ebe" } ]
其中webSocketDebuggerUrl就是咱們須要的打開remote debugging 的鑰匙express
接下來咱們連上ws,就能夠愉快的遠程操做頁面了,正如chrome devtools所作的那樣,下面是一個例子:json
const WebSocket = require('ws'); const puppeteer = require('puppeteer'); (async () => { // Puppeteer launches browser with a --remote-debugging-port=0 flag, // parses Remote Debugging URL from Chromium's STDOUT and exposes // it as |browser.wsEndpoint()|. const browser = await puppeteer.launch(); // Create a websocket to issue CDP commands. const ws = new WebSocket(browser.wsEndpoint(), {perMessageDeflate: false}); await new Promise(resolve => ws.once('open', resolve)); console.log('connected!'); ws.on('message', msg => console.log(msg)); console.log('Sending Target.setDiscoverTargets'); ws.send(JSON.stringify({ id: 1, method: 'Target.setDiscoverTargets', params: { discover: true }, })); })();
更多例子能夠在這裏api
如上面例子所示,當ws鏈接後,一個發給瀏覽器的指令大概包括3部分id,method,params,好比一個執行一段console.log('hello')代碼的指令:瀏覽器
{ "id": 235, "method": "Runtime.evaluate", "params": { "expression": "console.log('hello');", "objectGroup": "console", "includeCommandLineAPI": true, "silent": false, "contextId": 1, "returnByValue": false, "generatePreview": true, "userGesture": true, "awaitPromise": false } }
chrome devtools能夠完成的功能很是龐大,而這些功能基本都是使用這樣的一個個指令實現的,讓人想起那句古老的中國名言:九層之臺,起於壘土。本文完websocket
參考資料:
https://chromedevtools.github.io/devtools-protocol
https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md