كيفية استخدام Inertia.js في مشاريع Laravel الخاصة بك

نشرت: 2022-12-08

أصبحت التطبيقات متعددة الصفحات (MPAs) أقل شيوعًا يومًا بعد يوم. تستخدم المنصات الشهيرة مثل Facebook و Twitter و YouTube و Github والعديد من الأنظمة الأخرى بالفعل تقنية تطبيق الصفحة الواحدة (SPA) بدلاً من ذلك.

تتيح هذه التقنية العصرية للمستخدمين التفاعل مع تطبيقات الويب بسرعة واستجابة لأن كل شيء يتم تقديمه من جانب العميل. ومع ذلك ، قد يكون الأمر صعبًا بالنسبة للمطورين الذين يقومون بإنشاء تطبيقات مقدمة من جانب الخادم بأطر مثل Laravel أو Django.

لحسن الحظ ، تدخلت Inertia.js وجاءت لإنقاذ.
العنصر المفقود الذي تحتاجه مشاريع Laravel الخاصة بك؟ القصور الذاتي. تعرف على المزيد في هذا الدليل الشامل انقر للتغريد
في هذه المقالة ، سنوضح كيف يمكنك البدء في استخدام Inertia.js وكيفية استخدامه مع Laravel و Vue.js و Tailwind CSS لإنشاء تطبيق ويب مدونة حديث. سنشارك أيضًا في كيفية جعل SPAs أكثر ملاءمة لكبار المسئولين الاقتصاديين ، بالإضافة إلى بعض الحيل الأخرى.

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

لماذا واس؟

قبل أن نسأل لماذا يجب علينا استخدام القصور الذاتي ، يجب أن نسأل أولاً: "لماذا SPA؟"

لماذا يفضل أي شخص التطبيقات المقدمة من جانب العميل على التطبيقات التقليدية من جانب الخادم؟ ما الذي قد يجبر مطور Laravel كامل المكدس على توديع مكونات الشفرة؟

الإجابة المختصرة: لأن السرعة والاستجابة ضروريان لأي تفاعل ناجح للمستخدم.

في حالة MPAs ، يرسل المتصفح باستمرار الطلبات إلى الخلفية ، والتي تقوم بعد ذلك بتنفيذ العديد من استعلامات قاعدة البيانات. بعد استعلامات معالجة قاعدة البيانات والخادم وتسليمها إلى المتصفح ، يتم عرض الصفحة.

لكن SPA مختلفة. يجلب التطبيق كل ما يحتاجه المستخدم مباشرة إلى الصفحة ، مما يلغي الحاجة إلى أن يرسل المتصفح استفسارات أو يعيد تحميل الصفحة لعرض عناصر HTML جديدة.

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

ومع ذلك ، قد يكون إنشاء تطبيق من صفحة واحدة صعبًا على مطوري Laravel لأنه سيتطلب منهم البدء في استخدام Vue.js أو React بدلاً من قوالب الشفرات ، مما يؤدي إلى فقدان العديد من جواهر Laravel التي توفر الوقت والجهد.

الآن بعد أن أصبح لدينا Inertia.js ، كل هذا تغير.

لماذا القصور الذاتي؟

إذا كان مطورو Laravel يقومون ببناء SPA على الويب باستخدام Vue قبل Inertia ، فسيتعين عليهم إعداد واجهات برمجة التطبيقات وإرجاع بيانات JSON باستخدام Laravel ، ثم استخدام شيء مثل AXIOS لاسترداد البيانات في مكونات Vue. سيحتاجون أيضًا إلى شيء مثل Vue Router لإدارة المسارات ، مما يعني فقدان توجيه Laravel ، بالإضافة إلى الأدوات الوسيطة ووحدات التحكم.

من ناحية أخرى ، يتيح Inertia.js للمطورين إنشاء تطبيقات Vue و React و Svelte الحديثة أحادية الصفحة باستخدام التوجيه الكلاسيكي من جانب الخادم ووحدات التحكم. تم تصميم Inertia لمطوري Laravel و Ruby on Rails و Django للسماح لهم بإنشاء تطبيقات دون تغيير تقنيات الترميز الخاصة بهم لإنشاء وحدات تحكم ، وجلب البيانات من قاعدة بيانات ، وعرض طرق العرض

بفضل Inertia.js ، سيشعر مطورو Laravel بأنهم في المنزل تمامًا.

كيف يعمل القصور الذاتي

يمنحك إنشاء SPA باستخدام Laravel و Vue صفحة JavaScript كاملة للواجهة الأمامية ، لكن هذا لن يوفر لك تجربة تطبيق من صفحة واحدة. سيؤدي كل ارتباط تم النقر عليه إلى إعادة تشغيل إطار العمل من جانب العميل عند تحميل الصفحة التالية.

هذا هو المكان الذي يدخل فيه القصور الذاتي الصورة.

القصور الذاتي هو في الأساس مكتبة توجيه من جانب العميل. يسمح لك بالتنقل بين الصفحات دون الحاجة إلى إعادة تحميل الصفحة بأكملها. يتم تحقيق ذلك عبر مكون <Link> ، وهو عبارة عن غلاف خفيف الوزن حول علامة الارتساء القياسية.

عند النقر فوق ارتباط القصور الذاتي ، يعترض Inertia النقرة ويعيد توجيهك إلى XHR بدلاً من ذلك. لن يقوم المتصفح بإعادة تحميل الصفحة بهذه الطريقة ، مما يمنح المستخدم تجربة صفحة واحدة كاملة.

