יישום איזומורפי עם React ו- Nashorn

1. סקירה כללית

במדריך זה נבין מהי בדיוק אפליקציה איזומורפית. נדון גם בנאשורן, מנוע ה- JavaScript המצורף ל- Java.

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

2. קצת היסטוריה

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

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

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

עד מהרה החלו להופיע מסגרות רבות לפיתוח חזיתי, ששיפרו מאוד את חוויית היזם. החל מ- AngularJS מגוגל, תגובה מפייסבוק ומאוחר יותר, Vue, הם התחילו לתפוס את תשומת ליבם של המפתח.

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

חוויה סוחפת במכשירי כף יד מהירים יותר ויותר מחייבת עיבוד רב יותר מצד הלקוח.

3. מהי אפליקציה איזומורפית?

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

למרות זאת, אפשר גם להשתמש באותה מסגרת בצד השרת וליצור את אותו ממשק משתמש.

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

לגישה זו ישנם יתרונות עליהם נדון בהמשך.

יישומי רשת כאלה נקראים Isomorphic או Universal. כעת השפה בצד הלקוח היא באופן בלעדי JavaScript. לפיכך, כדי שאפליקציה איזומורפית תפעל, עלינו להשתמש ב- JavaScript גם בצד השרת.

Node.js היא ללא ספק הבחירה הנפוצה ביותר לבנות יישום שניתן על ידי השרת.

4. מה זה נאשורן?

אז היכן נכנס נאשורן ולמה עלינו להשתמש בו? נאשורן הוא מנוע JavaScript שארוז כברירת מחדל עם Java. לפיכך, אם כבר יש לנו יישום אחורי אינטרנט בג'אווה ורוצים לבנות אפליקציה איזומורפית, Nashorn די שימושי!

Nashorn שוחרר כחלק מג'אווה 8. זה מתמקד בעיקר בהתרת יישומי JavaScript מוטבעים בג'אווה.

נאשורן מרכיב JavaScript בזיכרון ל- Java Bytecode ומעביר אותו ל- JVM לביצוע. זה מציע ביצועים טובים יותר בהשוואה למנוע הקודם, קרנף.

5. יצירת אפליקציה איזומורפית

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

  • חזית: ממשק פשוט מבוסס React.js
  • Back-end: Back-end פשוט של Spring Boot עם Nashorn לעיבוד JavaScript

6. יישום חזיתי

נשתמש React.js ליצירת ממשק הקצה שלנו. React היא ספריית JavaScript פופולרית לבניית אפליקציות של עמודים בודדים. זה עוזר לנו לפרק ממשק משתמש מורכב לרכיבים היררכיים עם מצב אופציונלי ומחייב נתונים בכיוון אחד.

תגובה מנתחת את ההיררכיה הזו ויוצרת מבנה נתונים בזיכרון שנקרא DOM וירטואלי. זה עוזר ל- React למצוא שינויים בין מצבים שונים ולבצע שינויים מינימליים ב- DOM של הדפדפן.

6.1. רכיב תגובה

בואו ניצור את רכיב ה- React הראשון שלנו:

var App = React.createClass ({displayName: "App", handleSubmit: function () {var last = this.state.data [this.state.data.length-1]; var secondLast = this.state.data [this .state.data.length-2]; $ .ajax ({url: '/ next /' + last + '/' + secondLast, dataType: 'text', success: function (msg) {var series = this.state. data; series.push (msg); this.setState ({data: series});} .bind (this), error: function (xhr, status, err) {console.error ('/ next', status, err .toString ());} .bind (this)});}, componentDidMount: function () {this.setState ({data: this.props.data});}, getInitialState: function () {return {data: []};}, render: function () {return (React.createElement ("div", {className: "app"}, React.createElement ("h2", null, "מחולל פיבונאצ'י"), React.createElement ( "h2", null, this.state.data.toString ()), React.createElement ("קלט", {type: "submit", ערך: "הבא", onClick: this.handleSubmit})));}} );

עכשיו, בואו נבין מה עושה הקוד שלעיל:

  • ראשית, הגדרנו רכיב בכיתה ב- React שנקרא "App"
  • הכי פונקציה חשובה בתוך רכיב זה היא "לדקלם", שאחראי על יצירת ממשק המשתמש
  • סיפקנו סגנון className שהרכיב יכול להשתמש בו
  • אנו משתמשים במצב הרכיב כאן כדי לאחסן ולהציג את הסדרה
  • בעוד שהמדינה מאותחלת כרשימה ריקה, היא מביאה נתונים המועברים לרכיב כאביזר כאשר הרכיב מתקבל
  • לבסוף, בלחיצת כפתור "הוסף", מתבצעת שיחת jQuery לשירות REST
  • השיחה מביאה את המספר הבא ברצף ומוסיפה אותו למצב הרכיב
  • שינוי במצב הרכיב מחדש את הרכיב מחדש

