React Three Fiber + Next.js: بناء تجارب ويب ثلاثية الأبعاد تفاعلية من الصفر

AI Bot
بواسطة AI Bot ·

جاري تحميل مشغل تحويل النص إلى كلام الصوتي...

مقدمة

لم يعد الويب محصوراً في الواجهات المسطحة. من مُعدِّلات المنتجات وتصوير البيانات إلى المعارض التفاعلية والألعاب في المتصفح، أصبح المحتوى ثلاثي الأبعاد على الويب أداة أساسية في ترسانة كل مطور. كانت Three.js منذ فترة طويلة المكتبة المفضلة لعرض WebGL، لكن واجهتها الأمرية قد تبدو غريبة على مطوري React المعتادين على المكونات التصريحية.

React Three Fiber (R3F) يسد هذه الفجوة. إنه مُصيِّر React لـ Three.js يتيح لك بناء مشاهد ثلاثية الأبعاد باستخدام مكونات JSX والخطافات ونفس النموذج الذهني الذي تستخدمه بالفعل لواجهة المستخدم. بالاقتران مع @react-three/drei (مجموعة من المساعدات المفيدة) و @react-three/rapier (محرك فيزياء)، يمكنك إنشاء تجارب ثلاثية الأبعاد بمستوى إنتاجي دون كتابة أي WebGL خام.

في هذا الدليل، ستبني عرض منتج ثلاثي الأبعاد تفاعلي كامل — كرة عائمة يمكن للمستخدمين تدويرها، والنقر عليها لتغيير الألوان، ومشاهدتها ترتد بفيزياء واقعية. على طول الطريق، ستتقن المفاهيم الأساسية لـ R3F وتتعلم كيفية دمجه بشكل نظيف في تطبيق Next.js.

ما ستبنيه

بنهاية هذا الدليل، سيكون لديك:

  • تطبيق Next.js مع لوحة رسم ثلاثية الأبعاد بملء الشاشة
  • مشهد ثلاثي الأبعاد مع إضاءة وظلال وخرائط بيئة
  • تحكم مداري تفاعلي لحركة الكاميرا
  • كائنات ثلاثية الأبعاد متحركة بفيزياء نابضية
  • تغيير ألوان المواد بالنقر
  • أرضية مُمَكَّنة بالفيزياء مع كائنات مرتدة
  • تحسينات أداء للنشر الإنتاجي

المتطلبات الأساسية

قبل البدء، تأكد من أن لديك:

  • Node.js 20+ مثبت على جهازك
  • معرفة أساسية بـ React و TypeScript
  • إلمام بـ Next.js App Router (الصفحات تعمل أيضاً، لكننا نستخدم App Router)
  • محرر أكواد مثل VS Code مع إضافة ES7+ React
  • لا تحتاج خبرة سابقة في Three.js أو الأبعاد الثلاثية — نبدأ من الصفر

الخطوة 1: إعداد المشروع

أنشئ مشروع Next.js جديد وثبّت التبعيات المطلوبة:

npx create-next-app@latest r3f-showcase --typescript --tailwind --app --src-dir
cd r3f-showcase

الآن ثبّت React Three Fiber وحزم النظام البيئي:

npm install three @react-three/fiber @react-three/drei @react-three/rapier
npm install -D @types/three

إليك ما يفعله كل حزمة:

الحزمةالغرض
threeمكتبة Three.js الأساسية
@react-three/fiberمُصيِّر React لـ Three.js
@react-three/dreiمساعدات جاهزة (تحكم، محمّلات، مواد)
@react-three/rapierتكامل محرك الفيزياء
@types/threeتعريفات أنواع TypeScript

الخطوة 2: فهم Canvas

أساس كل تطبيق R3F هو مكون Canvas. يُنشئ سياق WebGL ويدير حلقة عرض Three.js لك.

أنشئ ملفاً جديداً في src/components/Scene.tsx:

"use client";
 
import { Canvas } from "@react-three/fiber";
 
export default function Scene() {
  return (
    <div className="h-screen w-full">
      <Canvas
        camera={{ position: [0, 2, 5], fov: 50 }}
        shadows
      >
        {/* مشهدنا ثلاثي الأبعاد سيكون هنا */}
        <mesh>
          <boxGeometry args={[1, 1, 1]} />
          <meshStandardMaterial color="royalblue" />
        </mesh>
      </Canvas>
    </div>
  );
}

