הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

האם פרומפט הוא טקסט טוב להודעת קומיט?

08/06/2025

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

Ask Claude to merge the auth code into the grant records.
Prompt: Let's give auth codes the same treatment we did refresh tokens, that is, store them in the grants table rather than separately. So, an auth code should have the format `{userId}:{grantId}:{randomSecret}` just like tokens do, and we should store the auth code hash inside the grant record. We should also make the grant record itself expire (by setting a TTL on the KV record) if the auth code is not claimed within (by default) ten minutes. But, once it is claimed and exchanged for a refresh token, then it no longer expires.

Once again there was some sort of technical glitch where Claude's changes to `completeAuthorization()` were not applied, so I had to ask it to read them out and copy/paste manually.

Also Claude did not fully update the doc, so I tried an additional prompt:

Additional prompt: You updated the storage schema to show that authCodeId is now part of grant: records, but you didn't remove the documentation of auth_code: records. Since those no longer exist, can you please remove that from the doc?

But Claude just edited some other parts without actually removing the docs about auth_code. So I will remove it myself in the next commit.

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

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

אני כן אשמח לראות את הפרומפטים מצורפים ל git repo אבל לא במקום הודעות קומיט. אני חושב שמנגנון כמו git-notes יכול לעבוד טוב יותר מהודעת הקומיט עצמה, ואז כלי כמו aider יוכל באופן אוטומטי אחרי כל קומיט להוסיף note עם כל פירוט השיחה שהובילה לקומיט זה, ואולי אפשר גם לכתוב תוספים ל VS Code או Cursor שיוכלו לקחת את כל השיחות שבוצעו בין שני קומיטים ולהפוך אותן ל note לקומיט האחרון.

קבוצת לימוד "מדברים AI"

07/06/2025

הי כולם,

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

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

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

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

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

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

https://www.tocode.co.il/talking_ai

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

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

שטויות שלמדתי על Agents בדרך הקשה

06/06/2025

כתיבת אייג'נט, כלומר תוכנה שעוטפת LLM כדי לשלב מבנה דטרמניסטי עם "חשיבה" לא דטרמניסטית דורשת שינוי גישה מסוים בעבודת הפיתוח. אלה כמה טיפים שלמדתי בדרך הקשה אבל היום כבר לא אוותר עליהם:

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

  2. קבלת מידע מובנה מה LLM - לאנגצ'יין וגם Vercel AI SDK יודעים לבקש מה LLM לקבל את התוצאה בצורת אוביקט וגם מוודאים שקיבלו את האוביקט הצפוי. אין שום סיבה היום לפרסר לבד תשובות של LLM-ים.

  3. חלק לא מבוטל מהבקשות ייכשלו או יחזירו מידע לא נכון. יש לוודא מנגנוני Retry לכל שלב במערכת שמשתמש ב LLM.

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

  5. שילוב מידע LLM-י עם קוד רגיל - למרות ש LLM שמח לענות על כל שאלה, לא כל התשובות שלו מדויקות. אם אני רוצה להוציא מילים משיר עדיף לי להשתמש ב API מסודר שמחזיר את המילים במקום לבקש מ LLM שיאזין לשיר, כי אולי ה LLM לא יבין חלק מהמילים. אם אני צריך להוציא טקסט מ HTML שהמבנה שלו צפוי עדיף להשתמש בספריית Web Scraping קלאסית במקום לסמוך על LLM שאולי ימציא תוכן. הרבה פעמים אני אשתמש בקוד קלאסי כדי לאסוף את המידע וב LLM כדי לנתח אותו ולתמצת אותו.

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

טיפים לעבודה עם AI על פרויקט קיים

05/06/2025

רוצים לשמוע יותר על עבודה עם AI על פרויקט קיים? בואו לוובינר! היום בשעה 10:00 אספר בהרחבה על כל הטיפים פה בפוסט ואף יותר. הוובינר ללא הקלטה כדי שאפשר יהיה לדבר ברוגע על מהפכת ה AI והפחד, ההתרגשות והשינוי שהיא מביאה. זה הלינק:

