بناء SSG الذي طالما أردته: ساندويتش 11 عامًا ، Vite و JAM

نشرت: 2022-03-10
ملخص سريع ↬ في يناير 2020 ، شرع بن هولمز في القيام بما يفعله كل مطور ويب كل عام: إعادة بناء موقعه الشخصي. في هذه المقالة ، يشاركنا قصته حول كيف شرع في بناء خط أنابيب البناء الخاص به من نقطة الصفر المطلق وخلق Slinkity.

لا أعرف عنك ، لكنني غمرتني جميع أدوات تطوير الويب المتوفرة لدينا هذه الأيام. سواء كنت تحب Markdown ، HTML عادي ، React ، Vue ، Svelte ، قوالب Pug ، مقاود ، Vibranium - يمكنك على الأرجح مزجها مع بعض بيانات CMS والحصول على كوكتيل موقع ثابت لطيف.

لن أخبرك بأدوات تطوير واجهة المستخدم التي يجب الوصول إليها لأنها كلها رائعة - اعتمادًا على احتياجات مشروعك. يدور هذا المنشور حول العثور على مولد الموقع الثابت المثالي لأي مناسبة ؛ شيء يتيح لنا استخدام قوالب JS-less مثل تخفيض السعر للبدء ، وإحضار "جزر" من التفاعل المستند إلى المكونات حسب الحاجة.

أنا أقوم بتقطير ما تعلمته لمدة عام في منشور واحد هنا. لن نتحدث فقط عن الكود (المعروف أيضًا باسم duct-taping 11ty و Vite معًا) ، لكننا سنستكشف أيضًا سبب كون هذا النهج عالميًا جدًا لمشاكل Jamstackian. سنتطرق إلى:

  • نهجان لإنشاء موقع ثابت ، ولماذا يجب علينا سد الفجوة ؛
  • حيث لا تزال اللغات القوالب مثل Pug و Nunjucks مفيدة ؛
  • عندما يجب أن تدخل أطر عمل المكونات مثل React أو Svelte حيز التنفيذ ؛
  • كيف يساعدنا عالم Vite الجديد الذي تمت إعادة تحميله سريعًا في جلب تفاعل JS إلى HTML مع ما يقرب من صفر من التكوينات ؛
  • كيف يكمل هذا سلسلة بيانات 11ty ، حيث يجلب بيانات CMS إلى أي إطار عمل مكون أو قالب HTML قد ترغب فيه.

لذلك دون مزيد من اللغط ، ها هي قصتي عن نصوص بناء رهيبة ، واختراقات مجمعة ، وشريط لاصق معكرونة (في النهاية) أعطاني SSG الذي طالما أردته: ساندويتش 11 عامًا ، Vite و Jam يسمى Slinkity!

انقسام كبير في إنشاء موقع ثابت

قبل الغوص ، أريد مناقشة ما سأسميه "معسكرين" في إنشاء موقع ثابت.

في المعسكر الأول ، لدينا مولد موقع ثابت "بسيط". لا تجلب هذه الأدوات حزم JavaScript وتطبيقات الصفحة الواحدة وأي كلمات طنانة أخرى نتوقعها. إنهم يقومون فقط بتثبيت أساسيات Jamstack: اسحب البيانات من أي كائن JSON من CMS تفضله ، وقم بتحريك هذه البيانات إلى قوالب HTML + CSS. تهيمن أدوات مثل Jekyll و Hugo و 11ty على هذا المعسكر ، مما يتيح لك تحويل دليل تخفيض السعر والملفات السائلة إلى موقع ويب كامل الوظائف. الفوائد الرئيسية:

  • منحنى التعلم الضحل
    إذا كنت تعرف لغة HTML ، فأنت على ما يرام!
  • أوقات بناء سريعة
    نحن لا نعالج أي شيء معقد ، لذا فإن كل مسار يبنى في لمح البصر.
  • وقت فوري للتفاعل
    ليس هناك (أو القليل جدًا) جافا سكريبت لتحليل العميل.

الآن في المعسكر الثاني ، لدينا مولد موقع ثابت "ديناميكي". تقدم هذه الأطر المكونة مثل React و Vue و Svelte لتحقيق التفاعل إلى Jamstack. هذه تفي بالوعد الأساسي نفسه المتمثل في دمج بيانات CMS مع مسارات موقعك في وقت الإنشاء. الفوائد الرئيسية:

  • مصمم للتفاعل
    هل تحتاج إلى صورة متحركة دائرية؟ شكل متعدد الخطوات؟ ما عليك سوى إضافة كتلة صلبة مكونة من HTML و CSS و JS.
  • إدارة الدولة
    يسمح شيء مثل React Context لمتاجر Svelte بمشاركة البيانات بشكل سلس بين المسارات. على سبيل المثال ، عربة التسوق على موقع التجارة الإلكترونية الخاص بك.

