ภาพรวมสถาปัตยกรรม

ส่วนขยายคือกลุ่มไฟล์ ZIP ของ HTML, CSS, JavaScript, รูปภาพ และไฟล์อื่นๆ ที่ใช้ในแพลตฟอร์มเว็บ ซึ่งจะปรับแต่งประสบการณ์การท่องเว็บ Google Chrome ส่วนขยายสร้างขึ้นโดยใช้เทคโนโลยีเว็บและสามารถใช้ API เดียวกับที่เบราว์เซอร์มีให้กับเว็บแบบเปิด

ส่วนขยายมีความสามารถที่เป็นไปได้ที่หลากหลาย โดยสามารถแก้ไขเนื้อหาเว็บที่ผู้ใช้เห็นและโต้ตอบ หรือขยาย และเปลี่ยนแปลงลักษณะการทำงานของเบราว์เซอร์ได้

ให้คิดว่าส่วนขยายคือประตูสู่การทำให้เบราว์เซอร์ Chrome เป็นเบราว์เซอร์ที่ปรับเปลี่ยนในแบบของผู้ใช้มากที่สุด

ไฟล์ส่วนขยาย

ส่วนขยายจะแตกต่างกันไปตามประเภทของไฟล์และจำนวนไดเรกทอรี แต่ทุกไฟล์จำเป็นต้องมี [ไฟล์ Manifest][ไฟล์ Manifest] ส่วนขยายบางอย่างที่เป็นพื้นฐานแต่มีประโยชน์อาจมีเพียงไฟล์ Manifest และไอคอนแถบเครื่องมือ

ไฟล์ Manifest ชื่อว่า manifest.json ให้ข้อมูลเบราว์เซอร์เกี่ยวกับส่วนขยาย เช่น ไฟล์ที่สำคัญที่สุดและความสามารถที่ส่วนขยายอาจใช้

{
  "name": "My Extension",
  "version": "2.1",
  "description": "Gets information from Google.",
  "icons": {
    "128": "icon_16.png",
    "128": "icon_32.png",
    "128": "icon_48.png",
    "128": "icon_128.png"
  },
  "background": {
    "persistent": false,
    "scripts": ["background_script.js"]
  },
  "permissions": ["https://*.google.com/", "activeTab"],
  "browser_action": {
    "default_icon": "icon_16.png",
    "default_popup": "popup.html"
  }
}

ส่วนขยายต้องมีไอคอนอยู่ในแถบเครื่องมือของเบราว์เซอร์ ไอคอนแถบเครื่องมือช่วยให้เข้าถึงได้ง่าย และช่วยให้ ผู้ใช้ทราบว่าส่วนขยายใดบ้างถูกติดตั้ง ผู้ใช้ส่วนใหญ่จะโต้ตอบกับส่วนขยายที่ใช้ป๊อปอัปด้วยการคลิกที่ไอคอน

ส่วนขยาย Google Mail Checker นี้ใช้การทำงานของเบราว์เซอร์ ดังนี้

ภาพหน้าจอของส่วนขยาย Google Mail Checker

ส่วนขยาย Mappy นี้ใช้การทำงานของหน้าเว็บและสคริปต์เนื้อหา:

ภาพหน้าจอของส่วนขยาย Mappy

การอ้างอิงถึงไฟล์

คุณจะอ้างอิงไฟล์ของส่วนขยายได้โดยใช้ URL แบบสัมพัทธ์ เช่นเดียวกับไฟล์ในหน้า HTML ทั่วไป

<img src="images/my_image.png">

นอกจากนี้ แต่ละไฟล์ยังเข้าถึงได้โดยใช้ URL ที่สมบูรณ์

chrome-extension://EXTENSION_ID/PATH_TO_FILE

ใน URL ที่สมบูรณ์ EXTENSION_ID คือตัวระบุที่ไม่ซ้ำกันซึ่งระบบส่วนขยายสร้างขึ้นสำหรับส่วนขยายแต่ละรายการ คุณดูรหัสของส่วนขยายที่โหลดทั้งหมดได้โดยไปที่ URL chrome://extensions PATH_TO_FILE คือตำแหน่งของไฟล์ภายใต้โฟลเดอร์ด้านบนของส่วนขยาย ซึ่งจะตรงกับ URL แบบสัมพัทธ์