https://us06web.zoom.us/j/86295492018?pwd=7lGAenxpaXM7oe25PqcDzFkWrhNqpS.1

ועכשיו תקציר הטיפים לאלה מכם שלא יצליחו להגיע:

  1. סדר וארגון - כשאתם מקופיילוט לבצע משימה על פרויקט קיים הוא קודם כל מנסה להבין את המשימה ובשביל זה הוא מנסה להבין את מבנה הפרויקט. הבעיה היא שהוא צריך להבין את מבנה הפרויקט כל פעם מחדש וזה מתסכל ופותח פתח לטעויות. במקום לתת לקופיילוט לעבוד קשה בקשו ממנו פעם אחת לנתח את מבנה הפרויקט ולבנות קובץ architecture.md שמתאר את כל ארכיטקטורת המערכת, כולל כל מבנה התיקיות והטבלאות בבסיס הנתונים. את הקובץ תוכלו לצרף לכל משימה עתידית או לכתוב כלל שקופיילוט שיצרף אותו אוטומטית.

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

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

  4. תיאור תהליכים מרכזיים במערכת - כמו שכתבנו את architecture.md כדאי לכתוב קובץ flows.md או processes.md שיתאר את התהליכים המרכזיים של המערכת ואיזה קבצים ופונקציות מקושרים לכל תהליך. וכן כדאי לתת ל AI לכתוב גם את הקובץ הזה ולזכור לעדכן אותו כל פעם שמשנים קוד. ככל שהמידע שם יותר מדויק יהיה ל AI קל יותר לבצע משימות (ופה יש הבדל מורגש בין Cursor ל Copilot. קרסר בונה לעצמו RAG מכל המידע של הפרויקט ולכן יותר קל לו להתמצא, בקופיילוט אנחנו צריכים לעשות את העבודה).

  5. אם יש לכם סט בדיקות לפרויקט תוכלו לחבר את הרצת הבדיקות בתור "כלי" או MCP Server ואז קופיילוט יוכל אחרי שהוא כותב קוד לוודא שהוא לא שבר כלום וגם להוסיף בדיקות על קוד חדש.

  6. שימו לב לשיחה עם ה AI והתחילו לעבוד בפינוי מכשולים - ה AI מנסה למצוא איפה משתמשים בפרויקט במנגנון מסוים? הוסיפו את זה לקבצי הסיכום. ה AI מנסה לגשת לקבצים לא קשורים? עדכנו את ה Prompt והסבירו לו על איזה קבצים לעבוד. ה AI מנסה לכתוב לעצמו קובץ הגדרות טיפוסים של ריאקט? בדקו למה הוא לא מוצא את קובץ הטיפוסים הרגיל. התאמת הפרויקט לעבודה עם AI היא תהליך איטרטיבי בו אנחנו מזהים איזה דברים גורמים ל AI להתפזר, מחזירים אותו למסלול ומתקנים את המכשול בפרויקט כדי שפעם הבאה הוא לא ירד מהשביל. בהתחלה זה המון עבודה אבל אז זה משתפר ורואים תוצאות.

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

חדש באתר: קורס Full Stack React

04/06/2025

אופס הם עשו את זה שוב. אבל אולי ככה זה בתעשייה.

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

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

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

