ToCode
الذهاب إلى القناة على Telegram
1 420
المشتركون
لا توجد بيانات24 ساعات
+27 أيام
-230 أيام
أرشيف المشاركات
1 420
# עוד 3 פיצ'רים של ES13 בהם אתם אשכרה הולכים להשתמש
ג'אווהסקריפט כל הזמן מתקדמת ולמרות שכבר ירדנו מרכבת ההרים שהיתה ES6, עדיין יש שיפורים קטנים שהופכים את החיים לקלים יותר כל יום. אז נכון כשחושבים על ES13 מיד קופץ לראש סימן הסולמית והיכולת להגדיר פונקציות פרטיות, אבל האמת שבזה אני לא רואה סיבה להשתמש. הנה 3 פיצ'רים אחרים שדווקא כן יכולים להיכנס לקוד שלי-
## האיבר האחרון במערך (סוף סוף)
הפיצ'ר שהכי חיכיתי לו ב JavaScript הגיע. טוב, לא בדיוק בצורה שרציתי אבל מספיק דומה. אם יש לכם ביד מערך תוכלו להשתמש בפונקציה
at כדי לגשת לאיברים עם תמיכה במספרים שליליים כדי לגשת מהסוף. זה הקוד:
const x = [10, 20, 30, 40, 50];
// prints: 50
console.log(x.at(-1));
## חיפוש מהסוף
ואם כבר מדברים על סוף, הפונקציה findLast היא כמו find אבל מהסוף. זה נראה ככה:
const x = [10, 20, 30, 40, 50];
// prints 50
x.findLast(i => i > 30)
// prints 40
x.find(i => i > 30)
## אפשר לכתוב await גם מחוץ לפונקציה
והפינוק הכי גדול של ES13 (הידועה גם בתור ES2022) הוא היכולת לכתוב await מחוץ לכל פונקציה. את זה בטוח ראיתם ב dev tools ומסתבר שאפשר לכתוב אותו בכל מודול.
זה אומר שאם יש לכם קובץ שתלוי במידע מבחוץ כדי להיטען אתם כבר לא צריכים להגדיר פונקציית main אסינכרונית, ואפשר פשוט לכתוב:
const response = await fetch('/theme');
const theme = await response.json();
document.body.backgroundColor = theme.background;1 420
# ואז הם הציעו "בואו נחליף את ה Backend"
בדרך כלל כשחושבים על קוד "קריא" אנחנו חושבים על קוד שמי שקורא אותו יכול להבין מה הוא עושה יחסית בקלות, ועל קוד לא קריא בתור קוד שצריך מאוד להתאמץ כדי להבין מה קורה בו. כשמסתכלים על פונקציה בודדת קל לראות איזה דברים הופכים קוד ללא קריא למשל כשהפונקציה ארוכה מדי, כוללת המון תנאים ושמות המשתנים הם פשוט רצף אקראי של אותיות. במערכת גדולה כבר הרבה יותר קשה לחשוב על קוד קריא דרך היכולת "לקרוא" אותו, פשוט כי יש יותר מדי ממנו. וככל שיש יותר קוד ככה יהיה יותר קשה להבין מה כל חלק עושה ובמה הוא תלוי.
דרך נוספת לדבר על קוד קריא שאולי יותר מתאימה למערכות גדולות תהיה לבדוק כמה מסובך לענות על שאלה ספציפית לגבי הקוד, ואז להכין לעצמנו רשימה של שאלות שחשוב לנו שיהיה קל לענות עליהן. בניגוד ל"כמה הקוד מובן", כשיש לנו שאלה ספציפית בראש הקריטריון הופך ליותר קשיח.
בשביל הדוגמה נדמיין Service שכתוב בריאקט ומתחבר לשרת Backend, אבל גם מתחבר לכל מיני APIs ברשת. בקוד יש כמה מאות קומפוננטות, חלקן לוקחות מידע מה Backend דרך SWR, חלקן מעדכנות מידע באמצעות fetch וקומפוננטות אחרות משתמשות בממשקים ייעודיים של APIs חיצוניים כדי לתקשר עם אותם APIs. ועכשיו נשאל "איפה אני מוצא רשימה של כל בקשות הרשת שה Service שלי מסוגל להוציא?"
במקרה הטוב אם הקוד קריא ביחס לשאלה הזאת יהיה לנו במערכת קובץ אחד שמטפל בכל הבקשות שיוצאות מהיישום ומהווה "נקודת יציאה" לכל Backend או API. הקומפוננטות תמיד יעברו דרך נקודת יציאה זו וכך בשביל לענות על השאלה צריך רק לפתוח את הקובץ.
במקרה הפחות טוב כל קומפוננטה תקרא בדרך שלה ל API או ה Backend שהיא עובדת מולו, ונצטרך לעבור על הקומפוננטות אחת אחת כדי לאסוף את כל הקריאות.
קשה מאוד לכתוב קוד שיהיה קריא ביחס לכל שאלה, אבל לאורך זמן ככל שנאסוף יותר שאלות שמעניינות אותנו נוכל לכוון את הקוד שלנו כדי שיהיה קריא ביחס לאותן שאלות, וכך לשפר את איכות המערכת ומהירות הפיתוח.
1 420
<input type="submit" name="commit" value="send" data-disable-with="send" /> </form> </template></turbo-stream>קוד JavaScript מתוך הספריה Turbo יפענח את התשובה ויעדכן אוטומטית את העמוד. בלי טעינה מחדש ובלי הפניה למקומות אחרים, ממש כמו שהיה קורה עם כל פריימוורק צד לקוח. ## שיתוף ההודעות עם גולשים אחרים בזמן אמת וכמובן השלב הכי מדליק בעמוד הוא השיתוף בזמן אמת באמצעות Web Sockets: במקום לשלוח את הוראת העדכון "בתגובה" לגולש שיצר הודעה חדשה, אני יכול לשלוח את אותה הוראת עדכון דרך Socket, פשוט כי משהו בשרת השתנה. בצורה כזאת כל הגולשים יקבלו את ההודעה החדשה בלי שיצטרכו לרענן את העמוד. הקוד לשלב השלישי נמצא כאן: שלב 3 ובעיקרון הוא מורכב בסך הכל משני שינויים. במודל
app/models/message.rb הוספתי את השורה:
class Message < ApplicationRecord
after_create_commit { broadcast_append_to('messages') }
end
שמפעילה פקודת שידור אחרי כל יצירת הודעה.
ב Controller מחקתי את ההוראה ליצור הודעה חדשה, כי היא תגיע מה Broadcast:
def create
@message = Message.new(message_params)
respond_to do |format|
if @message.save
format.html { redirect_to messages_path }
format.turbo_stream do
render turbo_stream: [
turbo_stream.replace('new_message', partial: 'new_message_form')
]
end
else
format.html { render :index, status: :unprocessable_entity }
end
end
end
ובטמפלייט הוספתי את הפקודה:
<%= turbo_stream_from "messages" %>
לקובץ app/views/messages/index.html.erb. שימו לב שהמילה messages שם זהה לפרמטר שהעברתי ל broadcast_append_to שהיה במודל.
התוצאה - כל משתמש יכול לשלוח הודעה לשרת, ההודעה גם תיכנס לבסיס הנתונים וגם תישלח ב Web Socket לכל הגולשים האחרים באתר. וכל זה בלי לכתוב שורת JavaScript אחת.
## מה הלאה
הדוגמה שהוצגה כאן מאוד פשטנית - בעולם האמיתי היינו צריכים לנהל משתמשים, קבוצות ולשלוח עדכונים רק לאנשים שהעדכון באמת רלוונטי עבורם. תשמחו לשמוע שבריילס יש את כל הכלים לעשות את זה, כולל ניהול הרשאות ברישום לעדכונים והכל בתוך הכלים של ריילס.
טורבו Streams, שזה החלק שמקבל הוראות מהשרת ומעדכן את העמוד תומך במספר פעולות מובנות עבור הוספה ומחיקה בכל מיני מקומות (הוספה לסוף, הוספה להתחלה ודברים כאלה), וגם מאפשר לכם לכתוב קוד JavaScript כדי לממש פעולות חדשות משלכם, כך שגם בתוכניות גדולות יותר כנראה שלא תיתקעו.
בצד השלילי וכמו תמיד בפריימוורקים מהסוג הזה, כשהשליטה שלכם מוגבלת לפעמים קשה יותר למצוא באגים או לממש Use Cases מתוחכמים יותר, למשל לא ברור איך לממש Optimistic Updates או מצב Offline כשצריך את השרת לכל שינוי.
בשורה התחתונה אם אתם כבר בריילס והאפליקציה שלכם לא מאוד מתוחכמת שילוב טכנולוגיה כמו Turbo Streams יעזור לכם להישאר בריילס בלי לשכתב את הכל לפריימוורק צד-לקוח.1 420
# בואו נבנה לוח מודעות ב Rails בלי JavaScript
אחת הדוגמאות הראשונות שאני מראה ל Web Sockets היא בניה של לוח מודעות משותף לכמה גולשים - כל פעם שגולש אחד שולח הודעה, ההודעה מיד מופיעה על המסך של כל האחרים. והיום ננסה לבנות את אותו לוח מודעות בלי לכתוב שורה של JavaScript, רק באמצעות המנגנונים המובנים ב Rails.
## שלב 1 - לוח מודעות
השלב הראשון בדרך ללוח מודעות משותף הוא בניית לוח מודעות. וכן הוא יהיה משותף כי יש לנו צד שרת, אבל עדיין לא בזמן אמת. הקוד לשלב הזה נמצא כאן:
לוח מודעות שלב 1
בניתי מודל בשביל הודעה וקונטרולר עם הקוד הבא:
class MessagesController < ApplicationController
def index
@messages = Message.all
@message = Message.new
end
def create
@message = Message.new(message_params)
@message.save!
redirect_to messages_path
end
def message_params
params.require(:message).permit(:text)
end
end
הפונקציה היחידה כאן שמייצרת HTML היא index, שאחראית על הצגת כל ההודעות וגם מציגה טופס ליצירת הודעה חדשה. הקוד של התבנית מחולק לשני קבצים, הקובץ הראשון הוא app/views/messages/index.html.erb וזה הקוד שלו:
<h1>Messages#index</h1>
<%= render partial: 'message', collection: @messages %>
<%= form_for @message, url: messages_path, method: :POST do |f| %>
<%= f.label :text %>
<%= f.text_field :text %>
<%= f.submit :send %>
<% end %>
והקובץ השני הוא ה HTML של כל הודעה בקובץ app/views/messages/_message.html.erb:
<p><%= message.text %></p>
<hr />
נשים לב כבר שבלי שום JavaScript Framework או שום דבר אני מקבל בקלות הפרדה שבה כל חלק בעמוד כתוב בקובץ נפרד, וחלק אחד - רשימת ההודעות - משתמש בחלק השני - דף ההודעה.
אם תפעילו את הקוד תוכלו לגלוש מקומית לנתיב:
http://localhost:3000/messages
לראות רשימה של שתי הודעות מובנות וטופס שיוצר הודעות חדשות. הטופס מגיע לפונקציה create ב controller שתשמור את ההודעה החדשה ותשלח Redirect לנתיב רשימת ההודעות, שם הגולש יראה את כל ההודעות ואת ההודעה החדשה שלו.
## שיפור ביצועים - דילוג על ה Redirect
שלב שני בדרך ליצירת הלוח השיתופי הוא שיפור הארכיטקטורה - במקום לענות לגולש עם הודעת Redirect, אנחנו נשלח הודעת Turbo Stream שזה בעצם בקשה לעדכון העמוד לפי כללים מסוימים. במקרה שלנו יהיו שתי הודעות:
1. בקשה להוסיף את ההודעה החדשה לרשימת ההודעות.
2. בקשה לנקות את הטקסט בטופס.
הקוד לשלב הזה נמצא כאן:
שלב 2
בשביל לשלוח את ההודעות לגולש כתבתי את הקוד הבא בפונקציה create:
def create
@message = Message.new(message_params)
respond_to do |format|
if @message.save
format.html { redirect_to messages_path }
format.turbo_stream do
render turbo_stream: [
turbo_stream.append('messages', partial: 'message', locals: { message: @message }),
turbo_stream.replace('new_message', partial: 'new_message_form')
]
end
else
format.html { render :index, status: :unprocessable_entity }
end
end
end
וזה הכל - בעצם שתי השורות:
turbo_stream.append('messages', partial: 'message', locals: { message: @message }),
turbo_stream.replace('new_message', partial: 'new_message_form')
הן ההוראות לעמוד לעדכן את ה HTML לפי הפרטים החדשים. כשהדפדפן יקבל את התשובה מה POST, שנראית ככה:
<turbo-stream action="append" target="messages"><template><p>new text</p>
<hr />
</template></turbo-stream><turbo-stream action="replace" target="new_message"><template><form class="new_message" id="new_message" action="/messages" accept-charset="UTF-8" method="post"><input type="hidden" name="authenticity_token" value="Z4ROwg-7zOPU38BqhifwH3AdWu6NZ8f-Oy-xoPV_ZClJxs0FjpwmjtYeG3Pcd2QyasuRhrGRi9QEP1I27gb0DA" autocomplete="off" />
<label for="message_text">Text</label>
<input type="text" name="message[text]" id="message_text" />1 420
# מעקפים
מה קורה כשיש באג במערכת שאתה לא מצליח למצוא? נכון, כותבים מעקף. מעקף הוא מנגנון שבגדול אומר "אין לי מושג למה הגענו לכאן, אבל אם כבר אתה כאן אז עדיף שתפנה ימינה". אנחנו מגיעים למעקפים דרך התרסקויות או באגים - פונקציה אמורה לקבל מספר ופתאום מופעלת עם מחרוזת ולכן מתרסקת. אחרי שלא הצלחת למצוא שום נתיב בקוד שגורם לפונקציה לקבל מחרוזת הצעד הבא הוא לעדכן את קוד הפונקציה לטפל גם במחרוזות, למשל:
function isInCanvas(x, y) {
if (typeof x === 'string') {
x = Number(x);
}
if (typeof y === 'string') {
y = Number(y);
}
// check if (x,y) is in the canvas
}
וכן יש שתי בעיות עם מעקפים:
1. הם מקשים על קריאת הקוד - יום אחד בעוד חודשיים (או שבועיים) כשמישהו יגיע להסתכל על הפונקציה הוא לא יבין למה היא צריכה להתמודד גם עם מחרוזות.
2. הם מתרבים ויוצרים תרבות של מעקפים - לאורך זמן מנהלים ומתכנתים מתמכרים לרעיון המעקפים ומוסיפים מעקף במקום להשקיע את הזמן בחיפוש הבאג האמיתי, מה שרק מחמיר את הבעיה כי אותו באג יכול להשפיע על עוד מקומות במערכת, ואז גם בהם נצטרך להוסיף מעקפים.
החיים זה לא ספר לימוד וברור שבמערכת אמיתית תצטרכו להכניס יותר ממעקף אחד. כדאי כשאתם עושים את זה להיות ברורים, להוסיף הערה בקוד שמסבירה מה מצב המעקף ומה מצאתם עד עכשיו והרציניים באמת גם יוסיפו ל Backlog ב Jira משימה חדשה להסיר את המעקף, כשיהיה זמן כמובן.1 420
# פיצ'ר חשוב אבל לא בשבילי
אם את עובדת עם React ולא יודעת איך לכתוב Custom Hook שווה לעצור עכשיו וללמוד את זה, מאחר ו Custom Hook הוא אחד המנגנונים הבסיסיים של שיתוף קוד בין קומפוננטות, ובכל פרויקט ריאקט מגיע הרגע שמישהו יכתוב אחד.
אבל אם באותו React את לא יודעת מה זה Server Side Rendering או למה להשתמש ב
useDeferredValue, לא קרה כלום. זה אולי יהיה מכשול בראיונות עבודה אבל בחיים האמיתיים יש הרבה פרויקטים שלא צריכים את הפיצ'רים האלה, ויותר מזה - יש הרבה פרויקטים בהם בגלל שינסו להטמיע את הפיצ'רים האלה הפרויקט רק יהפוך ליותר קשה לתחזוקה.
הייתי שמח אם בתיעוד של ספריה היינו רואים ליד כל פונקציה איזה דירוג שאומר כמה כדאי להשתמש בה - מ"אם אתה לא משתמש במנגנון הזה הקוד שלך שבור" ל-"אם אתה משתמש במנגנון הזה הקוד שלך שבור". עד שזה יקרה האחריות עלינו להפעיל שיקול דעת, וכדאי לזכור, רק בגלל שהפיצ'ר קיים לא אומר שהוא רלוונטי (או אי פעם יהיה) לעולם שלכם.1 420
# את הטעות הזאת אפילו TypeScript לא הצליח לתפוס
בדיוק כשחשבתי שמצאתי את האור ו TypeScript יתקן לי את כל הבאגים יחסינו הגיעו למשבר. הכל התחיל בפונקציה תמימה שלוקחת מחרוזת, מחליפה בתוכה כמה סימנים ומחזירה את הטקסט המוחלף:
function replaceByDictionary(text: string, replacements: Record<string, string>) {
let interpolatedText = text;
for (const [key, value] of Object.entries(replacements)) {
interpolatedText = interpolatedText.replace(key, value);
}
}
בלי לשים לב לבאג המשכתי להשתמש בפונקציה כדי לשלוח את הטקסט המוחלף לשרת:
const replacedText = replaceByDictionary("I love TypeScript", { "I": "Everyone" });
await fetch(`https://tocode.requestcatcher.com/test?text=${replacedText}`, { method: 'POST' });
רק כדי להישאר עם לב (וקוד) שבור כשגיליתי שהבקשה שתכל'ס נשלחה לשרת היתה עם ה URL:
POST /test?text=undefined
מה קרה כאן? למה טייפסקריפט פספס? התשובה פשוטה - הסקת טיפוסים אוטומטית גרמה לטייפסקריפט להגדיר את replacedText בתור void, ואופרטור הגרש ההפוך יודע לקבל משתני void בתוך מחרוזות. חוקי לגמרי, ובכלל לא מה שהתכוונתי.
הפיתרון? כמו תמיד בתכנות אין פיתרונות קסם, אבל כן יש שתי אפשרויות מרכזיות:
אפשר להחליט שאנחנו לא אוהבים את הסקת הטיפוסים של טייפסקריפט, ומגדירים את replacedText בתור string בעצמנו. זה אומר לכתוב:
const replacedText: string = replaceByDictionary("I love TypeScript", { "I": "Everyone" });
ועל זה טייפסקריפט כבר יצעק.
או (ולדעתי עדיף) להחליט להוציא לפונקציה את הקוד ששולח טקסט לשרת, ואז נקבל:
async function postText(text: string) {
await fetch(`https://tocode.requestcatcher.com/test?text=${replacedText}`, { method: 'POST' });
}
const replacedText = replaceByDictionary("I love TypeScript", { "I": "Everyone" });
await postText(replacedText);
בגישה כזאת אנחנו גם שומרים על הגמישות לשנות את קוד השליחה לשרת בעתיד, גם מפרידים בין הלוגיקה (לעדכן את הטקסט) לבין מה עושים עם התוצאה (שולחים לשרת), והכי חשוב, מקבלים מטייפסקריפט את ההגנה שרצינו.1 420
# שני סוגים של קוד נכון
יש קוד נכון כי הוא מכיל את האבסטרקציה הנכונה, כי הוא מטפל בכל מקרי הקצה, כי הוא רץ בביצועים טובים ולא כולל חולשות אבטחה. אני מאוד אוהב קוד נכון אבל הסוג הזה של נכון הוא לא משהו שקל לכתוב בפעם הראשונה. רוב הפעמים הוא דורש יותר מידע על המערכת ממה שיש לנו, ויותר מניסיון אחד בשביל לקלוע.
אבל יש גם קוד נכון כי הוא כתוב לפי Best Practices. קוד שנכתב נכון בפעם הראשונה כי לא משנה מתי אנחנו כותבים אותו, לכתוב את הגירסה הנכונה לא יותר מסובך מלכתוב גירסה לא נכונה. לדוגמה לכתוב ב Dockerfile את השורה:
FROM postgres:15.1
במקום:
FROM postgres
כי latest מתישהו הולך להפוך למשהו אחר ואני לא רוצה שבסיס הנתונים ישתדרג לי מתחת לרגליים.
או ב JavaScript נעדיף לכתוב:
JSON.parse(data);
על פני:
eval('(' + data + ')');
למרות שגם הגירסה השניה עובדת, כי הגירסה הראשונה מהירה יותר ומתמודדת טוב יותר עם מידע שאינו JSON.
מן המפורסמות ש"אופטימיזציה שמקדימה את זמנה היא שורש כל רשע", אבל זה לא תירוץ לכתוב קוד גרוע. אם אתם יכולים ויש לכם את כל הנתונים, תמיד עדיפה הגירסה הנכונה וכמה שיותר מוקדם.1 420
בעבודה עם ורסל אתם מקבלים מקום חינמי לגמרי לאחסן ולהגיש ממנו את פרויקט ה flask שלכם, אבל לא רק זה - אתם מקבלים הזדמנות לעבוד עם הכלים הכי מפנקים של התעשיה, כלים שימשיכו לשרת אתכם גם כשהפרויקט יגדל (ותרצו לעבור לאחת התוכניות בתשלום שלהם). היכולות להתקין תלויות, להעלות ולראות כל גירסה ולשמור על חיבור בין ה Deployment ל git, וכמובן המחיר (חינם לגמרי) הן סיבות מצוינות לבחירה ב vercel בתור בית לפרויקט הפייתון הבא שלכם.
1 420
# ורסל מציעה את הדרך הקלה ביותר להעלות יישום Flask לענן
ורסל (vercel) מפורסמת בזכות הפריימוורק next.js, אותה יצר אותו גיירום ראוך שהקים גם את ורסל. אבל חוץ מפרויקטי ריאקט לורסל יש עוד לא מעט פיצ'רים בשרוול. הם חולמים להיות שכבה מעל AWS שתאפשר הקמה קלה יותר של שירותים מבוססי ענן, ולפחות לפי התקנת יישום flask על התשתיות שלהם - הם מקיימים ובגדול. בואו נראה איך זה עובד.
## מה אנחנו בונים
בשביל הדוגמה אני אעבוד על הקוד מהמאגר: https://github.com/ynonp/flask-demo-on-vercel. אגב, את הסטארטר למאגר יצרתי דרך הממשק הגרפי של ורסל בעמוד יצירת פרויקט חדש שלהם.
הפרויקט מורכב מתיקיה בשם api ובה קובץ
index.py שמטפל בכל הבקשות הנכנסות. זה תוכנו:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return 'some new text'
@app.route('/about')
def about():
return 'About'
הקובץ הוא קובץ flask רגיל לגמרי ועוד מעט נראה איך לעדכן אותו כדי להחזיר JSON במקום מחרוזות.
חוץ ממנו יש בפרויקט קובץ בשם requirements.txt עם התוכן הבא:
Flask==2.2.2
אבל כמובן שאפשר להוסיף אליו שורות כדי להוסיף תלויות לפרויקט, וקובץ בשם vercel.json שמתאר את מבנה הפרויקט בשביל ה Deployment:
{
"builds": [
{
"src": "api/index.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "api/index.py"
}
]
}
## העלאה לשרת
ורסל מייצרים Deployment חדש בצורה אוטומטית אחרי כל Push לפרויקט. הם גם שומרים את כל ה Deployments הישנים שלכם, ויש אופציה במסך ההגדרות של הפרויקט להגביל את הגישה לאותם Deployments ניסיוניים. בלחיצת כפתור אתם "מקדמים" Deployment מסוים כך שיהפוך ל Production Deployment.
בפרויקט הדוגמה שלי יצרתי מספר Deployments. כשהתחלתי לעבוד יצרתי Deployment ראשון שזמין בקישור הזה:
https://flask-demo-on-vercel-4k95r1get-ynonp.vercel.app
אחרי זה עדכנתי את הקוד ויצרתי Deployment נוסף שזמין בקישור הזה:
https://flask-demo-on-vercel-ayghas8d3-ynonp.vercel.app
לא משנה כמה גירסאות עוד אמשיך לבנות, הקישורים הישנים ימשיכו לעבוד וכך אני תמיד יכול להשוות את הפרויקט עם איך שעבד בעבר, ובעצם לכל קומיט ב git יש לי גם Preview Version שלו שנשאר לתמיד.
נעדכן את הפרויקט וניצור גירסה חדשה שמחזירה את הטקסט בתור JSON. בגלל שזה פרויקט flask אני יכול להריץ אותו מקומית עם:
python -m flask --app api.index run
עכשיו אפשר לגלוש ל http://localhost:5000/ כדי לקבל את הטקסט. אני מעדכן את הקוד ב api/index.py לקוד הבא שיחזיר את הטקסט בתור JSON:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():
return { "text": "Hello WOrld" }
@app.route('/about')
def about():
return 'About'
ועכשיו גלישה מחדש לעמוד מחזירה את ה JSON:
{ text: "Hello WOrld" }
אחרי העדכון אני רוצה להעלות את הגירסה החדשה לשרת - וזה ממש פשוט! מפעיל:
$ git commit -a -m 'return JSON'
$ git push
עכשיו במסך הניהול של ורסל אני רואה גירסה חדשה, אני רואה את מזהה הקומיט והודעת הקומיט ויכול להשתמש וקיבלתי קישור חדש כדי לראות את הגירסה החדשה שלי באוויר:
https://flask-demo-on-vercel-e6irs1pie-ynonp.vercel.app
כשהגירסה מוכנה אני יכול לחבר אותה ל Production שוב דרך מסכי הניהול של ורסל. אני לוחץ על כפתור Promote To Production ומקבל את ה JSON בדומיין הראשי של האפליקציה, אותו גם קיבלתי מ vercel בקישור https://flask-demo-on-vercel.vercel.app.1 420
# הפיטורים בטק (או: מה עושים עם הזמן הפנוי)
רק לפני כמה חודשים היה נדמה שהעולם הוא כמו חנות ממתקים ענקית ואנחנו רק צריכים לבחור איזה סוכריה לפתוח קודם, והנה נהפכה הקערה על פיה וכולם חוששים מהציוץ הבא ואיפה יהיו הפיטורים הבאים. ולמרות שכל אחד היה רוצה לחשוב שהוא "טוב מכדי שיפטרו אותו" המציאות מראה שלא משנה כמה אתם טובים, חברה שסוגרת מוצר לא ממהרת להעביר את האנשים לעבוד על מוצר אחר.
אז בין אם אתם כבר בבית מחכים לימים טובים יותר או עדיין עובדים אבל חוששים, הנה כמה טיפים שיכולים לעזור להעביר את הזמן עד הגאות הבאה-
## זה זמני
דבר ראשון וחשוב לזכור הוא שעליו וירידות כאלה הן זמניות. היום כולם ממהרים לסגור מוצרים אבל רק לפני שנה כולם גייסו והייתם צריכים להדוף הצעות שכר פסיכיות. כמו שלא צריך להתרגש כשמציעים לך משכורת גבוהה כך כדאי לקחת את הדברים בפרופורציה כשלוקחים אותה. ימים טובים יותר יבואו.
זה גם בסדר לספוג ירידה בשכר או פגיעה בתנאים. כשהשכר יורד בכל התעשיה, קשה לצפות שהחברה הבאה בה תתחילו לעבוד תרצה להציע יותר ממה שהציעו לכם לפני שנה. בכל מקרה עדיף להיות בעשיה ואם יש הזדמנות למשרה מעניינת (גם בשכר יותר נמוך) אני הייתי לוקח.
מה שלא כדאי לעשות זה לטחון ראיונות עבודה ולחפש את הדבר הגדול הבא. בתקופות כאלה הרבה יותר קשה למצוא ולא סביר שעוד ראיונות זה מה שחסר לכם.
## הפרויקט ההוא שרצית לכתוב
מה כן כדאי לעשות עם הזמן? הדבר הכי חשוב הוא להישאר בעשיה, והדרך הכי קלה לעשות את זה היא לקחת פרויקט שתמיד רציתם לכתוב ולא היה לכם זמן. זו יכולה להיות מערכת אינטרנטית שתעזור לעמותה או ארגון שקרוב ללבכם, יכול להיות כלי שיעזור לכם בתחביב או רעיון שחשבתם עליו בעבודה הקודמת ואף פעם לא היה לכם זמן ליישם.
יום אחד הכסף יחזור לשוק ומישהו ישאל אתכם בראיון מה עשיתם עם הזמן הפנוי. פרויקט טכנולוגי שמשתמש בכלים מתקדמים (בתוך התחום הספציפי שאתם עובדים בו) יכול להיות בדיוק הסיפור שהם יחפשו.
## הקורס ההוא שרצית לקחת
תמיד רצית להיכנס לעולם ה Front End ולא היה זמן? אולי חלמת על פיתוח יישומי בינה מלאכותית אבל תמיד עזבת את הקורס ההוא בקורסרה אחרי השבוע השני? נו, מי אמר זמן פנוי ולא קיבל?
קורסים מקצועיים הפכו זולים מאוד או אפילו כמעט חינמיים בשנים האחרונות. כבר לא צריך לנסוע לארה"ב או להיכנס לחובות כדי להירשם לאוניברסיטה. הרצאות מוקלטות ותרגולים זמינים אונליין בכל נושא, ואתם צריכים רק למצוא וללמוד. עכשיו עם Chat GPT אפילו לא צריך מורה ואפשר לתת לבינה מלאכותית לענות על רוב השאלות.
## העסק הקטן שהתכוונת לפתוח
תקופות של משבר הן הזמן הכי טוב לפתוח עסק קטן חדש, שייתן לכם הכנסה צדדית גם בזמן המשבר וגם אחריו. כמתכנתים הדברים המרכזיים שאנחנו יכולים לעשות יהיו:
1. לבנות ספריית קוד פתוח ולאסוף תרומות מאנשים שאוהבים את הספריה (כפתורי ה"קנו לי קפה" או patreon למיניהם).
2. לבנות מוצר Saas שתוכלו למכור אליו גישה (כאן יש כמה רעיונות)
3. לבנות אפליקציית מובייל ולמכור אותה דרך חנויות האפליקציות (כאן יש כמה רעיונות)
הדבר החשוב כמובן הוא לא רק המוצר אלא בחירת השוק, החיבור למי שאולי ירצה לשלם על מוצר כזה והחיפוש אחרי הלקוחות הראשונים. חוויה כזאת יכולה להיות מאוד מועילה ולתת לכם פרספקטיבה טובה יותר איתה תגיעו לתפקיד הבא כשהעולם יחזור לגייס.
אז נכון אף אחד לא אוהב להישאר בבית כל היום ולהסתכל בפחד על חשבון הבנק המתרוקן, אבל עם ניצול נכון של הזמן יש סיכוי לצאת מחוזקים גם מהתקופה הקרובה.
متاح الآن! بحث تيليغرام 2025 — أهم رؤى العام 