รหัสส่วนขยายสามารถเปลี่ยนแปลงได้ขณะทำงานกับส่วนขยายที่คลายการแพคข้อมูล กล่าวอย่างเจาะจงคือ รหัสของส่วนขยายที่คลายการแพคข้อมูลจะมีการเปลี่ยนแปลงหากโหลดส่วนขยายจากไดเรกทอรีอื่น รหัสจะเปลี่ยนอีกครั้งเมื่อมีแพ็กเกจส่วนขยาย หากโค้ดของส่วนขยายต้องใช้ URL ที่สมบูรณ์ ก็สามารถใช้เมธอด chrome.runtime.getURL() เพื่อหลีกเลี่ยงการฮาร์ดโค้ดรหัสในระหว่างการพัฒนา

สถาปัตยกรรม

สถาปัตยกรรมของส่วนขยายจะขึ้นอยู่กับฟังก์ชันการทำงานของส่วนขยาย แต่ส่วนขยายที่มีประสิทธิภาพหลายรายการจะมีองค์ประกอบหลายอย่าง ดังนี้

สคริปต์ที่ทำงานอยู่เบื้องหลัง

สคริปต์พื้นหลังเป็นเครื่องจัดการเหตุการณ์ของส่วนขยาย ซึ่งมี Listener สำหรับเหตุการณ์ของเบราว์เซอร์ที่สำคัญต่อส่วนขยายนั้น จะไม่มีความเคลื่อนไหวจนกว่าเหตุการณ์จะเริ่มทำงาน แล้วดำเนินการตามตรรกะตามคำสั่ง สคริปต์เบื้องหลังที่มีประสิทธิภาพจะโหลดเมื่อจำเป็นเท่านั้น โดยจะยกเลิกการโหลดเมื่อไม่มีการใช้งาน

องค์ประกอบ UI

อินเทอร์เฟซผู้ใช้ของส่วนขยายควรมีประโยชน์และเรียบง่าย UI ควรปรับแต่งหรือเพิ่มประสิทธิภาพให้ประสบการณ์การท่องเว็บโดยไม่เบี่ยงเบนความสนใจไปจาก UI ส่วนขยายส่วนใหญ่มีการทำงานของเบราว์เซอร์หรือการทำงานของหน้าเว็บ แต่อาจมี UI รูปแบบอื่นๆ ได้ เช่น เมนูตามบริบท, การใช้แถบอเนกประสงค์ หรือการสร้างแป้นพิมพ์ลัด

หน้า UI ของส่วนขยาย เช่น ป๊อปอัป อาจมีหน้า HTML ทั่วไปที่มีตรรกะ JavaScript ส่วนขยายจะเรียกใช้ tabs.create หรือ window.open() เพื่อแสดงไฟล์ HTML เพิ่มเติมที่มีอยู่ในส่วนขยายได้ด้วย

ส่วนขยายที่ใช้การดำเนินการในหน้าเว็บและป๊อปอัปจะใช้ API เนื้อหาประกาศ เพื่อตั้งกฎในสคริปต์เบื้องหลังเพื่อกำหนดเวลาที่ป๊อปอัปพร้อมใช้งานสำหรับผู้ใช้ได้ เมื่อตรงตามเงื่อนไข สคริปต์พื้นหลังจะสื่อสารกับป๊อปอัปเพื่อให้ผู้ใช้คลิกไอคอนของไอคอนนั้นได้

หน้าต่างเบราว์เซอร์ที่มีการทำงานของหน้าเว็บที่แสดงป๊อปอัป

สคริปต์เนื้อหา

ส่วนขยายที่อ่านหรือเขียนลงในหน้าเว็บจะใช้สคริปต์เนื้อหา สคริปต์เนื้อหามี JavaScript ที่ทำงานในบริบทของหน้าเว็บที่โหลดลงในเบราว์เซอร์ สคริปต์เนื้อหาจะอ่านและแก้ไข DOM ของหน้าเว็บที่เบราว์เซอร์เข้าชม

