הזרקת סקריפטים לתוכן בתוספי Chrome: מדריך מלא

כאשר תוסף מפסיק להגיב לשינויים בדף לאחר ניווט בתוך אתר, המשתמשים מאבדים אמון במוצר. אנחנו מפתחים ומיישמים content script שמטפל כראוי בניווט SPA ובשינויי DOM. הצוות שלנו מספק את הפרויקט במפתח מלא—מביקורת ועד תמיכה שוטפת—ומבטיח שהתוסף פועל באופן אמין.

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

אלה רק חלק מהסוגים הטכניים של אתרים שאנו עובדים איתם, ולכל אחד מהם יכולים להיות מאפיינים ופונקציונליות ספציפיים משלו, וכן ניתן להתאים אותם לצרכים ולמטרות הספציפיים של הלקוח.

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
הזרקת סקריפטים לתוכן בתוספי Chrome: מדריך מלא
בינוני
~2-3 ימים

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1359
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113
  • פיתוח אתר עבור SBH Partners
    פיתוח אתר עבור SBH Partners
    1201
  • פיתוח אתר עבור Red Pear
    פיתוח אתר עבור Red Pear
    619

שליטה בהזרקת סקריפטים לתוכן בתוספי דפדפן

תארו לעצמכם: פיתחתם תוסף Chrome שמדגיש מחירים באתר מסחר אלקטרוני. הסקריפט המוזרק עובד בטעינה הראשונית, אבל כשהמשתמש מנווט לעגלת הקניות דרך pushState, הסקריפט מפסיק להגיב—MutationObserver לא מופעל. זהו מלכוד קלאסי של SPA. אנחנו נתקלים במקרים כאלה כמעט בכל פרויקט שני. במאמר זה, נפרק כיצד להזריק נכון סקריפט תוסף, לטפל בניווט SPA, לארגן חילופי נתונים עם סקריפט הרקע, ולהימנע מטעויות אופייניות.

סקריפט תוכן (נקרא גם סקריפט מוזרק) הוא מנגנון להזרקת קוד לדף. אנו משלבים סקריפט תוכן—קובץ JavaScript שהדפדפן מזריק להקשר של דף היעד בסביבה מבודדת, כמתואר בתיעוד תוספי Chrome. זה מספק גישה ל-DOM אך לא למשתני הדף—גם הגנה וגם מגבלה. הניסיון שלנו: 5+ שנים בשוק ולמעלה מ-30 פרויקטים מוצלחים בפיתוח תוספי דפדפן. סקריפטים לתוכן נועדו לשנות את ה-DOM של דף היעד. הלקוחות שלנו בדרך כלל חוסכים 20-30% מזמן הפיתוח על ידי ניצול דפוסי ההזרקה המבוססים שלנו.

כיצד הדפדפן טוען סקריפט תוכן

הנה תהליך שלב-אחר-שלב להזרקת סקריפט תוכן:

  1. הצהירו על סקריפטים ותנאי ההזרקה שלהם ב-manifest.json (MV3).
  2. הגדירו את הפרמטר run_at כדי לשלוט בתזמון ההזרקה.
  3. אופציונלית, השתמשו בהזרקה דינמית דרך document_start מ-service worker.

ב-manifest.json, הצהירו על סקריפטים ותנאי ההזרקה שלהם. הפרמטר document_end קובע מתי הסקריפט מוזרק. להלן השוואה:

run_at רגע ההזרקה מתי להשתמש
document_idle לפני בניית ה-DOM כדי ליירט בקשות מוקדמות
{ "manifest_version": 3, "content_scripts": [ { "matches": ["https://*.example.com/*"], "js": ["content/injected.js"], "css": ["content/injected.css"], "run_at": "document_idle", "world": "ISOLATED" } ] } ה-DOM מוכן, משאבים עדיין נטענים כדי לשנות מבנה לפני רינדור
chrome.scripting.executeScript אחרי DOMContentLoaded ברירת מחדל בטוחה לרוב המשימות
{
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": ["https://*.example.com/*"],
      "js": ["content/injected.js"],
      "css": ["content/injected.css"],
      "run_at": "document_idle",
      "world": "ISOLATED"
    }
  ]
}