והנה שנים חולפות ורוח חדשה שוב נשבה באקוסיסטם והפעם היא נקראת Server Components: היכולת לכתוב אפליקציות Full Stack מלאות בריאקט כאשר קומפוננטות מסוימות מריצות קוד בצד שרת וקומפוננטות אחרות מריצות קוד בדפדפן, ולפעמים קומפוננטות מסוימות ירוצו גם בצד שרת וגם בדפדפן. פיצול זה של סביבת הריצה של הקומפוננטות פותח המון דלתות חדשות עבור ספריה כמו ריאקט והופך אותה, בעזרת האקוסיסטם שסביבה ובמיוחד Next.JS למנוע המרכזי בפיתוח יישומי Full Stack היום. בתזמון מושלם כל סוכני ה AI התאהבו בריאקט והסטאק הדיפולטי של AI מורכב היום מ React, Next, Shadcn, Tailwind ו TypeScript. וכך לא נותרה ברירה וגם אנחנו צריכים להתקדם עם רוח הזמן.

אני שמח להשיק את קורס React החדש שקיבל את השם: Full Stack React

הקורס אינו הרחבה של הקורס הקיים אלא פיתוח מאפס של כל הבניין שנקרא ריאקט בצורה נכונה ומוכוונת אפליקציות Full Stack. בקורס תלמדו:

  1. איך לכתוב אפליקציית Full Stack עם React, Next, Tailwind, Shadcn ב TypeScript.

  2. איך לארגן את הקוד בצורה הטובה ביותר כדי שלא יאכזב אתכם גם כשהאפליקציה תגדל.

  3. עשרות תבניות לשימוש חוזר בקוד ושילוב קוד חיצוני עם המערכת שלכם.

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

  5. איך לזהות ולפתור בעיות ביצועים באפליקציות React ו Next.

אני כותב כאן Next אבל למעשה בסך הכל השתמשתי ב Next כדי ללמד את הקונספט של קומפוננטות צד-שרת וקומפוננטות צד-לקוח. לפני כמה ימים פרסמתי כאן שיכולת זו שולבה כבר גם ב React Router ואין ספק שזו תהיה הדרך המרכזית לבנות יישומי Full Stack בריאקט בשנים הקרובות. צריך להגיד, אם אתם בונים אפליקציית Client Side בלבד בריאקט הכל בסדר והקורס עדיין מאוד יעזור לכם מאחר ואני מלמד שם את ריאקט עצמה מקצה לקצה וגם איך להשתמש ב Next כדי לכתוב אפליקציית Client Side בלבד.

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

איך להגדיל את ה timeout עם langchainrb

03/06/2025

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

הממשק עצמו של langchainrb ממש נוח ובמיוחד אהבתי את היכולת לקבל תוצאה בתור אוביקט כשמעבירים JSON Schema, כלומר קוד כזה:

json_schema = {
  type: "object",
  properties: {
    name: {
      type: "string",
      description: "Persons name"
    },
    age: {
      type: "number",
      description: "Persons age"
    },
    interests: {
      type: "array",
      items: {
        type: "object",
        properties: {
          interest: {
            type: "string",
            description: "A topic of interest"
          },
          levelOfInterest: {
            type: "number",
            description: "A value between 0 and 100 of how interested the person is in this interest"
          }
        },
        required: ["interest", "levelOfInterest"],
        additionalProperties: false
      },
      minItems: 1,
      maxItems: 3,
      description: "A list of the person's interests"
    }
  },
  required: ["name", "age", "interests"],
  additionalProperties: false
}
parser = Langchain::OutputParsers::StructuredOutputParser.from_json_schema(json_schema)
prompt = Langchain::Prompt::PromptTemplate.new(template: "Generate details of a fictional character.\n{format_instructions}\nCharacter description: {description}", input_variables: ["description", "format_instructions"])
prompt_text = prompt.format(description: "Korean chemistry student", format_instructions: parser.get_format_instructions)

llm = Langchain::LLM::OpenAI.new(api_key: ENV["OPENAI_API_KEY"])
llm_response = llm.chat(messages: [{role: "user", content: prompt_text}]).completion
parser.parse(llm_response)