الشروع في القصور الذاتي

صفحة بسيطة بها "مدونة Kinsta" في بانر أزرق في الأعلى وصف واحد من نماذج بطاقات المقالات.
نموذج صفحة تم إنشاؤه باستخدام Inertia.js

لفهم Inertia وكيفية دمجه مع Laravel ، سنقوم ببناء تطبيق ويب مدونة باسم Kinsta Blog باستخدام أقوى مجموعة تحرير وسرد ، Laravel للواجهة الخلفية ، Vue.js لواجهة JavaScript الأمامية ، و Tailwind CSS للتصميم.

إذا كنت تفضل اتباع هذا البرنامج التعليمي في بيئة محلية ، فيمكنك استخدام DevKinsta ، وهي أداة قوية للمطورين والمصممين والوكالات التي تمكنهم من إنشاء تطبيقات ويب WordPress فردية ومتعددة الصفحات. لحسن الحظ ، يمكن دمج WordPress بسهولة مع Laravel باستخدام حزمة Corcel.

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

لتحقيق أقصى استفادة من هذا البرنامج التعليمي ، يجب أن تكون على دراية بما يلي:

  • أساسيات Laravel (التثبيت وقاعدة البيانات وترحيل قواعد البيانات ونماذج Eloquent ووحدات التحكم والتوجيه)
  • أساسيات Vue.js (التثبيت والهيكل والنماذج)

إذا كنت تشعر بعدم اليقين ، تحقق من هذه البرامج التعليمية الرائعة المجانية والمدفوعة من Laravel. خلاف ذلك ، دعنا نقفز.

الخطوة الأولى: تثبيت Core Elements

