การสร้างไซต์แบบคงที่ด้วยส่วนประกอบโดยใช้ Nunjucks

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างรวดเร็ว ↬ แม้ว่าคุณจะไม่ได้ใช้ JavaScript ฝั่งไคลเอ็นต์เลยเพื่อสร้างไซต์ แต่ก็ไม่ได้หมายความว่าคุณต้องละทิ้งแนวคิดในการสร้างด้วยส่วนประกอบ เรียนรู้วิธีสร้างไซต์สแตติกด้วยความช่วยเหลือของตัวประมวลผลล่วงหน้า HTML

ทุกวันนี้มันค่อนข้างเป็นที่นิยม และฉันกล้าพูดเลยว่าเป็นความคิดที่ดี ในการสร้างไซต์ที่มีส่วนประกอบ แทนที่จะสร้างหน้าเว็บทั้งหมดทีละหน้า เราสร้างระบบของส่วนประกอบต่างๆ (เช่น แบบฟอร์มการค้นหา การ์ดบทความ เมนู ส่วนท้าย) จากนั้นจึงรวมเว็บไซต์เข้ากับส่วนประกอบเหล่านั้น

กรอบงาน JavaScript เช่น React และ Vue เน้นแนวคิดนี้อย่างมาก แต่แม้ว่าคุณจะไม่ได้ใช้ JavaScript ฝั่งไคลเอ็นต์เลยในการสร้างไซต์ แต่ก็ไม่ได้หมายความว่าคุณจะต้องเลิกล้มแนวคิดในการสร้างด้วยส่วนประกอบ! ด้วยการใช้ตัวประมวลผลล่วงหน้า HTML เราสามารถสร้างไซต์แบบคงที่และยังคงได้รับประโยชน์ทั้งหมดจากการทำให้ไซต์ของเราเป็นนามธรรมและเนื้อหาเป็นส่วนประกอบที่นำกลับมาใช้ใหม่ได้

ไซต์แบบคงที่นั้นเป็นที่นิยมในทุกวันนี้ และถูกต้องแล้ว เนื่องจากไซต์เหล่านี้มีความรวดเร็ว ปลอดภัย และราคาไม่แพงในการโฮสต์ แม้แต่ Smashing Magazine ก็ยังเป็นเว็บนิ่ง เชื่อหรือไม่!

มาลองดูไซต์ที่ฉันเพิ่งสร้างโดยใช้เทคนิคนี้กัน ฉันใช้ CodePen Projects เพื่อสร้างมัน ซึ่งมี Nunjucks เป็นตัวประมวลผลล่วงหน้า ซึ่งเหมาะกับงานนี้อย่างสมบูรณ์แบบ

ไซต์สี่หน้าที่มีส่วนหัว การนำทาง และส่วนท้ายที่สอดคล้องกัน

นี่คือไมโครไซต์ ไม่จำเป็นต้องใช้ CMS เต็มรูปแบบเพื่อจัดการหน้าหลายร้อยหน้า ไม่จำเป็นต้องใช้ JavaScript เพื่อจัดการกับการโต้ตอบ แต่จำเป็นต้องมีหน้าไม่กี่หน้าที่ใช้เค้าโครงเดียวกันทั้งหมด

ส่วนหัวและส่วนท้ายที่สอดคล้องกัน
ส่วนหัวและส่วนท้ายที่สอดคล้องกันในทุกหน้า
เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

HTML เพียงอย่างเดียวไม่มีวิธีแก้ปัญหาที่ดี สิ่งที่เราต้องการคือ การนำเข้า ภาษาอย่าง PHP ทำให้สิ่งนี้ง่ายขึ้นด้วย <?php include "header.php"; ?> <?php include "header.php"; ?> แต่โฮสต์ไฟล์คงที่ไม่ทำงาน PHP (โดยตั้งใจ) และ HTML เพียงอย่างเดียวก็ไม่ช่วยอะไร โชคดีที่เราสามารถประมวลผลล่วงหน้าร่วมกับ Nunjucks ได้

การนำเข้าส่วนประกอบลงในเพจ
การนำเข้าส่วนประกอบเป็นไปได้ในภาษาเช่น PHP

การสร้าง เล ย์เอาต์ รวมถึงส่วน HTML ที่แสดงส่วนหัว การนำทาง และส่วนท้ายนั้นเหมาะสมอย่างยิ่ง เทมเพลต Nunjucks มีแนวคิดเรื่องบล็อก ซึ่งช่วยให้เราใส่เนื้อหาลงในจุดนั้นได้เมื่อเราใช้เลย์เอาต์

 <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>The Power of Serverless</title> <link rel="stylesheet" href="/styles/style.processed.css"> </head> <body> {% include "./template-parts/_header.njk" %} {% include "./template-parts/_nav.njk" %} {% block content %} {% endblock %} {% include "./template-parts/_footer.njk" %} </body>