هناك إيجابيات متميزة لأي من النهجين. ولكن ماذا لو اخترت SSG من المعسكر الأول مثل Jekyll ، فقط لإدراك ستة أشهر في مشروعك أنك بحاجة إلى بعض التفاعل مع المكون؟ أو تختار شيئًا مثل NextJS لتلك المكونات القوية ، فقط لتكافح مع منحنى التعلم لـ React ، أو KB من JavaScript غير ضرورية في منشور مدونة ثابت؟

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

حسنًا ، دعنا نسير في رحلة التعلم الخاصة بي قليلاً.

ملحوظة: إذا كنت قد بيعت بالفعل على قالب ثابت مع 11ty لبناء مواقعك الثابتة ، فلا تتردد في الانتقال إلى إرشادات التعليمات البرمجية المثيرة.

المزيد بعد القفز! أكمل القراءة أدناه ↓

الانتقال من المكونات إلى القوالب وواجهات برمجة تطبيقات الويب

في كانون الثاني (يناير) 2020 ، شرعت في القيام بما يفعله كل مطور ويب كل عام: إعادة بناء موقعي الشخصي. لكن هذه المرة ستكون مختلفة. لقد تحدت نفسي لبناء موقع ويدي مقيدتان خلف ظهري ، ولا يُسمح ببناء أطر عمل أو خطوط أنابيب!

لم تكن هذه مهمة بسيطة كمتخلص لـ React. ولكن مع رفع رأسي عالياً ، شرعت في بناء خط أنابيب البناء الخاص بي من نقطة الصفر المطلقة. هناك الكثير من الشفرات المكتوبة بشكل سيئ يمكنني مشاركتها من الإصدار 1 من موقعي الشخصي ... لكنني سأسمح لك بالنقر فوق "قراءة" إذا كنت شجاعًا جدًا. بدلاً من ذلك ، أريد التركيز على الوجبات السريعة ذات المستوى الأعلى التي تعلمتها تجويع نفسي من ملذات JS المذنب.

تذهب القوالب إلى أبعد مما قد تعتقد

جئت في هذا المشروع لاستعادة جافا سكريبت غير المرغوب فيه. هناك بعض الاحتياجات المتعلقة بالموقع الثابت التي أحببتها باستخدام الأطر القائمة على المكونات لملء:

  1. نريد تقسيم موقعي إلى مكونات قابلة لإعادة الاستخدام لواجهة مستخدم يمكنها قبول كائنات JS كمعلمات (تُعرف أيضًا باسم "الدعائم").
  2. نحتاج إلى إحضار بعض المعلومات في وقت الإنشاء للدخول إلى موقع الإنتاج.
  3. نحتاج إلى إنشاء مجموعة من مسارات URL إما من دليل الملفات أو كائن JSON الدهني للمحتوى.

القائمة مأخوذة من هذا المنشور على مدونتي الشخصية.

لكن ربما لاحظت ... لا يحتاج أي من هؤلاء حقًا إلى JavaScript. تم تصميم أطر عمل المكونات مثل React بشكل أساسي للتعامل مع مخاوف إدارة الحالة ، مثل تطبيق Facebook على الويب الذي يلهم React في المقام الأول. إذا كنت تقوم بتقسيم موقعك إلى مكونات صغيرة الحجم أو عناصر نظام تصميم ، فإن القوالب مثل Pug تعمل بشكل جيد أيضًا!

خذ شريط التنقل هذا على سبيل المثال. في Pug ، يمكننا تحديد "mixin" الذي يتلقى البيانات كدعامات:

 // nav-mixins.pug mixin NavBar(links) // pug's version of a for loop each link in links a(href=link.href) link.text

بعد ذلك ، يمكننا تطبيق هذا المزيج في أي مكان على موقعنا.

 // index.pug // kinda like an ESM "import" include nav-mixins.pug html body +NavBar(navLinksPassedByJS) main h1 Welcome to my pug playground

إذا "عرضنا" هذا الملف مع بعض البيانات ، فسنحصل على index.html جميل لخدمة ما يصل إلى مستخدمينا.

 const html = pug.render('/index.pug', { navLinksPassedByJS: [ { href: '/', text: 'Home' }, { href: '/adopt', text: 'Adopt a Pug' } ] }) // use the NodeJS filesystem helpers to write a file to our build await writeFile('build/index.html', html)

بالتأكيد ، هذا لا يعطي التفاصيل الدقيقة مثل CSS المحدد لمزيجاتك ، أو JavaScript ذو الحالة التي تريدها. لكن لها بعض الفوائد القوية جدًا على شيء مثل React:

  1. لسنا بحاجة إلى حزم خيالية لا نفهمها.
    لقد كتبنا للتو مكالمة pug.render هذه يدويًا ، ولدينا بالفعل المسار الأول لموقع جاهز للنشر.
  2. نحن لا نشحن أي JavaScript إلى المستخدم النهائي.
    غالبًا ما يعني استخدام React إرسال وقت تشغيل كبير لتشغيل متصفحات الأشخاص. من خلال استدعاء دالة مثل pug.render في وقت الإنشاء ، فإننا نحتفظ بكل JS إلى جانبنا أثناء إرسال ملف .html نظيف في النهاية.