للتركيز على Inertia.js والوصول إلى الجزء الممتع على الفور ، تأكد من أن لديك الإعداد التالي جاهزًا للبدء:

  1. مشروع Laravel 9 الذي تم تركيبه حديثًا باسم kinsta-blog
  2. تم تثبيت Tailwind CSS CLI في مشروع Laravel الخاص بنا
  3. مكونان من مكونات الشفرة في kinsta-blog / resources / views لعرض الصفحة الرئيسية للمدونة ومقال واحد على المدونة كما هو موضح أدناه:

    "/ resources / views / index.blade.php ":

     <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Kinsta Blog</title> </head> <body> <header> <h1>Kinsta Blog</h1> </header> <main> <h2>Read our latest articles</h2> <section> <article> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h3>Title for the blog</h3> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem itaque error vel perferendis aliquam numquam dignissimos, expedita perspiciatis consectetur! </p> <a href="#">Read more</a> </article> </section> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </body> </html>

    "/ resources / views / show.blade.php ":

     <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Kinsta Blog</title> </head> <body> <main> <article> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h1>Title for the blog</h1> <p>Article content goes here</p> </article> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </body> </html>
  4. قاعدة بيانات MySQL المحلية المسماة kinsta_blog متصلة بمشروعنا:

    " .env ":

     DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=kinsta_blog DB_USERNAME=root DB_PASSWORD=
  5. نموذج المادة والهجرات والمصانع:

    "التطبيق / النماذج / article.php ":

     <?php namespace AppModels; use IlluminateDatabaseEloquentFactoriesHasFactory; use IlluminateDatabaseEloquentModel; class Article extends Model { use HasFactory; protected $fillable = ['title', 'excerpt', 'body']; }

    "قاعدة البيانات / عمليات الترحيل / create_articles_table.php ":

     <?php use IlluminateDatabaseMigrationsMigration; use IlluminateDatabaseSchemaBlueprint; use IlluminateSupportFacadesSchema; return new class extends Migration { public function up() { Schema::create('articles', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('excerpt'); $table->text('body'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('articles'); } };

    "قاعدة البيانات / المصانع / ArticleFactory.php ":

     <?php namespace DatabaseFactories; use IlluminateDatabaseEloquentFactoriesFactory; class ArticleFactory extends Factory { public function definition() { return [ 'title' => $this->faker->sentence(6), 'excerpt' => $this->faker->paragraph(4), 'body' => $this->faker->paragraph(15), ]; } }

هذا كل ما نحتاجه للبدء! الآن دعنا نبدأ العمل ونقدم Inertia.js لمشروعنا.

الخطوة الثانية: تثبيت Inertia

تنقسم عملية تثبيت القصور الذاتي إلى مرحلتين رئيسيتين: جانب الخادم (Laravel) وجانب العميل (VueJs).

دليل التثبيت الرسمي في وثائق Inertia قديم بعض الشيء لأن Laravel 9 يستخدم الآن Vite افتراضيًا ، لكننا سنتناول ذلك أيضًا.

1. جانب الخادم

أول شيء يتعين علينا القيام به هو تثبيت محولات Inertia من جانب الخادم باستخدام الأمر الطرفي أدناه عبر Composer.

 composer require inertiajs/inertia-laravel

سنقوم الآن بإعداد قالب الجذر الخاص بنا ، والذي سيكون ملف نصلي مفرد سيتم استخدامه لتحميل ملفات CSS و JS ، بالإضافة إلى جذر القصور الذاتي الذي سيتم استخدامه لتشغيل تطبيق JavaScript الخاص بنا.

نظرًا لأننا نستخدم أحدث إصدار من Laravel 9 v9.3.1 ، يجب علينا أيضًا تمكين Vite للعمل بسحره من خلال تضمينه في علاماتنا في / resources / views / app.blade.php :

 <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <!-- Fetch project name dynamically --> <title inertia>{{ config('app.name', 'Laravel') }}</title> <!-- Scripts --> @vite('resources/js/app.js') @inertiaHead </head> <body class="font-sans antialiased"> @inertia </body> </html>

لاحظ كيف يمكننا جلب عنوان المشروع ديناميكيًا عن طريق إضافة سمة Inertia إلى علامات <title> .

أضفنا أيضًا التوجيه @vite إلى الرأس للسماح لـ Vite بمعرفة مسار ملف JavaScript الرئيسي حيث أنشأنا تطبيقنا واستوردنا CSS. Vite هي أداة تساعد في تطوير JavaScript و CSS من خلال السماح للمطورين بمشاهدة تغييرات الواجهة الأمامية دون الحاجة إلى تحديث الصفحة أثناء التطوير المحلي.

ستكون خطوتنا التالية هي إنشاء برمجيات وسيطة HandleInertiaRequests ونشرها في مشروعنا. يمكننا القيام بذلك عن طريق تشغيل الأمر الطرفي أدناه داخل الدليل الجذر لمشروعنا:

 php artisan inertia:middleware

بمجرد اكتمال ذلك ، توجه إلى "App / Http / Kernel " وقم بتسجيل HandleInertiaRequests باعتبارها العنصر الأخير في البرامج الوسيطة على الويب:

 'web' => [ // ... AppHttpMiddlewareHandleInertiaRequests::class, ],

2. جانب العميل

بعد ذلك ، يتعين علينا تثبيت تبعيات الواجهة الأمامية Vue.js 3 بنفس الطريقة كما هو الحال على جانب الخادم:

 npm install @inertiajs/inertia @inertiajs/inertia-vue3 // or yarn add @inertiajs/inertia @inertiajs/inertia-vue3

بعد ذلك ، عليك سحب Vue.js 3:

 npm install [email protected]

ثم قم بتحديث ملف JavaScript الأساسي لتهيئة Inertia.js باستخدام Vue.js 3 و Vite و Laravel:

"resources / js / app.js ":

 import "./bootstrap"; import "../css/app.css"; import { createApp, h } from "vue"; import { createInertiaApp } from "@inertiajs/inertia-vue3"; import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; createInertiaApp({ title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue") ), setup({ el, app, props, plugin }) { return createApp({ render: () => h(app, props) }) .use(plugin) .mount(el); }, });

في مقتطف الشفرة أعلاه ، نستخدم حل resolvePageComponent plugin solutionPageComponent ، ونطلب منه حل مكوناتنا من الدليل ./Pages/$name.vue . هذا لأننا سنحفظ مكونات Inertia الخاصة بنا في هذا الدليل لاحقًا في مشروعنا ، وسيساعدنا هذا المكون الإضافي في تحميل هذه المكونات تلقائيًا من الدليل الصحيح.

كل ما تبقى هو تثبيت vitejs/plugin-vue :

 npm i @vitejs/plugin-vue

وتحديث ملف vite.config.js :

 import { defineConfig } from "vite"; import laravel from "laravel-vite-plugin"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ plugins: [ laravel({ input: ["resources/css/app.css", "resources/js/app.js"], refresh: true, }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], });

الخطوة الأخيرة هي تثبيت تبعياتنا وتجميع ملفاتنا:

 npm install npm run dev

وفويلا! لديك تطبيق Laravel 9 عامل مع Vue.js 3 و Vite. الآن نحن بحاجة لرؤية شيء ما يحدث في العمل!

إنشاء صفحات القصور الذاتي

هل تتذكر ملفي الشفرة هذين ( الفهرس والعرض ) لعرض صفحتنا الرئيسية ومقال واحد؟

ملف الشفرة الوحيد الذي سنحتاجه أثناء استخدام Inertia هو app.blade.php ، والذي استخدمناه مرة واحدة بالفعل عندما كنا نقوم بتثبيت Inertia. إذن ماذا يحدث لتلك الملفات الآن؟

سنقوم بتحويل هذه الملفات من مكونات النصل إلى مكونات Inertia.js.

تحتوي كل صفحة في التطبيق الخاص بك على وحدة التحكم الخاصة بها ومكون JavaScript مع القصور الذاتي. يتيح لك هذا الحصول فقط على البيانات المطلوبة لتلك الصفحة ، دون استخدام واجهة برمجة التطبيقات. صفحات القصور الذاتي ليست أكثر من مكونات جافا سكريبت ، في حالتنا هي مكونات Vue.js. ليس لديهم أي شيء جدير بالملاحظة عنهم بشكل خاص. لذا فإن ما سنفعله هو التفاف كل محتوى HTML بين علامات <template> وأي شيء متعلق بجافا سكريبت سيتم تغليفه بعلامات <script> .

أنشئ مجلدًا باسم "الصفحات" وانقل ملفاتك إليه. لذلك سيكون لدينا " index.blade.php " و " show.blade.php " في " ./resources/js/Pages ". بعد ذلك سنقوم بتغيير تنسيق الملف إلى ".vue" بدلاً من ".blade.php" أثناء جعل الحرف الأول من أسمائهم كبيرًا وتحويل محتواه إلى مكون Vue.js قياسي. سنستبعد العلامات <html> و <head> و <body> لأنها مدرجة بالفعل في مكون شفرة الجذر الرئيسي.

"resources / js / Pages / Index.vue ":

 <script setup> // </script> <template> <header> <h1>Kinsta Blog</h1> </header> <main> <h2>Read our latest articles</h2> <section> <article> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h3>Title for the blog</h3> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem itaque error vel perferendis aliquam numquam dignissimos, expedita perspiciatis consectetur! </p> <a href="#">Read more</a> </article> </section> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </template>

"resources / js / Pages / Show.vue ":

 <script setup> // </script> <template> <header> <h1>Welcome to Kinsta Blog</h1> </header> <main> <article> <h1>Title for the blog</h1> <p>Article content goes here</p> </article> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </template>

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

قم بإنشاء مجلد يسمى "Layouts" في " / resources / js " وداخل هذا المجلد قم بإنشاء ملف باسم "KinstaLayout.vue". سيحتوي هذا الملف على رأس الصفحة وتذييلها والملف main مع <slot /> للسماح بتضمين جميع المكونات المغلفة بهذا التخطيط بداخله. يجب أن يبدو هذا الملف كالتالي:

"resources / js / Layouts / KinstaLayout.vue ":

 <script setup></script> <template> <header> <h1>Kinsta Blog</h1> </header> <main> <slot /> </main> <footer> <h2>Join our Newsletter</h2> <input type="email" /> </footer> </template>

ثم سنقوم باستيراد هذا التصميم الجديد في صفحاتنا ولف كل محتوى HTML به. يجب أن تبدو مكوناتنا كما يلي:

Index.vue :

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; </script> <template> <KinstaLayout> <section> <h2>Read our latest articles</h2> <article> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h3>Title for the blog</h3> <p> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Illum rem itaque error vel perferendis aliquam numquam dignissimos, expedita perspiciatis consectetur! </p> <a href="#">Read more</a> </article> </section> </KinstaLayout> </template>

Show.vue :

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; </script> <template> <KinstaLayout> <article> <h1>Title for the blog</h1> <p>Article content goes here</p> </article> </KinstaLayout> </template>

مسارات Laravel وتجسيد القصور الذاتي

أولاً ، دعنا نستخدم ملف " ArticleFactory " الذي لدينا من نقطة انطلاق البرنامج التعليمي الخاص بنا وننشر بعض المقالات في قاعدة البيانات الخاصة بنا.

"database / seeders / databaseSeeder.php ":

 <?php namespace DatabaseSeeders; use AppModelsArticle; use IlluminateDatabaseSeeder; class DatabaseSeeder extends Seeder { public function run() { Article::factory(10)->create(); } }

ثم اضغط على الأمر Terminal أدناه لترحيل جداولك وبذر البيانات المزيفة من المصانع:

 php artisan migrate:fresh --seed

سيؤدي هذا إلى إنشاء 10 مقالات مزيفة في قاعدة البيانات ، والتي سنحتاج إلى تمريرها إلى وجهة نظرنا باستخدام توجيه Laravel. الآن بعد أن استخدمنا القصور الذاتي لتقديم العروض ، ستتغير الطريقة التي اعتدنا عليها في كتابة مساراتنا قليلاً. لنقم بإنشاء مسار Laravel Inertia الأول في "route / web.php " ونعيد عرض الصفحة الرئيسية من "/ resources / js / Pages / Index.vue ".

"المسارات / web.php ":

 <?php use AppModelsArticle; use IlluminateSupportFacadesRoute; use InertiaInertia; Route::get('/', function () { return Inertia::render('Index', [ 'articles' => Article::latest()->get() ]); })->name('home');

لاحظ أننا استوردنا Inertia ولم نستخدم view() Laravel المساعد لإرجاع العرض ، لكننا استخدمنا Inertia::render . سيبحث Inertia أيضًا بشكل افتراضي عن اسم الملف الذي ذكرناه في مسارنا في مجلد الصفحات في "resources / js".

توجه إلى ملف الفهرس وقم بتعيين البيانات المسترجعة كعنصر وحلقة فوقها باستخدام v-for لإظهار النتائج. بين علامات البرنامج النصي ، حدد البيانات التي تم تمريرها كعنصر خاص. كل ما يحتاجه القصور الذاتي إلى معرفته هو نوع البيانات التي تتوقعها ، والتي في حالتنا عبارة عن كائن "مقال" يحتوي على مجموعة من المقالات.

"resources / js / Pages / Index.vue ":

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; defineProps({ Articles: Object, }); </script>

لاحظ أنه يكفي تعريفها فقط على أنها خاصية دون إعادتها لأننا نستخدم تنسيق setup لواجهة برمجة تطبيقات التكوين Vue.js 3. إذا كنا نستخدم خيارات API ، فسنحتاج إلى إعادتها.

لنجعل الحلقة:

 <template> <KinstaLayout> <h2>Read our latest articles</h2> <section> // Looping over articles <article v-for="article in articles":key="article.id"> <div> <img src="/images/kinsta-logo.png" alt="Article thumbnail" /> </div> <h3>{{article.title}}</h3> <p>{{article.excerpt}}</p> <a href="#">Read more</a> </article> </section> </KinstaLayout> </template>

npm run dev (اتركه قيد التشغيل لأننا نستخدم Vite) ويعمل php artisan serve لبدء خادم تطوير laravel والوصول إلى موقعنا على الويب ، وسنرى الصفحة المتوقعة تعرض جميع المقالات العشرة في قاعدة البيانات.

الآن ، نحن نستخدم ملحق Vue DevTools من Google Chrome ، والذي يتيح لنا تصحيح أخطاء تطبيقي. دعنا نوضح لك كيف يتم تمرير بياناتنا إلى المكون.

يعرض ملحق Vue DevTools من Chrome قائمة بخصائص القصور الذاتي للصفحة المفتوحة.
فحص خصائص القصور الذاتي.

يتم تمرير "المقالات" إلى المكون ككائن خاص يحتوي على مصفوفة من المقالات ؛ كل مقال في المصفوفة هو أيضًا كائن له خصائص تتوافق مع البيانات التي حصل عليها من قاعدة البيانات. هذا يعني أن أي بيانات نقوم بنقلها من Laravel إلى Inertia ستعامل كخاصية.

استخدام Tailwind CSS مع Inertia.js

نظرًا لأن Tailwind مثبتة بالفعل في مشروعنا عند نقطة البداية ، فكل ما علينا فعله هو إخبارها بقراءة مكونات القصور الذاتي الخاصة بنا. يمكن تحقيق ذلك عن طريق تحرير " tailwind.config.js " على النحو التالي:

 /** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./storage/framework/views/*.php", "./resources/views/**/*.blade.php", "./resources/js/**/*.vue", ], theme: { extend: {}, }, plugins: [], };

ثم تأكد من أننا قمنا باستيراد ملف CSS الخاص بنا في "resources / js / app.js ":

 import "../css/app.css";

والآن نحن جاهزون لتصميم مكوناتنا.

"resources / js / Pages / Index.vue ":

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; defineProps({ articles: Object, }); </script> <template> <KinstaLayout> <h2 class="text-2xl font-bold py-10">Read our latest articles</h2> <section class="space-y-5 border-b-2 pb-10"> <article v-for="article in articles" :key="article.id" class="flex justify-center items-center shadow-md bg-white rounded-xl p-4 mx-auto max-w-3xl" > <img src="/images/kinsta-logo.png" class="w-32 h-32 rounded-xl object-cover" alt="" /> <div class="flex flex-col text-left justify-between pl-3 space-y-5"> <h3 class="text-xl font-semibold text-indigo-600 hover:text-indigo-800" > <a href="#">{{ article.title }}</a> </h3> <p> {{ article.excerpt }} </p> <a href="#" class="text-indigo-600 hover:text-indigo-800 w-fit self-end font-semibold" >Read more</a > </div> </article> </section> </KinstaLayout> </template>

"resources / js / Layouts / KinstaLayout.vue ":

 <script setup></script> <template> <Header class="bg-gradient-to-r from-blue-700 via-indigo-700 to-blue-700 w-full text-center py-4" > <h1 class="text-white font-bold text-4xl">Kinsta Blog</h1> </Header> <main class="container mx-auto text-center"> <slot /> </main> <footer class="bg-gradient-to-b from-transparent to-gray-300 w-full text-center mt-5 py-10 mx-auto" > <h2 class="font-bold text-xl pb-5">Join our Newsletter</h2> <input class="rounded-xl w-80 h-12 px-3 py-2 shadow-md" type="email" placeholder="Write your email.." /> </footer> </template>

إذا نظرت إلى المتصفح ، ستلاحظ أن Vite قام بالفعل بتحديث الصفحة باستخدام Tailwind magic.

صورة قابلة للتمرير تُظهر إصدارًا عاملاً من مثال "مدونة Kinsta" من المثال السابق.
تقديم خصائص القصور الذاتي.

روابط القصور الذاتي

الآن بعد أن أصبح لدينا صفحة رئيسية تعمل يمكنها عرض جميع المقالات في قاعدة البيانات ، نحتاج إلى إنشاء مسار آخر لعرض المقالات الفردية. لنقم بإنشاء مسار جديد ونضبط عنوان URL على حرف بدل "id":

"المسارات / web.php "

 <?php use AppModelsArticle; use IlluminateSupportFacadesRoute; use InertiaInertia; Route::get('/', function () { return Inertia::render('Index', [ 'articles' => Article::latest()->get() ]); })->name('home'); Route::get('/posts/{article:id}', function (Article $article) { return Inertia::render('Show', [ 'article' => $article ]); })->name('article.show');

قمنا باستيراد نموذج "المقالة" وأضفنا مسارًا جديدًا لإرجاع مكون القصور الذاتي Show.vue . استفدنا أيضًا من ربط نموذج مسار Laravel ، والذي يسمح لـ Laravel بالحصول تلقائيًا على المقالة التي نشير إليها.

كل ما نحتاجه الآن هو وسيلة لزيارة هذا الطريق بالنقر فوق ارتباط من الصفحة الرئيسية دون الحاجة إلى إعادة تحميل الصفحة بأكملها. هذا ممكن مع أداة Inertia السحرية <Link> . ذكرنا في المقدمة أن Inertia تستخدم <Link> كغلاف لعلامة الربط القياسية <a> ، وأن هذا الغلاف يهدف إلى جعل زيارات الصفحة سلسة قدر الإمكان. في القصور الذاتي ، يمكن أن تعمل علامة <Link> كعلامة ربط تؤدي طلبات <GET> ، ولكنها يمكن أن تعمل أيضًا كعلامة <button> و <form> في نفس الوقت. دعونا نرى كيف يمكننا تطبيقه على مشروعنا.

في index.vue الخاص بنا ، سنقوم باستيراد <Link> من Inertia ، وإزالة علامات الربط <a> واستبدالها بعلامات Inertia <Link> . سيتم تعيين السمة href على عنوان URL للمسار الذي قمنا بإنشائه مسبقًا لعرض المقالة:

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; import { Link } from "@inertiajs/inertia-vue3"; defineProps({ articles: Object, }); </script> <template> <KinstaLayout> <section class="space-y-5 border-b-2 pb-10"> <h2 class="text-2xl font-bold pt-10 mx-auto text-center"> Read our latest articles </h2> <article v-for="article in articles" :key="article.id" class="flex justify-center items-center shadow-md bg-white rounded-xl p-4 mx-auto max-w-3xl" > <img src="/images/kinsta-logo.png" class="w-32 h-32 rounded-xl object-cover" alt="" /> <div class="flex flex-col text-left justify-between pl-3 space-y-5" > <h3 class="text-xl font-semibold text-indigo-600 hover:text-indigo-800" > <Link :href="'/posts/' + article.id">{{ article.title }}</Link> </h3> <p> {{ article.excerpt }} </p> <Link :href="'/posts/' + article.id" class="text-indigo-600 hover:text-indigo-800 w-fit self-end font-semibold" >Read more </Link> </div> </article> </section> </KinstaLayout> </template>

دعونا نصمم Show.vue مع Tailwind لجعلها تبدو أكثر أناقة وجاهزة لزيارتنا. ونحتاج أيضًا إلى إخباره بأنه يجب أن يتوقع عنصر "مقال" وتعيينه كعنصر أساسي:

 <script setup> import KinstaLayout from "../Layouts/KinstaLayout.vue"; defineProps({ article: Object, }); </script> <template> <KinstaLayout> <article class="mx-auto mt-10 flex justify-center max-w-5xl border-b-2"> <img src="/images/kinsta-logo.png" class="w-80 h-80 rounded-xl mx-auto py-5" alt="" /> <div class="text-left flex flex-col pt-5 pb-10 px-10"> <h1 class="text-xl font-semibold mb-10">{{ article.title }}</h1> <p>{{ article.body }}</p> </div> </article> </KinstaLayout> </template>

الآن عندما نضغط على عنوان المقالة أو "قراءة المزيد" ، سيتم نقلنا بطريقة سحرية إلى Show.vue دون تحديث الصفحة.

هل تعاني من مشاكل التوقف و WordPress؟ Kinsta هو حل الاستضافة المصمم لتوفير الوقت! تحقق من ميزاتنا
تعرض صفحة "مدونة Kinsta" النموذجية بطاقات مقالات بها روابط عمل.
روابط القصور الذاتي في المكان.

في حالتنا ، نحن نستخدم <Link> كعلامة ربط ترسل طلب GET إلى المسار وإعادة البيانات الجديدة ، ولكن يمكننا استخدام <Link> PUT ، ووضع ، PATCH ، POST DELETE

"المسارات / web.php ":

 <Link href="/logout" method="post" as="button" type="button">Logout</Link>

نصائح وحيل لقصور Laravel يجب أن تعرفها

لدينا الآن SPA عاملة مبنية باستخدام Laravel و Inertia و Tailwind CSS. لكن يمكن أن يساعدنا القصور الذاتي في تحقيق المزيد. حان الوقت لاكتساب بعض تقنيات القصور الذاتي التي ستساعد المطورين وزوار التطبيق على حدٍ سواء.

توليد عناوين المواقع

ربما لاحظت أننا أضفنا أسماء إلى مسارات Laravel دون استخدامها. يتيح لنا القصور الذاتي استخدام المسارات المسماة داخل مكوناتنا بدلاً من تدوين المسار بالكامل يدويًا.

يمكننا تحقيق ذلك عن طريق تثبيت حزمة Ziggy في مشروعنا:

 composer require tightenco/ziggy

ثم توجه إلى "resources / js / app.js" وقم بتحديثه على النحو التالي:

 import "./bootstrap"; import "../css/app.css"; import { createApp, h } from "vue"; import { createInertiaApp } from "@inertiajs/inertia-vue3"; import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m"; createInertiaApp({ title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue") ), setup({ el, app, props, plugin }) { return createApp({ render: () => h(app, props) }) .use(plugin) .use(ZiggyVue, Ziggy) .mount(el); }, });