بعض النقاط المهمة:

  • "use client" مطلوب لأن R3F يستخدم واجهات برمجة المتصفح (WebGL) وخطافات React داخلياً
  • camera يحدد الموضع الأولي وزاوية الرؤية
  • shadows يُفعّل خرائط الظل عالمياً
  • mesh هو لبنة البناء الأساسية — هندسة مع مادة

حدّث src/app/page.tsx لعرض المشهد:

import dynamic from "next/dynamic";
 
const Scene = dynamic(() => import("@/components/Scene"), {
  ssr: false,
  loading: () => (
    <div className="flex h-screen w-full items-center justify-center bg-black">
      <p className="text-white">جارٍ تحميل المشهد ثلاثي الأبعاد...</p>
    </div>
  ),
});
 
export default function Home() {
  return <Scene />;
}

استخدم دائماً الاستيراد dynamic مع ssr: false لمكونات R3F في Next.js. Three.js يصل إلى window و document اللذين لا يوجدان أثناء العرض من جانب الخادم.

شغّل خادم التطوير لرؤية أول مكعب ثلاثي الأبعاد:

npm run dev

يجب أن ترى مكعباً أزرق على خلفية سوداء. يبدو مسطحاً لأنه ليس لدينا إضاءة بعد.

الخطوة 3: إضافة الإضاءة والبيئة

الإضاءة هي ما يحول الكائنات المسطحة إلى مرئيات ثلاثية الأبعاد واقعية. أنشئ src/components/Lighting.tsx:

"use client";
 
import { Environment } from "@react-three/drei";
 
export default function Lighting() {
  return (
    <>
      {/* إضاءة محيطة للإنارة الأساسية */}
      <ambientLight intensity={0.3} />
 
      {/* ضوء اتجاهي رئيسي (مثل الشمس) */}
      <directionalLight
        position={[5, 8, 5]}
        intensity={1.5}
        castShadow
        shadow-mapSize-width={2048}
        shadow-mapSize-height={2048}
        shadow-camera-far={20}
        shadow-camera-left={-5}
        shadow-camera-right={5}
        shadow-camera-top={5}
        shadow-camera-bottom={-5}
      />
 
      {/* ضوء تعبئة من الجانب المعاكس */}
      <directionalLight
        position={[-3, 4, -5]}
        intensity={0.4}
      />
 
      {/* خريطة بيئة HDR لانعكاسات واقعية */}
      <Environment preset="city" />
    </>
  );
}

مكون Environment من drei يحمّل خريطة بيئة HDR توفر انعكاسات واقعية على الأسطح المعدنية واللامعة. خاصية preset تقدم عدة خيارات مدمجة: city، sunset، dawn، night، warehouse، forest، apartment، studio، park، و lobby.

الخطوة 4: إنشاء الكائن ثلاثي الأبعاد التفاعلي

الآن لنبني نجم عرضنا — كرة ثلاثية الأبعاد تفاعلية تستجيب لأحداث التمرير والنقر. أنشئ src/components/InteractiveSphere.tsx:

"use client";
 
import { useRef, useState } from "react";
import { useFrame } from "@react-three/fiber";
import { MeshDistortMaterial } from "@react-three/drei";
import type { Mesh } from "three";
 
const COLORS = ["#ff6b6b", "#4ecdc4", "#45b7d1", "#96ceb4", "#feca57"];
 
export default function InteractiveSphere() {
  const meshRef = useRef<Mesh>(null);
  const [colorIndex, setColorIndex] = useState(0);
  const [hovered, setHovered] = useState(false);
 
  // حلقة الرسوم المتحركة — تعمل كل إطار (~60fps)
  useFrame((state, delta) => {
    if (!meshRef.current) return;
 
    // حركة طفو لطيفة
    meshRef.current.position.y =
      Math.sin(state.clock.elapsedTime * 0.8) * 0.3 + 1.5;
 
    // دوران بطيء
    meshRef.current.rotation.y += delta * 0.3;
 
    // تكبير عند التمرير
    const targetScale = hovered ? 1.2 : 1;
    meshRef.current.scale.lerp(
      { x: targetScale, y: targetScale, z: targetScale } as any,
      0.1
    );
  });
 
  const handleClick = () => {
    setColorIndex((prev) => (prev + 1) % COLORS.length);
  };
 
  return (
    <mesh
      ref={meshRef}
      castShadow
      onClick={handleClick}
      onPointerOver={() => setHovered(true)}
      onPointerOut={() => setHovered(false)}
    >
      <sphereGeometry args={[1, 64, 64]} />
      <MeshDistortMaterial
        color={COLORS[colorIndex]}
        roughness={0.2}
        metalness={0.8}
        distort={hovered ? 0.4 : 0.2}
        speed={2}
      />
    </mesh>
  );
}