لهذا السبب أعتقد أن القوالب هي "قاعدة" رائعة للمواقع الثابتة. ومع ذلك ، فإن القدرة على الوصول إلى أطر عمل المكونات التي نستفيد منها حقًا سيكون أمرًا رائعًا. المزيد عن ذلك لاحقًا.

القراءة الموصى بها : كيفية إنشاء قوالب زاوية أفضل باستخدام Pug بواسطة Zara Cooper

لا تحتاج إلى إطار عمل لبناء تطبيقات صفحة واحدة

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

تتلاشى مع انتقال المسح العمودي
تتلاشى مع انتقال المسح العمودي. (معاينة كبيرة)

حسنًا ، لا يمكننا القيام بذلك إذا كانت كل صفحة عبارة عن ملف .html خاص بها. يتم تحديث المتصفح بالكامل عندما ننتقل من ملف HTML إلى آخر ، لذلك لا يمكننا الحصول على تأثير التلاشي المتقاطع الجميل (نظرًا لأننا سنعرض كلتا الصفحتين فوق بعضهما البعض لفترة وجيزة).

نحن بحاجة إلى طريقة "لجلب" HTML و CSS في أي مكان ننتقل إليه ، وتحريكها في العرض باستخدام JavaScript. هذا يبدو وكأنه وظيفة لتطبيقات صفحة واحدة! لقد استخدمت متصفحًا بسيطًا ومتوسط ​​API لهذا الغرض:

  1. اعترض كل نقرات الارتباط الخاصة بك باستخدام مستمع الحدث.
  2. إحضار واجهة برمجة التطبيقات (API ) : قم بإحضار جميع الموارد لأي صفحة تريد زيارتها ، وانتقل إلى الجزء الذي أريد تحريكه في العرض: المحتوى خارج شريط التنقل (الذي أريد أن يظل ثابتًا أثناء الرسوم المتحركة).
  3. واجهة برمجة تطبيقات الرسوم المتحركة على الويب : حرك المحتوى الجديد لعرضه كإطار رئيسي.
  4. history API : قم بتغيير المسار المعروض في شريط عنوان URL بالمتصفح باستخدام window.history.pushState({}, 'new-route') . خلاف ذلك ، يبدو أنك لم تغادر الصفحة السابقة!

من أجل الوضوح ، إليك توضيح مرئي لمفهوم تطبيق الصفحة الواحدة هذا باستخدام بحث بسيط واستبدال ( مقالة المصدر ):

عملية التوجيه خطوة بخطوة من جانب العميل: 1. يتم إرجاع الهامبرغر النادر المتوسط ​​، 2. نطلب برغرًا جيدًا باستخدام واجهة برمجة التطبيقات (API) ، 3. نقوم بتدليك الاستجابة ، 4. نخرج عنصر "باتي" ونطبقه إلى صفحتنا الحالية.
عملية التوجيه خطوة بخطوة من جانب العميل: 1. يتم إرجاع الهامبرغر النادر المتوسط ​​، 2. نطلب برغرًا جيدًا باستخدام واجهة برمجة التطبيقات (API) ، 3. نقوم بتدليك الاستجابة ، 4. نخرج عنصر "باتي" ونطبقه إلى صفحتنا الحالية. (معاينة كبيرة)

ملاحظة : يمكنك أيضًا زيارة الكود المصدري من موقعي الشخصي.

بالتأكيد ، يمكن لبعض عمليات الاقتران بين React et al ومكتبة الرسوم المتحركة التي تختارها القيام بذلك. ولكن بالنسبة لحالة استخدام بسيطة مثل انتقال التلاشي ... تعد واجهات برمجة تطبيقات الويب قوية جدًا من تلقاء نفسها. وإذا كنت تريد انتقالات أكثر قوة للصفحة على قوالب ثابتة مثل Pug أو HTML عادي ، فإن مكتبات مثل Swup ستخدمك جيدًا.

ما أحضر 11ty إلى الطاولة

كنت أشعر بالرضا تجاه القليل من SSG في هذه المرحلة. من المؤكد أنه لا يمكنه جلب أي بيانات CMS في وقت الإنشاء ، ولم يدعم التنسيقات المختلفة حسب الصفحة أو حسب الدليل ، ولم يحسن صوري ، ولم يكن به تصميمات تدريجية.

حسنًا ، قد أحتاج إلى بعض المساعدة.