توجه إلى "/ resources / views / app.blade.php " وقم بتحديث الرأس باستخدام التوجيه @route :

 <!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Fetch project name dynamically --> <title inertia>{{ config('app.name', 'Laravel') }}</title> <!-- Scripts --> @routes @vite('resources/js/app.js') @inertiaHead </head> <body class="font-sans antialiased"> @inertia </body> </html>

... وقم بتحديث حزم NPM الخاصة بك عن طريق الضغط على الأمرين الطرفيين التاليين:

 npm install && npm run dev

تتيح لنا هذه الحزمة استخدام المسارات المسماة داخل مكونات القصور الذاتي الخاصة بنا ، لذلك دعنا نتوجه إلى Index.vue ونزيل المسار اليدوي القديم واستبدله باسم المسار أثناء تمرير البيانات بشكل طبيعي كما لو كنا في وحدة التحكم الخاصة بنا.

سنستبدل هذا:

 <Link :href="'/posts/' + article.id"> {{ article.title }} </Link>

…مع هذا:

 <Link :href="route('article.show', article.id)"> {{ article.title }} </Link>

سيعطينا هذا نفس السلوك الذي كان لدينا بالضبط ولكنه أكثر ملاءمة للمطورين ومفيدًا للغاية عندما يتوقع مسارك العديد من المعلمات.