المفاهيم الرئيسية المُقدمة هنا:

  • useFrame — خطاف الرسوم المتحركة في R3F. يعمل في كل إطار عرض، مما يمنحك الوصول إلى ساعة Three.js ووقت الدلتا. لا تستخدم أبداً requestAnimationFrame مباشرة — useFrame متكامل مع حلقة عرض R3F.
  • MeshDistortMaterial — مساعد drei ينشئ تأثير سطح متموج ومشوه. خاصيتا distort و speed تتحكمان في التشويه.
  • أحداث المؤشر — R3F يدعم onClick، onPointerOver، onPointerOut والمزيد، تماماً مثل عناصر DOM في React العادية. في الخلفية، يستخدم إسقاط الأشعة لتحديد أي كائن ثلاثي الأبعاد يتفاعل معه الماوس.
  • lerp — الاستيفاء الخطي للانتقالات السلسة. بدلاً من القفز إلى المقياس المستهدف، ننتقل بسلاسة نحوه في كل إطار.

الخطوة 5: إضافة التحكم المداري

اسمح للمستخدمين بتدوير الكاميرا وتقريبها حول المشهد. حدّث مكون Scene:

"use client";
 
import { Canvas } from "@react-three/fiber";
import { OrbitControls, ContactShadows } from "@react-three/drei";
import Lighting from "./Lighting";
import InteractiveSphere from "./InteractiveSphere";
 
export default function Scene() {
  return (
    <div className="h-screen w-full bg-gradient-to-b from-gray-900 to-black">
      <Canvas
        camera={{ position: [0, 2, 5], fov: 50 }}
        shadows
      >
        <Lighting />
        <InteractiveSphere />
 
        {/* أرضية مع ظلال تلامسية */}
        <ContactShadows
          position={[0, -0.5, 0]}
          opacity={0.5}
          scale={10}
          blur={2}
          far={4}
        />
 
        {/* تحكم الكاميرا */}
        <OrbitControls
          enablePan={false}
          minDistance={3}
          maxDistance={10}
          minPolarAngle={Math.PI / 6}
          maxPolarAngle={Math.PI / 2.2}
        />
      </Canvas>
    </div>
  );
}

تهيئة OrbitControls تحد من حركة الكاميرا لمنع المستخدمين من الذهاب تحت الأرض أو التقريب بعيداً جداً. ContactShadows ينشئ ظلاً ناعماً تحت الكائن دون الحاجة إلى أرضية فعلية.

الخطوة 6: تحميل نماذج ثلاثية الأبعاد

غالباً ما تستخدم المشاريع الحقيقية نماذج ثلاثية الأبعاد بدلاً من الأشكال البدائية. R3F يدعم نماذج GLTF/GLB أصلياً عبر خطاف useGLTF من drei.

أنشئ مكون محمّل النماذج في src/components/Model.tsx:

"use client";
 
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { useGLTF, Float } from "@react-three/drei";
import type { Group } from "three";
 
interface ModelProps {
  url: string;
  scale?: number;
  position?: [number, number, number];
}
 
export default function Model({ url, scale = 1, position = [0, 0, 0] }: ModelProps) {
  const groupRef = useRef<Group>(null);
  const { scene } = useGLTF(url);
 
  useFrame((state) => {
    if (!groupRef.current) return;
    groupRef.current.rotation.y = state.clock.elapsedTime * 0.2;
  });
 
  return (
    <Float
      speed={1.5}
      rotationIntensity={0.3}
      floatIntensity={0.5}
    >
      <group ref={groupRef} position={position} scale={scale}>
        <primitive object={scene.clone()} castShadow receiveShadow />
      </group>
    </Float>
  );
}

مكون Float من drei يضيف حركة طفو لطيفة تلقائياً. خطاف useGLTF يتعامل مع التحميل والتخزين المؤقت والتخلص من نماذج GLTF.

يمكنك العثور على نماذج ثلاثية الأبعاد مجانية في poly.pizza و sketchfab.com و market.pmnd.rs. حمّلها بتنسيق GLB وضعها في مجلد public/models/.