نظرًا لجميع ما تعلمته من الإصدار 1 ، أعتقد أنني اكتسبت حقي في التخلي عن قاعدة "عدم وجود خطوط أنابيب إنشاء تابعة لطرف ثالث" والوصول إلى الأدوات الحالية. تبين ، 11ty لديها كنز دفين من الميزات التي أحتاجها!

  • جلب البيانات في وقت البناء باستخدام ملفات .11ydata.js ؛
  • البيانات العالمية متاحة لجميع القوالب الخاصة بي من مجلد _data ؛
  • إعادة التحميل أثناء التطوير باستخدام Browsersync ؛
  • دعم تحويلات HTML الرائعة ؛
  • ... والعديد من الأشياء الجيدة الأخرى.

إذا كنت قد جربت مجموعات SSG العارية مثل Jekyll أو Hugo ، فيجب أن يكون لديك فكرة جيدة عن كيفية عمل 11ty. الفرق الوحيد؟ 11ty يستخدم JavaScript بالكامل.

يدعم 11ty بشكل أساسي كل مكتبة قوالب موجودة ، لذلك كان من دواعي سرورنا عرض جميع صفحات Pug الخاصة بي على مسارات .html . لقد ساعد خيار تسلسل التخطيط في إعداد تطبيق الصفحة الواحدة المزيف أيضًا. كنت بحاجة فقط إلى برنامج script واحد لجميع مساراتي ، وتخطيط "عام" لاستيراد هذا البرنامج النصي:

 // _includes/base-layout.html <html> <body> <!--load every page's content between some body tags--> {{ content }} <!--and apply the script tag just below this--> <script src="main.js"></script> </body> </html> // random-blog-post.pug --- layout: base-layout --- article h2 Welcome to my blog p Have you heard the story of Darth Plagueis the Wise?

طالما أن main.js تقوم بكل ما تعترضه الروابط التي اكتشفناها ، فلدينا انتقالات للصفحة!

أوه ، وشلال البيانات

لذلك ساعدت 11ty في تنظيف جميع أكواد السباغيتي من الإصدار 1. لكنها جلبت قطعة مهمة أخرى: واجهة برمجة تطبيقات نظيفة لتحميل البيانات في تخطيطاتي. هذا هو الخبز والزبدة في نهج Jamstack. بدلاً من جلب البيانات في المتصفح باستخدام معالجة JavaScript + DOM ، يمكنك:

  1. إحضار البيانات في وقت البناء باستخدام Node.
    قد يكون هذا استدعاء لواجهة برمجة تطبيقات خارجية ، أو استيراد JSON أو YAML محلي ، أو حتى محتوى مسارات أخرى على موقعك (تخيل تحديث جدول المحتويات كلما تمت إضافة مسارات جديدة).
  2. أدخل تلك البيانات في مساراتك. تذكر أن وظيفة .render التي كتبناها سابقًا:
 const html = pug.render('/index.pug', { navLinksPassedByJS: [ { href: '/', text: 'Home' }, { href: '/adopt', text: 'Adopt a Pug' } ] })

... ولكن بدلاً من استدعاء pug.render في كل مرة ، نسمح لـ 11ty بفعل ذلك من وراء الكواليس.

بالتأكيد ، لم يكن لدي الكثير من البيانات لموقعي الشخصي. لكن كان من الرائع إنشاء ملف .yaml لجميع مشاريعي الشخصية:

 # _data/works.yaml - title: Bits of Good Homepage hash: bog-homepage links: - href: https://bitsofgood.org text: Explore the live site - href: https://github.com/GTBitsOfGood/bog-web text: Scour the Svelt-ified codebase timeframe: May 2019 - present tags: - JAMstack - SvelteJS - title: Dolphin Audio Visualizer ...

والوصول إلى تلك البيانات عبر أي قالب:

 // home.pug .project-carousel each work in works h3 #{title} p #{timeframe} each tag in tags ...

قادمة من عالم "عرض العملاء" مع تطبيق create-response-app ، كان هذا اكتشافًا كبيرًا جدًا. لا مزيد من إرسال مفاتيح API أو نقاط JSON الكبيرة إلى المتصفح.

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

كنت سعيدًا في هذه المرحلة لكن شيئًا ما كان مفقودًا

لقد ذهبت بعيدًا بشكل مدهش من خلال التخلي عن المكونات المستندة إلى JS واحتضان القوالب (مع انتقالات الصفحة المتحركة للتمهيد). لكنني أعلم أن هذا لن يلبي احتياجاتي إلى الأبد. هل تتذكر الانقسام الكبير الذي بدأنا به؟ حسنًا ، من الواضح أنه لا يزال هناك هذا الوادي بين إعداد البناء الخاص بي (بقوة في المعسكر رقم 1) وملاذ تفاعل JS-ified (التالي ، SvelteKit ، والمزيد من المعسكر رقم 2). قل أريد أن أضيف:

  • نموذج منبثق مع مفتاح تبديل مفتوح / مغلق ،
  • نظام تصميم قائم على المكونات مثل Material UI ، مكتمل بتصميم النطاق ،
  • شكل معقد متعدد الخطوات ، ربما يكون مدفوعًا بآلة الدولة.