مؤشرات التقدم

هذه واحدة من أجمل سمات Inertia.js ؛ نظرًا لأن SPA توفر تجربة مستخدم تفاعلية ، فإن الحصول على ملاحظات مستمرة حول ما إذا كان يتم تحميل الطلب سيكون إضافة رائعة للتطبيق. يمكن تحقيق ذلك من خلال مكتبة منفصلة يقدمها القصور الذاتي.

مكتبة "@ inertiajs / progress" عبارة عن غلاف حول NProgress يعرض بشكل مشروط مؤشرات التحميل وفقًا لأحداث Inertia. لا تحتاج حقًا إلى معرفة كيفية عمل ذلك من وراء الكواليس ، لذلك دعونا نجعله يعمل.

يمكننا تثبيت هذه المكتبة باستخدام الأمر الطرفي أدناه:

 npm install @inertiajs/progress

بمجرد تثبيته ، نحتاج إلى استيراده في " resources / js / app.js "

 import "./bootstrap"; import "../css/app.css"; import { createApp, h } from "vue"; import { createInertiaApp } from "@inertiajs/inertia-vue3"; import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m"; import { InertiaProgress } from "@inertiajs/progress"; createInertiaApp({ title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue") ), setup({ el, app, props, plugin }) { return createApp({ render: () => h(app, props) }) .use(plugin) .use(ZiggyVue, Ziggy) .mount(el); }, }); InertiaProgress.init({ color: "#000000", showSpinner: true });

