كيفية استضافة تطبيق Remix؟
في هذه المقالة، ستتعرف في هذه المقالة على كل ما تحتاج إلى معرفته لبدء استخدام Remix. سنلقي نظرة على إيجابياته وسلبياته، وسنوضح كيفية إنشاء تطبيق Remix، وأخيرًا، كيفية نشر Remix.
Contents
ما هو Remix؟
Remix هو إطار عمل ويب حديث كامل المكدس لبناء تطبيقات ويب سريعة وبسيطة ومرنة. وهو يستفيد من قوة العرض من جانب الخادم (SSR)، مما يتيح أوقات تحميل أسرع وتحسين تحسين محركات البحث لتطبيقات الويب الديناميكية.
باستخدام Remix، يمكن للمطورين دمج منطق جانب العميل ومنطق جانب الخادم بسلاسة ضمن قاعدة شيفرة موحدة. بالمقارنة مع أطر React الشائعة الأخرى، يقوم Remix بالكثير من الأشياء بشكل مختلف. يتضمن ذلك:
- التوجيه المستند إلى ملف (ملف في دليل المسارات يمثل مساراً محدداً)
- معالجة النماذج التقليدية (باستخدام HTML وطلبات HTTP، على غرار PHP)
- إدارة الحالة (يتم تخزين الحالة على الخادم فقط)
- تحميل البيانات (منفصلة عن المكونات)
تم إنشاء Remix في عام 2020 وكان متاحاً في البداية بموجب رسوم ترخيص سنوية. لاحقاً، في أكتوبر 2021، قرر فريق Remix أن يكون المشروع مفتوح المصدر. وهو متاح الآن بموجب ترخيص MIT.
في نهاية عام 2022، استحوذت Shopify على شركة Remix مقابل 2.1 مليار دولار.
فوائد Remix
دعنا نلقي نظرة على الفوائد الرئيسية لاستخدام إطار عمل Remix.
التنقل المستند إلى الملفات
تم بناء Remix على React Router، وهو حل توجيه قوي من جانب العميل. في الواقع، تم إنشاء Remix بواسطة نفس فريق المطورين الذي أنشأ React Router.
يستخدم إطار العمل نظام تنقل قائم على الملفات، مما يبسط تنظيم التعليمات البرمجية. يسمح للمطورين بربط المسارات والمكونات والموارد بملفات أو دلائل محددة.
إليك مثالاً على ذلك:
app/
└── routes/
├── $noteId.tsx // matches: /<noteId>/
├── $noteId_.destroy.tsx // matches: /<noteId>/destroy
├── $noteId_.edit.tsx // matches: /<noteId>/edit
├── _index.tsx // matches: /
└── create.tsx // matches: /create
أفضل ما في الأمر أنه يدعم التوجيه المتداخل عبر . ينتج عن ذلك أوقات تحميل أقصر ومعالجة أفضل للأخطاء والمزيد!
العرض من جانب الخادم (SSR)
تستفيد Remix من قوة العرض من جانب الخادم.
في تطبيقات React الفانيلا، عادةً ما يتم جلب البيانات من جانب العميل ثم حقنها في DOM. يُعرف هذا باسم التصيير من جانب العميل (CSR).
من ناحية أخرى، يتبع Remix نهجًا مختلفًا. فهو يقوم أولاً بجلب البيانات على الواجهة الخلفية، ثم يعرض HTML مع البيانات التي تم جلبها، ثم يقدمها إلى العميل.
يميل العرض من جانب الخادم إلى الحصول على أداء أفضل وتطبيقات أكثر ملاءمة لتحسين محركات البحث.
التعامل مع النماذج
يعيد Remix التعامل مع الشكل إلى الأساسيات.
بدلاً من استخدام مجموعة من المكونات المتحكم بها و JavaScript، فإنه يستخدم نماذج HTML التقليدية وطلبات HTTP.
عندما يتم إرسال نموذج، فإنه يرسل طلب HTTP إلى مسار محدد، والذي تتم معالجته بعد ذلك على جانب الخادم باستخدام الدالة action()
. تعمل بشكل مشابه ل PHP القديمة الجيدة.
هذا يعني أن Remix لا يتطلب أي JavaScript على الإطلاق لمعالجة النماذج. على الرغم من أن هذا أمر رائع، إلا أنه قد يجعل التحقق من صحة النماذج وعرض الأخطاء أكثر صعوبة بعض الشيء.
إدارة الدولة
في هذا السياق، تشير الحالة في هذا السياق إلى مزامنة بيانات الخادم والعميل.
يجعل Remix إدارة الحالة أمرًا سهلاً للغاية. فهو يلغي الحاجة إلى Redux أو Zustand أو React Query أو Apollo أو أي مكتبة أخرى لإدارة الحالة من جانب العميل.
عند استخدام Remix يتم التعامل مع جميع الحالات بواسطة الخادم. لا يحتفظ العميل بأي حالة تقريبًا؛ وبالتالي فإن عملية المزامنة غير مطلوبة.
يتم تمرير البيانات من الخادم إلى العميل من خلال دوال مختلفة مثل أداة التحميل()
والإجراء()
.
التحولات وواجهة المستخدم المتفائلة
تجعل انتقالات Remix الانتقال بين الصفحات سلسًا وسريعًا من خلال تحميل البيانات مسبقًا واستخدام الرسوم المتحركة.
تعكس واجهة المستخدم المتفائلة إجراءات المستخدم على الفور، مما يجعل المواقع الإلكترونية أكثر استجابة من خلال عرض التغييرات قبل تأكيدها.
تعمل التحولات وواجهة المستخدم المتفائلة على تحسين تجربة المستخدم بشكل كبير من خلال تقليل زمن الاستجابة المتصوَّر وتوفير ملاحظات فورية.
حدود Remix
على الرغم من أن Remix رائع، إلا أنه يأتي مع بعض القيود.
مجمع
Remix ليس أسهل إطار عمل سهل الاستخدام، ووثائقه (وقت كتابة هذا التقرير) ليست الأفضل.
يقوم الإطار أيضًا بالكثير من الأشياء بشكل مختلف عن React الفانيليا. إذا كنت مطور React، فقد يستغرق الأمر بعض الوقت لتستوعب جميع مفاهيم Remix المختلفة.
أقل شعبية
لا يزال Remix إطار عمل جديد نسبيًا. يعود إصداره العام إلى أكتوبر 2021 فقط. وهو أقل نضجًا واختبارًا مقارنةً ببعض المنافسين، مثل Next.js.
وبالنظر إلى نجوم GitHub، يمكننا أن نرى أن Remix (27 ألف نجمة) أقل شعبية بكثير من Next.js (120 ألف نجمة). حتى وقت كتابة هذا التقرير، لم يتم اعتماد Remix من قبل أي من عمالقة التكنولوجيا باستثناء Shopify.
مقترنة بإحكام
تحتوي تطبيقات Remix على واجهة أمامية وخلفية مقترنة بإحكام. بينما يصلح هذا النهج للمشاريع الصغيرة، يفضل بعض المطورين مرونة الواجهة الأمامية والخلفية المنفصلة.
بالإضافة إلى ذلك، يمكن أن يؤدي فصل الواجهة الأمامية عن الخلفية إلى جعل الشيفرة البرمجية أكثر قابلية للصيانة وأسهل للاختبار.
لا يوجد SSG أو ISR
لا يدعم Remix توليد المواقع الثابتة (SSG) أو التجديد الثابت المتزايد (ISR).
كيف يتم نشر تطبيق Remix؟
في هذا القسم، سننشئ تطبيق Remix وننشره.
المتطلبات الأساسية
للمتابعة، ستحتاج إلى
- فهم أساسيات TypeScript
- خبرة في Docker (وتقنية التجميع في حاويات)
- Node.js ومعرف JavaScript IDE مثبت على جهازك
- سطح مكتب Docker مثبت على جهازك
نظرة عامة على المشروع
خلال هذه المقالة، سنعمل على تطبيق ويب للملاحظات. سيسمح تطبيق الويب للمستخدمين بإنشاء الملاحظات واسترجاعها وتحريرها وحذفها.
بالنسبة للواجهة الخلفية، سنستخدم Back4app BaaS، وبالنسبة للواجهة الأمامية، سنستخدم إطار عمل Remix. بمجرد ترميز الواجهة الأمامية، سننشرها على حاويات Back4app.
سيبدو المنتج النهائي بهذا الشكل:
أقترح عليك أولاً متابعة تطبيق الويب الخاص بالملاحظات. بعد هذه المقالة، يجب أن تكون قادرًا على نشر تطبيقات Remix الخاصة بك.
الواجهة الخلفية
في هذا القسم من المقالة، سنستخدم Back4app لبناء الواجهة الخلفية لتطبيقنا.
إنشاء تطبيق
ابدأ بتسجيل الدخول إلى حساب Back4app الخاص بك (أو إنشاء حساب إذا كنت لا تزال بحاجة إلى الحصول عليه).
عند تسجيل الدخول، ستتم إعادة توجيهك إلى بوابة “تطبيقاتي”. لإنشاء خلفية تحتاج أولاً إلى إنشاء تطبيق Back4app. للقيام بذلك، انقر على “إنشاء تطبيق جديد”.
يوفر تطبيق Back4app حلين:
- الواجهة الخلفية كخدمة (BaaS) – حل متكامل للواجهة الخلفية
- الحاويات كخدمة (CaaS) – منصة تنسيق الحاويات القائمة على Docker
بما أننا نعمل على واجهة خلفية، اختر “الواجهة الخلفية كخدمة”.
قم بتسمية تطبيقك، واترك كل شيء آخر كما هو افتراضي، وانقر على “إنشاء”.
ستستغرق المنصة بعض الوقت لإعداد كل ما هو مطلوب للواجهة الخلفية. يتضمن ذلك قاعدة البيانات، وواجهة التطبيق، والتوسع، والأمان، وما إلى ذلك.
بمجرد أن يصبح تطبيقك جاهزاً، ستتم إعادة توجيهك إلى عرض قاعدة بيانات التطبيق في الوقت الفعلي.
قاعدة البيانات
للمضي قدماً، دعنا نهتم بقاعدة البيانات.
بما أننا ننشئ تطبيقًا بسيطًا نسبيًا، سنحتاج إلى نموذج واحد فقط – دعنا نسميه ملاحظة
. لإنشائه، انقر على زر “إنشاء صف” في أعلى يسار الشاشة.
قم بتسميته "ملاحظة
“، وقم بتمكين “تمكين القراءة والكتابة العامة”، وانقر على “إنشاء فئة وإضافة أعمدة”.
ثم، أضف الأعمدة التالية:
+-----------+--------------+----------------+----------+
| Data type | Name | Default value | Required |
+-----------+--------------+----------------+----------+
| String | emoji | <leave blank> | yes |
+-----------+--------------+----------------+----------+
| String | title | <leave blank> | yes |
+-----------+--------------+----------------+----------+
| File | content | <leave blank> | no |
+-----------+--------------+----------------+----------+
بمجرد إنشاء الفصل، قم بتعبئة قاعدة البيانات بعينة من البيانات. قم بإنشاء بعض الملاحظات من خلال توفير الرموز التعبيرية والعناوين والمحتوى. بدلاً من ذلك، قم باستيراد تصدير قاعدة البيانات هذه.
عظيم، هذا كل شيء!
لقد نجحنا في إنشاء واجهة خلفية دون كتابة أي كود برمجي.
لمعرفة المزيد عن الواجهة الخلفية كخدمة – راجع ما هي الواجهة الخلفية كخدمة؟
الواجهة الأمامية
في هذا القسم من المقالة، سنقوم ببناء الواجهة الأمامية لتطبيقنا باستخدام إطار عمل Remix.
إنشاء-Remix
أسهل طريقة لتهيئة مشروع Remix هي عبر أداة إنشاء Remix
. تعمل هذه الأداة على إنشاء مشروع Remix جاهز للإنتاج.
فهو يعتني ببنية الدليل والتبعيات، ويقوم بإعداد المجمّع، وما إلى ذلك.
أنشئ مشروع Remix جديد عن طريق تشغيل الأمر التالي:
$ npx create-remix@latest remix-notes
Initialize a new git repository? Yes
Install dependencies with npm? Yes
إذا لم يسبق لك استخدام ميزة
Create-remix،
فسيتم تثبيتها تلقائياً.
بمجرد إنشاء المشروع، قم بتغيير الدليل النشط الخاص بك إليه:
$ cd remix-notes
وأخيراً، ابدأ تشغيل خادم التطوير:
$ npm run dev
افتح متصفح الويب المفضل لديك وانتقل إلى http://localhost:5173. يجب أن تظهر صفحة الهبوط الافتراضية لـ Remix على شاشتك.
TailwindCSS
لجعل حياتنا أسهل قليلاً، سنستخدم TailwindCSS. TailwindCSS هو إطار عمل يعتمد على الأداة المساعدة أولًا يتيح لك إنشاء واجهات أمامية بسرعة دون كتابة أي CSS عادي.
أولاً، قم بتثبيته باستخدام npm:
$ npm install -D tailwindcss postcss autoprefixer
بعد ذلك، قم بتشغيل بدء تشغيل tailwindcss
:
$ npx tailwindcss init --ts -p
سيؤدي ذلك إلى تهيئة مشروعك وإنشاء ملف tailwind.config.ts في جذر المشروع.
قم بتعديل خاصية المحتوى
الخاصة به هكذا لإعلام Tailwind بالملفات التي ستُستخدم فيها فئات الأداة المساعدة:
// tailwind.config.ts
import type {Config} from "tailwindcss";
export default {
content: ["./app/**/*.{js,jsx,ts,tsx}"], // new
theme: {
extend: {},
},
plugins: [],
} satisfies Config;
قم بإنشاء ملف جديد باسم tailwind.css في دليل التطبيق بالمحتويات التالية:
/* app/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
وأخيراً، استورده في root.tsx عبر الروابط
:
// app/root.tsx
// other imports
import {LinksFunction} from "@remix-run/node";
import stylesheet from "~/tailwind.css?url";
export const links: LinksFunction = () => [
{ rel: "stylesheet", href: stylesheet },
];
// ...
هذا كل شيء!
لقد قمنا بتثبيت TailwindCSS بنجاح.
المسارات
سيحتوي تطبيق الويب الخاص بنا على نقاط النهاية التالية:
/
يعرض جميع الملاحظات/إنشاء
يسمح للمستخدمين بإنشاء ملاحظات/
يعرض ملاحظة محددة/
/ حذف يسمح للمستخدمين بحذف ملاحظة معينة
لتحديد هذه المسارات، قم بإنشاء بنية الدليل التالية في مجلد التطبيق:
app/
└── routes/
├── $noteId.tsx
├── $noteId_.destroy.tsx
├── $noteId_.edit.tsx
├── _index.tsx
└── create.tsx
كما قد تكون خمنت، تُستخدم البادئة $
للمعلمات الديناميكية، وتُستخدم البادئة .
المشاهدات
للمضي قدماً، دعونا ننفذ المناظر.
لجعل شيفرتنا أكثر أمانًا من حيث النوع، سننشئ واجهة باسم Note
تشبه فئة قاعدة بيانات Note
.
أنشئ مجلدًا باسم المخزن، وأنشئ داخله NoteModel.ts بالمحتويات التالية:
// app/store/NoteModel.ts
export default interface NoteModel {
objectId: string;
emoji: string;
title: string;
content: string;
createdAt: Date;
updatedAt: Date;
}
ثم الصق كود العرض ل _index.tsx، و $noteId.tsx، و create.tsx:
// app/routes/_index.tsx
import {Link, NavLink} from "@remix-run/react";
import NoteModel from "~/store/NoteModel";
const notes = [
{objectId: "1", emoji: "📝", title: "My First Note"},
{objectId: "2", emoji: "📓", title: "My Second Note"},
{objectId: "3", emoji: "📔", title: "My Third Note"},
] as NoteModel[];
export default function Index() {
return (
<>
<Link to={`/create`}>
<div className="bg-blue-500 hover:bg-blue-600 text-lg font-semibold text-white
px-4 py-3 mb-2 border-2 border-blue-600 rounded-md"
>
+ Create
</div>
</Link>
{notes.map(note => (
<NavLink key={note.objectId} to={`/${note.objectId}`}>
<div className="hover:bg-slate-200 text-lg font-semibold
px-4 py-3 mb-2 border-2 border-slate-300 rounded-md"
>
{note.emoji} {note.title}
</div>
</NavLink>
))}
</>
);
}
// app/routes/$noteId.tsx
import {Form} from "@remix-run/react";
import NoteModel from "~/store/NoteModel";
const note = {
objectId: "1", emoji: "📝", title: "My First Note", content: "Content here.",
createdAt: new Date(), updatedAt: new Date(),
} as NoteModel;
export default function NoteDetails() {
return (
<>
<div className="mb-4">
<p className="text-6xl">{note.emoji}</p>
</div>
<div className="mb-4">
<h2 className="font-semibold text-2xl">{note.title}</h2>
<p>{note.content}</p>
</div>
<div className="space-x-2">
<Form
method="post" action="destroy"
onSubmit={(event) => event.preventDefault()}
className="inline-block"
>
<button
type="submit"
className="bg-red-500 hover:bg-red-600 font-semibold text-white
p-2 border-2 border-red-600 rounded-md"
>
Delete
</button>
</Form>
</div>
</>
);
}
// app/routes/create.tsx
import {Form} from "@remix-run/react";
export default function NoteCreate() {
return (
<>
<div className="mb-4">
<h2 className="font-semibold text-2xl">Create Note</h2>
</div>
<Form method="post" className="space-y-4">
<div>
<label htmlFor="emoji" className="block">Emoji</label>
<input
type="text" id="emoji" name="emoji"
className="w-full border-2 border-slate-300 p-2 rounded"
/>
</div>
<div>
<label htmlFor="title" className="block">Title</label>
<input
type="text" id="title" name="title"
className="w-full border-2 border-slate-300 p-2 rounded"
/>
</div>
<div>
<label htmlFor="content" className="block">Content</label>
<textarea
id="content" name="content"
className="w-full border-2 border-slate-300 p-2 rounded"
/>
</div>
<div>
<button
type="submit"
className="bg-blue-500 hover:bg-blue-600 font-semibold
text-white p-2 border-2 border-blue-600 rounded-md"
>
Create
</button>
</div>
</Form>
</>
);
}
لا يوجد شيء خيالي في هذا الرمز. كل ما فعلناه هو استخدام JSX مع TailwindCSS لإنشاء واجهة المستخدم.
كما لاحظت، جميع المكوّنات غير خاضعة للتحكم (نحن لا نستخدم useState())
. علاوة على ذلك، نحن نستخدم نموذج HTML فعلي.
هذا لأن إطار عمل Remix يتعامل مع النماذج المشابهة لـ PHP باستخدام طلبات HTTP، على عكس React.
Parse
هناك طرق متعددة للاتصال بالواجهة الخلفية المستندة إلى Back4app. يمكنك استخدام
- واجهة برمجة تطبيقات RESTful API
- واجهة برمجة تطبيقات GraphQL
- Parse SDK
الطريقة الأسهل والأكثر قوة هي بالتأكيد Parse SDK. Parse SDK عبارة عن مجموعة أدوات تطوير برمجيات توفر عددًا من فئات الأدوات المساعدة والطرق للاستعلام عن بياناتك ومعالجتها بسهولة.
ابدأ بتثبيت Parse عبر npm:
$ npm install -i parse @types/parse
أنشئ ملف .env في جذر المشروع هكذا :
# .env
PARSE_APPLICATION_ID=<your_parse_app_id>
PARSE_JAVASCRIPT_KEY=<your_parse_js_key>
تأكد من استبدال
<your_parse_app_id>
و<your_parse_js_key>
ببيانات الاعتماد الفعلية. للحصول على بيانات الاعتماد، انتقل إلى تطبيقك وحدد “إعدادات التطبيق > الخادم والأمان” على الشريط الجانبي.
ثم، قم بتهيئة Parse في أعلى ملف root.tsx هكذا:
// app/root.tsx
// other imports
import Parse from "parse/node";
const PARSE_APPLICATION_ID = process.env.PARSE_APPLICATION_ID || "";
const PARSE_HOST_URL = "https://parseapi.back4app.com/";
const PARSE_JAVASCRIPT_KEY = process.env.PARSE_JAVASCRIPT_KEY || "";
Parse.initialize(PARSE_APPLICATION_ID, PARSE_JAVASCRIPT_KEY);
Parse.serverURL = PARSE_HOST_URL;
سنُنشئ ملفًا منفصلًا باسم api/backend.ts لإبقاء طرق العرض الخاصة بنا نظيفة من منطق الاتصال الخلفي.
قم بإنشاء api/backend.ts بالمحتويات التالية:
// app/api/backend.ts
import Parse from "parse/node";
import NoteModel from "~/store/NoteModel";
export const serializeNote = (note: Parse.Object<Parse.Attributes>): NoteModel => {
return {
objectId: note.id,
emoji: note.get("emoji"),
title: note.get("title"),
content: note.get("content"),
createdAt: new Date(note.get("createdAt")),
updatedAt: new Date(note.get("updatedAt")),
};
}
export const getNotes = async (): Promise<NoteModel[]> => {
// ...
}
export const getNote = async (objectId: string): Promise<NoteModel | null> => {
// ...
}
// Grab the entire file from:
// https://github.com/duplxey/back4app-containers-remix/blob/master/app/api/backend.ts
وأخيرًا، عدّل طرق العرض لجلب بيانات الواجهة الخلفية ومعالجتها:
// app/routes/index.tsx
import {json} from "@remix-run/node";
import {Link, NavLink, useLoaderData} from "@remix-run/react";
import {getNotes} from "~/api/backend";
export const loader = async () => {
const notes = await getNotes();
return json({notes});
};
export default function Index() {
const {notes} = useLoaderData<typeof loader>();
return (
// ...
);
}
// app/routes/$noteId.tsx
import {getNote} from "~/api/backend";
import {json, LoaderFunctionArgs} from "@remix-run/node";
import {Form, useLoaderData} from "@remix-run/react";
import {invariant} from "@remix-run/router/history";
export const loader = async ({params}: LoaderFunctionArgs) => {
invariant(params.noteId, "Missing noteId param");
const note = await getNote(params.noteId);
if (note == null) throw new Response("Not Found", {status: 404});
return json({note});
};
export default function NoteDetails() {
const {note} = useLoaderData<typeof loader>();
return (
// ...
);
}
// app/routes/create.tsx
import {ActionFunctionArgs, redirect} from "@remix-run/node";
import {Form} from "@remix-run/react";
import {createNote} from "~/api/backend";
export const action = async ({request}: ActionFunctionArgs) => {
const formData = await request.formData();
const {emoji, title, content} = Object.fromEntries(formData)
as Record<string, string>;
const note = await createNote(emoji, title, content);
return redirect(`/${note?.objectId}`);
};
export default function NoteCreate() {
return (
// ...
);
}
// app/routes/$noteId_.destroy.tsx
import type {ActionFunctionArgs} from "@remix-run/node";
import {redirect} from "@remix-run/node";
import {invariant} from "@remix-run/router/history";
import {deleteNote} from "~/api/backend";
export const action = async ({params}: ActionFunctionArgs) => {
invariant(params.noteId, "Missing noteId param");
await deleteNote(params.noteId);
return redirect(`/`);
};
ملخص الكود
- استخدمنا دالة Remix
loader()
لتحميل البيانات. بمجرد تحميل البيانات، مررناها إلى طريقة العرض بصيغة JSON عبر الدالةjson()
.
- استخدمنا دالة Remix
action()
للتعامل مع إرسال النموذج (على سبيل المثال،POST
).
- تم تمرير
معرف الملاحظة
إلى طرق العرض كمعامل.
يجب أن يعمل التطبيق الآن بشكل كامل ومزامنته مع الواجهة الخلفية لتطبيق Back4app. تأكد من أن كل شيء يعمل عن طريق إنشاء بعض الملاحظات وتحريرها ثم حذفها.
تطبيق Dockerize
في هذا القسم، سنقوم في هذا القسم بإرساء واجهة Remix الأمامية.
ملف إرساء
ملف Dockerfile هو ملف نصي عادي يحدد الخطوات التي يجب على محرك Docker تنفيذها لإنشاء صورة.
تشمل هذه الخطوات تعيين دليل العمل، وتحديد الصورة الأساسية، ونقل الملفات، وتنفيذ الأوامر، وغير ذلك.
عادةً ما يتم تصوير التعليمات بأحرف كبيرة وتليها مباشرةً الوسيطات الخاصة بها.
لمعرفة المزيد حول جميع التعليمات، راجع مرجع Dockerfile.
أنشئ ملف Dockerfile في جذر المشروع بالمحتويات التالية:
# Dockerfile
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "run", "start"]
يعتمد ملف Dockerfile هذا على صورة العقدة: 20
. يقوم أولاً بتعيين دليل العمل ونسخ الحزمة.json وتثبيت التبعيات.
بعد ذلك، يبني المشروع ويعرض المنفذ 3000
ويخدم التطبيق.
.dockerignore
عند العمل مع Docker، ستسعى عادةً إلى إنشاء صور صغيرة قدر الإمكان.
نظرًا لأن مشروعنا يحتوي على ملفات معينة لا يجب أن تكون في الصورة (على سبيل المثال، .git،
الإنشاء،
إعدادات IDE)، سنستبعدها. للقيام بذلك، سننشئ ملف .dockerignore الذي يعمل بشكل مشابه لملف .gitignore.
أنشئ ملف .dockerignore في جذر المشروع :
# .dockerignore
.idea/
.cache/
build/
node_modules/
قم بتكييف .dockerignore وفقًا لاحتياجات مشروعك .
البناء والاختبار
قبل دفع صورة Docker إلى السحابة، من الجيد اختبارها محليًا.
أولاً، قم ببناء الصورة:
$ docker build -t remix-notes:1.0 .
بعد ذلك، قم بإنشاء حاوية باستخدام الصورة التي تم إنشاؤها حديثًا:
$ docker run -it -p 3000:3000
-e PARSE_APPLICATION_ID=<your_parse_app_id>
-e PARSE_JAVASCRIPT_KEY=<your_parse_javascript_key>
-d remix-notes:1.0
تأكد من استبدال
<your_parse_app_id>
و<your_parse_javascript_key>
ببيانات الاعتماد الفعلية.
يجب أن يكون تطبيقك الآن متاحًا على http://localhost:3000. يجب أن يتصرف بنفس الطريقة التي كان عليها قبل عملية الإرساء.
الدفع إلى GitHub
لنشر تطبيق على حاويات Back4app، يجب عليك أولاً دفع التعليمات البرمجية المصدرية إلى GitHub. للقيام بذلك، يمكنك اتباع الخطوات التالية:
- سجّل الدخول إلى حسابك على GitHub (أو سجّل الدخول).
- إنشاء مستودع GitHub جديد.
- انتقل إلى مشروعك المحلي وقم بتهيئته:
git init
- أضف كل التعليمات البرمجية إلى نظام التحكم في الإصدار:
git add .
- إضافة الأصل البعيد عبر
git remote add origin
عبرgit remote add origin
- التزم بجميع التعليمات البرمجية عبر
التزام git -m "الالتزام الأولي"
- ادفع الكود إلى GitHub
git push origin master
نشر التطبيق
في هذا القسم الأخير، سننشر الواجهة الأمامية في حاويات Back4app.
سجّل الدخول إلى حساب Back4app الخاص بك وانقر على “إنشاء تطبيق جديد” لبدء عملية إنشاء التطبيق.
نظرًا لأننا ننشر الآن تطبيقًا في حاويات، حدد “الحاويات كخدمة”.
بعد ذلك، يجب عليك ربط حساب GitHub الخاص بك مع Back4app واستيراد المستودع الذي قمت بإنشائه مسبقًا. بمجرد الاتصال، حدد الريبو.
يسمح Back4app Containers بالتهيئة المتقدمة. ومع ذلك، بالنسبة لتطبيقنا البسيط، ستكفي الإعدادات التالية:
- اسم التطبيق: Remix-notes (أو اختر اسمك)
- متغيرات البيئة:
parse_application_id
,parse_javascript_key
استخدم القيم التي استخدمتها في ملف .env لمتغيرات البيئة.
بمجرد الانتهاء من تكوين النشر، انقر على “نشر”.
انتظر بضع لحظات حتى يكتمل النشر. بمجرد النشر، انقر على الرابط الأخضر على الجانب الأيسر من الشاشة لفتح التطبيق في متصفحك.
للاطلاع على برنامج تعليمي مفصل، يُرجى مراجعة وثائق Back4app’s Container Remix الخاصة بـ Back4app.
هذا كل شيء! تم الآن نشر تطبيقك بنجاح ويمكن الوصول إليه من خلال الرابط المقدم. بالإضافة إلى ذلك، أصدر Back4app شهادة SSL مجانية لتطبيقك.
الخاتمة
على الرغم من كونه إطار عمل جديد نسبيًا، إلا أن Remix يتيح للمطورين إنشاء تطبيقات ويب قوية كاملة المكدس.
يعالج إطار العمل العديد من تعقيدات تطبيقات الويب، مثل التعامل مع النماذج، وإدارة الحالة، وغيرها.
لقد تعلمت في هذه المقالة كيفية إنشاء تطبيق Remix ونشره. يجب أن تكون الآن قادرًا على استخدام Back4app لإنشاء واجهة خلفية بسيطة وحاويات Back4app لنشر تطبيقاتك المعبأة في حاويات.
الكود المصدري للمشروع متاح على back4app-containers-remix repo.