لتحميل النماذج مسبقاً وتجنب ومضات التحميل:

// في أسفل ملف مكون Model
useGLTF.preload("/models/sneaker.glb");

الخطوة 7: إضافة الفيزياء

الفيزياء تبث الحياة في مشهدك بتفاعلات واقعية. أنشئ src/components/PhysicsScene.tsx:

"use client";
 
import { Physics, RigidBody, CuboidCollider } from "@react-three/rapier";
import { useState } from "react";
 
function BouncingBall({ position }: { position: [number, number, number] }) {
  const [color, setColor] = useState("#ff6b6b");
 
  return (
    <RigidBody
      position={position}
      restitution={0.8}
      friction={0.5}
      colliders="ball"
    >
      <mesh
        castShadow
        onClick={() => setColor(`hsl(${Math.random() * 360}, 70%, 60%)`)}
      >
        <sphereGeometry args={[0.3, 32, 32]} />
        <meshStandardMaterial color={color} roughness={0.3} metalness={0.6} />
      </mesh>
    </RigidBody>
  );
}
 
function Ground() {
  return (
    <RigidBody type="fixed">
      <CuboidCollider args={[10, 0.1, 10]} position={[0, -1, 0]} />
      <mesh receiveShadow position={[0, -1, 0]}>
        <boxGeometry args={[20, 0.2, 20]} />
        <meshStandardMaterial color="#1a1a2e" />
      </mesh>
    </RigidBody>
  );
}
 
export default function PhysicsScene() {
  const balls = Array.from({ length: 10 }, (_, i) => ({
    id: i,
    position: [
      (Math.random() - 0.5) * 4,
      3 + Math.random() * 5,
      (Math.random() - 0.5) * 4,
    ] as [number, number, number],
  }));
 
  return (
    <Physics gravity={[0, -9.81, 0]}>
      <Ground />
      {balls.map((ball) => (
        <BouncingBall key={ball.id} position={ball.position} />
      ))}
    </Physics>
  );
}

مكون Physics يغلف مشهدك ويطبق الجاذبية. RigidBody يجعل الكائنات تشارك في محاكاة الفيزياء. الخصائص الرئيسية:

  • restitution — الارتداد (0 = بدون ارتداد، 1 = ارتداد مثالي)
  • friction — احتكاك السطح (0 = جليد، 1 = مطاط)
  • type="fixed" — يجعل الكائن غير قابل للتحريك (مثالي للأرضيات والجدران)
  • colliders — ينشئ تلقائياً أشكال التصادم (ball، cuboid، hull، trimesh)

الخطوة 8: تأثيرات ما بعد المعالجة

أضف جودة سينمائية مع المعالجة اللاحقة. ثبّت حزمة التأثيرات:

npm install @react-three/postprocessing

أنشئ src/components/Effects.tsx:

"use client";
 
import { EffectComposer, Bloom, ChromaticAberration, Vignette } from "@react-three/postprocessing";
 
export default function Effects() {
  return (
    <EffectComposer>
      <Bloom
        luminanceThreshold={0.6}
        luminanceSmoothing={0.9}
        intensity={0.5}
      />
      <Vignette eskil={false} offset={0.1} darkness={0.5} />
      <ChromaticAberration offset={[0.0005, 0.0005]} />
    </EffectComposer>
  );
}
  • Bloom — ينشئ تأثير توهج على الأسطح اللامعة
  • Vignette — يعتّم حواف الشاشة لإحساس سينمائي
  • ChromaticAberration — يضيف تأثير انحراف لوني خفيف

تأثيرات ما بعد المعالجة يمكن أن تؤثر بشكل كبير على الأداء في الأجهزة المحمولة. وفّر دائماً طريقة لتعطيلها، أو استخدم خطاف useDetectGPU من drei لضبط الجودة تلقائياً.

الخطوة 9: جودة متجاوبة وتكيفية

تطبيقات الأبعاد الثلاثية في الإنتاج يجب أن تعمل على كل شيء من الحواسيب عالية الأداء إلى الهواتف ذات الميزانية المحدودة. أنشئ src/components/AdaptiveScene.tsx:

"use client";
 
import { useThree } from "@react-three/fiber";
import { useDetectGPU, PerformanceMonitor } from "@react-three/drei";
import { useState, useEffect } from "react";
 
