MasterScripter

V8Js: ג'אווהסקריפט בצד שרת עם PHP

הידעתם? ג'אווה סקריפט היא השפה הפופולארית ביותר כבר 5 שנים ברציפות.
אבל אתם בטח יודעים את זה אחרי שקראתם את הפוסט של שלומקה על סקר המפתחים של Stack Overflow.

כמעט לא ניתן למצוא היום אתר שלא עושה שימוש בסיסי לפחות בשפה ורוב האתרים עושים שימוש נרחב בשפה – בין היתר על ידי שימוש בפריימוורקים וספריות כדוגמת Angular, React, Vue וכו'.
הספריות הללו לוקחות על עצמן את האחריות הכבדה שברנדור ה – HTML ואם לומר את האמת – הן עושות את זה דיי טוב.

אבל – לרנדור ה – HTML בדפדפן יש השלכות:

זמן טעינה איטי יותר

רנדור ראשוני של התוכן (כלומר ה – HTML) בצד-לקוח איטי בהרבה מאשר בצד-שרת ויש "דף לבן" עד שמסתיים תהליך ההורדה של הקוד והביצוע שלו.

קוד מקור בלתי נראה

מכיוון שרנדור ה – HTML נעשה בצד-הלקוח, קוד המקור הראשוני לא מייצג את קוד המקור בפועל.
זה עשוי להביא לפגיעה בקידום – הנראות של קוד האתר נפגעת. נכון, מנוע החיפוש של גוגל מסוגל לצפות במרבית התוכן שמרונדר בצד-לקוח (תוכן דינמי),
אבל מעבר לכך שמנועי חיפוש רבים לא, גם גוגל מעדיפה שתרנדרו את האתרים שלכם בצד השרת מטעמי ביצועים.

קבלו את הדוגמה ממדריך Angular:

https://angular.io/resources/live-examples/toh-6/ts/eplnkr.html

אם נסתכל על קוד המקור (בקובץ index.html), אפשר לראות שבתוך תגית ה – body יש רק אלמנט אחד:

<my-app></my-app>

הדרך האידיאלית להתמודד עם הבעיות האלו היא לבצע חלוקת תפקידים:

  • את המסמך הראשוני, יש לרנדר בצד-שרת
  • עדכונים למסמך יש לרנדר בצד-לקוח

אבל איך אפשר לעשות את זה, אם הספריות הפופולריות ביותר, Angular ו – React, לוקחות על עצמן את הרנדור?
התשובה היא להריץ את הספריות הללו גם בשרת (כדי לרנדר את המסמך הראשוני) וגם בדפדפן (כדי לעדכן את המסמך).

V8: להריץ Javascript בשרת

V8 הוא מנוע ג'אווהסקריפט בקוד פתוח שנבנה על-ידי גוגל;
גם הדפדפן של גוגל (כרום) וגם סביבת הפיתוח Node.js מתבססות על המנוע בשביל להריץ ג'אווהסקריפט.

ואכן Node.js היא הפתרון הפופולרי ביותר לרנדור מסמך HTML בצד השרת על-ידי שימוש בג'אווהסקריפט – הרי זה ממש המטרה שלשמה היא נוצרה.
למפתחים ב – Angular יש את Angular Universal – רנדור Angular בצד-שרת שנבנתה עבור שרת Node.js.

בעצם, שימוש ב – Node.js מאפשר רנדור של כל ספריית ג'אווהסקריפט בצד השרת.

אבל מה איתנו – מפתחי PHP?! האם נותרנו מאחור?
התשובה מורכבת. אמנם יש פתרון – הרי בשביל מה אני כותב את הפוסט הזה? אבל הפתרון מעט מסורבל וקשה להבנה.
למזלכם – אני פה כדי לעשות את זה קל להבנה ופשוט לעיכול! הכירו:

V8Js – הרחבה ל – PHP שמריצה Javascript