להזרקה דינמית (מ-service worker או לפי דרישה), השתמשו ב-// background/service-worker.js chrome.action.onClicked.addListener(async (tab) => { await chrome.scripting.executeScript({ target: { tabId: tab.id, allFrames: false }, files: ['content/injected.js'], world: 'ISOLATED' }); }); :

// background/service-worker.js
chrome.action.onClicked.addListener(async (tab) => {
  await chrome.scripting.executeScript({
    target: { tabId: tab.id, allFrames: false },
    files: ['content/injected.js'],
    world: 'ISOLATED'
  });
});

השוואה בין עולם ISOLATED ו-MAIN

world גישה ל-DOM גישה ל-JS של הדף בידוד מתי להשתמש
ISOLATED מלאה אין גבוה ברירת מחדל
MAIN מלאה מלאה נמוך Monkey-patching, יירוט API

שימוש בעולם ISOLATED בטוח פי 10 מעולם MAIN לרוב המשימות, מכיוון שהוא מונע התנגשויות משתנים מקריות. world: 'MAIN' מעניק גישה למשתני הדף אך מקריב בידוד—השתמשו רק כשבאמת נחוץ (לדוגמה, יירוט קריאות API מקוריות).

למה סקריפט תוכן נכשל בדפי SPA?

בניווט בצד הלקוח, הדפדפן אינו טוען מחדש את סקריפט התוכן. MutationObserver על אלמנט ה- הוא דרך אמינה לזהות שינויי נתיב—הוא יעיל פי 5 מסקר עם setInterval במעברים תכופים.

let lastUrl = location.href;
const urlObserver = new MutationObserver(() => {
  if (location.href !== lastUrl) {
    lastUrl = location.href;
    onNavigate(location.href);
  }
});
urlObserver.observe(document.querySelector('title') ?? document.head, {
  subtree: true,
  characterData: true,
  childList: true
});

עבודה עם ה-DOM

סקריפט מוזרק רואה את כל ה-DOM, כולל Shadow DOM. לתוכן דינמי (SPA), MutationObserver הוא חובה. דוגמה: הדגשת כל המחירים בדף:

function highlightPrices() {
    const walker = document.createTreeWalker(
        document.body,
        NodeFilter.SHOW_TEXT,
        {
            acceptNode(node) {
                return /\$[\d,]+\.?\d{0,2}/.test(node.textContent) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
            }
        }
    );
    const nodes = [];
    while (walker.nextNode()) nodes.push(walker.currentNode);
    nodes.forEach(node => {
        const span = document.createElement('span');
        span.innerHTML = node.textContent.replace(
            /(\$[\d,]+\.?\d{0,2})/g,
            '<mark class="ext-price-highlight">$1</mark>'
        );
        node.parentNode.replaceChild(span, node);
    });
}

const observer = new MutationObserver((mutations) => {
    for (const mutation of mutations) {
        if (mutation.addedNodes.length > 0) highlightPrices();
    }
});
observer.observe(document.body, { childList: true, subtree: true });
highlightPrices();

בפרויקט מסחר אלקטרוני לאחרונה, צמצמנו את זמן עיבוד ה-DOM מ-120ms ל-30ms לכל ניווט על ידי אצירת עדכונים ב-let lastUrl = location.href; const urlObserver = new MutationObserver(() => { if (location.href !== lastUrl) { lastUrl = location.href; onNavigate(location.href); } }); urlObserver.observe(document.querySelector('title') ?? document.head, { subtree: true, characterData: true, childList: true }); ושימוש ב-function highlightPrices() { const walker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, { acceptNode(node) { return /\$[\d,]+\.?\d{0,2}/.test(node.textContent) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP; } } ); const nodes = []; while (walker.nextNode()) nodes.push(walker.currentNode); nodes.forEach(node => { const span = document.createElement('span'); span.innerHTML = node.textContent.replace( /(\$[\d,]+\.?\d{0,2})/g, '<mark class="ext-price-highlight">$1</mark>' ); node.parentNode.replaceChild(span, node); }); } const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.addedNodes.length > 0) highlightPrices(); } }); observer.observe(document.body, { childList: true, subtree: true }); highlightPrices(); להליכה בעץ. אופטימיזציה זו הביאה להפחתה של 75% בזמן העיבוד.

