es
Feedback
ToCode

ToCode

Ir al canal en Telegram

טיפים קצרים למתכנתים מאת ינון פרק

Mostrar más
1 419
Suscriptores
+124 horas
-17 días
-530 días
Archivo de publicaciones
ToCode
1 419
איך עובד פרויקט Rails עם ESBuild החלום של DHH עבור ריילס הוא לוותר על ה Build Step ופשוט לשלב בדף ה HTML את הקישורים לסקריפטים באמצעות ES Modules. בזכות התמיכה של דפדפנים ב HTTP2 וב Import maps הסיפור הזה אפילו עובד די טוב בפרויקטי ריילס המסתמכים על JavaScript. אבל כשאנחנו מוסיפים TypeScript וריאקט לתמונה העסק מסתבך ושלב בניה הופך הכרחי. גירסה 7 של ריילס שילבה ממשק סטנדרטי לבניית קבצי Front End שנקרא JS Bundling. מנגנון זה מאפשר לעבוד עם esbuild, webpack או rollup ולשלב אותם בתוך פרויקט ריילס. אבל מה שמיוחד ב JS Bundling בעולם של ריילס הוא שאין קובץ הגדרות אחד שעובד על כל הכלים ובמקום זה עלינו לבחור את אחד מהכלים ולבנות לו את קובץ ההגדרות בעצמנו. לפני כמה שבועות פרסמתי כאן מדריך שמסביר איך לשלב React ו TypeScript בפרויקט ריילס ושם הצעתי על הספריה vite-ruby. היום אני רוצה להראות מבנה פרויקט דומה אבל הפעם בעזרת esbuild ותוך שימוש ב JSBundling. יצירת הפרויקט והגדרות תחילה אני יוצר פרויקט ריילס חדש עם הפקודה:
$ rails new myapp -j esbuild
הפרויקט שנוצר כולל קובץ package.json עם הגדרת סקריפט לבניה:
  "scripts": {
    "build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets"
  },