export function AdaptivePixelRatio() {
  const { gl } = useThree();
  const GPUTier = useDetectGPU();
 
  useEffect(() => {
    if (GPUTier.tier === 0 || GPUTier.isMobile) {
      gl.setPixelRatio(1);
    } else if (GPUTier.tier === 1) {
      gl.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));
    } else {
      gl.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    }
  }, [GPUTier, gl]);
 
  return null;
}
 
export function AdaptivePerformance({
  children,
}: {
  children: (dpr: number) => React.ReactNode;
}) {
  const [dpr, setDpr] = useState(1.5);
 
  return (
    <PerformanceMonitor
      onIncline={() => setDpr(Math.min(dpr + 0.5, 2))}
      onDecline={() => setDpr(Math.max(dpr - 0.5, 0.5))}
    >
      {children(dpr)}
    </PerformanceMonitor>
  );
}

PerformanceMonitor يراقب معدلات الإطارات ويضبط الجودة تلقائياً. عندما تنخفض الإطارات، يقلل نسبة البكسل؛ وعندما يكون الأداء جيداً، يزيد الجودة.

الخطوة 10: تجميع كل شيء معاً

الآن اجمع كل شيء في المشهد النهائي. حدّث src/components/Scene.tsx:

"use client";
 
import { Suspense } from "react";
import { Canvas } from "@react-three/fiber";
import { OrbitControls, ContactShadows, Html, Preload } from "@react-three/drei";
import Lighting from "./Lighting";
import InteractiveSphere from "./InteractiveSphere";
import Effects from "./Effects";
import { AdaptivePixelRatio } from "./AdaptiveScene";
 
function Loader() {
  return (
    <Html center>
      <div className="flex flex-col items-center gap-2">
        <div className="h-8 w-8 animate-spin rounded-full border-2 border-white border-t-transparent" />
        <p className="text-sm text-white">جارٍ تحميل المشهد...</p>
      </div>
    </Html>
  );
}
 
export default function Scene() {
  return (
    <div className="relative h-screen w-full bg-gradient-to-b from-gray-900 to-black">
      {/* طبقة واجهة المستخدم */}
      <div className="absolute right-0 top-0 z-10 p-6">
        <h1 className="text-3xl font-bold text-white">عرض منتج ثلاثي الأبعاد</h1>
        <p className="mt-2 text-gray-400">انقر على الكرة لتغيير الألوان</p>
        <p className="text-gray-400">اسحب للتدوير • مرر للتقريب</p>
      </div>
 
      <Canvas
        camera={{ position: [0, 2, 5], fov: 50 }}
        shadows
        dpr={[1, 2]}
        gl={{ antialias: true, alpha: false }}
      >
        <AdaptivePixelRatio />
 
        <Suspense fallback={<Loader />}>
          <Lighting />
          <InteractiveSphere />
 
          <ContactShadows
            position={[0, -0.5, 0]}
            opacity={0.5}
            scale={10}
            blur={2}
            far={4}
          />
 
          <Effects />
          <Preload all />
        </Suspense>
 
        <OrbitControls
          enablePan={false}
          minDistance={3}
          maxDistance={10}
          minPolarAngle={Math.PI / 6}
          maxPolarAngle={Math.PI / 2.2}
          autoRotate
          autoRotateSpeed={0.5}
        />
      </Canvas>
    </div>
  );
}

الإضافات الرئيسية:

  • Suspense مع Loader مخصص — يعرض مؤشر تحميل أثناء تحميل الأصول
  • Preload all — يحمّل جميع الأصول في شجرة المشهد مسبقاً
  • dpr={[1, 2]} — يحد نطاق نسبة البكسل لأداء ثابت
  • autoRotate — يدور الكاميرا ببطء عندما لا يتفاعل المستخدم
  • Html — يعرض HTML عادي داخل المشهد ثلاثي الأبعاد، دائماً مواجهاً للكاميرا

أفضل ممارسات الأداء

عند نشر R3F في الإنتاج، تذكر هذه القواعد:

  1. الشبكات المُنسَخة — إذا كان لديك العديد من الكائنات المتطابقة، استخدم InstancedMesh بدلاً من شبكات فردية. هذا يقلل من مكالمات الرسم بشكل كبير.
import { Instances, Instance } from "@react-three/drei";
 