6.2. באמצעות רכיב התגובה

תגובה מחפשת אלמנט בשם "div" בדף ה- HTML כדי לעגן את תוכנו. כל שעלינו לעשות הוא לספק דף HTML עם רכיב "div" זה ולטעון את קבצי JS:

   שלום תגובה ReactDOM.render (React.createElement (אפליקציה, {נתונים: [0,1,1]}), document.getElementById ("שורש")); 

אז בואו נראה מה עשינו כאן:

  • אָנוּ ייבא את ספריות ה- JS הנדרשות, תגיב, תגובת דומיין ו- jQuery
  • לאחר מכן הגדרנו אלמנט "div" הנקרא "שורש"
  • ייבאנו גם את קובץ JS עם רכיב React שלנו
  • לאחר מכן, קראנו לרכיב ה- React "App" עם נתוני זרעים, שלושת המספרים הראשונים של פיבונאצ'י

7. יישום אחורי

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

7.1. תלות Maven

ליישום הפשוט שלנו, נשתמש ב- JSP יחד עם Spring MVC, לכן נוסיף כמה תלות ל- POM שלנו:

 org.springframework.boot spring-boot-starter-web org.apache.tomcat.embed tomcat-embed-jasper provided 

הראשון הוא התלות הרגילה של אתחול האביב ליישום אינטרנט. השני נדרש כדי להרכיב JSPs.

7.2. בקר אינטרנט

בואו ניצור כעת את בקר האינטרנט שלנו, שיעבד את קובץ ה- JavaScript שלנו ויחזיר HTML באמצעות JSP:

מחלקה ציבורית @ Controller MyWebController {@RequestMapping ("/") ציבורי מחרוזת (מודל מפה) זורק Exception {ScriptEngine nashorn = ScriptEngineManager חדש (). GetEngineByName ("nashorn"); nashorn.eval (FileReader חדש ("static / js / react.js")); nashorn.eval (FileReader חדש ("static / js / react-dom-server.js")); nashorn.eval (FileReader חדש ("static / app.js")); אובייקט html = nashorn.eval ("ReactDOMServer.renderToString (" + "React.createElement (App, {data: [0,1,1]})" + ");"); model.put ("content", String.valueOf (html)); להחזיר "אינדקס"; }}

אז מה בדיוק קורה כאן:

  • אנו מביאים מופע של ScriptEngine מסוג נאשורן מ ScriptEngineManager
  • אז אנחנו טען ספריות רלוונטיות ל- React, react.js ו- react-dom-server.js
  • אנו טוענים גם את קובץ JS שלנו שמכיל את רכיב התגובה שלנו "App"
  • לבסוף, אנו מעריכים קטע JS היוצר אלמנט תגובה עם הרכיב "App" וכמה נתוני זרע
  • זה מספק לנו פלט של React, קטע HTML כ- לְהִתְנַגֵד
  • אנו מעבירים את קטע ה- HTML הזה כנתונים לתצוגה הרלוונטית - JSP

7.3. JSP

עכשיו, איך נעבד את קטע ה- HTML הזה ב- JSP שלנו?

נזכיר ש- React מוסיף אוטומטית את הפלט שלו לאלמנט בשם "div" - "שורש" במקרה שלנו. למרות זאת, נוסיף ידנית את קטע ה- HTML שנוצר בצד השרת לאותו אלמנט ב- JSP שלנו.

בואו נראה איך ה- JSP נראה עכשיו:

   שלום תגיב! $ {content} ReactDOM.render (React.createElement (אפליקציה, {נתונים: [0,1,1]}), document.getElementById ("שורש")); 

זה אותו דף שיצרנו קודם, למעט העובדה שהוספנו את קטע ה- HTML שלנו לחלוקה "שורש", שהיה ריק קודם.

7.4. בקר מנוחה

לבסוף, אנו זקוקים גם לנקודת קצה REST בצד השרת אשר נותנת לנו את מספר פיבונאצ'י הבא ברצף:

@RestController מחלקה ציבורית MyRestController {@RequestMapping ("/ next / {last} / {secondLast}") אינדקס ציבורי int (@PathVariable ("last") int last, @PathVariable ("secondLast") int secondLast) זורק חריג {return last + secondLast; }}

שום דבר לא מפואר כאן, רק בקר Spring REST פשוט.

8. הפעלת האפליקציה

כעת, לאחר שסיימנו את חזית הקצה שלנו כמו גם את הקצה האחורי שלנו, הגיע הזמן להריץ את היישום.

עלינו להתחיל ביישום אתחול האביב כרגיל, תוך שימוש בכיתת האתחול:

@SpringBootApplication מחלקה ציבורית יישום מרחיב את SpringBootServletInitializer {@Override מוגן SpringApplicationBuilder להגדיר (יישום SpringApplicationBuilder) {להחזיר application.sources (Application.class); } ראשי ריק סטטי ציבורי (String [] args) זורק Exception {SpringApplication.run (Application.class, args); }}

כשאנחנו מנהלים את השיעור הזה, Spring Boot מרכיב את ה- JSP שלנו והופך אותם לזמינים ב- Tomcat מוטבע יחד עם שאר יישומי האינטרנט.

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

בואו להבין את השתלשלות האירועים:

  • הדפדפן מבקש דף זה
  • כאשר מגיעה הבקשה לדף זה, בקר האינטרנט של Spring מעבד את קבצי ה- JS
  • מנוע Nashorn מייצר קטע HTML ומעביר אותו ל- JSP
  • JSP מוסיף קטע HTML זה לאלמנט div "שורש", ולבסוף מחזיר את דף ה- HTML לעיל
  • הדפדפן מעבד את ה- HTML, ובינתיים מתחיל להוריד קבצי JS
  • לבסוף, הדף מוכן לפעולות בצד הלקוח - אנו יכולים להוסיף מספרים נוספים בסדרה

הדבר החשוב שיש להבין כאן הוא מה קורה אם React מוצא קטע HTML באלמנט היעד "div". במקרים כאלו, תגובה משווה את השבר הזה למה שיש לו ולא מחליף אותו אם הוא מוצא שבר קריא. זה בדיוק מה שמאפשר עיבוד בצד השרת ואפליקציות איזומורפיות.

9. מה עוד אפשרי?

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

  • יצרנו רק רכיב תגובה אחד ביישום שלנו כשבמציאות זה יכול להיות כמה מרכיבים היוצרים היררכיה אשר מעבירים נתונים דרך אביזרים
  • היינו רוצים צור קבצי JS נפרדים לכל רכיב לשמור על ניהולם ולניהול התלות שלהם באמצעות "ייצוא / דרישה" או "ייצוא / ייבוא"
  • יתרה מכך, יתכן שלא ניתן יהיה לנהל מדינה רק בתוך רכיבים; אולי נרצה להשתמש ספריית ניהול מדינה כמו Redux
  • יתר על כן, ייתכן שיהיה עלינו לקיים אינטראקציה עם שירותים חיצוניים כתופעות לוואי של פעולות; זה עשוי לדרוש מאיתנו להשתמש דפוס כמו redux-thunk או Redux-Saga
  • והכי חשוב, נרצה מינוף JSX, סיומת תחביר ל- JS לתיאור ממשק המשתמש

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

הנוהג המקובל במקרים כאלה הוא למנף מקבץ מודולים כמו Webpack או Rollup. מה שהם עושים בעיקר הוא לעבד את כל קבצי המקור של React ולצרור אותם לקובץ JS יחיד יחד עם כל התלות. זה תמיד דורש מהדר JavaScript מודרני כמו Babel כדי לאסוף JavaScript כדי להיות תואם לאחור.

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

10. היתרונות של אפליקציה איזומורפית

אז דיברנו הרבה על אפליקציות איזומורפיות ואפילו יצרנו יישום פשוט עכשיו. אבל מדוע בכלל צריך להיות לנו אכפת מזה? בואו להבין כמה מהיתרונות העיקריים בשימוש באפליקציה איזומורפית.

10.1. עיבוד עמוד ראשון

אחד היתרונות המשמעותיים ביותר של אפליקציה איזומורפית הוא העיבוד המהיר יותר של העמוד הראשון. ביישום האופייני לעיבוד צד הלקוח, הדפדפן מתחיל להוריד את כל חפצי JS ו- CSS.

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

10.2. ידידותי SEO

אַחֵר התועלת שמצוטטת לעתים קרובות עם עיבוד בצד השרת קשורה ל- SEO. ההערכה היא כי בוטים לחיפוש אינם מסוגלים לעבד JavaScript ולכן אינם רואים דף אינדקס המוצג בצד הלקוח באמצעות ספריות כמו React. לכן דף שניתנו בצד השרת ידידותי יותר ל- SEO. ראוי לציין, עם זאת, כי הרובוטים של מנועי החיפוש המודרניים טוענים שהם מעבדים JavaScript.

11. מסקנה

במדריך זה עברנו את המושגים הבסיסיים של יישומים איזומורפיים ומנוע ה- JavaScript של נאשורן. עוד בדקנו כיצד לבנות אפליקציה איזומורפית עם Spring Boot, React ו- Nashorn.

לאחר מכן דנו באפשרויות האחרות להרחיב את היישום החזיתי ואת היתרונות של שימוש באפליקציה איזומורפית.

כמו תמיד, ניתן למצוא את הקוד ב- GitHub.