פרסת את Strapi לסביבת ייצור, וחודש לאחר מכן קבצים אובדים במהלך פריסה? או שהשרת האחורי קורס תחת עומס בעת הגשת נכסים סטטיים? מצב מוכר: ספריית המדיה הסטנדרטית של Strapi מאחסנת הכל ב-public/uploads — טוב לפיתוח, אבל קריטי לייצור. במאמר זה, נעבור על הגדרת אחסון Strapi לייצור. במשך למעלה מ-10 שנים, הגדרנו ספריות מדיה עבור יותר מ-50 פרויקטים של Strapi ואנחנו יודעים כיצד להימנע מבעיות אלו. אנו משלבים אחסון ענן המבוסס על S3, Cloudinary או R2, מוסיפים אופטימיזציה אוטומטית של תמונות ובקרת סוגי קבצים. נסקור הגדרה נכונה שמבטלת כאבי ראש.
אחסון מקומי אינו פותר שלוש בעיות מרכזיות. ראשית, קבצים אינם משוכפלים בין מופעים: עם קנה מידה אופקי, כל שרת רואה רק את הקבצים שלו. שנית, קבצים מקומיים אובדים כאשר מכולות נבנות מחדש (Docker יוצר מחדש את השכבה). ולבסוף, ביצועים: הגשת קבצים סטטיים דרך Node.js איטית יותר מאשר דרך CDN של ספק ענן. הגדרה נכונה של ספריית מדיה מפחיתה את זמן טעינת הדף ב-30–40% ומבטלת סיכוני גיבוי. בחודש אחד, אחסון מקומי יכול להוביל להפסדים משמעותיים עקב השבתה, ואופטימיזציה של תמונות חסכה ללקוח סכום משמעותי על תעבורה.
למה לא כדאי להשתמש באחסון מקומי בייצור
אחסון מקומי ב-public/uploads מתאים רק לפיתוח. בייצור, הוא יוצר צווארי בקבוק: אין סובלנות לתקלות, קשה להרחיב, וקבצים יכולים לאבד בכל פריסה. אחסון ענן פותר את כל הבעיות הללו: קבצים מאוחסנים באופן מרכזי, נגישים מכל מקום דרך CDN, ואינם אובדים בעת הפעלה מחדש של מכולות.
איזה ספק לבחור לספריית המדיה של Strapi?
| ספק | חבילה | תכונות |
|---|---|---|
| AWS S3 | @strapi/provider-upload-aws-s3 |
הגדרה גמישה, אינטגרציה עם CloudFront, SDK בוגר |
| Cloudinary | @strapi/provider-upload-cloudinary |
אופטימיזציה מובנית של תמונות, פורמטים אוטומטיים (WebP, AVIF) |
| DigitalOcean Spaces | דרך aws-s3 |
תואם S3, מחיר קבוע עבור 250 GB |
| Cloudflare R2 | דרך aws-s3 |
ללא דמי יציאה, רשת הפצה גלובלית |
Cloudinary מעבד תמונות פי 2-3 מהר יותר מ-S3 עם פונקציות Lambda. R2 מנצח במחיר עם נפחי תעבורה גבוהים — ללא חיוב על רוחב פס יוצא.
הגדרת AWS S3
התקן את החבילה: npm install @strapi/provider-upload-aws-s3. הגדרה ב-config/plugins.js:
module.exports = ({ env }) => ({
upload: {
config: {
provider: 'aws-s3',
providerOptions: {
s3Options: {
credentials: {
accessKeyId: env('AWS_ACCESS_KEY_ID'),
secretAccessKey: env('AWS_ACCESS_KEY_SECRET'),
},
region: env('AWS_REGION', 'eu-central-1'),
endpoint: env('AWS_ENDPOINT', undefined), // для S3-совместимых
params: {
ACL: env('AWS_ACL', 'public-read'),
Bucket: env('AWS_BUCKET'),
},
},
},
actionOptions: {
upload: {},
uploadStream: {},
delete: {},
},
},
},
});
Amazon S3 הוא שירות אחסון אובייקטים מ-AWS, בשימוש נרחב לאחסון קבצים.
הגדרת Cloudflare R2
R2 תואם ל-API של S3, עם יציאה חינם:
module.exports = ({ env }) => ({
upload: {
config: {
provider: 'aws-s3',
providerOptions: {
s3Options: {
credentials: {
accessKeyId: env('R2_ACCESS_KEY_ID'),
secretAccessKey: env('R2_SECRET_ACCESS_KEY'),
},
region: 'auto',
endpoint: `https://${env('CF_ACCOUNT_ID')}.r2.cloudflarestorage.com`,
params: {
Bucket: env('R2_BUCKET'),
},
},
},
},
},
});
לגישה ציבורית לקבצים, יש צורך בדומיין R2 מותאם אישית או ב-Cloudflare Worker.
הגדרת Cloudinary
התקן את החבילה: module.exports = ({ env }) => ({ upload: { config: { provider: 'aws-s3', providerOptions: { s3Options: { credentials: { accessKeyId: env('AWS_ACCESS_KEY_ID'), secretAccessKey: env('AWS_ACCESS_KEY_SECRET'), }, region: env('AWS_REGION', 'eu-central-1'), endpoint: env('AWS_ENDPOINT', undefined), // для S3-совместимых params: { ACL: env('AWS_ACL', 'public-read'), Bucket: env('AWS_BUCKET'), }, }, }, actionOptions: { upload: {}, uploadStream: {}, delete: {}, }, }, }, }); . הגדרה:
module.exports = ({ env }) => ({
upload: {
config: {
provider: 'cloudinary',
providerOptions: {
cloud_name: env('CLOUDINARY_NAME'),
api_key: env('CLOUDINARY_KEY'),
api_secret: env('CLOUDINARY_SECRET'),
},
actionOptions: {
upload: {
folder: env('CLOUDINARY_FOLDER', 'strapi'),
transformation: [{ quality: 'auto', fetch_format: 'auto' }],
},
uploadStream: {},
delete: {},
},
},
},
});בפרויקט אחד עם 500,000 תמונות, העברנו את ספריית המדיה ל-Cloudinary ביומיים, והפחתנו את זמן טעינת הדף מ-4.2 שניות ל-1.1 שניות. זה התאפשר הודות לאופטימיזציה אוטומטית ו-CDN.
פורמטי תמונה ונקודות עצירה
Strapi יוצר אוטומטית מספר גדלים בעת העלאה. הגדרה ב-module.exports = ({ env }) => ({ upload: { config: { provider: 'aws-s3', providerOptions: { s3Options: { credentials: { accessKeyId: env('R2_ACCESS_KEY_ID'), secretAccessKey: env('R2_SECRET_ACCESS_KEY'), }, region: 'auto', endpoint: `https://${env('CF_ACCOUNT_ID')}.r2.cloudflarestorage.com`, params: { Bucket: env('R2_BUCKET'), }, }, }, }, }, }); :
breakpoints: { xlarge: 1920, large: 1000, medium: 750, small: 500, xsmall: 64, }, בתגובת ה-API, השדה npm install @strapi/provider-upload-cloudinary מכיל כתובות URL עבור כל גרסה. גדלים ושימושים אופייניים:
| גודל | רוחב (פיקסלים) | שימוש אופייני |
|---|---|---|
| xlarge | 1920 | באנרים לשולחן עבודה |
| large | 1000 | מאמרים, תוכן לשולחן עבודה |
| medium | 750 | תמונות כרטיסים |
| small | 500 | תמונות ממוזערות ברשימות |
| xsmall | 64 | אייקונים, אווטארים |
סינון סוגי קבצים ומגבלות גודל
הגבלת גודל העלאה וסוגי MIME:
// config/plugins.js
module.exports = {
upload: {
config: {
sizeLimit: 20 * 1024 * 1024, // 20 МБ
},
},
};
// src/extensions/upload/strapi-server.js
module.exports = (plugin) => {
const originalUpload = plugin.controllers.upload.upload;
plugin.controllers.upload.upload = async (ctx) => {
const { files } = ctx.request;
const allowed = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
const invalid = Object.values(files).flat()
.filter(f => !allowed.includes(f.type));
if (invalid.length) {
return ctx.badRequest('Неподдерживаемый тип файла');
}
return originalUpload(ctx);
};
return plugin;
}; תהליך ההגדרה
- ניתוח דרישות: קביעת נפח קבצים, תקציב, צרכי ביצועים.
- בחירת ספק: בהתבסס על עלות, מיקום גיאוגרפי של משתמשים, צרכי עיבוד.
- הגדרת ספק: התקנת חבילה, הגדרת משתני סביבה, בדיקת חיבור.
- הגדרת נקודות עצירה: התאמת גדלים לעיצוב האתר (בדרך כלל 640, 1024, 1920).
- סינון ומגבלות: הגדרת סוגי MIME מותרים וגודל קובץ מקסימלי.
- העברת נתונים: העברת קבצים קיימים מהדיסק המקומי ועדכון הפניות במסד הנתונים.
- בדיקות: אימות העלאה, תצוגה וביצועים.
- תיעוד והדרכה: מסירת הוראות לצוות הלקוח.
פרטי העברה
ההעברה מתבצעת באמצעות סקריפט שמעתיק קבצים מ-`public/uploads` ל-bucket של S3 ומעדכן רשומות במסד הנתונים של Strapi. עבור כמה ג'יגה-בייט, התהליך אורך 1-2 ימים. לפני ההעברה, נוצר תמיד גיבוי של מסד הנתונים והקבצים. לאחר ההעברה, כל קישורי אובייקטי המדיה מצביעים לאחסון הענן.לוחות זמנים
- הגדרת ספק S3/R2/Cloudinary — כמה שעות.
- העברת קבצים קיימים מאחסון מקומי — יום אחד (תלוי בנפח).
- סינון סוגים מותאם אישית + מגבלות — כמה שעות.
מה כלול
- הגדרת אחסון ספק (S3, Cloudinary, R2).
- הגדרת נקודות עצירה ואופטימיזציה של תמונות.
- יישום סינון סוגי קבצים וגודל.
- העברת קבצים קיימים לאחסון ענן.
- תיעוד והוראות לצוות שלך.
- הבטחת פעולה תקינה ותמיכה לחודש אחד לאחר ההגדרה.
קבלו ייעוץ על הגדרת ספריית המדיה של Strapi — נעזור לכם לבחור את הפתרון האופטימלי וליישם אותו ללא השבתה. צרו קשר כדי לדון בפרויקט שלכם. הזמינו ביקורת על ההגדרה הנוכחית שלכם — נבדוק צווארי בקבוק.







