العرفان
يحلّ Carats عددًا قليلًا من المسارات وأسماء الملفات بالعرف. والانحراف عنها ينجح حتى لا ينجح، لذا يجدر الالتزام بها.
مجلدات الصفحات
يعيش كل مسار في مجلده الخاص تحت src/client/pages، ويصدِّر المجلد مكوّنًا افتراضيًا من index.tsx بجوار ورقة أنماط بالاسم نفسه. أما المجلدات التي تبدأ بشرطة سفلية ليست مسارات؛ إنها لبنات بناء مشتركة تشير إليها المسارات التي تحتاجها.
src/client/pages/
├── _layout/ # shared building block, not a route
│ ├── index.tsx
│ └── _layout.sass
├── _error/ # suspense.error
│ └── index.tsx
├── _not_found/ # suspense.notFound
│ └── index.tsx
├── home/ # '/'
│ ├── index.tsx
│ └── home.sass
├── market/ # '/market'
│ ├── index.tsx
│ └── market.sass
├── profile/ # '/profile'
│ ├── index.tsx
│ └── profile.sass
└── trade/ # '/trade/:symbol'
├── index.tsx
└── trade.sass
الشرطة السفلية البادئة هي ما يعلّم مجلدًا بأنه لبنة بناء لا صفحة. فهي تُبقي المكونات المشتركة بعيدًا في شجرة الملفات وتُشير إلى أنها ليست مسارات مقصودة.
التخطيط المشترك
لا يوجد تخطيط قائم على عُرف الملفات مثل Next.js. فمكوّن _layout يستورده الصفحات التي تحتاجه، ما يجعل التركيب صريحًا ويتيح لصفحة أن تخرج عنه. ويغلّف القالب المرجعي كل صفحة بالتخطيط نفسه لمشاركة الترويسة والتذييل وقائمة الجوال.
// src/client/pages/profile/index.tsx
import { Burnish } from '@carats/render';
import Layout from '../_layout';
import './profile.sass';
export default Burnish(function (user: User) {
this.head = <>
<title>Profile for {user.name}</title>
</>;
return (
<Layout>
<h1>{user.name}</h1>
</Layout>
);
});
يُصيّر التخطيط `props.children` حيثما ينتمي محتوى الصفحة، وهذه هي آلية التركيب الوحيدة. لا توجد شجرة مسارات متداخلة ولا التفاف تلقائي، لذا فإن التبعية ظاهرة في الاستيراد.
صفحات الخطأ وغير الموجود
مكوّنا تعليق error وnotFound مكوّنان عاديان. يستقبل الأول Error المُلقى فيستطيع قراءة message وstack، ولا يستقبل الثاني شيئًا. ويجدر تغليف الاثنين في التخطيط المشترك كي يُصيَّر هيكل الموقع حتى عند الفشل.
DTO عامة
الواجهات الموضوعة في src/dto عامة، لأن typeRoots يشير إلى ذلك المجلد. وهذا ما يتيح كتابة دالة خادمية بصيغة culet
// src/dto/user.d.ts
interface User {
id: string
name: string
username: string
email: string
phone: string
website: string
}
لا يملك الواجهة `export`، وهذا ما يجعله عامًا. ومع إشارة `typeRoots` إلى `src/dto` يُحل `culet
ورقات الأنماط
تستورد الصفحة أو المكوّن ورقة SASS الخاصة به، وتستورد تلك الورقة base.sass بـ @use ... as *. والامتداد اختياري في المسار. احتفظ بعمليات التصفير العامة والرموز في base.sass ولا شيء غير ذلك هناك.
// src/client/pages/trade/trade.sass
@use '../../base' as *
#trade
.trade-header
display: flex
الامتداد في مسار `@use` اختياري، والمسار نسبي إلى ورقة الأنماط لا إلى المكوّن. و`base.sass` هو الملف الوحيد الذي يعرّف الرموز؛ وكل ملف آخر يستهلكها.
التسمية
تُسمّى مجلدات المسارات بعد مقطع المسار، ويجب أن يتطابق اسم المعامل الديناميكي في الوجه وفي الدالة الخادمية. وتُسمّى ملفات الدوال الخادمية بعد الإجراء الذي تؤديه وتُصدِّر الدالة افتراضيًا، ثم تُثبَّت في نقطة دخول الخادم.