سيظهر هذا شريط تحميل وأداة تحميل دوارة باللون الأسود ، ولكن يمكننا تغيير اللون مع خيارات أخرى مفيدة يمكن العثور عليها في وثائق مؤشر التقدم Inertia.js.

رأس "Kinsta Blog" الأزرق مع مؤشر الدوران في أعلى اليمين.
مؤشر تقدم القصور الذاتي (أعلى اليمين).

إدارة التمرير

في بعض الحالات ، قد ترغب في الانتقال إلى صفحة جديدة مع الحفاظ على نفس موضع التمرير. ربما ستحتاج إلى هذا إذا سمحت للمستخدمين بترك تعليقات ؛ سيؤدي هذا إلى إرسال نموذج وتحميل التعليق الجديد من قاعدة البيانات إلى المكون الخاص بك ؛ ستريد أن يحدث هذا دون أن يفقد المستخدم موضع التمرير. يعتني القصور الذاتي بهذا من أجلنا.

في حالتنا ، دعنا نطبق هذا على علامة <Link> الخاصة بنا في Index.vue . للحفاظ على موضع التمرير أثناء إعادة التوجيه إلى صفحة مختلفة باستخدام <Link> في Inertia ، كل ما نحتاج إلى القيام به هو إضافة سمة preserve-scroll إلى <Link> :

 <Link :href="route('article.show', article.id)" preserve-scroll> {{ article.title }} </Link>