หน้าต่างเบราว์เซอร์ที่มีการทำงานของหน้าเว็บและสคริปต์เนื้อหา

สคริปต์เนื้อหาสื่อสารกับส่วนขยายระดับบนสุดได้โดยการแลกเปลี่ยนข้อความและจัดเก็บค่าโดยใช้ storage API

แสดงเส้นทางการสื่อสารระหว่างสคริปต์เนื้อหาและส่วนขยายระดับบนสุด

หน้าตัวเลือก

หน้าตัวเลือกจะเปิดใช้การปรับแต่งส่วนขยายเช่นเดียวกับที่ส่วนขยายอนุญาตให้ผู้ใช้ปรับแต่งเบราว์เซอร์ Chrome คุณสามารถใช้ตัวเลือกต่างๆ เพื่อเปิดใช้ฟีเจอร์และอนุญาตให้ผู้ใช้เลือกฟังก์ชันการทำงานที่ตรงกับความต้องการ

การใช้ API ของ Chrome

นอกจากมีสิทธิ์เข้าถึง API เดียวกันกับหน้าเว็บแล้ว ส่วนขยายยังใช้ API เฉพาะส่วนขยายที่ทำให้เกิดการผสานรวมกับเบราว์เซอร์ได้อย่างเหนียวแน่น ทั้งส่วนขยายและหน้าเว็บจะเข้าถึงเมธอด window.open() มาตรฐานเพื่อเปิด URL ได้ แต่ส่วนขยายจะระบุหน้าต่างที่ URL นั้นควรแสดงได้โดยใช้เมธอด tabs.create ของ Chrome API แทน

เมธอดอะซิงโครนัสเทียบกับวิธีซิงโครนัส

เมธอด API ของ Chrome ส่วนใหญ่เป็นแบบอะซิงโครนัส โดยวิธีเหล่านั้นจะส่งกลับทันทีโดยไม่ต้องรอให้การทำงาน เสร็จสิ้น หากส่วนขยายต้องการทราบผลลัพธ์ของการดำเนินการแบบอะซิงโครนัส ส่วนขยายจะส่งฟังก์ชันเรียกกลับไปยังเมธอดได้ ระบบจะเรียกใช้โค้ดเรียกกลับในภายหลัง หรืออาจเกิดขึ้นในภายหลังหลังจากที่เมธอดแสดงผลกลับมา

หากส่วนขยายจำเป็นต้องนำแท็บที่ผู้ใช้เลือกอยู่ไปยัง URL ใหม่ ส่วนขยายนั้นจะต้องรับรหัสของแท็บปัจจุบัน จากนั้นอัปเดตที่อยู่ของแท็บนั้นเป็น URL ใหม่

หากเมธอด tabs.query เป็นแบบซิงโครนัส อาจมีลักษณะดังนี้

//THIS CODE DOESN'T WORK
var tab = chrome.tabs.query({'active': true}); //WRONG!!!
chrome.tabs.update(tab.id, {url:newUrl});
someOtherFunction();

วิธีนี้จะล้มเหลวเนื่องจาก query() เป็นแบบอะซิงโครนัส และแสดงผลโดยไม่ต้องรอให้งานเสร็จสมบูรณ์ และไม่แสดงค่า เมธอดจะเป็นแบบอะซิงโครนัสเมื่อพารามิเตอร์เรียกกลับ พร้อมใช้งานในลายเซ็น

// Signature for an asynchronous method
chrome.tabs.query(object queryInfo, function callback)

หากต้องการค้นหาแท็บให้ถูกต้องและอัปเดต URL แท็บนั้น ส่วนขยายต้องใช้พารามิเตอร์เรียกกลับ

//THIS CODE WORKS
chrome.tabs.query({'active': true}, function(tabs) {
  chrome.tabs.update(tabs[0].id, {url: newUrl});
});
someOtherFunction();