إذا كنت من محبي JS الخالص ، فمن المحتمل أن يكون لديك إجابات أقل من إطار العمل لجميع حالات الاستخدام هذه. ولكن هناك سبب لم يعد JQuery هو المعيار بعد الآن! هناك شيء جذاب حول إنشاء مكونات منفصلة وسهلة القراءة من HTML ، وأنماط محددة النطاق ، وأجزاء من متغيرات "حالة" JavaScript. تقدم React و Vue و Svelte وما إلى ذلك الكثير من التفاصيل الدقيقة لتصحيح الأخطاء واختبار أن التلاعب المباشر في DOM لا يمكن أن يتطابق تمامًا.

إذن هذا هو سؤالي المليون دولار:

هل يمكننا استخدام قوالب HTML مباشرة للبدء ، وإضافة مكونات React / Vue / Svelte تدريجيًا حيث نريدها؟

الجواب نعم . دعونا نحاول ذلك.

11ty + Vite: مباراة صنعت في الجنة ️

هذا هو الحلم الذي أتخيله هنا. أينما أريد إدراج شيء تفاعلي ، أريد ترك القليل من العلم في القالب الخاص بي "لوضع مكون X React هنا." قد يكون هذا هو بناء جملة الرمز القصير الذي يدعمه 11ty:

 # Super interesting programming tutorial Writing paragraphs has been fun, but that's no way to learn. Time for an interactive code example! {% react './components/FancyLiveDemo.jsx' %}

لكن تذكر أن القطعة المكونة من 11 قطعة تتجنب (عن قصد): طريقة لتجميع كل ما تبذلونه من JavaScript. قادمًا من نقابة OG للتجميع ، ربما يقفز عقلك لبناء عمليات Webpack أو Rollup أو Babel هنا. إنشاء ملف نقطة دخول أولي كبير ، وإخراج بعض التعليمات البرمجية المحسّنة الجميلة ، أليس كذلك؟

حسنًا ، نعم ، لكن هذا يمكن أن يكون متورطًا بشكل كبير. إذا كنا نستخدم مكونات React ، على سبيل المثال ، فربما نحتاج إلى بعض اللوادر لـ JSX ، عملية Babel الرائعة لتحويل كل شيء ، مترجم لاستيراد وحدات SASS و CSS ، شيء للمساعدة في إعادة التحميل المباشر ، وما إلى ذلك.

إذا كان هناك فقط أداة يمكنها رؤية ملفات .jsx بنا ومعرفة بالضبط ما يجب فعله بها.

أدخل: Vite

كان Vite حديث المدينة مؤخرًا. من المفترض أن تكون أداة الكل في واحد لبناء أي شيء في JavaScript. إليك مثال يمكنك تجربته في المنزل. لنقم بإنشاء دليل فارغ في مكان ما على جهازك ونثبت بعض التبعيات:

 npm init -y # Make a new package.json with defaults set npm i vite react react-dom # Grab Vite + some dependencies to use React

الآن ، يمكننا إنشاء ملف index.html ليكون بمثابة "نقطة دخول" لتطبيقنا. سنبقي الأمر بسيطًا جدًا:

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>Hello Vite! (wait is it pronounced "veet" or "vight"...)</h1> <div></div> </body> </html>

الشيء الوحيد المثير للاهتمام هو أن div id="root" في المنتصف. سيكون هذا هو جذر مكون React الخاص بنا في لحظة!

إذا كنت ترغب في ذلك ، يمكنك تشغيل خادم Vite لرؤية ملف HTML العادي في متصفحك. فقط قم بتشغيل vite (أو npx vite إذا لم يتم تكوين الأمر في جهازك الطرفي) ، وسترى هذا الناتج المفيد:

 vite vX.XX dev server running at: > Local: http://localhost:3000/ > Network: use `--host` to expose ready in Xms.

يشبه اسم كل ملف .html على خادمنا ، مثله مثل Browsersync أو خوادم مطوّرة أخرى شائعة. لذلك إذا أعدنا تسمية index.html إلى about.html ، فسنزور http://localhost:3000/about/ (نعم ، ستحتاج إلى شرطة مائلة لاحقة!)

الآن دعونا نفعل شيئًا مثيرًا للاهتمام. إلى جانب ملف index.html هذا ، أضف مكون React أساسي من نوع ما. سنستخدم حالة استخدام useState هنا لإثبات التفاعل:

 // TimesWeMispronouncedVite.jsx import React from 'react' export default function TimesWeMispronouncedVite() { const [count, setCount] = React.useState(0) return ( <div> <p>I've said Vite wrong {count} times today</p> <button onClick={() => setCount(count + 1)}>Add one</button> </div> ) }