הבעיה היחידה היא ה timeouts הקצרים מדי ובמיוחד בעבודה עם Gemini. הבעיה היא הקוד הזה מקוד הספריה:

    def http_post(url, params)
      http = Net::HTTP.new(url.hostname, url.port)
      http.use_ssl = url.scheme == "https"
      http.set_debug_output(Langchain.logger) if Langchain.logger.debug?

      request = Net::HTTP::Post.new(url)
      request.content_type = "application/json"
      request.body = params.to_json

      response = http.request(request)

      JSON.parse(response.body)
    end

שאחראי לתקשורת עם ג'מיני ולא כולל אפשרות להגדרת timeout.

אז כן קודם כל פתחתי Issue אבל אז נזכרתי שאנחנו ברובי והוספתי את הקובץ config/initializers/langchain_patch.rb עם התוכן הבא:

require 'langchain/llm/google_gemini'

# This module adds a dedicated `read_timeout` attribute to the class.
module GoogleGeminiTimeoutAttribute
  # This one line creates two methods for us:
  # 1. `read_timeout` (the getter, to read the value)
  # 2. `read_timeout=` (the setter, to assign the value)
  # It manages the underlying instance variable `@read_timeout`.
  attr_accessor :read_timeout

  # We still patch http_post to use the value from our new attribute.
  def http_post(url, params)
    http = Net::HTTP.new(url.hostname, url.port)
    http.use_ssl = url.scheme == "https"
    http.set_debug_output(Langchain.logger) if Langchain.logger.debug?
    http.read_timeout = @read_timeout if @read_timeout

    request = Net::HTTP::Post.new(url)
    request.content_type = "application/json"
    request.body = params.to_json

    response = http.request(request)

    JSON.parse(response.body)
  end
end

Langchain::LLM::GoogleGemini.prepend(GoogleGeminiTimeoutAttribute)

שורת המפתח היא:

http.read_timeout = @read_timeout if @read_timeout

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

ועכשיו אפשר להגדיר את ה timeout בצורה פשוטה על ידי כתיבת הערך לאוביקט:

llm = Langchain::LLM::GoogleGemini.new(
  api_key: Rails.application.credentials.google_api_key,
  default_options: { chat_model: 'gemini-2.5-pro-preview-05-06' },
)
llm.read_timeout = 600

קומפוננטות צד שרת הגיעו ל React Router

02/06/2025

מרגע ש Vercel לקחה את ההובלה בפיתוח של ריאקט היה ברור איך הוויכוח הזה יסתיים וש React Router תאלץ להדביק את הפער. קשה מאוד בפיתוח ללכת נגד הזרם ובמקרה שלנו נגד הכיוון של הספריה שעבורה אתה בונה. הגישה של ריאן פלורנס לאורך הדרך היתה ש Server Components לא מספיק יציבים וממילא עם רמיקס (או ריאקט ראוטר 7) אין בהם צורך.

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

לסקרנים זה ריפו דוגמה שהחברים בריאקט ראוטר פרסמו: https://github.com/ryanflorence/rsc-movies

בתיקיית routes/home אני מוצא את ה Server Component של דף הבית:

import { MovieGrid } from "../components/movie-grid.tsx";
import { MovieTile } from "../components/movie-tile.tsx";

export const shouldRevalidate = () => false;

export async function ServerComponent() {
  let featuredMovieIds = [32932, 23643, 29915, 30895, 31472, 33411];

  return (
    <>
      <title>RR RSC Movies</title>
      <MovieGrid>
        {featuredMovieIds.map((id: number) => (
          <MovieTile key={id} id={id} />
        ))}
      </MovieGrid>
    </>
  );
}

וב components/add-to-favorites דוגמה לקומפוננטת צד לקוח:

"use client";
import { useFormStatus } from "react-dom";

