AWS Amplify וחלופות ענן
AWS Amplify · Azure Static Web Apps · Firebase · Supabase · Vercel · Netlify
בהשוואה
TypeScript תחילה
תפעולית
ותמחור
מבוא: למה Full-Stack ללא שרתים?
שירותי Full-Stack מנוהלים מפחיתים חלק מעבודת הקצאת המשאבים והפריסה; הם אינם מבטלים תכנון ארכיטקטורה, הרשאות, גיבויים, ניטור, תגובה לתקלות או ניהול עלויות. ההשוואה מפרידה בין אירוח היישום לבין מסדי נתונים ושירותי זהות שעשויים לדרוש הגדרות נפרדות.
הסקירה של שש הפלטפורמות להלן היא כלי לתכנון שנבדק מול תיעוד הספקים הנוכחי, לא מבחן ביצועים או הצעת מחיר. דוגמאות Amplify הן הגדרות לימודיות חלקיות, ולא יישום שנפרס או נבדק. בדקו תלויות, הרשאות ענן וחיובי שירות לפני התאמתן.
📊 השוואת תכונות הפלטפורמות
| פלטפורמה | אימות זהות | מסד נתונים | אחסון | פונקציות | CI/CD | שיקולי ניידות |
|---|---|---|---|---|---|---|
| AWS Amplify Gen 2 | Cognito | DynamoDB דרך Amplify Data; שילובי SQL נפרדים | S3 | Lambda | ✅ מובנה | תלות במשאבים ובממשקי AWS |
| Firebase | Firebase Auth | Firestore/RTDB; קיימת גם SQL Connect | GCS | Cloud Functions | ✅ מובנה | עבודת מעבר של מודל הנתונים, SDK ושירותים |
| Supabase | Supabase Auth | PostgreSQL | תואם S3 | Edge Functions | אפשרויות פריסה וענפים באמצעות GitHub | ניידות Postgres; עדיין נדרשת העברת שירותים ותפעול |
| Vercel | ספריית אימות או ספק לפי בחירת היישום | שילוב מסד נתונים התלוי בספק | Vercel Blob | Edge/Serverless | ✅ מבוסס Git | תלות במסגרת, בסביבת ריצה ובספקים |
| Azure Static Web Apps | Entra ID ו־GitHub מוגדרים מראש; ספקים מותאמים בנפרד | חיבור לשירות מסד נתונים נפרד | אירוח סטטי; Blob הוא שירות נפרד | Azure Functions | ✅ GitHub Actions | תלות בשירותי Azure ובפריסה |
| Netlify | Netlify Identity עדיין נתמכת | Netlify Database — Postgres — או ספק חיצוני | Netlify Blobs | Netlify Functions | ✅ מובנה | תלות בפונקציות, באחסון ובספקים |
AWS Amplify Gen 2: צד שרת המבוסס על TypeScript
Amplify Gen 2 משתמשת בהגדרות TypeScript דרך @aws-amplify/backend למשאבים כגון אימות זהות, נתונים, אחסון ופונקציות, על בסיס כלי תשתית כקוד. שלד הפרויקט אינו כולל אוטומטית כל משאב שמופיע בארכיטקטורה רעיונית. חברו את המשאבים ב־backend.ts ובדקו את ההרשאות שנוצרו. ראו הגדרה ידנית.
# Educational example only; not executed here. # From a disposable local frontend project directory: npm create amplify@latest # Typical backend files (storage is added only when configured): amplify/ auth/resource.ts data/resource.ts backend.ts tsconfig.json # Frontend source and package.json belong to your chosen app scaffold.
import { type ClientSchema, a, defineData } from '@aws-amplify/backend';
const schema = a.schema({
Todo: a
.model({
content: a.string().required(),
isDone: a.boolean().default(false),
priority: a.enum(['LOW', 'MEDIUM', 'HIGH']),
dueDate: a.date(),
owner: a.string(), // Owners can reassign this field by default.
})
.authorization(allow => [
allow.owner(), // Owner CRUD; other rules below also grant access
allow.groups(['Admins']).to(['read', 'update']),
]),
});
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: 'userPool',
},
});
import { defineAuth, secret } from '@aws-amplify/backend';
export const auth = defineAuth({
loginWith: {
email: true,
externalProviders: {
google: {
clientId: secret('GOOGLE_CLIENT_ID'),
clientSecret: secret('GOOGLE_CLIENT_SECRET'),
},
callbackUrls: ['http://localhost:3000', 'https://example.com'],
logoutUrls: ['http://localhost:3000', 'https://example.com'],
},
},
multifactor: {
mode: 'OPTIONAL',
totp: true,
},
userAttributes: {
preferredUsername: { required: false, mutable: true },
},
});
שימוש ב־Amplify בממשק React
// src/TodoList.tsx: partial educational component, not a complete app.
// The app entry point must run Amplify.configure(outputs) before this module
// is used, and show this component only in its authenticated UI.
import { useEffect, useState } from 'react';
import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource';
const client = generateClient<Schema>();
type Todo = Schema['Todo']['type'];
export function TodoList() {
const [todos, setTodos] = useState<Todo[]>([]);
const [failed, setFailed] = useState(false);
const [busy, setBusy] = useState(false);
useEffect(() => {
const sub = client.models.Todo.observeQuery().subscribe({
next: ({ items }) => setTodos([...items]),
error: () => setFailed(true),
});
return () => sub.unsubscribe();
}, []);
async function change(todo?: Todo) {
if (busy) return;
setBusy(true);
setFailed(false);
try {
const result = todo
? await client.models.Todo.update({ id: todo.id, isDone: !todo.isDone })
: await client.models.Todo.create({ content: 'Demo task', isDone: false });
if (result.errors?.length) setFailed(true);
} catch {
setFailed(true);
} finally {
setBusy(false);
}
}
return <div>
{failed && <p role="status">Request failed. Please try again.</p>}
<ul>{todos.map(todo => <li key={todo.id}>
<button type="button" disabled={busy} onClick={() => void change(todo)}>
{todo.isDone ? 'Done: ' : 'Not done: '}{todo.content}
</button>
</li>)}</ul>
<button type="button" disabled={busy} onClick={() => void change()}>Add demo task</button>
</div>;
}
Firebase לעומת Amplify: ההבדלים העיקריים
🤔 מדריך לבחירת פלטפורמה
- שקלו Amplify כאשר הצוות כבר מכיר זהויות ותפעול ב־AWS
- בדקו את שילוב SQL ואת תכונות GraphQL הנדרשים
- בדקו היקף שירות, חוזים ובקרות מול דרישות התאימות
- תכננו במפורש שכפול בין אזורים, מעבר בעת תקלה ומיקום נתונים
- בדקו הרשאות צוות ומורכבות מחזור חיי זהויות
- השוו תמיכת SDK ליישום Android או iOS המיועד
- מדדו סנכרון, התנגשויות והרשאות בעומס שלכם
- בנו אב־טיפוס עם מגבלות מציאותיות ותוכנית מעבר
- התחשבו בניסיון ובתפעול קיימים ב־Google Cloud
- בדקו מטמון לא מקוון ויישוב שינויים ב־SDK הנבחר
- העריכו אילו תכונות והרחבות PostgreSQL נדרשות
- אם נבחר אירוח עצמי, תקצבו עדכונים, גיבויים ותמיכה
- תכננו ובדקו מדיניות אבטחה ברמת השורה
- תכננו מעבר נתונים, אימות זהות ו־API משירות קיים
- בנו מודל עלות כולל במקום להניח שתפעול קוד פתוח חינמי
- בדקו תאימות מסגרת וסביבת ריצה ל־Next.js או Nuxt.js
- העריכו תהליך פיתוח ממשק לצד האחריות לצד השרת
- השוו תהליך תצוגה מקדימה ובקרות פריסה
- מדדו השהיה מקצה לקצה, לרבות אזור מסד הנתונים
- בדקו חיבורי מסד נתונים, מאגרי חיבורים ועלויות ספק
Azure Static Web Apps עם Functions
Azure Static Web Apps יכולה לשלב אירוח ממשק סטטי עם שירותי API נתמכים, לרבות Azure Functions. ספקי האימות המוגדרים מראש הם Microsoft Entra ID ו־GitHub; אימות כשלעצמו אינו מגביל משתמשים לדייר שלכם. יש לבדוק בנפרד ספק מותאם וכללי הרשאה לנתיבים. Azure AD B2C אינה זמינה לרכישה ללקוחות חדשים החל מ־1 במאי 2025. ראו ברירות המחדל לאימות והודעת הזמינות של B2C.
# Illustrative workflow only; not installed or run.
# Review and pin actions to approved full commit SHAs before production.
name: Azure Static Web Apps example
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened, closed]
branches: [main]
permissions:
contents: read
jobs:
upload:
if: >-
github.event_name == 'push' ||
(github.event_name == 'pull_request' && github.event.action != 'closed' &&
github.event.pull_request.head.repo.full_name == github.repository)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
action: upload
app_location: /
api_location: api
output_location: dist
close_preview:
if: >-
github.event_name == 'pull_request' && github.event.action == 'closed' &&
github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
steps:
- uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
action: close
Supabase: חלופת קוד פתוח ל־Firebase
Supabase משלבת PostgreSQL עם אימות זהות, אחסון, פונקציות ויכולות זמן אמת. המודל היחסי שלה שונה מ־Firestore, אך Firebase אינה מוגבלת ל־NoSQL: שירות SQL Connect משתמש ב־Cloud SQL for PostgreSQL. ב־Supabase נדרשות הגדרות מדיניות גישה והרשאות; מפתח לקוח אינו תחליף לאבטחה ברמת השורה. ראו Firebase SQL Connect וסוגי המפתחות של Supabase.
// Partial Vite browser example; not executed.
// Preconditions: existing authenticated session, least-privilege grants/RLS,
// reviewed articles schema and todos publication for Realtime.
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
import.meta.env.VITE_SUPABASE_URL,
import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY
);
// Never use a secret/service_role key in a browser bundle.
const channel = supabase.channel('demo-todos').on('postgres_changes', {
event: 'UPDATE', schema: 'public', table: 'todos'
}, () => {
// Refresh only the UI data this user is authorized to read.
// Do not log row contents or credentials.
}).subscribe();
// Assumes articles.fts is an English tsvector column with a matching index.
const { data: articles, error } = await supabase.from('articles')
.select('id, title')
.textSearch('fts', 'typescript & amplify', { config: 'english' })
.eq('published', true)
.order('created_at', { ascending: false })
.limit(10);
if (error) {
// Show a generic error in the UI; handle details without leaking private data.
}
// On component teardown, await or otherwise handle this promise:
async function dispose() {
await supabase.removeChannel(channel);
}
// Authentication UI/session renewal and invocation of dispose belong to the app.
תכנון עלויות: מספר משתמשים חודשי לבדו אינו אומדן חשבון
בנו מודל של קריאות וכתיבות, חישוב, אחסון, העברת נתונים, דקות בנייה, תכונות זהות, אזור, תמיכה וזכאות למסלול בתשלום. המכסות החינמיות שונות בין השירותים ועשויות להשתנות. הרשומות הבאות מציינות גורמי עלות ולא סכומים חודשיים בני השוואה; עיינו בתמחור הספקים המקושר לפני התחייבות.
סיכום והמלצות
בחרו לפי דרישות ולא לפי מנצחת אוניברסלית: גבולות זהות, מודל נתונים, אזורים, בקרות פריסה, תפעול ועלות מעבר. ניסיון ב־AWS עשוי להקל על הערכת Amplify; צורך ב־PostgreSQL עשוי להעדיף אפשרות יחסית; תהליך פיתוח הממשק עשוי להצדיק השוואה של Vercel או Netlify. אף אחד מהשיקולים אינו מוכיח שיפור שנמדד בפרודוקטיביות או בביצועים של הצוות שלכם.
לפני אימוץ פלטפורמה, תעדו תוכנית בדיקה מורשית עם נתונים סינתטיים, מגבלות תקציב, בדיקות שחזור ותנאי יציאה. מסלולים חינמיים אינם מתאימים אוטומטית לייצור מסחרי. תשתית מנוהלת משנה את האחריות ואינה מבטלת אותה. לא בוצעה לצורך מאמר זה שום פעולה בחשבון, בתשתית, בחיוב או בזהות.
מקורות ראשוניים
- התחלה עם React ו־Amplify
- יצירת שלד Amplify
- הגדרת Amplify Data
- הרשאות בעלות
- כללי הרשאה משולבים
- ספקי זהות חיצוניים
- מצבי אימות רב־גורמי
- ברירות מחדל לאימות ב־Azure
- זמינות B2C
- תהליך בנייה ב־Azure
- פעולת Checkout
- שירות יחסי ב־Firebase
- פריסת Supabase דרך GitHub
- עדכון תמיכת Netlify Identity
- מסד הנתונים של Netlify
- שילובי מסדי נתונים ב־Vercel
- גבולות מפתחות API ב־Supabase
- שינויי Postgres
- חיפוש טקסט מלא ב־Postgres
- תמחור Firebase
- תמחור Supabase
- תמחור Vercel
- תמחור Amplify
- תמחור Azure Static Web Apps