الآن ، دعنا نحمل هذا المكون على صفحتنا. هذا كل ما علينا إضافته إلى index.html الخاص بنا:

 <!DOCTYPE html> ... <body> <h1>Hello Vite! (wait is it pronounced "veet" or "vight"...)</h1> <div></div> <!--Don't forget type="module"! This lets us use ES import syntax in the browser--> <script type="module"> // path to our component. Note we still use .jsx here! import Component from './TimesWeMispronouncedVite.jsx'; import React from 'react'; import ReactDOM from 'react-dom'; const componentRoot = document.getElementById('root'); ReactDOM.render(React.createElement(Component), componentRoot); </script> </body> </html>

نعم ، هذا كل شيء. لا داعي لتحويل ملف .jsx بنا إلى ملف .js جاهز للمتصفح بأنفسنا! أينما يرى Vite استيراد .jsx ، فسيقوم تلقائيًا بتحويل هذا الملف إلى شيء يمكن أن تفهمه المتصفحات. لا يوجد مجلد dist أو build حتى عند العمل في التطوير ؛ يعالج Vite كل شيء أثناء التنقل - مع استكمال إعادة تحميل الوحدة النمطية الساخنة في كل مرة نقوم فيها بحفظ تغييراتنا.

حسنًا ، لدينا أداة بناء قادرة بشكل لا يصدق. كيف يمكننا إحضار هذا إلى قوالبنا الـ 11؟

تشغيل Vite بجانب 11ty

قبل أن ننتقل إلى الأشياء الجيدة ، دعونا نناقش الجري 11ty و Vite جنبًا إلى جنب. انطلق وقم بتثبيت 11ty كعنصر تبعية في دليل المشروع نفسه من القسم الأخير:

 npm i -D @11ty/eleventy # yes, it really is 11ty twice

الآن دعونا نجري فحصًا بسيطًا قبل الرحلة لمعرفة ما إذا كانت 11 عامًا تعمل أم لا. لتجنب أي لبس ، أقترح عليك:

  1. حذف هذا الملف index.html من السابق ؛
  2. انقل هذا TimesWeMispronouncedVite.jsx داخل دليل جديد. قل ، components/ ؛
  3. قم بإنشاء مجلد src لكي تعيش فيه ؛
  4. أضف قالبًا إلى دليل src هذا لكي تتم معالجة 11ty.

على سبيل المثال ، ملف blog-post.md بالمحتويات التالية:

 # Hello world! It's markdown here

يجب أن يبدو هيكل مشروعك كما يلي:

 src/ blog-post.md components/ TimesWeMispronouncedVite.jsx

الآن ، قم بتشغيل 11ty من جهازك الطرفي كما يلي:

 npx eleventy --input=src

إذا سارت الأمور على ما يرام ، يجب أن ترى إخراج بناء مثل هذا:

 _site/ blog-post/ index.html

حيث _site هو دليل الإخراج الافتراضي الخاص بنا ، و blog-post/index.html هو ملف تخفيض السعر الذي تم تحويله بشكل جميل للتصفح.

عادة ، سنقوم بتشغيل npx eleventy --serve بتدوير خادم مطور وزيارة صفحة /blog-post . لكننا نستخدم Vite لخادم التطوير لدينا الآن! الهدف هنا هو:

  1. احصل على أحد عشر شخصًا من إنشاء تخفيض السعر ، الصلصال ، _site ، والمزيد إلى دليل الموقع.
  2. Point Vite في نفس الدليل _site حتى يتمكن من معالجة مكونات React ، وواردات النمط الفاخر ، والأشياء الأخرى التي لم يلتقطها 11ty.

إذن ، عملية بناء من خطوتين ، مع تسليم 11 قطعة من Vite. إليك أمر CLI الذي ستحتاجه لبدء تشغيل 11ty و Vite في وضع "المراقبة" في وقت واحد:

 (npx eleventy --input=src --watch) & npx vite _site

يمكنك أيضًا تشغيل هذه الأوامر في محطتين منفصلتين لتسهيل تصحيح الأخطاء.

مع أي حظ ، يجب أن تكون قادرًا على زيارة http://localhost:3000/blog-post/ (مرة أخرى ، لا تنسَ الشرطة المائلة اللاحقة!) لرؤية ملف Markdown الذي تمت معالجته.

الترطيب الجزئي بالرموز القصيرة

دعونا نجري ملخصًا موجزًا ​​للرموز المختصرة. حان الوقت لإعادة النظر في بناء الجملة هذا من وقت سابق:

 {% react '/components/TimesWeMispronouncedVite.jsx' %}

بالنسبة لأولئك الذين ليسوا على دراية بالرموز القصيرة: فهي تشبه استدعاء الوظيفة تقريبًا ، حيث تقوم الوظيفة بإرجاع سلسلة من HTML لتنزلق إلى صفحتك. "تشريح" رمزنا القصير هو:

  • {% … %}
    غلاف يدل على بداية ونهاية الكود القصير.
  • react
    اسم وظيفة الرمز القصير لدينا سنقوم بتكوينها في لحظة.
  • '/components/TimesWeMispronouncedVite.jsx'
    الوسيطة الأولى (والوحيدة) لوظيفة الرمز القصير الخاصة بنا. يمكنك الحصول على العديد من الحجج كما تريد.