V8Js מטמיעה את מנוע הג'אווהסקריפט של גוגל V8 ב – PHP ובעצם מאפשרת למפתחים להריץ קוד JS בארגז חול – כלומר ללא חשש שהקוד יפגע בתוכנית האם שרצה.
ההרחבה כתובה בקוד-פתוח ומציעה מספר מצומצם יחסית של פקודות – נעבור עליהן בהמשך המאמר.

דף ההרחבה ב – GitHub

אוקיי, אני חושב שמיצינו את ההקדמה והגיע הזמן לדבר האמיתי.
וודאו שאתם מצויידים ב – PHP 5.3.3 ומעלה, הגרסה הנמוכה ביותר שתומכת בהרחבה.
עם זאת, קחו בחשבון שבמאמר אני עושה שימוש ב – PHP 7 ולכן (ובלי קשר) אני ממליץ לכם להשתדרג. אבל למה שתקשיבו לי? אם יש מישהו להקשיב לו זה שלומקה שרשם מאמר על PHP 7

איך להתקין V8Js

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

משתמשי ווינדוס – יש לי חדשות טובות ורעות: הטובות הן שאני אדריך אתכם צעד-צעד איך להתקין את ההרחבה.
הרעות – זה הולך להיות מסורבל. שנתחיל?

שלב ראשון: איסוף מידע

כדי להתקדם, עלינו לברר שני דברים:

האם Thread Safety מופעל?

כדי לבדוק, יש לכם שתי אפשרויות:

  1. צרו קובץ PHP בשם phpinfo.php שמכיל קריאה לפונקציה phpinfo() וחפשו "Thread Safety"
  2. בשורת הפקודות (CMD), רשמו : php -i | findstr "Thread"

אם רשום Disabled אזי Thread Safety מכובה, אחרת הוא מופעל (Enabled).

גרסת PHP

כדי לבדוק מהי גרסת ה – PHP, יש לכם שתי אפשרויות:

  1. פתחו שנית את הקובץ phpinfo.php , גרסת ה – PHP תופיע בראש העמוד
  2. בשורת הפקודות (CMD) רשמו: php -v

* אם השימוש בשורת הפקודות לא עובד ומתקבלת שגיאה, עליכם לנווט אל התיקייה שבה מותקן PHP

x86 או x64?

כדי לבדוק, פתחו את "המחשב שלי" ("מחשב זה", "This Computer"), לחצו קליק ימני ובחרו במאפיינים / Properties ובדקו מה מופיע תחת "System Type" / "סוג מערכת".
ככה זה נראה ב – Windows 10:

סוג מערכת

אוקיי אוקיי! יש לנו את כל מה שאנחנו צריכים – שימו גיטרות! (או: עברו לשלב השני)

שלב שני: להוריד את הקבצים הדרושים

התקנת הרחבות PHP בווינדוס יכולה להיעשות בשתי דרכים:

  1. לקמפל את ההרחבה לתוך PHP
  2. לטעון קבצי DLL

האפשרות השנייה היא גם הקלה יותר.
אם תיאלצו מסיבה כזו ואחרת לבחור באפשרות הראשונה, ניתן למצוא מידע נוסף בתיעוד הרשמי של PHP: התקנת הרחבה ל – PHP בווינדוס (אנגלית).
את ההרחבה עצמה ניתן להוריד כאן.

לפני שאתם ממשיכים לאפשרות הזאת – שווה לבדוק האם האפשרות השנייה רלוונטית עבורכם!

משתמש בשם Jan-E בפורום ApacheLounge משחרר גרסאות PHP שמכילות את קבצי ה – DLL של הספריה V8Js:
https://www.apachelounge.com/viewtopic.php?t=6359

ניתן לחלץ מההורדות שלו את קבצי ההרחבה של V8Js ולהוסיף אותם להתקנת ה- PHP שלכם. בואו נראה איך עושים את זה:

רשימת הקישורים מחולקת לפי גרסאות: PHP 5.3, PHP 5.4, PHP 5.5, PHP 5.6, PHP 7.0 ו – PHP 7.1.
בחרו את הקישור הרלוונטי עבורכם – לדוגמה, אם גרסת ה – PHP שלכם היא 7.0 x86 ו Thread Safety מכובה, הלינק הרלוונטי עבורכם הוא:

https://phpdev.toolsforresearch.com/php-7.0.17-nts-Win32-VC14-x86.zip

nts משמעותו Non Thread Safety.

אבל רגע! מה קורה אם גרסת ה – PHP שלכם היא 7.0.13?
במקרה כזה, נסו להתאים את הקישור לגרסה המתאימה:

https://phpdev.toolsforresearch.com/php-7.0.13-nts-Win32-VC14-x86.zip

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

שלב שלישי: חילוץ הקבצים המתאימים

את הקבצים הבאים יש לחלץ לתיקייה בה מותקנת PHP:

  • v8.dll
  • icui18n.dll (רק ב – php 7)
  • icuuc.dll (רק ב – php 7)

את הקובץ הבא יש לחץ לתיקייה ext שנמצאת בתוך התיקייה בה מותקנת PHP:

  • php_v8js.dll

שלב רביעי: הוספת ההרחבה

כעת, פתחו את הקובץ php.ini וחפשו "Windows Extensions".
מתחת להרחבה האחרונה הוסיפו את השורה הבאה:

extension=php_v8js.dll

הוספת ההרחבה V8Js לקובץ php.ini

בנוסף, וודאו שתיקיית ההרחבות מוגדרת – חפשו:

extension_dir = "ext"

אם השורה כתובה בהערה (מתחילה בנקודה-פסיק) מחקו את הנקודה-פסיק:

הגדרת תיקיית הרחבות בקובץ php.ini

שלב חמישי: אתחול השרת

הגענו לרגע האמת – אתחלו את השרת!
כדי לבדוק אם ההתקנה עברה בהצלחה:

פתחו את הקובץ phpinfo.php וחפשו "v8js".
אם המסך הבא מופיע, ההתקנה עברה בהצלחה:

V8Js מותקן

או:

פתחו את שורת הפקודות והריצו את הפקודה הבאה:

php -i | findstr "v8js"

אם המסך הבא מופיע, ההתקנה עברה בהצלחה:

v8js מותקן

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

אם ההתקנה לא עברה בהצלחה, נסו לעבור על המדריך מהתחלה.
רוב הסיכויים שהקבצים שהורדתם לא מתאימים לגרסת ה – PHP שמותקנת.

עדיין לא הצלחתם? כתבו לי בתגובות ואנסה לעזור!

ולברי המזל שהגיעו עד הלום, שנריץ קצת ג'אווהסקריפט בשרת, עם PHP?!

בקטנה: שלום עולם

בואו נתחיל בדוגמה קלילה.
צרו קובץ חדש בשם HelloWorld.php.

בשלב הראשון ניצור מופע מסוג V8Js:

בואו נתעמק בממשק של V8Js:

executeString

הפונקציה מקבלת קוד ג'אווהסקריפט (מחרוזת;string) ומחזירה את התוצאה של הרצת הקוד.
חשוב להבין שאנחנו לא נמצאים בסביבת דפדפן ולכן משתנים כמו window או document לא קיימים כאן!

מה כן זמין עבורנו?

הדפסה: print או var_dump

הפונקציה print מקבילה לפקודה echo  – מדפיסה מחרוזת.
הפונקציה var_dump זהה למקבילתה ב – PHP.

סיום הריצה: exit

הפונקציה exit מקבילה לפקודה exit ומסיימת את ריצת הסקריפט.

לדוגמה הבסיסית שלנו, זה מספיק. בואו נראה איך בפועל זה נראה (נסו לנחש מה יודפס):

אוקיי, קצת סדר בבלאגן:

המשתנה $script מכיל מערך פקודות ג'אווהסקריפט.
לאחר מכן נעשה ניסיון להריץ את המחרוזת (הפונקציה implode הופכת מערך למחרוזת).