نصائح لتحسين محركات البحث

منذ ولادة SPAs ، كان الناس قلقين بشأن تحسين محركات البحث (SEO). من المعروف أنه إذا كنت تستخدم نهج SPA ، فستجد محركات البحث صعوبة في الزحف إلى تطبيق الويب الخاص بك لأن كل شيء يتم عرضه من جانب العميل ، مما يؤدي إلى عدم ظهور موقع الويب الخاص بك في أعلى نتائج البحث ؛ ومع ذلك ، كيف يمكن لتلك المنصات الشهيرة مثل Facebook و Github أن تصبح الآن SPA ولا تزال تعمل بشكل جيد في تحسين محركات البحث؟

حسنًا ، هذه ليست مهمة: مستحيل بعد الآن. تقدم Inertia بعض الحلول لمساعدة منتجعك الصحي على أن يصبح صديقًا لكبار المسئولين الاقتصاديين.

Inertia Vue SSR مع Laravel و Vite

تبحث محركات البحث دائمًا عن HTML على موقع الويب الخاص بك من أجل تحديد المحتوى ؛ ومع ذلك ، إذا لم يكن لديك HTML في عناوين URL الخاصة بك ، فستزداد صعوبة هذه المهمة. عند تطوير SPA ، كل ما لديك على صفحتك هو JavaScript و JSON. قدم Inertia ميزة التقديم من جانب الخادم (SSR) التي يمكنك إضافتها إلى تطبيقك. يتيح ذلك لتطبيقك عرض زيارة أولية للصفحة مسبقًا على الخادم ثم إرسال HTML المعروض إلى المتصفح. يتيح ذلك للمستخدمين رؤية صفحاتك والتفاعل معها قبل تحميلها بالكامل ، وله أيضًا مزايا أخرى ، مثل تقصير الوقت الذي تستغرقه محركات البحث لفهرسة موقعك.

لتلخيص كيفية عملها ، ستحدد Inertia ما إذا كانت تعمل على خادم Node.js وستعرض أسماء المكونات والخصائص وعنوان URL وإصدار الأصول إلى HTML. سيوفر هذا للمستخدم ومحرك البحث عمليا كل ما تقدمه صفحتك.