תקשורת עם Background Service Worker

סקריפט התוכן אינו יכול לגשת ישירות ל-chrome.tabs, לכן השתמשו בשליחת הודעות. לסטרימינג דו-כיווני, הקימו פורט:

// content/injected.js
const port = chrome.runtime.connect({ name: 'content-stream' });
port.onMessage.addListener((msg) => {
  if (msg.type === 'DATA_CHUNK') appendChunk(msg.data);
});
port.postMessage({ type: 'START_STREAM', url: location.href });

התרחיש האופייני הוא בקשה חד-פעמית דרך // content/injected.js const port = chrome.runtime.connect({ name: 'content-stream' }); port.onMessage.addListener((msg) => { if (msg.type === 'DATA_CHUNK') appendChunk(msg.data); }); port.postMessage({ type: 'START_STREAM', url: location.href }); . ה-background חייב לקרוא ל-chrome.runtime.sendMessage עם true אם התגובה היא אסינכרונית.

איך להימנע מהתנגשויות סגנון בעת הזרקת סקריפט תוכן?

שתי גישות: Shadow DOM לבידוד UI מלא (מספק בידוד סגנון של 100%), או CSS עם ספציפיות גבוהה וקידומות מחלקות ייחודיות (לדוגמה, ext-). אם הדף אוכף CSP מחמיר, הזריקו סגנונות דרך chrome.scripting.insertCSS מה-service worker.

העברת נתונים מהדף לסקריפט התוכן

מכיוון שההקשרים של JavaScript מבודדים, השתמשו ב-window.postMessage מסקריפט הדף (או עולם MAIN) והאזינו בסקריפט התוכן עם אימות event.source === window.

מה כלול בעבודה

פיתוח סקריפט תוכן מפתח כולל:

  • הגדרת manifest והצהרת סקריפט
  • טיפול בניווט SPA ותוכן דינמי
  • אינטגרציה עם background service worker דרך הודעות
  • הבטחת בידוד סגנון ועמידה ב-CSP
  • בדיקות על דפי יעד (עד 10 אתרים)
  • מתן תיעוד ותמיכה

בעיות אופייניות ופתרונות

בעיה נפוצה: סקריפט תוכן מפסיק לפעול אחרי מעבר SPA. פתרון: MutationObserver על . בעיה נוספת: CSP חוסם סגנונות מובנים—השתמשו ב-<code>allFrames: true</code>. לביצועים, הריצו פעולות DOM כבדות ב-<code>requestAnimationFrame</code> ומשימות בזמן סרק ב-<code>requestIdleCallback</code>.

סיבוכים נוספים
  • אם הדף משתמש ב-Shadow DOM, ודאו שסקריפט התוכן שלכם חודר כראוי לשורשי צל פתוחים. שורשים סגורים אינם נגישים.
  • כדי להזריק לתוך iframes, הגדירו allFrames: true בהגדרת הסקריפט.

עם 5+ שנים בשוק ולמעלה מ-30 פרויקטים שנמסרו, אנו מביאים מומחיות מוכחת בפיתוח תוספי דפדפן. אנו מבטיחים ביצועים אמינים של התוסף ב-Chrome, Edge ו-Opera. צרו קשר להערכת פרויקט או להזמנת סקריפט תוכן מותאם. קבלו ייעוץ—המהנדסים שלנו יעזרו ליישם סקריפט תוכן בכל מורכבות.