โปรดสังเกตว่าไฟล์ที่รวมอยู่นั้นมีชื่อว่า _file.njk นั่นไม่จำเป็นทั้งหมด อาจเป็น header.html หรือ icons.svg แต่ตั้งชื่อแบบนี้เพราะ 1) ไฟล์ที่ขึ้นต้นด้วยขีดล่างเป็นวิธีการมาตรฐานในการบอกว่าไฟล์เหล่านี้เป็นเพียงบางส่วน ใน CodePen Projects หมายความว่าพวกเขาจะไม่พยายามคอมไพล์เพียงลำพัง 2) โดยตั้งชื่อมันว่า .njk เราสามารถใช้ Nunjucks มากขึ้นในนั้นได้ถ้าเราต้องการ

บิตเหล่านี้ไม่มีอะไรพิเศษเลย สิ่งเหล่านี้เป็นเพียงส่วนเล็ก ๆ ของ HTML ที่มีจุดประสงค์เพื่อใช้ในแต่ละหน้าสี่หน้าของเรา

 <footer> <p>Just a no-surprises footer, people. Nothing to see here.<p> </footer>

ด้วยวิธีนี้ เราสามารถทำการเปลี่ยนแปลงหนึ่งรายการและให้การเปลี่ยนแปลงนั้นมีผลกับทั้งสี่หน้า

การใช้เค้าโครงสำหรับสี่หน้า

ตอนนี้แต่ละหน้าของเราทั้งสี่หน้าสามารถเป็นไฟล์ได้ เริ่มต้นด้วย index.njk ซึ่งใน CodePen Projects จะได้รับการประมวลผลและสร้างไฟล์ index.html โดยอัตโนมัติทุกครั้งที่คุณบันทึก

ไฟล์ index.njk
เริ่มต้นด้วยไฟล์ index.njk

นี่คือสิ่งที่เราสามารถใส่ใน index.njk เพื่อใช้เลย์เอาต์และวางเนื้อหาบางส่วนในบล็อกนั้น:

 {% extends "_layout.njk" %} {% block content %} <h1>Hello, World!</h1> {% endblock %}

ที่จะซื้อโฮมเพจที่ใช้งานได้อย่างสมบูรณ์ให้เรา! ดี! แต่ละหน้าสี่หน้าสามารถทำสิ่งเดียวกันได้ แต่ใส่เนื้อหาที่แตกต่างกันในบล็อก และเรามีไซต์สี่หน้าเล็กๆ ที่จัดการได้ง่าย

รวบรวม index.html
ไฟล์ index.njk ถูกคอมไพล์เป็น index.html

สำหรับบันทึก ฉันไม่แน่ใจว่าฉันจะเรียกส่วนเล็กๆ เหล่านี้ที่เราใช้ ส่วนประกอบ ซ้ำ เรากำลังดำเนินการอย่างมีประสิทธิภาพและแบ่งเลย์เอาต์ออกเป็นส่วนๆ ฉันคิดว่าส่วนประกอบเป็นเหมือนก้อนที่นำกลับมาใช้ใหม่ได้ซึ่งยอมรับข้อมูลและส่งออกข้อมูลในเวอร์ชันเฉพาะของตัวเองด้วยข้อมูลนั้น เราจะไปที่นั้น

กำลังใช้งานการนำทาง

ตอนนี้เราได้ทำซ้ำกลุ่ม HTML ที่เหมือนกันในสี่หน้าแล้ว เป็นไปได้ไหมที่จะใช้ CSS ที่ไม่ซ้ำกันกับรายการการนำทางแต่ละรายการเพื่อระบุหน้าปัจจุบัน เราสามารถทำได้ด้วย JavaScript และดูที่ window.location และอื่นๆ แต่เราสามารถทำได้โดยไม่ต้องใช้ JavaScript เคล็ดลับคือการวาง class บน <body> เฉพาะสำหรับแต่ละหน้าและใช้ใน CSS

ใน _layout.njk ของเรา เรามีชื่อคลาสออกมาเป็นตัวแปร:

 <body class="{{ body_class }}">

ก่อนที่เราจะเรียกเลย์เอาต์นั้นในหน้าแต่ละเพจ เราจะตั้งค่าตัวแปรนั้น:

 {% set body_class = "home" %} {% extends "_layout.njk" %}

สมมติว่าการนำทางของเรามีโครงสร้างเหมือน

 <nav class="site-nav"> <ul> <li class="nav-home"> <a href="/"> Home </a> ...

ตอนนี้ เราสามารถกำหนดเป้าหมายลิงก์นั้นและใช้สไตล์พิเศษได้ตามต้องการโดยทำดังนี้

 body.home .nav-home a, body.services .nav-services a { /* continue matching classes for all pages... */ /* unique active state styling */ } 