ومع ذلك ، نظرًا لأننا نتعامل مع Laravel ، فإن هذا لا معنى له لأن Laravel هو إطار عمل PHP ولا يعمل على خادم Node.js. لذلك ، سنقوم بإعادة توجيه الطلب إلى خدمة Node.js ، والتي ستعرض الصفحة وتعيد HTML. سيؤدي ذلك إلى جعل تطبيق Laravel Vue ملائمًا لكبار المسئولين الاقتصاديين بشكل افتراضي.

First, we need to install the Vue.js SSR npm package:

 npm install @vue/server-renderer

Another helpful Inertia “NPM” package provides a simple “HTTP” server. It is strongly recommended that you install it:

 npm install @inertiajs/server

Then, in “resources/js/”, we'll add a new file named ssr.js . This file will be very similar to the app.js file we created when installing Inertia, only it will execute in Node.js rather than the browser:

 import { createSSRApp, h } from "vue"; import { renderToString } from "@vue/server-renderer"; import { createInertiaApp } from "@inertiajs/inertia-vue3"; import createServer from "@inertiajs/server"; import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; import { ZiggyVue } from "../../vendor/tightenco/ziggy/dist/vue.m"; const appName = "Laravel"; createServer((page) => createInertiaApp({ page, render: renderToString, title: (title) => `${title} - ${appName}`, resolve: (name) => resolvePageComponent( `./Pages/${name}.vue`, import.meta.glob("./Pages/**/*.vue") ), setup({ app, props, plugin }) { return createSSRApp({ render: () => h(app, props) }) .use(plugin) .use(ZiggyVue, { ...page.props.ziggy, location: new URL(page.props.ziggy.location), }); }, }) );

Make sure not to include everything in the ssr.js file since it will not be visible to visitors; this file is only for search engines and browsers to show the data within your page, so include only what is important to your data or only what will make your data available.

“By default, Inertia's SSR server will operate on port 13714. However, you can change this by providing a second argument to the createServer method.” Inertia DOCss.

The Inertia.js DOCs aren't explaining how to integrate Inertia SSR with Vite, but we will go through this now. Head to vite.config.js and paste the below:

 import { defineConfig } from "vite"; import laravel from "laravel-vite-plugin"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ plugins: [ laravel({ input: "resources/js/app.js", ssr: "resources/js/ssr.js", }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], });

Next, head to package.json and change the build script:

 "build": "vite build && vite build --ssr"

Now if we run npm run build , Vite will build our SSR bundle for production. For more information about this you may visit Inertia SSR DOCs and Vite SSR DOCs.

Title and Meta

Because JavaScript applications are rendered within the document's <body> , they cannot render markup to the document's <head> because it is outside of their scope. Inertia has a <Head> component that may be used to set the page <title> , <meta> tags, and other <head> components.

To add <head> element to your Page, we must import <head> from Inertia same as we did with <Link> component:

import { Head } from '@inertiajs/inertia-vue3' <Head> <title>Kinsta Blog</title> <meta name="description" content="Kinsta blog for developers"> </Head>

يمكننا أيضًا إضافة عنوان عالمي لجميع الصفحات ، وهذا سيضيف اسم التطبيق الخاص بك بجوار العنوان في كل صفحة. لقد فعلنا ذلك بالفعل في ملف app.js :

 createInertiaApp({ title: (title) => `${title} - ${appName}`, // });

مما يعني أننا إذا أضفنا <head title="Homepage"> في الصفحة الرئيسية لتطبيقنا بعنوان ، فسيتم عرض هذا على النحو التالي: <title>Home - My App</title> .

مراقبة تطبيقك

تعد السرعة أحد أهم العوامل في تحسين أداء تحسين محركات البحث على موقع الويب الخاص بك. إذا كنت تستخدم WordPress لموقع الويب الخاص بك ، لهذا السبب ، ستساعدك Kinsta APM في مراقبة تطبيقك ومراقبته عن كثب أثناء العمل. يساعدك على تحديد مشكلات أداء WordPress وهو متاح مجانًا على جميع المواقع المستضافة على Kinsta.

ملخص

يعد Inertia.js أحد أهم التقنيات المتاحة ؛ امزجها مع Laravel ولديك تطبيق صفحة واحدة حديث مبني باستخدام PHP و JavaScript. كان تايلور أوتويل ، مبتكر Laravel ، مهتمًا جدًا بالقصور الذاتي لدرجة أن Laravel أطلق أطقم البداية الأكثر شيوعًا ، Laravel Breeze و Jetstream ، بدعم Inertia و SSR.
تعرف على كيفية البدء في استخدام Inertia.js وكيفية استخدامه مع Laravel و Vue.js و Tailwind CSS لإنشاء مدونة تطبيق ويب حديثة في هذا الدليل Click to Tweet
إذا كنت من محبي Laravel أو مطورًا محترفًا ، فإن Inertia.js سوف يلفت انتباهك بلا شك. في هذا البرنامج التعليمي ، قمنا بإنشاء مدونة أساسية ومباشرة للغاية في بضع دقائق فقط. لا يزال هناك الكثير لنتعلمه عن القصور الذاتي ، وقد يكون هذا المقال الأول فقط من بين العديد من المقالات والبرامج التعليمية.

ماذا عن Laravel تود منا أن نستكشفه؟ واسمحوا لنا أن نعرف في قسم التعليقات أدناه.