מכיוון שהמחרוזת תקינה ולא נזרקה חריגה, הרצת הקובץ HelloWorld.php תדפיס על המסך שלכם שלום עולם!
המחרוזת "התוכנית נגמרה?" לא תופיע כי היא נקראה לאחר הפונקציה exit, שכזכור מסיימת את ריצת הסקריפט.

כמו שאמרתי, אי אפשר להשתמש במשתני דפדפן כמו window או document, אם ננסה:

נקבל שגיאה שאומרת לנו בדיוק את זה:

V8Js::compileString():1: ReferenceError: document is not defined

טעינת מודולים

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

זה נשמע מסובך, אבל בפועל זה משחק ילדים:

אם ננסה להריץ את הקובץ דרך V8Js:

נקבל שגיאה – מכיוון שטרם הגדרנו module loader:

V8Js::compileString():1: No module loader

אז בואו נגדיר אחד!

setModuleLoader

הפונקציה setModuleLoader מקבלת כפרמטר פונקציה (callable) –
שמקבלת מחרוזת שמייצגת את המודול שניסינו לטעון וצריכה להחזיר קוד ג'אווהסקריפט מוכן להפעלה.
ניתן ליישם בכל דרך שרוצים בהתאם לפרוייקט עליו אתם עובדים. דוגמה ליישום:

כעת, בכל פעם שבסקריפט תהיה קריאה ל – require, ה – Module Loader יחפש את הספריה בתיקייה scripts.
כך לדוגמה, כאשר נרשום:

require('react')

הפונקציה תקבל כפרמטר את המחרוזת react ותנסה להחזיר את הקובץ שנמצא בנתיב ./scripts/react.js

כעת, אם נריץ את הקובץ React.php עם ה – Module Loader שהגדרנו:

כעת המשתנה Example מוכן לשימוש ללא כל שגיאה!
כדי לרנדר אלמנט של React בשרת עלינו להשתמש בספרייה ReactDomServer:

וזהו זה! אם תיגשו לקובץ React.php תוכלו לראות על המסך את ההודעה: This is example.
אבל יותר חשוב, אם תסתכלו על קוד המקור, יתגלה לפניכם הקוד שרינדרנו בשרת:
<div data-reactroot="" data-reactid="1" data-react-checksum="-1940384550">This is Example</div>

ואם הגעתם עד לפה, אני שמח להגיד שהשגתי את מטרתי: הראתי לכם איך להריץ Javascript בשרת עם PHP – ולצאת מזה בחיים!

איך למנוע שגיאות ב – 60 שניות

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

דוגמה טובה היא הפונקציה console.log שנעשה בה שימוש רווח ולא זמינה ב – V8.
כדי להימנע משגיאות, נגדיר אותה:

שימו לב שאתם משתמשים ביכולת הזו בחכמה – ולא מייצרים שגיאות לוגיות!

אם הגעת עד לפה, הגיע הזמן להירשם לניוזלטר!

Summary
Article Name
V8Js - ג'אווהסקריפט בצד שרת עם PHP
Description
לרנדר HTML בדפדפן זה רע. אבל מה עושים כשספריית ה - Javascript שבה אתה משתמש אחראית על רנדור HTML? במילה אחת: V8Js
Author
Publisher Name
MasterScripter
Publisher Logo
תגיות: , ,
אודות 
hello world! אני יונתן, מתעסק בתכנות ופיתוח WEB פלוס מינוס מאז שאני זוכר את עצמי. ב2013 הקמתי את קבוצת סיזן ביחד השותף היקר שלי - שלומי שלומקה זק. ביום מתעסק בפיתוח ועיצוב אתרי אינטרנט ואפליקציות, עיצוב חוויית משתמש, הקמת מיזמים, ועוד..אבל מה שלא ידעתם עליי - זה שבלילה אני באטמן. אל תגלו לאף אחד!

תגובה אחת

  1. איתן

    11 באפריל 2017 - 5:55
    תגובה

    מעניין מאוד. תודה!

השאר/י תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *