บทนำ — ข้อผิดพลาดจริงที่ทำให้ต้องเขียนบทความนี้
ผมเคยเสียเวลาหลายชั่วโมงกับข้อผิดพลาดนี้:
Error: Could not load manifest.json
Details: serviceworker.js file not found or invalid
Manifest version 2 is deprecated.
You must use Manifest V3 for new extensions.
วันนี้ผมจะสอนทุกขั้นตอนการสร้าง Chrome Extension ที่เชื่อมต่อกับ AI API แบบครบวงจร โดยใช้ HolySheep AI ซึ่งมีอัตราเพียง ¥1=$1 ประหยัดมากกว่า 85% เมื่อเทียบกับผู้ให้บริการอื่น
Manifest V3 คืออะไร และทำไมต้องเปลี่ยน
Manifest V3 เป็นเวอร์ชันใหม่ของ Chrome Extension API ที่ Google บังคับใช้ตั้งแต่ปี 2023 โดยมีการเปลี่ยนแปลงสำคัญ:
- ไม่รองรับ Background Pages แบบเดิม ต้องใช้ Service Worker แทน
- ไม่รองรับ remote_code ใน Manifest ต้องโหลดโค้ดจากไฟล์ในเครื่องเท่านั้น
- ต้องใช้ Declarative Net Request แทน webRequest blocking
- Content Script ต้องสื่อสารผ่าน Message Passing
โครงสร้างโปรเจกต์
my-ai-extension/
├── manifest.json
├── background.js
├── content.js
├── popup.html
├── popup.js
├── styles.css
└── icons/
├── icon16.png
├── icon48.png
└── icon128.png
1. สร้าง manifest.json
{
"manifest_version": 3,
"name": "AI Assistant powered by HolySheep",
"version": "1.0.0",
"description": "AI Assistant โดยใช้ HolySheep API",
"permissions": [
"storage",
"activeTab",
"scripting"
],
"host_permissions": [
"https://api.holysheep.ai/*"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"content_scripts": [
{
"matches": [""],
"js": ["content.js"]
}
],
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
2. background.js — Service Worker สำหรับจัดการ API
// การตั้งค่า API ของ HolySheep
const HOLYSHEEP_CONFIG = {
baseUrl: 'https://api.holysheep.ai/v1',
model: 'gpt-4.1'
};
// ฟังก์ชันเรียกใช้ HolySheep API
async function callHolySheepAI(messages, apiKey) {
const response = await fetch(${HOLYSHEEP_CONFIG.baseUrl}/chat/completions, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${apiKey}
},
body: JSON.stringify({
model: HOLYSHEEP_CONFIG.model,
messages: messages,
max_tokens: 2000,
temperature: 0.7
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(API Error ${response.status}: ${errorData.error?.message || response.statusText});
}
return await response.json();
}
// รับข้อความจาก Content Script หรือ Popup
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'getAIResponse') {
chrome.storage.local.get(['apiKey'], async (result) => {
try {
const apiKey = result.apiKey;
if (!apiKey) {
sendResponse({ error: 'กรุณาตั้งค่า API Key ก่อน' });
return;
}
const data = await callHolySheepAI(request.messages, apiKey);
sendResponse({ data: data });
} catch (error) {
sendResponse({ error: error.message });
}
});
return true; // บอก Chrome ว่าจะส่ง response แบบ async
}
});
// ตั้งค่า API Key
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'setApiKey') {
chrome.storage.local.set({ apiKey: request.apiKey }, () => {
sendResponse({ success: true });
});
return true;
}
});
3. popup.html และ popup.js — UI สำหรับผู้ใช้
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<title>AI Assistant</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<h2>🤖 HolySheep AI</h2>
<div id="setupSection">
<label>API Key:</label>
<input type="password" id="apiKeyInput" placeholder="ใส่ API Key ของคุณ">
<button id="saveKeyBtn">บันทึก</button>
<p class="hint">สมัครที่ <a href="https://www.holysheep.ai/register" target="_blank">holysheep.ai</a></p>
</div>
<div id="chatSection" style="display:none;">
<textarea id="userInput" rows="4" placeholder="พิมพ์คำถามของคุณ..."></textarea>
<button id="sendBtn">ส่ง</button>
<div id="response"></div>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>
// popup.js
document.addEventListener('DOMContentLoaded', () => {
const setupSection = document.getElementById('setupSection');
const chatSection = document.getElementById('chatSection');
const apiKeyInput = document.getElementById('apiKeyInput');
const saveKeyBtn = document.getElementById('saveKeyBtn');
const userInput = document.getElementById('userInput');
const sendBtn = document.getElementById('sendBtn');
const responseDiv = document.getElementById('response');
// โหลด API Key ที่บันทึกไว้
chrome.storage.local.get(['apiKey'], (result) => {
if (result.apiKey) {
setupSection.style.display = 'none';
chatSection.style.display = 'block';
}
});
// บันทึก API Key
saveKeyBtn.addEventListener('click', () => {
const apiKey = apiKeyInput.value.trim();
if (!apiKey) {
alert('กรุณาใส่ API Key');
return;
}
chrome.runtime.sendMessage({
action: 'setApiKey',
apiKey: apiKey
}, (response) => {
if (response.success) {
setupSection.style.display = 'none';
chatSection.style.display = 'block';
}
});
});
// ส่งข้อความ
sendBtn.addEventListener('click', async () => {
const message = userInput.value.trim();
if (!message) return;
responseDiv.innerHTML = '⏳ กำลังประมวลผล...';
chrome.runtime.sendMessage({
action: 'getAIResponse',
messages: [{ role: 'user', content: message }]
}, (response) => {
if (response.error) {
responseDiv.innerHTML = ❌ ข้อผิดพลาด: ${response.error};
} else {
const answer = response.data.choices[0].message.content;
responseDiv.innerHTML = ✅ ${answer};
}
});
});
});
4. content.js — ดึงข้อความจากเว็บไซต์
// content.js - ทำงานในหน้าเว็บที่ผู้ใช้เปิดอยู่
let selectedText = '';
// ตรวจจับการเลือกข้อความ
document.addEventListener('mouseup', () => {
const selection = window.getSelection();
selectedText = selection.toString().trim();
});
// สร้าง Context Menu
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'getSelectedText') {
sendResponse({ text: selectedText });
}
});
// เพิ่มปุ่มลัดในเว็บ
const aiButton = document.createElement('button');
aiButton.innerHTML = '🤖 ถาม AI';
aiButton.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
padding: 12px 20px;
background: #6366f1;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
z-index: 999999;
`;
document.body.appendChild(aiButton);
aiButton.addEventListener('click', () => {
if (!selectedText) {
alert('กรุณาเลือกข้อความที่ต้องการถามก่อน');
return;
}
chrome.runtime.sendMessage({
action: 'getAIResponse',
messages: [
{ role: 'system', content: 'คุณเป็นผู้ช่วย AI ที่ตอบคำถามจากเนื้อหาที่ผู้ใช้เลือก' },
{ role: 'user', content: เนื้อหาที่เลือก: "${selectedText}" }
]
}, (response) => {
if (response.error) {
alert(ข้อผิดพลาด: ${response.error});
} else {
const answer = response.data.choices[0].message.content;
alert(🤖 AI: ${answer});
}
});
});
5. styles.css
.container {
width: 350px;
padding: 20px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
h2 {
margin: 0 0 15px 0;
color: #1f2937;
}
label {
display: block;
margin-bottom: 5px;
font-weight: 600;
}
input {
width: 100%;
padding: 10px;
border: 1px solid #d1d5db;
border-radius: 6px;
margin-bottom: 10px;
box-sizing: border-box;
}
button {
width: 100%;
padding: 10px;
background: #6366f1;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
}
button:hover {
background: #4f46e5;
}
textarea {
width: 100%;
padding: 10px;
border: 1px solid #d1d5db;
border-radius: 6px;
margin-bottom: 10px;
resize: none;
box-sizing: border-box;
}
#response {
margin-top: 15px;
padding: 12px;
background: #f3f4f6;
border-radius: 6px;
white-space: pre-wrap;
font-size: 14px;
}
.hint {
font-size: 12px;
color: #6b7280;
margin-top: 5px;
}
ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
1. 401 Unauthorized — API Key ไม่ถูกต้อง
// ❌ ข้อผิดพลาดที่พบ
{
"error": {
"message": "Invalid API key provided",
"type": "invalid_request_error",
"code": "invalid_api_key"
}
}
// ✅ วิธีแก้ไข
// 1. ตรวจสอบว่า API Key ถูกส่งอย่างถูกต้อง
const response = await fetch('https://api.holysheep.ai/v1/chat/completions', {
headers: {
'Authorization': Bearer ${apiKey}, // ต้องมี 'Bearer ' นำหน้า
'Content-Type': 'application/json'
}
});
// 2. ตรวจสอบว่า API Key ยังไม่หมดอายุ
// ไปที่ https://www.holysheep.ai/register เพื่อตรวจสอบ
2. ConnectionError: timeout — เชื่อมต่อไม่ได้
// ❌ ข้อผิดพลาดที่พบ
TypeError: Failed to fetch
NetworkError: Connection timeout
// ✅ วิธีแก้ไข
async function callAPIWithRetry(messages, apiKey, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 วินาที
const response = await fetch('https://api.holysheep.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${apiKey}
},
body: JSON.stringify({
model: 'gpt-4.1',
messages: messages
}),
signal: controller.signal
});
clearTimeout(timeoutId);
return await response.json();
} catch (error) {
if (error.name === 'AbortError') {
console.log(ครั้งที่ ${i + 1}: Timeout, ลองใหม่...);
} else if (i === maxRetries - 1) {
throw new Error(เชื่อมต่อไม่ได้หลังลอง ${maxRetries} ครั้ง);
}
}
}
}
3. Manifest V3 Service Worker ไม่ทำงาน
// ❌ ข้อผิดพลาดที่พบ
Service worker registration failed
Error: serviceworker.js not found
// ✅ วิธีแก้ไข
// 1. ตรวจสอบว่าไฟล์อยู่ในตำแหน่งที่ถูกต้อง
// manifest.json ต้องระบุชื่อไฟล์ที่ตรงกัน
"background": {
"service_worker": "background.js" // ไม่ใช่ background.ts หรือ background/sw.js
}
// 2. เปิด Chrome ไปที่ chrome://extensions/
// คลิก "Service Worker" link ใต้ extension ของคุณ
// ตรวจสอบ Console สำหรับ error logs
// 3. ถ้าใช้ ES Modules ต้องระบุ type ใน manifest
"background": {
"service_worker": "background.js",
"type": "module" // เพิ่มบรรทัดนี้ถ้าใช้ import
}
4. CORS Error — ข้อจำกัดของ Manifest V3
// ❌ ข้อผิดพลาดที่พบ
Access to fetch at 'https://api.holysheep.ai/v1/chat/completions'
from origin 'https://example.com' has been blocked by CORS policy
// ✅ วิธีแก้ไข
// ใน Manifest V3 ต้องเพิ่ม host_permissions ใน manifest.json
{
"manifest_version": 3,
"host_permissions": [
"https://api.holysheep.ai/*" // เพิ่ม domain ที่ต้องการเรียก
]
}
// หรือเรียก API จาก background.js แทน content.js
// เพราะ background service worker ไม่มี CORS restriction
ราคาและข้อมูลสำคัญของ HolySheep AI
| โมเดล | ราคา ($/MTok) | ราคาจริง |
|---|---|---|
| GPT-4.1 | $8.00 | ประหยัด 85%+ |
| Claude Sonnet 4.5 | $15.00 | ประหยัด 85%+ |
| Gemini 2.5 Flash | $2.50 | ประหยัด 85%+ |
| DeepSeek V3.2 | $0.42 | ประหยัด 85%+ |
จุดเด่นของ HolySheep:
- 💰 อัตราเพียง ¥1=$1 ประหยัดกว่า 85% เมื่อเทียบกับผู้ให้บริการอื่น
- ⚡ Latency น้อยกว่า 50ms สำหรับการตอบสนองที่รวดเร็ว
- 💳 รองรับ WeChat และ Alipay สำหรับชำระเงิน
- 🎁 รับเครดิตฟรีเมื่อลงทะเบียน
วิธีทดสอบ Extension
- เปิด Chrome ไปที่
chrome://extensions/ - เปิด Developer mode ที่มุมขวาบน
- คลิก "Load unpacked" แล้วเลือกโฟลเดอร์ project
- คลิกที่ไอคอน Extension แล้วตั้งค่า API Key จาก HolySheep AI
- ทดสอบโดยเลือกข้อความบนเว็บไซต์ใดก็ได้แล้วกดปุ่ม AI
สรุป
การสร้าง Chrome Extension ที่เชื่อมต่อกับ AI API ใน Manifest V3 ต้องระวังเรื่อง Service Worker, Message Passing และ CORS Policy โดยเฉพาะ การใช้ HolySheep AI ทำให้ประหยัดค่าใช้จ่ายได้มากกว่า 85% พร้อมความเร็วตอบสนองน้อยกว่า 50ms
👉 สมัคร HolySheep AI — รับเครดิตฟรีเมื่อลงทะเบียน