function Particles() {
  return (
    <Instances limit={1000}>
      <sphereGeometry args={[0.05, 8, 8]} />
      <meshStandardMaterial color="white" />
      {positions.map((pos, i) => (
        <Instance key={i} position={pos} />
      ))}
    </Instances>
  );
}
  1. تحرير الموارد — R3F يتعامل مع هذا تلقائياً للمكونات التي تُفصل، لكن إذا أنشأت مواد أو هندسات يدوياً، استدعِ دائماً .dispose().

  2. ضغط القوام — استخدم تنسيق KTX2 للقوام بدلاً من PNG/JPG. drei يوفر useKTX2 لهذا.

  3. استخدم frameloop="demand" — إذا كان مشهدك ثابتاً في الغالب، اضبط هذا على Canvas للعرض فقط عندما يتغير شيء:

<Canvas frameloop="demand">
  1. تجنب إعادة العرض — استخدم useFrame للرسوم المتحركة بدلاً من حالة React. تغييرات حالة React تُحفّز إعادة عرض المكونات؛ useFrame يعمل خارج مصالحة React.

استكشاف الأخطاء وإصلاحها

خطأ "window is not defined"

يحدث هذا عندما يعمل كود R3F أثناء العرض من جانب الخادم. استخدم دائماً الاستيرادات الديناميكية مع ssr: false:

const Scene = dynamic(() => import("@/components/Scene"), { ssr: false });

شاشة سوداء بدون أخطاء

عادةً مشكلة إضاءة. تأكد من وجود مصدر ضوء واحد على الأقل. جرّب إضافة <ambientLight intensity={1} /> للتحقق من وجود الكائنات.

أداء ضعيف على الهاتف المحمول

  • قلل تعقيد الهندسة (شرائح أقل)
  • خفّض نسبة البكسل: dpr={[0.5, 1]}
  • عطّل الظلال: احذف خاصية shadows من Canvas
  • احذف تأثيرات ما بعد المعالجة

الكائنات لا تستقبل النقرات

R3F يستخدم إسقاط الأشعة لأحداث المؤشر. تأكد من أن الشبكة لديها هندسة مرفقة — الهندسات غير المرئية أو ذات الحجم الصفري لن تسجل النقرات.

الخطوات التالية

الآن بعد أن أتقنت الأساسيات، استكشف هذه المجالات:

  • مواد الشيدر — اكتب شيدرات GLSL مخصصة مع shaderMaterial من drei
  • نص ثلاثي الأبعاد — استخدم Text3D من drei مع خطوط مخصصة
  • رسوم متحركة مبنية على التمرير — اجمع R3F مع ScrollControls لتجارب ثلاثية الأبعاد مدفوعة بالتمرير
  • VR/AR — R3F يدعم WebXR أصلياً مع مكون XR
  • متعدد اللاعبين — اجمع مع WebSockets لتجارب ثلاثية الأبعاد مشتركة

الخلاصة

React Three Fiber يحوّل تطوير الويب ثلاثي الأبعاد من مهارة متخصصة إلى شيء يمكن لأي مطور React تعلمه. من خلال معاملة الكائنات ثلاثية الأبعاد كمكونات، واستخدام الخطافات للرسوم المتحركة، والاستفادة من مكتبة مساعدات drei الواسعة، يمكنك بناء تجارب ثلاثية الأبعاد بمستوى إنتاجي دون خبرة عميقة في Three.js.

النقاط الرئيسية من هذا الدليل:

  • Canvas هو نقطة دخولك — غلّف دائماً محتوى R3F فيه
  • useFrame هو حلقة الرسوم المتحركة — لا تستخدم أبداً requestAnimationFrame
  • drei هو صندوق أدواتك — تحقق منه قبل بناء حلول مخصصة
  • الاستيرادات الديناميكية مع تعطيل SSR إلزامية في Next.js
  • الأداء يتطور مع الوعي — نسبة البكسل والنسخ ومستوى التفصيل مهمة

ابدأ ببساطة، كرر، ودع الطبيعة التصريحية لـ React توجه بنية مشهدك ثلاثي الأبعاد. الويب ثلاثي الأبعاد في بدايته فقط، وأنت الآن مجهز لبنائه.


هل تريد قراءة المزيد من الدروس التعليمية؟ تحقق من أحدث درس تعليمي لدينا على دليل 2026 لنشر Laravel + Vue: من Docker إلى GitHub Actions وCoolify.

ناقش مشروعك معنا

نحن هنا للمساعدة في احتياجات تطوير الويب الخاصة بك. حدد موعدًا لمناقشة مشروعك وكيف يمكننا مساعدتك.

دعنا نجد أفضل الحلول لاحتياجاتك.

مقالات ذات صلة