ในโค้ดข้างต้น บรรทัดจะทำงานตามลำดับต่อไปนี้: 1, 4, 2 ระบบจะเรียกใช้ฟังก์ชันเรียกกลับที่ระบุสำหรับ query() จากนั้นจะเรียกใช้บรรทัดที่ 2 แต่หลังจากมีข้อมูลเกี่ยวกับแท็บที่เลือกไว้ในปัจจุบันเท่านั้น เหตุการณ์นี้จะเกิดขึ้นในบางครั้งหลังจากที่ query() กลับมา แม้ว่า update() จะเป็นแบบอะซิงโครนัส แต่โค้ดจะไม่ใช้พารามิเตอร์เรียกกลับ เนื่องจากส่วนขยายไม่ได้ทำอะไรกับผลลัพธ์ของการอัปเดต

// Synchronous methods have no callback option and returns a type of string
string chrome.runtime.getURL()

วิธีนี้จะแสดงผล URL แบบซิงโครนัสเป็น string และจะไม่ทำงานแบบอะซิงโครนัสอื่นๆ

รายละเอียดเพิ่มเติม

ดูข้อมูลเพิ่มเติมได้ในเอกสารอ้างอิง API ของ Chrome และดูวิดีโอต่อไปนี้

การสื่อสารระหว่างหน้าเว็บ

คอมโพเนนต์ที่แตกต่างกันในส่วนขยายมักจะต้องสื่อสารกัน หน้า HTML ต่างๆ จะค้นหากันและกันได้โดยใช้เมธอดของ chrome.extension เช่น getViews() และ getBackgroundPage() เมื่อหน้าเว็บมีการอ้างอิงหน้าส่วนขยายอื่นๆ หน้าแรกสามารถเรียกใช้ฟังก์ชันในหน้าอื่นๆ และจัดการ DOM ของหน้าเว็บเหล่านั้น นอกจากนี้ องค์ประกอบทั้งหมดของส่วนขยายยังเข้าถึงค่าที่เก็บไว้โดยใช้ storage API และสื่อสารผ่านการส่งข้อความได้ด้วย

การบันทึกข้อมูลและโหมดไม่ระบุตัวตน

ส่วนขยายสามารถบันทึกข้อมูลโดยใช้ storage API, Web Storage API ของ HTML5 หรือการส่งคำขอของเซิร์ฟเวอร์ที่ทำให้ประหยัดอินเทอร์เน็ตได้ เมื่อส่วนขยายต้องการบันทึกบางอย่าง ให้พิจารณาก่อนว่าส่วนขยายนั้นมาจากหน้าต่างที่ไม่ระบุตัวตนหรือไม่ โดยค่าเริ่มต้น ส่วนขยายจะไม่ทำงานในหน้าต่างที่ไม่ระบุตัวตน

โหมดไม่ระบุตัวตนบอกไว้ว่าหน้าต่างจะไม่มีรอยทาง เมื่อต้องจัดการกับข้อมูลจาก หน้าต่างที่ไม่ระบุตัวตน ส่วนขยายควรเป็นไปตามเงื่อนไขนี้ หากส่วนขยายบันทึกประวัติการท่องเว็บตามปกติ โปรดอย่าบันทึกประวัติการเข้าชมจากหน้าต่างที่ไม่ระบุตัวตน อย่างไรก็ตาม ส่วนขยายสามารถจัดเก็บค่ากำหนด จากหน้าต่างใดก็ได้ ทั้งในโหมดไม่ระบุตัวตน

หากต้องการตรวจหาว่าหน้าต่างอยู่ในโหมดไม่ระบุตัวตนหรือไม่ ให้ตรวจสอบพร็อพเพอร์ตี้ incognito ของออบเจ็กต์ tabs.Tab หรือ windows.Window ที่เกี่ยวข้อง

function saveTabData(tab) {
  if (tab.incognito) {
    return;
  } else {
    chrome.storage.local.set({data: tab.url});
  }
}

ดำเนินการขั้นตอนถัดไป

หลังจากอ่านภาพรวมและจบบทแนะนำเริ่มต้นใช้งานแล้ว นักพัฒนาซอฟต์แวร์ควรพร้อมที่จะเริ่มเขียนส่วนขยายของตนเองแล้ว เจาะลึกโลกของ Chrome ที่กำหนดเอง ด้วยแหล่งข้อมูลต่อไปนี้