دعونا نرسل أول رمز قصير لدينا! أضف ملف .eleventy.js إلى قاعدة مشروعك ، وأضف إدخال التكوين هذا لرمز react القصير الخاص بنا:

 // .eleventy.js, at the base of the project module.exports = function(eleventyConfig) { eleventyConfig.addShortcode('react', function(componentPath) { // return any valid HTML to insert return `<div>This is where we'll import ${componentPath}</div>` }) return { dir: { // so we don't have to write `--input=src` in our terminal every time! input: 'src', } } }

الآن ، دعنا نضيف إلى blog-post.md القصير الجديد. الصق هذا المحتوى في ملف Markdown الخاص بنا:

 # Super interesting programming tutorial Writing paragraphs has been fun, but that's no way to learn. Time for an interactive code example! {% react '/components/TimesWeMispronouncedVite.jsx' %}

وإذا قمت بتشغيل أحد npx eleventy ، فيجب أن ترى هذا الإخراج في دليل /blog-post/index.html _site

 <h1>Super interesting programming tutorial</h1> <p>Writing paragraphs has been fun, but that's no way to learn. Time for an interactive code example!</p> <div>This is where we'll import /components/TimesWeMispronouncedVite.jsx</div>

كتابة الرمز المختصر الخاص بالمكون

الآن دعنا نفعل شيئًا مفيدًا بهذا الرمز القصير. هل تتذكر علامة script التي كتبناها أثناء تجربة Vite؟ حسنًا ، يمكننا فعل الشيء نفسه في رمزنا القصير! هذه المرة سنستخدم الوسيطة componentPath لإنشاء الاستيراد ، لكن مع الاحتفاظ بالباقي كما هو:

 // .eleventy.js module.exports = function(eleventyConfig) { let idCounter = 0; // copy all our /components to the output directory // so Vite can find them. Very important step! eleventyConfig.addPassthroughCopy('components') eleventyConfig.addShortcode('react', function (componentPath) { // we'll use idCounter to generate unique IDs for each "root" div // this lets us use multiple components / shortcodes on the same page idCounter += 1; const componentRootId = `component-root-${idCounter}` return ` <div></div> <script type="module"> // use JSON.stringify to // 1) wrap our componentPath in quotes // 2) strip any invalid characters. Probably a non-issue, but good to be cautious! import Component from ${JSON.stringify(componentPath)}; import React from 'react'; import ReactDOM from 'react-dom'; const componentRoot = document.getElementById('${componentRootId}'); ReactDOM.render(React.createElement(Component), componentRoot); </script> ` }) eleventyConfig.on('beforeBuild', function () { // reset the counter for each new build // otherwise, it'll count up higher and higher on every live reload idCounter = 0; }) return { dir: { input: 'src', } } }

الآن ، يجب أن ينتج عن الاتصال بالرمز المختصر (على سبيل المثال {% react '/components/TimesWeMispronouncedVite.jsx' %} ) شيئًا مثل هذا:

 <div></div> <script type="module"> import Component from './components/FancyLiveDemo.jsx'; import React from 'react'; import ReactDOM from 'react-dom'; const componentRoot = document.getElementById('component-root-1'); ReactDOM.render(React.createElement(Component), componentRoot); </script>

عند زيارة خادم التطوير الخاص بنا باستخدام (npx eleventy --watch) & vite _site ، يجب أن نجد عنصر عداد قابل للنقر بشكل جميل.

تنبيه Buzzword - الترطيب الجزئي وهندسة الجزر

لقد أظهرنا للتو "هندسة الجزر" في أبسط أشكالها. هذه هي الفكرة القائلة بأن أشجارنا المكونة التفاعلية لا يجب أن تستهلك موقع الويب بالكامل. بدلاً من ذلك ، يمكننا تدوير أشجار صغيرة أو "جزر" في جميع أنحاء تطبيقنا اعتمادًا على المكان الذي نحتاج فيه بالفعل إلى هذا التفاعل. هل لديك صفحة هبوط أساسية من الروابط دون أي دولة لإدارتها؟ رائعة! لا حاجة للمكونات التفاعلية. ولكن هل لديك نموذج متعدد الخطوات يمكن أن يستفيد من مكتبة X React؟ لا مشكلة. استخدم تقنيات مثل هذا react القصير لتدوير جزيرة Form.jsx .

يسير هذا جنبًا إلى جنب مع فكرة "الترطيب الجزئي". من المحتمل أنك سمعت مصطلح "ترطيب" إذا كنت تعمل مع مكونات y SSGs مثل NextJS أو Gatsby. باختصار ، إنها طريقة من أجل:

  1. قم بجعل المكونات الخاصة بك إلى HTML ثابت أولاً.
    يمنح هذا المستخدم شيئًا لعرضه عند زيارته لموقع الويب الخاص بك في البداية.
  2. "هيدرات" HTML هذا مع التفاعل.
    هذا هو المكان الذي نربط فيه خطافات الحالة والعارضين لدينا ، حسنًا ، نجعل نقرات الأزرار تؤدي في الواقع إلى شيء ما.

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