בשביל להפעיל את הפרויקט משורת הפקודה אנחנו כותבים:
./bin/dev
זה גורם להפעלת הפקודות מתוך הקובץ Procfile שגם נוצר באותה תיקייה:
web: env RUBY_DEBUG_OPEN=true bin/rails server
js: yarn build --watch
פקודת ה js שם מפעילה את סקריפט הבנייה ומוסיפה לו את המתג watch. בצורה כזאת התהליך של js ימשיך לרוץ ולבנות מחדש את קבצי ה JavaScript כל פעם שיהיה שינוי בקבצים בעזרת esbuild. כשנרצה לבנות את הפרויקט לפרודקשן נפעיל:
./bin/rails assets:precompile
וזה יריץ אוטומטית את סקריפט ה build מקובץ ה package.json. בגלל פקודת הבניה שמוגדרת שם ESBuild יבנה את קבצי ה JavaScript וישמור אותם לתוך תיקיית app/assets/build. שם יאסוף אותם sprockets בגלל קובץ ההגדרות app/assets/config/manifest.js. זה תוכנו:
//= link_tree ../images
//= link_directory ../stylesheets .css
//= link_tree ../builds
בעזרת sprockets הקבצים יועתקו לתיקיית public וגם יקבלו תוספת של digest לשמם. אחרי בנייה אני מוצא את הקבצים הבאים שם:
$ ls public/assets/*.js
public/assets/actioncable-1c7f008c6deb7b55c6878be38700ff6bf56b75444a086fa1f46e3b781365a3ea.js
public/assets/actioncable.esm-06609b0ecaffe2ab952021b9c8df8b6c68f65fc23bee728fc678a2605e1ce132.js
public/assets/actiontext-78de0ebeae470799f9ec25fd0e20ae2d931df88c2ff9315918d1054a2fca2596.js
public/assets/actiontext.esm-328ef022563f73c1b9b45ace742bd21330da0f6bd6c1c96d352d52fc8b8857e5.js
public/assets/activestorage-503a4fe23aabfbcb752dad255f01835904e6961d5f20d1de13987a691c27d9cd.js
public/assets/activestorage.esm-b3f7f0a5ef90530b509c5e681c4b3ef5d5046851e5b70d57fdb45e32b039c883.js
public/assets/application-c3ea1831495badf025afd8fd7722fb857c51927f0cc017c366fda52f0d926be2.js
public/assets/common-4e2a87d110376bedbe6f1edea889eb9c368a64a988cab5d3d8527dafd52dc067.js
public/assets/hello-7301560822385b452fd44614e6fc857b520f5082b343eed0dea9d5d2812db9e4.js
public/assets/manifest-dad05bf766af0fe3d79dd746db3c1361c0583026cdf35d6a2921bccaea835331.js
public/assets/stimulus-autoloader-c584942b568ba74879da31c7c3d51366737bacaf6fbae659383c0a5653685693.js
public/assets/stimulus-f75215805563870a61ee9dc5a207ce46d4675c7e667558a54344fd1e7baa697f.js
public/assets/stimulus-importmap-autoloader-db2076c783bf2dbee1226e2add52fef290b5d31b5bcd1edd999ac8a6dd31c44a.js
public/assets/stimulus-loading-3576ce92b149ad5d6959438c6f291e2426c86df3b874c525b30faad51b0d96b3.js
public/assets/stimulus.min-dd364f16ec9504dfb72672295637a1c8838773b01c0b441bd41008124c407894.js
public/assets/trix-686ab55c2aea8035a7f728b61ec7afedfe857f70d6279ab453da775b7469e9e8.js
public/assets/turbo-84e828a0e6f1f9418a277df89df877e9a30524438cf8dc007c066655017a44bc.js

ToCode
1 419
אם ?? כל כך יותר טוב, למה לא משתמשים בו יותר? אופרטור ?? ב JavaScript, או בשמו הרשמי Nullish Coalescing operator, הוא גירסה הגיונית יותר של ||. טוב לפחות הגיונית יותר לחלק משמעותי מהמצבים. עבור || הערך 0 נחשב ל"שקר" ועבור ?? הוא נחשב ל"אמת". זה אומר שעם || יש לנו:
> const items = [10, 20, 30, 40]
undefined
> const firstIndexOfTenOrFifty = items.indexOf(10) || items.indexOf(50)
undefined
> firstIndexOfTenOrFifty
-1
לעומתו עם ?? אנחנו מקבלים את האינדקס הנכון של המספר 10:
> const items = [10, 20, 30, 40]
undefined
> const firstIndexOfTenOrFifty = items.indexOf(10) ?? items.indexOf(50)
undefined
> firstIndexOfTenOrFifty
0
אז למה בכל זאת אנחנו כמעט לא רואים אותו בקוד? כמה רעיונות: 1. אנחנו פחות מכירים ופחות רגילים להשתמש בתחביר חדש. 2. אנחנו חוששים שאלה שיקראו את הקוד לא מכירים. 3. אנחנו לא בטוחים באיזה דפדפנים הוא יעבוד (עובד בכל מקום). 4. ממילא רוב הזמן אנחנו בודקים "או" בין ערכים בוליאנים, אז זה לא כזה משנה. מה דעתכם? באיזו מידה אתם משתמשים בשני סימני השאלה? ולמה אתם לא משתמשים בו יותר?

ToCode
1 419
אתה עוד תשלם על זה אני עוזר ללקוח לשדרג מערכת ריילס. ההתחלה נראתה מבטיחה אבל שסיימנו את כל שינויי הגירסאות ועבודה לפי כל מדריכי השידרוג הגיע החלק הקשה - כל פעם שמתכנת או מתכנתת בפרויקט חשבו שהם יודעים יותר טוב מהתיעוד ובנו מנגנון מתוחכם כדי להתמודד עם משהו שנתפס בעיניהם כמגבלה של הספריה הפכה להיות מסע של פיתוח מחדש של המנגנון, כי הגירסה החדשה של הספריה לא מתאימה לרעיון המתוחכם מלפני שנתיים. אלה הדברים שסיבכו אותנו עד עכשיו: 1. כל מנגנון בניית ה JavaScript/CSS השתנה מאוד בריילס בשנים האחרונות. כשהפרויקט נכתב במקור לא היתה דרך סטנדרטית לשלב FrontEnd App עם קוד ריאקט ולכן כל פרויקט נראה אחרת. 2. שימוש ב Composite Primary Keys בעבר לא נתמך בריילס. היום הוא כבר נתמך ולכן יש לעדכן את הקוד שיעשה שימוש במנגנון החדש (כי הפיתרון הישן נשבר). 3. מנגנון קבצים מצורפים הפך סטנדרטי בריילס, מה שמחייב לשנות את המנגנון בקוד ולעדכן את הנתונים בבסיס הנתונים על הקבצים שכבר שמורים במערכת. בסוף הכל יעבוד טוב יותר זה ברור, אבל בינתיים השידרוג הזה הוא תזכורת טובה למה עדיף לשדרג בצעדים קטנים ותמיד לעבוד בצורה סטנדרטית.

ToCode
1 419
ה Killer Feature החדש של node.js (או: האם זה הסוף של דינו?) לא רחוק היום בו נוכל להפעיל קבצי TypeScript ב node.js, כך לפי דיון בנושא בגיטהאב של נוד (כבר עובד ב Nightly). אלה הדגשים של הפיצ'ר: 1. אין בדיקת טיפוסים בהרצה. זו אגב גם ההתנהגות של deno, באן וגם esbuild בפרונט אנד. הסיבה היא שאין טעם לבדוק טיפוסים לפני הרצה, ועדיף להשתמש בטיפוסים בתור טיפים ל IDE או לבדיקה יזומה כחלק מהרצת בדיקות או CI/CD. 2. אין תמיכה מובנית ב npm כמו שיש לדינו, במובן זה שיש חבילה שהיא חבילת TypeScript שמגיעה עם הגדרות הטיפוסים. מפיצי חבילות יכולים לכתוב קובץ טיפוסים ולהפיץ אותו, או יכולים להפיץ את הטיפוסים במסגרת חבילה חיצונית או מה שירצו. בכל זאת אין לי ספק שאפשרות להריץ TypeScript בלי שום ספרייה חיצונית תהפוך את node להרבה יותר תחרותי ותוציא הרבה מהאוויר מ deno ו bun. בהינתן שהאקוסיסטם של node הוא עדיין הגדול ביותר וכך כנראה יישאר, הייתרון המרכזי של דינו הוא deno deploy ושל bun זה הביצועים.

ToCode
1 419
שמות מועדים לפורענות הספריה swr משמשת למשיכת מידע מהרשת ביישום ריאקט. בשימוש הבסיסי הקוד עשוי להיראות כך:
import React from "react";
import useSWR from "swr";

const fetcher = (url) => fetch(url).then((res) => res.json());

export default function App() {
  const { data, error, isLoading } = useSWR(
    "https://api.github.com/repos/vercel/swr",
    fetcher
  );

  if (error) return "An error has occurred.";
  if (isLoading) return "Loading...";
  return (
    <div>
      <h1>{data.name}</h1>
      <p>{data.description}</p>
      <strong>👁 {data.subscribers_count}</strong>{" "}
      <strong>✨ {data.stargazers_count}</strong>{" "}
      <strong>🍴 {data.forks_count}</strong>
    </div>
  );
}
קשה לראות מהקוד אבל חוץ מהבאת מידע מהרשת הקריאה ל useSWR גם דואגת לעדכון אוטומטי של המידע בכל הזדמנות שהיא יכולה ובמיוחד בעת שינוי פוקוס. וככה מגיעים לבאג שקשה לאתר - משתמשים מתלוננים שמדי פעם דברים משתנים להם על המסך, אחרי חיפוש אנחנו מגלים שה"מדי פעם" הזה קורה כשעוברים לחלון אחר וחוזרים לחלון של האפליקציה והשינוי נגרם כי השרת מחזיר מידע קצת שונה כל פעם. אפילו בדוגמת הקוד שהדבקתי זה יכול להיות מאוד מבלבל למשתמשים כשהם עוברים בין חלונות ופתאום מספר הכוכבים של ריפו משתנה, שלא לדבר מצבים בהם השרת שולח מידע אקראי או אפילו בסדר אקראי. מה עושים? תשמחו לשמוע ש SWR מגיעה עם עוד פונקציה בשם המופלא useSWRImmutable. היא נועדה לפי התיעוד למקרים בהם המשאב (כלומר הדבר שאנחנו מקבלים מהשרת) לעולם לא משתנה, ולכן SWR לא ינסה אף פעם למשוך מחדש את המידע על דעת עצמו. השאלה היחידה שנשארה היא למה לקרוא לפונקציה useSWRImmutable כשברור שהאנשים היחידים שצריכים להפעיל אותה הם אלה שהמשאב שהם מושכים מהשרת הוא לא Immutable...

ToCode
1 419
מה שאפשר לתקן לפי התפיסה הרווחת לגבי איכות של מתכנתים (נינג'ות, כפי שמכונים במודעות הדרושים) אלה הדברים שכדאי להסתכל עליהם כשאנחנו מגיעים להעריך מתכנת או מתכנתת: 1. היכולת לבחור סטאק טכנולוגי מתאים לבעיה ולהצדיק את הבחירה. 2. היכולת לפתור בעיה מהר בתוך הסטאק הטכנולוגי הרלוונטי. 3. היכולת להיכנס לקוד, לתקן או להרחיב אותו בלי לשבור דברים קיימים. 4. היכולת לזהות בעיות מהר. 5. היכולת לבחור מבין מספר אלטרנטיבות את הפיתרון היעיל ביותר. אלה גם היכולות עליהן אנחנו נבחנים בראיונות עבודה ואלה היכולות שמתכנתים רבים מנסים לשפר. הבעיה, אם במקרה ניסיתם לשפר יכולות אלה, היא שזה מאוד קשה. אין ספר שמסביר "איך לפתור בעיות מהר" ואלה שיש לא ממש עוזרים. כל המיומנויות האלה נבנות עם הזמן ועם הניסיון, בתנאי שאנחנו יודעים לנצל את הזמן והניסיון בצורה נכונה. במילים אחרות ככל שנעבוד בצורה מקצועית יותר לאורך זמן אותן יכולות שקשה לשפר ישתפרו מעצמן. הדרך קדימה היא לשים לב לתהליך המקצועי: 1. המחויבות להשאיר קוד נקי אחרי שפותרים בעיה. 2. המחויבות להבין לעומק כל שורת קוד שאנחנו מכניסים למערכת, גם אם "זה עובד". 3. המחויבות לחפש מקרי קצה ולטפל בהם, גם כשה Happy Path כבר כתוב. 4. המחויבות לחפש כמה דרכי פעולה כדי שאפשר יהיה לבחור את הטובה ביותר. 5. המחויבות לבנות תהליכים שיעזרו גם למתכנתים שיבואו אחרינו. 6. המחויבות לחפש מקומות עבודה מאתגרים ושותפים שאפשר ללמוד מהם. מחויבות למצוינות לאורך זמן היא הדרך היחידה והבטוחה להתקדם.

ToCode
1 419
הספר שלא סיימתי הכלל הבסיסי של לימוד דרך הרגלים - מותר לעזוב ספר, אסור לעזוב את ההרגל. אם התחלת לקרוא ספר על SQL כדי ללמוד את הטכנולוגיה וגילית שהספר משעמם אין שום בעיה לעבור ללמוד דרך קורס, דרך תרגול, דרך צפיה בהרצאות ביוטיוב, דרך קריאת תיעוד או בכל שיטה אחרת. מה שחשוב זה להמשיך ללמוד את הנושא חצי שעה ביום (או כמה שתכננת לקרוא את הספר). הנה עוד כמה, עם הדגשים הרלוונטיים- 1. (כשלומדים נושא דרך פיתוח פרויקט) מותר לעזוב פרויקט, אסור לעזוב את הקידוד. והדגש - שימו לב שבפרויקט יש שלבים. אי אפשר להתקדם אם עושים רק התחלות של פרויקטים (או רק סופים). 2. (כשלומדים נושא דרך קורס) מותר לעזוב תרגיל, אסור לעזוב את הקורס. וגם פה נשים לב שאנחנו לא רוצים לדלג על כל התרגילים שקשורים לפרק מסוים, אבל אין שום בעיה לקחת כמה קורסים ולעשות Mix & Match לתרגילים מקורסים שונים. 3. (כשמנסים להשתפר בעבודת צוות) מותר לעזוב את הקבוצה, בתנאי שמוצאים קבוצה אחרת במקום. והדבר החשוב כשלומדים עבודת צוות הוא להתאמן על כמה שיותר תפקידים בתוך הקבוצה.

ToCode
1 419
טיפ סקאלה: שרת REST API פשוט עם cask הניסיון הראשון שלי לכתוב שרת API בסקאלה היה עם ספרייה בשם Tapir. טפיר מקסימה, יש לה המון תיעוד והרבה יכולות מתקדמות, אבל דווקא בדברים הפשוטים מצאתי פערים בתיעוד וגם בפונקציונאליות. המשך חיפושים הביא אותי לספריה בשם cask עליה אני רוצה לספר היום. אבל קודם הקוד:
package restapi
import cask._
import cask.model.{Request, Response}
import io.circe._
import io.circe.generic.auto._
import io.circe.syntax._
case class Demo(text: String)

object MyServer extends cask.MainRoutes {
  val JsonCorsHeaders: Seq[(String, String)] = Seq(
    "Content-Type" -> "application/json",
    "Access-Control-Allow-Origin" -> "*",
    "Access-Control-Allow-Methods" -> "GET, POST, PUT, DELETE, OPTIONS",
    "Access-Control-Allow-Headers" -> "Origin, X-Requested-With, Content-Type, Accept, Authorization"
  )

  @cask.options("/*")
  def options() = {
    cask.Response(
      "",
      headers = JsonCorsHeaders
    )
  }

  @cask.route("/", methods = Seq("get"))
  def hello() = {
    cask.Response(
      Demo("hello").asJson.toString,
      headers = JsonCorsHeaders
    )
  }


  initialize()
}
הקוד יצר אוביקט שאפשר להריץ אותו (לא צריך להוסיף לזה main או שום דבר), שמפעיל שרת ווב עם נתיב אחד - רק הנתיב הראשי, שמחזיר תמיד אוביקט JSON עם מפתח בשם text והערך hello. הוא מחזיר גם סט של כותרות שהגדרתי עבור CORS, ואם יהיו כמה נתיבים אפשר להשתמש באותו סט כותרות לכולם. בנוסף הקוד מגדיר טיפול גנרי למתודת OPTIONS, שוב בשביל ה CORS ששולחת רק את הכותרות כדי שדפדפנים יוכלו לקבל מידע משרת זה מכל דומיין. בשביל להתקין את Cask יש להוסיף ל build.sbt את השורה:
libraryDependencies += "com.lihaoyi" %% "cask" % "0.9.1"
וכן אני יודע שהייתם כותבים כזה ב node.js, פייתון או רובי בעשר דקות. בסקאלה זה לקח לי שעתיים, בעיקר בגלל בעיות בתיעוד ויותר מדי ספריות של שרתי ווב. לכל שפה יש גם את החסרונות שלה.

ToCode
1 419
כזה ניסיתי: Webvm.io צריכים סביבת לינוקס לתרגולים? webvm.io הוא אחד הפרויקטים המעניינים שראיתי באזור הזה. הם לקחו את Debian ומריצים אותה בדפדפן בתור אפליקציית Client Side בלבד דרך ווב אסמבלי, וגם בנו מנגנון שמאפשר לבנות כל Dockerfile למכונת לינוקס שרצה בדפדפן. מספיק להיכנס ללינק כדי להתרשם והנה עוד כמה דברים שאהבתי בפרויקט: 1. המכונה ממשיכה לרוץ כל הזמן (טוב, כל עוד הדפדפן דולק). אפילו כשעברתי למצב שינה והפעלתי את המחשב שוב אחרי שעות הכל חזר לאותו מצב. ככה זה כשאין צד שרת. 2. הרבה דברים עובדים אבל לאט. הפעלה ראשונה של פקודה היא איטית במיוחד ואחרי זה היא רק קצת איטית. 3. יש תמיכה ברשת דרך שירות שנקרא Tailscale. אני מודה שבינתיים הצלחתי רק לחבר את המכונה לכתובת IP ציבורית, אבל עדיין לא להגיע אליה ב SSH או לצאת ממנה. שני הדברים אמורים להיות אפשריים. 4. יש תמיכה בעבודה בתור root (נו זה רץ בדפדפן אז אין שום בעיית אבטחה). פשוט מפעילים su וכותבים את הסיסמה password. 5. יש על המכונה כבר כמה תוכנות כמו python, perl, gcc, vim, ruby. בגלל שלא הצלחתי להפעיל את החיבור לרשת גם לא הצלחתי להתקין תוכנות אחרות. 6. שינויים ב crontab שניסיתי לעשות לא נכתבו לכן אני מניח שחלק מהקבצים הם לקריאה בלבד. לא היתה בעיה ליצור קבצים בתיקיית הבית, להפעיל תוכנות או כל משימה אחרת של משתמש רגיל. סך הכל אם אתם מנסים ללמוד לינוקס ובמיוחד עבודה משורת הפקודה, ומחפשים סביבת תרגול שפשוט תעבוד בלחיצת כפתור אתר webvm הוא הפיתרון הטוב והמהיר ביותר שתוכלו למצוא. נסו ושתפו חוויות.