การกำหนดรูปแบบสถานะแอ็คทีฟบนการนำทาง
การจัดรูปแบบลิงก์การนำทางด้วยคลาสที่ใช้งานอยู่

โอ้และไอคอนเหล่านั้น? เหล่านี้เป็นเพียงไฟล์ . .svg แต่ละรายการที่ฉันใส่ในโฟลเดอร์และรวมไว้เช่น

 {% include "../icons/cloud.svg" %}

และนั่นทำให้ฉันจัดรูปแบบได้ดังนี้:

 svg { fill: white; }

สมมติว่าองค์ประกอบ SVG ภายในไม่มีแอตทริบิวต์การ fill อยู่แล้ว

การเขียนเนื้อหาใน Markdown

หน้าแรกของไมโครไซต์ของฉันมีเนื้อหาจำนวนมากอยู่ ฉันสามารถเขียนและบำรุงรักษาสิ่งนั้นใน HTML ได้อย่างแน่นอน แต่บางครั้งก็เป็นการดีที่จะทิ้งสิ่งนั้นไว้ให้ Markdown Markdown รู้สึกสะอาดตาในการเขียนและอาจดูง่ายขึ้นเล็กน้อยเมื่อมีสำเนาจำนวนมาก

นี่เป็นเรื่องง่ายมากในโครงการ CodePen ฉันสร้างไฟล์ที่ลงท้ายด้วย . .md ซึ่งจะถูกประมวลผลเป็น HTML โดยอัตโนมัติ จากนั้นจึงรวมไว้ในไฟล์ index.njk

Markdown คอมไพล์เป็น HTML บน CodePen Projects
ไฟล์ใน markdown ถูกคอมไพล์เป็น HTML ในโครงการ CodePen
 {% block content %} <main class="centered-text-column"> {% include "content/about.html" %} </main> {% endblock %}

การสร้างส่วนประกอบจริง

ให้พิจารณาว่าส่วนประกอบเป็นโมดูลที่ทำซ้ำได้ซึ่งส่งผ่านในข้อมูลเพื่อสร้างตัวเอง ในเฟรมเวิร์กอย่าง Vue คุณจะต้องทำงานกับคอมโพเนนต์ไฟล์เดียวที่แยกบิตของเทมเพลต HTML, CSS ที่มีขอบเขต และ JavaScript เฉพาะคอมโพเนนต์ เยี่ยมมาก แต่ไมโครไซต์ของเราไม่ต้องการอะไรแฟนซี

เราจำเป็นต้องสร้าง "การ์ด" บางอย่างโดยใช้เทมเพลตอย่างง่าย ดังนั้นเราจึงสามารถสร้างสิ่งต่างๆ ได้ดังนี้:

ส่วนประกอบสไตล์การ์ด
การสร้างส่วนประกอบที่ทำซ้ำได้ด้วยเทมเพลต

การสร้างองค์ประกอบที่ทำซ้ำได้ใน Nunjucks นั้นเกี่ยวข้องกับการใช้สิ่งที่พวกเขาเรียกว่ามาโคร มาโครนั้นเรียบง่ายอย่างโอชะ มันเหมือนกับ ว่า HTML มีฟังก์ชัน !

 {% macro card(title, content) %} <div class="card"> <h2>{{ title }}</h2> <p>{{ content }}</p> </div> {% endmacro %}

จากนั้นคุณเรียกมันว่าตามต้องการ:

 {{ card('My Module', 'Lorem ipsum whatever.') }}

แนวคิดทั้งหมดนี้คือการ แยกข้อมูลและมาร์กอัป สิ่งนี้ให้ประโยชน์ที่ชัดเจนและเป็นรูปธรรมแก่เรา:

  1. หากเราจำเป็นต้องทำการเปลี่ยนแปลงใน HTML เราสามารถเปลี่ยนแปลงได้ในมาโคร และจะมีการเปลี่ยนแปลงทุกที่ที่ใช้มาโครนั้น
  2. ข้อมูลไม่พันกันในมาร์กอัป
  3. ข้อมูลสามารถมาจากไหนก็ได้! เราเข้ารหัสข้อมูลในการเรียกใช้มาโครตามที่เราทำด้านบน หรือเราสามารถอ้างอิงข้อมูล JSON และวนซ้ำได้ ฉันแน่ใจว่าคุณสามารถจินตนาการถึงการตั้งค่าที่ข้อมูล JSON นั้นมาจาก CMS ที่ไม่มีส่วนหัว กระบวนการสร้าง ฟังก์ชันไร้เซิร์ฟเวอร์ งาน cron หรืออะไรก็ตาม

ตอนนี้ เรามีการ์ดที่ทำซ้ำได้เหล่านี้ซึ่งรวมข้อมูลและมาร์กอัป สิ่งที่เราต้องการ:

ข้อมูลและมาร์กอัปสำหรับส่วนประกอบจะถูกเก็บไว้แยกจากกัน
HTML ถูกควบคุมในมาโคร ในขณะที่ข้อมูลสามารถมาจากที่ใดก็ได้

สร้างส่วนประกอบได้มากเท่าที่คุณต้องการ

คุณสามารถใช้แนวคิดนี้และดำเนินการได้ ตัวอย่างเช่น ลองนึกภาพว่า Bootstrap เป็นกลุ่มของ CSS ที่คุณทำตามรูปแบบ HTML ที่จะใช้อย่างไร คุณสามารถทำให้แต่ละรูปแบบเหล่านี้เป็นมาโครและเรียกมันว่าตามความจำเป็น โดยพื้นฐานแล้ว การจัดองค์ประกอบเฟรมเวิร์ก

คุณสามารถซ้อนส่วนประกอบได้หากต้องการ โดยใช้ปรัชญาการออกแบบปรมาณู Nunjucks ก็มีตรรกะเช่นกัน ซึ่งหมายความว่าคุณสามารถสร้างองค์ประกอบตามเงื่อนไขและรูปแบบต่าง ๆ เพียงแค่ส่งข้อมูลที่แตกต่างกัน

ในไซต์ธรรมดาที่ฉันสร้าง ฉันสร้างมาโครที่แตกต่างกันสำหรับส่วนแนวคิดของไซต์ เนื่องจากเกี่ยวข้องกับข้อมูลที่แตกต่างกันเล็กน้อยและการออกแบบการ์ดที่ต่างกันเล็กน้อย

ส่วนประกอบการ์ดในส่วนไอเดีย
สามารถสร้างส่วนประกอบได้มากเท่าที่คุณต้องการ

กรณีด่วนต่อต้านไซต์คงที่

ฉันอาจโต้แย้งว่า ไซต์ส่วนใหญ่ ได้รับประโยชน์จากสถาปัตยกรรมแบบคอมโพเนนต์ แต่มีเพียงบางไซต์เท่านั้นที่เหมาะสมที่จะเป็นแบบคงที่ ฉันทำงานบนเว็บไซต์มากมายที่มีภาษาแบ็คเอนด์ที่เหมาะสมและมีประโยชน์

CSS-Tricks หนึ่งในไซต์ของฉัน มีสิ่งต่างๆ เช่น การเข้าสู่ระบบของผู้ใช้ด้วยระบบการอนุญาตที่ค่อนข้างซับซ้อน: ฟอรัม ความคิดเห็น อีคอมเมิร์ซ แม้ว่าสิ่งเหล่านี้จะไม่ได้หยุดความคิดที่จะทำงานแบบคงที่โดยสิ้นเชิง แต่ฉันมักจะดีใจที่มีฐานข้อมูลและภาษาแบ็คเอนด์ที่จะใช้งานได้ มันช่วยให้ฉันสร้างสิ่งที่ฉันต้องการและเก็บสิ่งต่าง ๆ ไว้ใต้หลังคาเดียวกัน

ออกไปและโอบกอดชีวิตคงที่!

จำไว้ว่าข้อดีอย่างหนึ่งของการสร้างในลักษณะที่เราทำในบทความนี้ก็คือผลลัพธ์ที่ได้คือไฟล์สแตติกจำนวนมาก โฮสต์ง่าย รวดเร็ว และปลอดภัย ถึงกระนั้น เราก็ไม่ต้องละทิ้งการทำงานในลักษณะที่เป็นมิตรต่อนักพัฒนา ไซต์นี้จะง่ายต่อการอัปเดตและเพิ่มในอนาคต

  • โปรเจ็กต์สุดท้ายคือไมโครไซต์ที่เรียกว่า The Power of Serverless for Front-End Developers (https://thepowerofserverless.info/)
  • หากคุณถามฉันว่าการโฮสต์ไฟล์แบบคงที่เป็นส่วนหนึ่งของการเคลื่อนไหวแบบไร้เซิร์ฟเวอร์
  • คุณสามารถดูรหัสทั้งหมด (และแม้กระทั่งแยกสำเนาสำหรับตัวคุณเอง) ได้จาก CodePen มันถูกสร้างขึ้น บำรุงรักษา และโฮสต์ทั้งหมดบน CodePen โดยใช้ CodePen Projects
  • CodePen Projects จัดการทุกอย่างของ Nunjucks ที่เราพูดถึงที่นี่ และสิ่งต่างๆ เช่น การประมวลผล Sass และการโฮสต์รูปภาพ ซึ่งฉันใช้ประโยชน์จากไซต์นี้ คุณสามารถทำซ้ำสิ่งเดียวกันได้ เช่น กระบวนการสร้างแบบอึกหรือ Grunt ในเครื่อง นี่คือโครงการต้นแบบที่คุณสามารถหมุนได้