export function AddToFavoritesButton({ isLiked }: { isLiked: boolean }) {
  let { pending } = useFormStatus();

  return (
    <button
      type="submit"
      onClick={event => {
        if (pending) event.preventDefault();
      }}
      className="font-instrumentSans font-semibold rounded-xl w-full text-xl border-[2px] py-2 px-5 group"
    >
      <span className="group-hover:scale-105 group-active:scale-100 inline-block transition-transform duration-100">
        {pending
          ? isLiked
            ? "Removing..."
            : "Adding..."
          : isLiked
            ? "Remove from favorites"
            : "Add to favorites"}
      </span>
    </button>
  );
}

נ.ב. בימים אלה אני מסיים עבודה על קורס ריאקט חדש לאתר שמתבסס על תבנית ה Client/Server ויכיל את הסטאק הדיפולטי של React / Next / TypeScript / Shadcn / Tailwind. אני מודה שהייתי מודאג מההתעקשות של ריאקט ראוטר על תבנית ה loaders שלהם ומאוד שמח שבסוף הם הצליחו להתקדם ולשלב את ה loaders על גבי התשתית הריאקטית. עדכון מסודר על הקורס יעלה כשיהיה מוכן כנראה אחרי החג.

טיפ נקסט - מגדירים displayName לפני ה memo

01/06/2025

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

import { memo } from 'react';

const NewMessage = memo(() => {
  return <p>demo</p>;
})

NewMessage.displayName = "foo";

export default NewMessage;

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

כשהעברתי את אותו קוד ל next זה לא עבד ושם הקומפוננטה שהופיע בכלי הפיתוח היה _c. הפיתרון היה להגדיר את ה displayName על הקומפוננטה לפני שמפעילים memo באופן הבא:

'use client';

import { memo } from 'react';

const NewMessage = () => {
  return <p>demo</p>;
}
NewMessage.displayName = 'foo';

export default memo(NewMessage);

ה AI האשים את מנגנון ה build של next, אבל אני לא בטוח שהוא צודק. אם יש לכם רעיונות אל תתביישו לשתף בתגובות.

אז כבר לא צריך State Management Library בריאקט?

31/05/2025

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

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

  1. סטייט גלובאלי מנוהל דרך קונטקסט (לדוגמה React Query) בצורה שקופה. אפשר להגיד שבמקום לחלק את האפליקציה ל slices בסגנון רידאקס אנחנו מחלקים אותו ל"תחומי אחריות גלובאליים" כשכל תחום אחריות מנוהל על ידי ספריה נפרדת.

  2. מבנה שטוח של קומפוננטה ראשית שמנהלת סטייט ומעבירה אותו בתור prop לילדים, במקום עץ עמוק של קומפוננטות.

  3. הסתמכות גדולה יותר על קוד צד שרת ועדכון הסטייט ישירות לקומפוננטות באמצעות Web Sockets או SSE.

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

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

סיכום וובינר GenAI ותוכניות להמשך

30/05/2025

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

דיברנו על איך לשלב AI בתהליך כתיבת הקוד וראינו מספר אסטרטגיות-

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

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

  3. הראיתי את Ask Mode של כלי הפיתוח והמלצתי להשתמש בו כדי ללמוד יותר על הפרויקט מתוך ה Cursor או ה VS Code. הלימוד הזה משרת שתי מטרות, גם נותן לנו נקודת מבט נוספת על הפרויקט וגם ולא פחות חשוב עוזר לנו להבין איך ה AI קורא את הפרויקט שלנו. הרבה פעמים שווה לסכם שיחות כאלה ב Ask Mode לקובץ Markdown (כלומר לבקש מה AI לסכם בשבילנו) ואז אפשר לצרף את הקובץ הזה לבקשות עתידיות.

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

עכשיו לגבי ההמשך:

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

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

  3. ולסיום בקשה מכם - אני מאוד אשמח לראות איך אתם עובדים עם AI בתוך Cursor או VS Code. אם הייתם אתמול (וגם אם לא) ואתם מוכנים שבוע הבא להציג 5-10 דקות איך אתם עובדים עם AI דרך פיצ'ר קטן כתבו לי ונתאם. אפשר דרך דף צור קשר פה באתר.