حسنًا ، حتى لا تفعل. قد يكون "ترطيب" موقع ويب بأكمله مكلفًا لأنك ستحتاج إلى حزمة JavaScript جاهزة لمعالجة كل عنصر DOM الأخير . لكن أسلوبنا في كتابة الرمز القصير المتقطع لا يغطي الصفحة بأكملها! بدلاً من ذلك ، نقوم بترطيب المحتوى الموجود "جزئيًا" ، مع إدخال المكونات عند الضرورة فقط.

لا تقلق ، هناك مكون إضافي لكل هذا: الانزلاق

دعنا نلخص ما اكتشفناه هنا:

  1. Vite عبارة عن مجمع قادر بشكل لا يصدق يمكنه معالجة معظم أنواع الملفات ( jsx و vue و svelte على سبيل المثال لا الحصر) بدون تهيئة إضافية.
  2. الرموز القصيرة هي طريقة سهلة لإدراج أجزاء من HTML في قوالبنا ، على غرار المكون.
  3. يمكننا استخدام الرموز القصيرة لتقديم حزم JS الديناميكية والتفاعلية أينما نريد باستخدام الترطيب الجزئي.

إذن ماذا عن عمليات الإنتاج المحسّنة؟ تحميل الأنماط المحددة بشكل صحيح؟ هيك ، باستخدام .jsx لإنشاء صفحات كاملة؟ حسنًا ، لقد جمعت كل هذا (وأكثر من ذلك بكثير!) في مشروع يسمى Slinkity. أنا متحمس لرؤية الترحيب المجتمعي الدافئ للمشروع ، وأحب أن تقوم ، عزيزي القارئ ، بتجربته بنفسك!

جرب دليل البدء السريع

عظيم جدا Astro's Pretty Great Too

القراء الذين يتطلعون إلى أحدث التقنيات ربما فكروا في Astro مرة واحدة على الأقل حتى الآن. ولا أستطيع أن ألومك! لقد تم تصميمه مع وضع هدف مشابه في الاعتبار: ابدأ باستخدام HTML عادي ، وأدخل مكونات ذات حالة أينما كنت في حاجة إليها. هيك ، سوف يسمحون لك حتى بالبدء في كتابة مكونات React داخل مكونات Vue أو Svelte داخل ملفات قالب HTML! إنه مثل إصدار MDX Xtreme.

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

لكن هل تدور كوكتيل 11ty + Vite بأداة مثل Slinkity؟ حسنًا ، إذا كان لديك بالفعل 11 موقعًا ، فيجب أن يثبت Vite في مكانه دون أي إعادة كتابة ، ويجب أن تغطي الرموز القصيرة العديد من حالات الاستخدام نفسها مثل ملفات .astro . سأعترف أنه بعيد عن الكمال الآن. لكن مهلا ، لقد كان مفيدًا حتى الآن ، وأعتقد أنه بديل قوي جدًا إذا كنت تريد تجنب إعادة الكتابة على مستوى الموقع!

تغليف

لقد خدمت تجربة Slinkity هذه احتياجاتي جيدًا حتى الآن (وعدد قليل منكم أيضًا!). لا تتردد في استخدام أي مكدس يعمل مع JAM الخاص بك. أنا متحمس فقط لمشاركة نتائج السنة التي قضيتها في فجور أداة البناء ، وأنا متحمس جدًا لمعرفة كيف يمكننا سد فجوة Jamstack الكبيرة.

قراءة متعمقة

هل تريد الغوص بشكل أعمق في الترطيب الجزئي ، أو ESM ، أو SSGs بشكل عام؟ تحقق من هذه:

  • هندسة الجزر
    بدأ منشور المدونة هذا من Jason Format بالفعل مناقشة حول "الجزر" و "الترطيب الجزئي" في تطوير الويب. إنها مليئة بالمخططات المفيدة والفلسفة الكامنة وراء الفكرة.
  • قم بتبسيط ثباتك باستخدام مولد موقع ثابت مخصص
    مقال آخر من SmashingMag يرشدك خلال صياغة منشئي مواقع الويب المستندة إلى Node من البداية. لقد كان مصدر إلهام كبير لي!
  • كيف أعادت ES Modules تعريف تطوير الويب
    منشور شخصي حول كيفية تغيير ES Modules للعبة تطوير الويب. يتعمق هذا قليلاً في "آنذاك والآن" من بناء جملة الاستيراد على الويب.
  • مقدمة لمكونات الويب
    تجول ممتاز حول ماهية مكونات الويب ، وكيفية عمل Shadow DOM ، والمكان الذي تثبت فيه فائدة مكونات الويب. استخدم هذا الدليل لتطبيق مكونات مخصصة على إطاري الخاص!