הנכסים של האתר (CSS, JS, SCSS) לא נכתבים ידנית ל-<head>. הקוד רושם אותם ב-PAGE, והליבה מפיקה מהם את התגים, מוסיפה גרסה לכתובת, מקמפלת SCSS ומאחדת קבצים לקבוצות. בעמוד הזה: איך רושמים נכסים, איך עובד .scss.css, איך בונים קבוצות minify, איפה מנהלים סקריפטים חיצוניים, ואיך הגרסה (attaches_version) מנקה מטמונים.
רישום נכס#
הרישום נעשה מקוד ה-PHP של ה-theme, של הבקר או של application/includes. החתימות המלאות ב-PAGE API וב-ref-page; כאן מה שחשוב לצינור:
// בתוך TEMPLATE_default::index() או בבקר
PAGE::add_asset("themes/default/style.scss.css"); // head, בסוף הרשימה
PAGE::add_asset("themes/default/app.js", false, "body_end"); // סוף ה-body
PAGE::add_asset_advanced("themes/default/slider.js", [
"area" => "body_end",
"defer" => true,
]);
PAGE::add_asset_advanced("themes/default/chat.js", [
"after_user_intraction" => true, // נטען רק בלחיצה או במקש הראשון
]);
כל נכס נפלט כתג בהתאם לסיומת. לכתובת יחסית מתווספים פרוטוקול ו-original_site_url, ולכל כתובת (CSS וגם JS) מתווסף ?ver=<attaches_version> (MISC::add_querystring_var), כך שהדפדפן וה-CDN מביאים גרסה חדשה אחרי שהגרסה עולה.
| אפשרות | התנהגות ב-CSS | התנהגות ב-JS |
|---|---|---|
async | preload ואז החלפה ל-media=print | מאפיין async |
defer | לא רלוונטי | מאפיין defer |
print | התוכן עובר FILES::scss($src) ומוטמע ב-<style> (אם נכשל: תג link) | לא רלוונטי |
after_user_intraction | הנכס לא נפלט ב-HTML, ונטען ע"י apply_after_interaction אחרי האינטראקציה הראשונה | כנ"ל |
רישום באותה כתובת פעמיים מחליף את הרישום הקודם ולא מכפיל אותו. prepend מכניס לראש הרשימה, ו-add_asset_advanced תמיד מוסיף לסוף.
SCSS: כתובות .scss.css#
הדפדפן לא יודע לטעון SCSS, אז הליבה מגישה קבצי SCSS מתחת לכתובת שנגמרת ב-.scss.css. ה-ROUTER מזהה את הסיומת ומעביר ל-minify::scss:
| כתובת | מה קורה |
|---|---|
/assets/<path>.scss.css | המקור נקרא מ-<core_path>/assets/<path> (ספריות הליבה) |
/<path>.scss.css | המקור נקרא מתיקיית האתר, <path>.scss |
כלומר ב-HTML כותבים themes/default/style.scss.css, ועל הדיסק יושב themes/default/style.scss. FILES::scss($file) עושה את העבודה:
- מסיר query ו-hash מהכתובת. כתובת חיצונית (עם דומיין אחר) מחזירה
false. - מאתר את קובץ המקור. אם אין
.scssאבל יש.cssפיזי באותו שם, מוחזר תוכן ה-CSS כמות שהוא. קובץ.cssרגיל נקרא ישירות. - בודק מטמון:
cache/<SERVER_NAME>/scss/<file>ver=<attaches_version>.css. קובץ מטמון ריק נחשב שריד מכתיבה שנקטעה ומקומפל מחדש. - מקמפל עם ScssPhp בפלט
COMPRESSED, כשתיקיית המקור היא נתיב ה-@import. כך@import "variables"בתוךstyle.scssמוצא את_variables.scssשלידו. - מתקן
url(...)יחסיים לנתיבים מוחלטים משורש האתר (נתיבים עםhttp,data:או/בתחילתם נשארים). - כותב את המטמון ומחזיר את ה-CSS. כשל קומפילציה (חריגה של ScssPhp) מחזיר
false.
// themes/default/style.scss
@import "variables";
@import "header";
.hero {
padding-inline: 1rem;
background: $brand;
}
כשהקומפילציה נכשלת (קובץ חסר, שגיאת תחביר, @import שלא נמצא) minify::scss עונה 500 עם Cache-Control: no-store וגוף scss compile failed. זה מכוון: תשובה ריקה עם 200 הייתה נשמרת ב-CDN לפי ה-ver והאתר היה נשאר בלי עיצוב. אם האתר נראה בלי סגנונות, פתחו את כתובת ה-.scss.css ישירות ובדקו את הסטטוס.
בקוד חדש ב-.scss של האתר השתמשו בתכונות לוגיות (padding-inline, margin-inline-start, inset-inline-end) ולא ב-left ו-right. האתר יכול להיות RTL.
קבוצות minify#
בעמוד רגיל כל נכס הוא בקשה נפרדת. קבוצת minify מאחדת כמה קבצים לבקשה אחת, minify/<id>.js או minify/<id>.css. הקבוצות מוגדרות בשתי טבלאות:
| טבלה | שדות עיקריים |
|---|---|
minify_groups | id, name, type (js או css), area (head, body_start, body_end), async, theme (ריק = כל ה-themes), ord |
minify_files | id, url (נתיב הקובץ מתיקיית האתר), group_id, ord |
הניהול בפאנל minify של האדמין (ADMINMODULE_minify): רשימת קבוצות, ולחיצה כפולה על קבוצה פותחת את רשימת הקבצים שלה. שינוי בפאנל מנקה את מפתחות המטמון minify_groups ו-minify.
בטעינת העמוד, PAGE::load קורא את שתי הטבלאות (מהמטמון, 30 יום) ורושם כל קבוצה שה-theme שלה ריק או שווה ל-theme הנוכחי. קבצים ששייכים לקבוצה לא נפלטים בנפרד. אפשר גם לרשום קבוצה ידנית:
PAGE::add_asset_group(3); // מזהה הקבוצה ב-minify_groups
מה minify::index עושה#
- טוען את הקבוצה לפי ה-
idשבכתובת. - JS: מדביק את כל הקבצים לפי
ordומעביר ב-JShrink. - CSS: קבצי
.scss.cssעובריםFILES::scss, שאר הקבצים נטענים ב-include(), וכלurl(...)יחסי נכתב מחדש לנתיב מוחלט. התגובה נשלחת עםExpiresו-Cache-Controlשל שבוע, ועם304כשהדפדפן שלחIf-Modified-Sinceחדש מספיק. - אם התוצאה אינה ריקה היא נכתבת ל-
cache/<SERVER_NAME>/minify/<id>.<type>ver=<ver>.<type>(קובץ זמני ואזrename, כדי שקורא לא יתפוס קובץ חצי כתוב). תוצאה ריקה לא נשמרת.
בקוד הליבה לא נמצא קורא של קובץ המטמון הזה בצד PHP (ל-scss/ יש, ב-cache_php_check). לא אימתתי איך קבצי minify/ מוגשים בבקשות חוזרות, כנראה לפי כללי שרת האינטרנט וה-CDN והגרסה שבכתובת.
קבצי CSS בקבוצה נטענים ב-include(), לא ב-file_get_contents: כל <?php שבתוכם יתבצע (CORE-26). רשמו בקבוצות רק קבצים שאתם שולטים בהם, ושמרו על הרשאות כתיבה מצומצמות לתיקיות האתר. כמו כן, קובץ JS חסר בקבוצה מסיים את הבקשה עם not found - <path>, וקבוצה של CSS שנבנית פעמיים באותו תהליך תיכשל על הצהרה כפולה של הפונקציה compress.
סקריפטים חיצוניים וניהול תגיות#
לסקריפטים של צד שלישי (אנליטיקס, פיקסלים, צ'אט) יש שני מנגנונים, ושניהם בלי שינוי קוד:
| פאנל | טבלה | מה זה |
|---|---|---|
Scripts (ADMINMODULE_Scripts) | scripts | סקריפט או תג HTML גולמי, עם area (head, body_start, body_end) ו-is_active. נפלט ב-HTML ע"י PAGE::output, ממוין לפי ord, וקיים רק באתר הציבורי. הרשימה במטמון scripts ל-48 שעות, והפאנל מנקה אותה |
Tag manager (ADMINMODULE_tag_manager) | tag_manager_groups, tag_manager | קבוצות של תגים, עם environment (all, dev, production), area, page_key, is_after_done ו-is_active |
תגי ה-tag manager לא נכתבים ל-HTML של העמוד. הם מוגשים כ-JS מהכתובת /tag_manager.js?id=<group_id>, שמחזירה applyTags([...]), ו-system.js מזריק כל תג למקום שנבחר (head, body_start או body_end). את תג ה-<script src> של קבוצה מסוימת מוסיפים בעצמכם (למשל כנכס או כסקריפט בפאנל Scripts); הליבה מוסיפה אוטומטית רק את tag_manager.js?id=system, כשקיים הקובץ system/system_tags.json. אפשר לסנן לפי מפתח: ?keys=checkout,cart מחזיר רק תגים עם page_key מתאים, ותג בלי page_key נטען תמיד. תגים עם environment שלא תואם ל-CONFIG::$environment מסוננים בשרת. תג שסומן is_after_done נטען רק אחרי שכל הסקריפטים החיצוניים של אותה קבוצה הסתיימו.
התשובה של tag_manager.js עם no-store, ולכל כתובת מקומית בתוכה (src או href) מתווסף ver. התגים עצמם נשמרים במטמון הפריטים tag_manager.
שני המנגנונים מזריקים קוד שרירותי לכל דף באתר, ללא סינון. הרשאה לערוך אותם שקולה להרשאה להריץ JS אצל כל המבקרים (ראו הקשחה). בטלו את is_active במקום למחוק כשמבררים בעיה.
attaches_version: ניקוי מטמונים#
attaches_version היא שורה בטבלת params (קריאה: PARAMS::get('attaches_version')). היא מספר שעולה ב-1 בכל פעולת "ניקוי מטמון" מהאדמין (Tools::delete_cache) ובכל עדכון גרסה של הליבה. הערך משתתף ב:
?ver=בכל נכס ש-PAGEפולט.- שם קובץ המטמון של SCSS ושל קבוצות minify.
- הכתובת
tag_manager.js?id=...&ver=....
כך נוצרת כתובת חדשה, והדפדפן וה-CDN מושכים גרסה חדשה בלי ניקוי ידני. המשמעות המעשית אחרי פריסה: שינוי ב-.scss או ב-.js לא יופיע עד שמנקים מטמון (ראו cache-admin).
שתי נקודות שלא מכוסות ע"י הגרסה: ייבוא מודולי Vue בפאנל הניהול מוסיף ?ver= עם time() (CORE-44), כך שהפאנל מוריד אותם מחדש בכל טעינה; וקבצי הליבה הסטטיים תחת /assets/ מוגשים דרך PHP עם readfile וללא Cache-Control או Last-Modified (CORE-57), כך שכל קובץ עובר את ה-bootstrap של המערכת.
ראו גם#
- PAGE API: חתימות
add_asset,add_asset_advanced,add_asset_groupושאר הממשק - Themes: איפה רושמים נכסים של theme
- תגיות SEO: מה עוד נכנס ל-
<head> - Frontend runtime:
system.jsוטעינת הנכסים בדפדפן - מצב הסוואה: שינוי הכתובות
minify/ו-tag_manager.jsב-HTML - ניקוי מטמון ו-מטמון עמודים