ภาพรวม
ส่วนขยาย DevTools จะเพิ่มฟังก์ชันการทำงานให้กับเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome ซึ่งสามารถเพิ่มแผง UI และแผงด้านข้างใหม่ โต้ตอบกับหน้าที่ตรวจสอบ รับข้อมูลเกี่ยวกับคําขอเครือข่าย และอื่นๆ ดูส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บแนะนำ ส่วนขยายของเครื่องมือสำหรับนักพัฒนาเว็บมีสิทธิ์เข้าถึงชุด API ส่วนขยายเพิ่มเติมสำหรับเครื่องมือสำหรับนักพัฒนาเว็บโดยเฉพาะ ดังนี้
ส่วนขยาย DevTools มีโครงสร้างเหมือนกับส่วนขยายอื่นๆ ทั้งหมด โดยอาจมีหน้าพื้นหลัง สคริปต์เนื้อหา และรายการอื่นๆ นอกจากนี้ ส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บแต่ละรายการยังมีหน้าเครื่องมือสำหรับนักพัฒนาเว็บซึ่งมีสิทธิ์เข้าถึง DevTools API
หน้าเครื่องมือสำหรับนักพัฒนาเว็บ
ระบบจะสร้างอินสแตนซ์ของหน้า DevTools ของส่วนขยายทุกครั้งที่หน้าต่าง DevTools เปิดขึ้น หน้าเครื่องมือสําหรับนักพัฒนาเว็บจะปรากฏตลอดอายุการใช้งานของหน้าต่างเครื่องมือสําหรับนักพัฒนาเว็บ หน้า DevTools มีสิทธิ์เข้าถึง DevTools API และชุด API ของส่วนขยายแบบจํากัด กล่าวโดยละเอียดคือ หน้าเครื่องมือสำหรับนักพัฒนาเว็บจะทําสิ่งต่อไปนี้ได้
- สร้างและโต้ตอบกับแผงโดยใช้
devtools.panels
API - ดูข้อมูลเกี่ยวกับหน้าต่างที่ตรวจสอบและประเมินโค้ดในหน้าต่างที่ตรวจสอบโดยใช้ API ของ
devtools.inspectedWindow
- ดูข้อมูลเกี่ยวกับคําขอเครือข่ายโดยใช้
devtools.network
API
หน้าเครื่องมือสำหรับนักพัฒนาเว็บใช้ API ส่วนใหญ่ของส่วนขยายไม่ได้โดยตรง โดยจะมีสิทธิ์เข้าถึงชุดย่อยเดียวกันของ extension
และ runtime
API เดียวกับที่สคริปต์เนื้อหามีสิทธิ์เข้าถึง หน้าเครื่องมือสำหรับนักพัฒนาเว็บสามารถสื่อสารกับหน้าเบื้องหลังได้โดยใช้การส่งข้อความ เช่นเดียวกับสคริปต์เนื้อหา ดูตัวอย่างได้ที่การแทรกสคริปต์เนื้อหา
การสร้างส่วนขยายเครื่องมือสำหรับนักพัฒนาเว็บ
หากต้องการสร้างหน้า DevTools สําหรับส่วนขยาย ให้เพิ่มช่อง devtools_page
ในไฟล์ Manifest ของส่วนขยาย
{
"name": ...
"version": "1.0",
"minimum_chrome_version": "10.0",
"devtools_page": "devtools.html",
...
}
ระบบจะสร้างอินสแตนซ์ของ devtools_page
ที่ระบุไว้ในไฟล์ Manifest ของส่วนขยายสำหรับหน้าต่าง DevTools ที่เปิดอยู่ทุกหน้าต่าง หน้าเว็บอาจเพิ่มหน้าส่วนขยายอื่นๆ เป็นแผงและแถบด้านข้างในหน้าต่าง DevTools โดยใช้ devtools.panels
API
โมดูล chrome.devtools.*
API ใช้ได้กับหน้าเว็บที่โหลดภายในหน้าต่าง DevTools เท่านั้น สคริปต์เนื้อหาและหน้าส่วนขยายอื่นๆ ไม่มี API เหล่านี้ ดังนั้น API จึงใช้งานได้ตลอดอายุของหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเท่านั้น
นอกจากนี้ API ของเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์บางรายการยังอยู่ในขั้นทดลอง โปรดดู chrome.experimental.* API เพื่อดูรายการ API เวอร์ชันทดลองและหลักเกณฑ์ในการใช้งาน
องค์ประกอบ UI ของเครื่องมือสำหรับนักพัฒนาเว็บ: แผงและแผงแถบด้านข้าง
นอกเหนือจากองค์ประกอบ UI ของส่วนขยายตามปกติ เช่น การดําเนินการของเบราว์เซอร์ เมนูตามบริบท และป๊อปอัป ส่วนขยาย DevTools ยังเพิ่มองค์ประกอบ UI ลงในหน้าต่าง DevTools ได้ด้วย ดังนี้
- แผงคือแท็บระดับบนสุด เช่น แผงองค์ประกอบ แหล่งที่มา และเครือข่าย
- แผงแถบด้านข้างแสดง UI เสริมที่เกี่ยวข้องกับแผง แผงสไตล์ รูปแบบที่คำนวณแล้ว และ Listeners เหตุการณ์ในแผงองค์ประกอบเป็นตัวอย่างของแผงด้านข้าง (โปรดทราบว่าลักษณะที่ปรากฏของแผงแถบด้านข้างอาจไม่ตรงกับรูปภาพ ทั้งนี้ขึ้นอยู่กับเวอร์ชันของ Chrome ที่คุณใช้อยู่และตำแหน่งที่ต่อเชื่อมหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บ)
แต่ละแผงเป็นไฟล์ HTML ของตัวเอง ซึ่งอาจมีทรัพยากรอื่นๆ (JavaScript, CSS, รูปภาพ และอื่นๆ) การสร้างแผงพื้นฐานจะมีลักษณะดังนี้
chrome.devtools.panels.create("My Panel",
"MyPanelIcon.png",
"Panel.html",
function(panel) {
// code invoked on panel creation
}
);
JavaScript ที่ดำเนินการในแผงหรือแผงด้านข้างจะมีสิทธิ์เข้าถึง API เดียวกันกับหน้าเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
การสร้างแผงแถบด้านข้างพื้นฐานสำหรับแผงองค์ประกอบจะมีลักษณะดังนี้
chrome.devtools.panels.elements.createSidebarPane("My Sidebar",
function(sidebar) {
// sidebar initialization code here
sidebar.setObject({ some_data: "Some data to show" });
});
การแสดงเนื้อหาในแผงแถบด้านข้างทำได้หลายวิธีดังนี้
- เนื้อหา HTML เรียกใช้
setPage
เพื่อระบุหน้า HTML ที่จะแสดงในแผง - ข้อมูล JSON ส่งออบเจ็กต์ JSON ไปยัง
setObject
- นิพจน์ JavaScript ส่งนิพจน์ไปยัง
setExpression
DevTools จะประเมินนิพจน์ในบริบทของหน้าเว็บที่ตรวจสอบ และแสดงผลลัพธ์
สําหรับทั้ง setObject
และ setExpression
แผงจะแสดงค่าตามที่ปรากฏในคอนโซล DevTools อย่างไรก็ตาม setExpression
ช่วยให้คุณแสดงองค์ประกอบ DOM และออบเจ็กต์ JavaScript ที่กำหนดเองได้ ขณะที่ setObject
รองรับเฉพาะออบเจ็กต์ JSON
การสื่อสารระหว่างคอมโพเนนต์ชิ้นงาน
ส่วนต่อไปนี้อธิบายสถานการณ์ทั่วไปบางอย่างสำหรับการรับส่งข้อมูลระหว่างคอมโพเนนต์ต่างๆ ของส่วนขยาย DevTools
การแทรกสคริปต์เนื้อหา
หน้าเครื่องมือสำหรับนักพัฒนาเว็บเรียก tabs.executeScript
โดยตรงไม่ได้ หากต้องการแทรกสคริปต์เนื้อหาจากหน้าเครื่องมือสำหรับนักพัฒนาเว็บ คุณต้องดึงข้อมูลรหัสของแท็บในหน้าต่างที่ตรวจสอบโดยใช้พร็อพเพอร์ตี้ inspectedWindow.tabId
และส่งข้อความไปยังหน้าเบื้องหลัง จากหน้าเบื้องหลัง ให้เรียกใช้ tabs.executeScript
เพื่อแทรกสคริปต์
ข้อมูลโค้ดต่อไปนี้แสดงวิธีแทรกสคริปต์เนื้อหาโดยใช้ executeScript
// DevTools page -- devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
backgroundPageConnection.onMessage.addListener(function (message) {
// Handle responses from the background page, if any
});
// Relay the tab ID to the background page
chrome.runtime.sendMessage({
tabId: chrome.devtools.inspectedWindow.tabId,
scriptToInject: "content_script.js"
});
โค้ดสําหรับหน้าพื้นหลัง
// Background page -- background.js
chrome.runtime.onConnect.addListener(function(devToolsConnection) {
// assign the listener function to a variable so we can remove it later
var devToolsListener = function(message, sender, sendResponse) {
// Inject a content script into the identified tab
chrome.tabs.executeScript(message.tabId,
{ file: message.scriptToInject });
}
// add the listener
devToolsConnection.onMessage.addListener(devToolsListener);
devToolsConnection.onDisconnect.addListener(function() {
devToolsConnection.onMessage.removeListener(devToolsListener);
});
});
การประเมิน JavaScript ในหน้าต่างที่ตรวจสอบ
คุณสามารถใช้เมธอด inspectedWindow.eval
เพื่อเรียกใช้โค้ด JavaScript ในบริบทของหน้าเว็บที่ตรวจสอบ คุณสามารถเรียกใช้เมธอด eval
จากหน้า แผง หรือแผงด้านข้างของเครื่องมือสำหรับนักพัฒนาเว็บ
โดยค่าเริ่มต้น ระบบจะประเมินนิพจน์ในบริบทของเฟรมหลักของหน้า ตอนนี้คุณอาจคุ้นเคยกับฟีเจอร์ commandline API ของ DevTools แล้ว เช่น การตรวจสอบองค์ประกอบ (inspect(elem)
) การหยุดพักที่ฟังก์ชัน (debug(fn)
) การคัดลอกไปยังคลิปบอร์ด (copy()
) และอื่นๆ
inspectedWindow.eval()
ใช้บริบทและตัวเลือกการเรียกใช้สคริปต์เดียวกันกับโค้ดที่พิมพ์ในคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บ ซึ่งช่วยให้เข้าถึง API เหล่านี้ภายใน eval ได้ ตัวอย่างเช่น SOAK ใช้ Inspect Element ดังนี้
chrome.devtools.inspectedWindow.eval(
"inspect($$('head script[data-soak=main]')[0])",
function(result, isException) { }
);
หรือจะใช้ตัวเลือก useContentScriptContext: true
สําหรับ inspectedWindow.eval()
เพื่อประเมินนิพจน์ในบริบทเดียวกับสคริปต์เนื้อหาก็ได้ การเรียกใช้ eval
ด้วย useContentScriptContext: true
จะไม่createบริบทสคริปต์เนื้อหา คุณจึงต้องโหลดสคริปต์บริบทก่อนเรียกใช้ eval
โดยเรียกใช้ executeScript
หรือระบุสคริปต์เนื้อหาในไฟล์ manifest.json
เมื่อบริบทสคริปต์บริบทมีอยู่แล้ว คุณจะใช้ตัวเลือกนี้เพื่อแทรกสคริปต์เนื้อหาเพิ่มเติมได้
เมธอด eval
มีประสิทธิภาพเมื่อใช้ในบริบทที่เหมาะสม และอันตรายเมื่อใช้อย่างไม่เหมาะสม ใช้เมธอด tabs.executeScript
หากไม่จําเป็นต้องเข้าถึงบริบท JavaScript ของหน้าเว็บที่ตรวจสอบ ดูข้อควรระวังโดยละเอียดและการเปรียบเทียบ 2 วิธีได้ที่ inspectedWindow
ส่งองค์ประกอบที่เลือกไปยังสคริปต์เนื้อหา
สคริปต์เนื้อหาไม่มีสิทธิ์เข้าถึงองค์ประกอบที่เลือกอยู่ในปัจจุบันโดยตรง อย่างไรก็ตาม โค้ดที่คุณเรียกใช้โดยใช้ inspectedWindow.eval
จะมีสิทธิ์เข้าถึงคอนโซลเครื่องมือสำหรับนักพัฒนาเว็บและ API บรรทัดคำสั่ง
เช่น ในโค้ดที่ประเมินแล้ว คุณสามารถใช้ $0
เพื่อเข้าถึงองค์ประกอบที่เลือก
วิธีส่งองค์ประกอบที่เลือกไปยังสคริปต์เนื้อหา
- สร้างเมธอดในสคริปต์เนื้อหาที่ใช้องค์ประกอบที่เลือกเป็นอาร์กิวเมนต์
- เรียกใช้เมธอดจากหน้าเครื่องมือสําหรับนักพัฒนาเว็บโดยใช้
inspectedWindow.eval
พร้อมตัวเลือกuseContentScriptContext: true
โค้ดในสคริปต์เนื้อหาอาจมีลักษณะดังนี้
function setSelectedElement(el) {
// do something with the selected element
}
เรียกใช้เมธอดจากหน้าเครื่องมือสําหรับนักพัฒนาเว็บดังนี้
chrome.devtools.inspectedWindow.eval("setSelectedElement($0)",
{ useContentScriptContext: true });
ตัวเลือก useContentScriptContext: true
ระบุว่าต้องประเมินนิพจน์ในบริบทเดียวกับสคริปต์เนื้อหาเพื่อให้เข้าถึงเมธอด setSelectedElement
ได้
การรับ window
ของแผงอ้างอิง
หากต้องการpostMessage
จากแผงเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ คุณจะต้องมีข้อมูลอ้างอิงถึงออบเจ็กต์ window
ของแผงนั้น
รับหน้าต่าง iframe ของแผงจากเครื่องจัดการเหตุการณ์ panel.onShown
onShown.addListener(function callback)
extensionPanel.onShown.addListener(function (extPanelWindow) {
extPanelWindow instanceof Window; // true
extPanelWindow.postMessage( // …
});
การรับส่งข้อความจากสคริปต์เนื้อหาไปยังหน้าเครื่องมือสำหรับนักพัฒนาเว็บ
การรับส่งข้อความระหว่างหน้าเครื่องมือสำหรับนักพัฒนาเว็บกับสคริปต์เนื้อหาเป็นแบบอ้อมผ่านหน้าเบื้องหลัง
เมื่อส่งข้อความไปยังสคริปต์เนื้อหา หน้าเบื้องหลังจะใช้เมธอด tabs.sendMessage
ได้ ซึ่งจะส่งข้อความไปยังสคริปต์เนื้อหาในแท็บที่เฉพาะเจาะจง ดังที่แสดงในการแทรกสคริปต์เนื้อหา
เมื่อส่งข้อความจากสคริปต์เนื้อหา จะไม่มีวิธีการสำเร็จรูปในการส่งข้อความไปยังอินสแตนซ์หน้าเว็บ DevTools ที่ถูกต้องซึ่งเชื่อมโยงกับแท็บปัจจุบัน วิธีแก้ปัญหาชั่วคราวคือคุณสามารถให้หน้าเครื่องมือสำหรับนักพัฒนาเว็บสร้างการเชื่อมต่อระยะยาวกับหน้าเบื้องหลัง และกำหนดให้หน้าเบื้องหลังแมปรหัสแท็บกับการเชื่อมต่อ เพื่อให้สามารถกำหนดเส้นทางข้อความแต่ละรายการไปยังการเชื่อมต่อที่ถูกต้อง
// background.js
var connections = {};
chrome.runtime.onConnect.addListener(function (port) {
var extensionListener = function (message, sender, sendResponse) {
// The original connection event doesn't include the tab ID of the
// DevTools page, so we need to send it explicitly.
if (message.name == "init") {
connections[message.tabId] = port;
return;
}
// other message handling
}
// Listen to messages sent from the DevTools page
port.onMessage.addListener(extensionListener);
port.onDisconnect.addListener(function(port) {
port.onMessage.removeListener(extensionListener);
var tabs = Object.keys(connections);
for (var i=0, len=tabs.length; i < len; i++) {
if (connections[tabs[i]] == port) {
delete connections[tabs[i]]
break;
}
}
});
});
// Receive message from content script and relay to the devTools page for the
// current tab
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// Messages from content scripts should have sender.tab set
if (sender.tab) {
var tabId = sender.tab.id;
if (tabId in connections) {
connections[tabId].postMessage(request);
} else {
console.log("Tab not found in connection list.");
}
} else {
console.log("sender.tab not defined.");
}
return true;
});
หน้าเครื่องมือสำหรับนักพัฒนาเว็บ (หรือแผงหรือแผงด้านข้าง) จะสร้างการเชื่อมต่อดังนี้
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "panel"
});
backgroundPageConnection.postMessage({
name: 'init',
tabId: chrome.devtools.inspectedWindow.tabId
});
การรับส่งข้อความจากสคริปต์ที่แทรกไปยังหน้าเครื่องมือสำหรับนักพัฒนาเว็บ
แม้ว่าโซลูชันข้างต้นจะใช้ได้กับสคริปต์เนื้อหา แต่โค้ดที่แทรกลงในหน้าเว็บโดยตรง (เช่น ผ่านการต่อท้ายแท็ก <script>
หรือผ่าน inspectedWindow.eval
) ต้องใช้กลยุทธ์ที่ต่างกัน ในบริบทนี้ runtime.sendMessage
จะไม่ส่งข้อความไปยังสคริปต์เบื้องหลังตามที่คาดไว้
วิธีแก้ปัญหาชั่วคราวคือคุณสามารถรวมสคริปต์ที่แทรกไว้กับสคริปต์เนื้อหาที่ทำหน้าที่เป็นสื่อกลาง หากต้องการส่งข้อความไปยังสคริปต์เนื้อหา คุณสามารถใช้ window.postMessage
API ต่อไปนี้เป็นตัวอย่างโดยสมมติว่าสคริปต์เบื้องหลังมาจากส่วนก่อนหน้า
// injected-script.js
window.postMessage({
greeting: 'hello there!',
source: 'my-devtools-extension'
}, '*');
// content-script.js
window.addEventListener('message', function(event) {
// Only accept messages from the same frame
if (event.source !== window) {
return;
}
var message = event.data;
// Only accept messages that we know are ours
if (typeof message !== 'object' || message === null ||
!message.source === 'my-devtools-extension') {
return;
}
chrome.runtime.sendMessage(message);
});
ตอนนี้ข้อความจะส่งผ่านจากสคริปต์ที่แทรก สคริปต์เนื้อหา สคริปต์เบื้องหลัง และสุดท้ายไปยังหน้าเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
นอกจากนี้ คุณยังดูเทคนิคการส่งข้อความแบบอื่น 2 วิธีได้ที่นี่
การตรวจจับเมื่อเครื่องมือสำหรับนักพัฒนาเว็บเปิดและปิด
หากส่วนขยายต้องติดตามว่าหน้าต่างเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่หรือไม่ คุณสามารถเพิ่มตัวรับฟัง onConnect ลงในหน้าเบื้องหลัง และเรียกใช้ connect จากหน้าเครื่องมือสำหรับนักพัฒนาเว็บ เนื่องจากแต่ละแท็บสามารถเปิดหน้าต่างเครื่องมือสําหรับนักพัฒนาเว็บของตัวเอง คุณจึงอาจได้รับเหตุการณ์การเชื่อมต่อหลายรายการ หากต้องการติดตามว่ามีหน้าต่าง DevTools เปิดอยู่หรือไม่ คุณต้องนับเหตุการณ์การเชื่อมต่อและการยกเลิกการเชื่อมต่อดังที่แสดงด้านล่าง
// background.js
var openCount = 0;
chrome.runtime.onConnect.addListener(function (port) {
if (port.name == "devtools-page") {
if (openCount == 0) {
alert("DevTools window opening.");
}
openCount++;
port.onDisconnect.addListener(function(port) {
openCount--;
if (openCount == 0) {
alert("Last DevTools window closing.");
}
});
}
});
หน้าเครื่องมือสำหรับนักพัฒนาเว็บจะสร้างการเชื่อมต่อดังนี้
// devtools.js
// Create a connection to the background page
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
ตัวอย่างส่วนขยายของเครื่องมือสําหรับนักพัฒนาเว็บ
เรียกดูแหล่งที่มาของตัวอย่างส่วนขยาย DevTools เหล่านี้
- ส่วนขยายเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของ Polymer - ใช้ตัวช่วยหลายรายการที่ทำงานในหน้าโฮสต์เพื่อค้นหาสถานะ DOM/JS เพื่อส่งกลับไปที่แผงที่กำหนดเอง
- ส่วนขยาย React DevTools - ใช้โมดูลย่อยของ Blink เพื่อนำคอมโพเนนต์ UI ของ DevTools มาใช้ซ้ำ
- Ember Inspector - แกนส่วนขยายที่แชร์กับอะแดปเตอร์สำหรับทั้ง Chrome และ Firefox
- Coquette-inspect - ส่วนขยายที่ใช้ React แบบสะอาดๆ ที่มีตัวแทนการแก้ไขข้อบกพร่องที่แทรกลงในหน้าเว็บโฮสต์
- แกลเลอรีส่วนขยายของ DevTools และตัวอย่างส่วนขยายมีแอปที่มีประโยชน์อีกมากมายให้ติดตั้ง ลองใช้ และเรียนรู้
ข้อมูลเพิ่มเติม
ดูข้อมูลเกี่ยวกับ API มาตรฐานที่ส่วนขยายใช้ได้ที่ chrome.* API และ Web API
ส่งความคิดเห็นถึงเรา ความคิดเห็นและคำแนะนำของคุณจะช่วยเราปรับปรุง API
ตัวอย่าง
คุณดูตัวอย่างที่ใช้ DevTools API ได้ในตัวอย่าง