ไทย

เรียนรู้วิธีการใช้ Next.js Layouts เพื่อสร้างแอปพลิเคชันที่แข็งแกร่ง ขยายขนาดได้ และรองรับการใช้งานทั่วโลก ค้นพบแนวทางปฏิบัติที่ดีที่สุดสำหรับคอมโพเนนต์ UI ที่ใช้ร่วมกัน

Next.js Layouts: การเรียนรู้รูปแบบคอมโพเนนต์ UI ที่ใช้ร่วมกันสำหรับแอปพลิเคชันระดับโลก

Next.js ได้กลายเป็นรากฐานที่สำคัญของการพัฒนาเว็บสมัยใหม่ มีชื่อเสียงในด้านความสามารถในการปรับปรุงกระบวนการสร้างแอปพลิเคชันที่มีประสิทธิภาพและเป็นมิตรต่อผู้ใช้ หัวใจสำคัญของความสามารถนี้คือการจัดการคอมโพเนนต์ UI อย่างมีประสิทธิภาพ และศูนย์กลางของสิ่งนี้คือพลังของ Next.js Layouts คู่มือฉบับสมบูรณ์นี้จะเจาะลึกถึงความซับซ้อนของการใช้ประโยชน์จาก Next.js Layouts เพื่อสร้างแอปพลิเคชันที่แข็งแกร่ง ขยายขนาดได้ และรองรับการใช้งานทั่วโลก เราจะสำรวจแนวทางปฏิบัติที่ดีที่สุดสำหรับการสร้างคอมโพเนนต์ UI ที่ใช้ร่วมกัน ซึ่งส่งเสริมการนำโค้ดกลับมาใช้ใหม่ ความสามารถในการบำรุงรักษา และประสบการณ์ผู้ใช้ที่ราบรื่นสำหรับผู้ใช้ทั่วโลก

ทำความเข้าใจความสำคัญของ Layouts ใน Next.js

ในแวดวงการพัฒนาเว็บ โดยเฉพาะกับเฟรมเวิร์กอย่าง Next.js เลย์เอาต์ทำหน้าที่เป็นรากฐานทางสถาปัตยกรรมที่ใช้สร้างส่วนต่อประสานผู้ใช้ของแอปพลิเคชันของคุณ มันคือพิมพ์เขียวสำหรับองค์ประกอบ UI ที่สอดคล้องและนำกลับมาใช้ใหม่ได้ ซึ่งเป็นตัวกำหนดประสบการณ์ผู้ใช้โดยรวม การคิดเกี่ยวกับเลย์เอาต์ในการออกแบบแอปพลิเคชันที่มีโครงสร้างที่ดีช่วยให้นักพัฒนาหลีกเลี่ยงการทำซ้ำของโค้ดและทำให้การบำรุงรักษาง่ายขึ้น โดยพื้นฐานแล้ว มันเป็นกรอบการทำงานสำหรับ:

แนวคิดหลักและประโยชน์ของ Next.js Layouts

1. ไฟล์ `_app.js` และ `_document.js`

ใน Next.js มีไฟล์พิเศษสองไฟล์ที่มีบทบาทสำคัญในการกำหนดเลย์เอาต์และการกำหนดค่าส่วนกลาง: `_app.js` และ `_document.js` การทำความเข้าใจวัตถุประสงค์ของไฟล์เหล่านี้เป็นพื้นฐานที่สำคัญ

2. ข้อดีของการใช้ Layouts

การใช้เลย์เอาต์มีข้อดีมากมาย โดยเฉพาะอย่างยิ่งเมื่อสร้างเว็บแอปพลิเคชันขนาดใหญ่และซับซ้อน:

การนำรูปแบบคอมโพเนนต์ UI ที่ใช้ร่วมกันมาใช้

1. การสร้างคอมโพเนนต์ Layout พื้นฐาน

มาสร้างคอมโพเนนต์เลย์เอาต์แบบง่ายๆ กัน คอมโพเนนต์นี้จะรวมส่วนหัว พื้นที่เนื้อหาหลัก และส่วนท้าย ซึ่งออกแบบมาเพื่อใช้ร่วมกันในหลายๆ หน้า

// components/Layout.js
import Head from 'next/head';

function Layout({ children, title }) {
  return (
    <>
      <Head>
        <title>{title} | My App</title>
        <meta name="description" content="My Next.js App" />
      </Head>
      <header>
        <h1>My App Header</h1>
      </header>
      <main>{children}</main>
      <footer>
        <p>© {new Date().getFullYear()} My App. All rights reserved.</p>
      </footer>
    </>
  );
}

export default Layout;

ในตัวอย่างนี้ คอมโพเนนต์ `Layout` จะได้รับ `children` และ `title` เป็น props `children` แทนเนื้อหาของหน้าที่จะถูกเรนเดอร์ภายในเลย์เอาต์ ในขณะที่ `title` จะตั้งค่าแท็กไตเติ้ลของหน้าสำหรับ SEO

2. การใช้คอมโพเนนต์ Layout ในหน้าเว็บ

ตอนนี้ เรามาใช้เลย์เอาต์นี้กับหน้าใดหน้าหนึ่งของคุณกัน (เช่น `pages/index.js`)

// pages/index.js
import Layout from '../components/Layout';

function HomePage() {
  return (
    <Layout title="Home">
      <h2>Welcome to the Home Page</h2>
      <p>This is the main content of the home page.</p>
    </Layout>
  );
}

export default HomePage;

ใน `pages/index.js` เรานำเข้าคอมโพเนนต์ `Layout` และครอบเนื้อหาของหน้าไว้ภายในนั้น เรายังระบุ `title` เฉพาะสำหรับหน้านั้นด้วย prop `children` ในคอมโพเนนต์ `Layout` จะถูกเติมด้วยเนื้อหาระหว่างแท็ก `<Layout>` ใน `index.js`

3. คุณสมบัติ Layout ขั้นสูง

ข้อควรพิจารณาสำหรับแอปพลิเคชันระดับโลก

เมื่อสร้างเลย์เอาต์สำหรับผู้ชมทั่วโลก สิ่งสำคัญคือต้องพิจารณาแง่มุมต่างๆ ของการทำให้เป็นสากลและโลกาภิวัตน์ (i18n/g11n) แนวทางปฏิบัติเหล่านี้ช่วยให้แน่ใจว่าแอปพลิเคชันของคุณสามารถเข้าถึงได้และเป็นมิตรต่อผู้ใช้สำหรับบุคคลจากภูมิหลังทางวัฒนธรรมที่หลากหลาย

1. Internationalization (i18n) และ Localization (l10n)

2. การนำ i18n มาใช้ใน Next.js Layouts

เพื่อนำ i18n มาใช้ใน Next.js คุณสามารถใช้ไลบรารีต่างๆ เช่น `next-i18next` หรือ `next/router` ในตัวสำหรับโซลูชันที่อิงตามการกำหนดเส้นทาง

นี่คือตัวอย่างแบบง่ายด้วย `next-i18next` โดยใช้ไฟล์ `_app.js` ซึ่งเป็นการตั้งค่า i18n ที่ระดับแอปพลิเคชัน ตรวจสอบให้แน่ใจว่าคุณได้ติดตั้งแพ็คเกจที่จำเป็นโดยใช้ `npm install i18next react-i18next next-i18next` ตัวอย่างนี้แสดงให้เห็นถึงการผสานรวมที่เรียบง่ายและอาจต้องมีการปรับเปลี่ยนตามความต้องการเฉพาะ

// _app.js
import { appWithTranslation } from 'next-i18next';
import '../styles/global.css'; // นำเข้าสไตล์ส่วนกลางของคุณ

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default appWithTranslation(MyApp);

ใน `_app.js` นี้ `appWithTranslation` จะให้บริบทการทำให้เป็นสากลแก่แอปพลิเคชัน

จากนั้น ในเลย์เอาต์ของคุณ ให้ใช้ hook `useTranslation` ที่จัดหาให้โดย `react-i18next`:

// components/Layout.js
import { useTranslation } from 'react-i18next';
import Head from 'next/head';

function Layout({ children, title }) {
  const { t } = useTranslation(); // รับฟังก์ชันการแปล

  return (
    <>
      <Head>
        <title>{t('layout.title', { title })}</title>
        <meta name="description" content={t('layout.description')} />
      </Head>
      <header>
        <h1>{t('layout.header')}</h1>
      </header>
      <main>{children}</main>
      <footer>
        <p>{t('layout.footer', { year: new Date().getFullYear() })}</p>
      </footer>
    </>
  );
}

export default Layout;

จากนั้นคุณจะต้องมีไฟล์การแปลของคุณ ซึ่งโดยทั่วไปจะเก็บไว้ในโครงสร้าง `public/locales/[locale]/[namespace].json` ตัวอย่างเช่น `public/locales/en/common.json` อาจมี:

{
  "layout": {
    "title": "{{title}} | แอปของฉัน",
    "description": "คำอธิบายแอป Next.js ของฉัน",
    "header": "ส่วนหัวของแอปของฉัน",
    "footer": "© {{year}} แอปของฉัน สงวนลิขสิทธิ์"
  }
}

และ `public/locales/fr/common.json` (สำหรับภาษาฝรั่งเศส) อาจมี:

{
  "layout": {
    "title": "{{title}} | Mon Application",
    "description": "Description de mon application Next.js",
    "header": "En-tête de mon application",
    "footer": "© {{year}} Mon application. Tous droits réservés."
  }
}

หมายเหตุ: ตัวอย่างนี้เป็นแนวทางพื้นฐานในการผสานรวม i18n และต้องการการกำหนดค่าเพิ่มเติม (เช่น การตรวจจับภาษา, การตั้งค่าการกำหนดเส้นทาง) โปรดศึกษาเอกสารของ `next-i18next` สำหรับคำแนะนำที่ครอบคลุม

3. การออกแบบที่ตอบสนองและเลย์เอาต์

การออกแบบที่ตอบสนองเป็นสิ่งสำคัญสำหรับผู้ชมทั่วโลก เลย์เอาต์ของคุณต้องปรับให้เข้ากับขนาดหน้าจอและอุปกรณ์ต่างๆ ใช้เฟรมเวิร์ก CSS เช่น Bootstrap, Tailwind CSS หรือสร้าง media queries แบบกำหนดเองเพื่อให้แน่ใจว่าได้รับประสบการณ์ที่สอดคล้องและเป็นมิตรต่อผู้ใช้ในทุกอุปกรณ์

4. ข้อควรพิจารณาด้านการเข้าถึงได้

ปฏิบัติตามแนวทางการเข้าถึงได้ (WCAG) เพื่อให้แอปพลิเคชันของคุณสามารถใช้งานได้สำหรับผู้ที่มีความพิการ ซึ่งรวมถึง:

5. การจัดรูปแบบวันที่และเวลา

ภูมิภาคต่างๆ มีแบบแผนที่แตกต่างกันสำหรับรูปแบบวันที่และเวลา ตรวจสอบให้แน่ใจว่าวันที่และเวลาแสดงอย่างถูกต้องตามท้องถิ่นของผู้ใช้ ไลบรารีอย่าง `date-fns` หรือ `Intl` API ในตัวของ JavaScript สามารถจัดการเรื่องนี้ได้

import { format } from 'date-fns';
import { useTranslation } from 'react-i18next';

function MyComponent() {
  const { i18n } = useTranslation();
  const currentDate = new Date();
  const formattedDate = format(currentDate, 'MMMM d, yyyy', { locale: i18n.language });

  return <p>{formattedDate}</p>;
}

6. การจัดรูปแบบสกุลเงิน

แสดงค่าเงินในรูปแบบที่ถูกต้องสำหรับแต่ละท้องถิ่น `Intl.NumberFormat` API มีประโยชน์อย่างมากสำหรับการจัดการการจัดรูปแบบสกุลเงิน

function MyComponent() {
  const { i18n } = useTranslation();
  const price = 1234.56;
  const formattedPrice = new Intl.NumberFormat(i18n.language, { // ใช้ i18n.language สำหรับท้องถิ่น
    style: 'currency',
    currency: 'USD', // หรือกำหนดสกุลเงินแบบไดนามิกตามความชอบของผู้ใช้
  }).format(price);

  return <p>{formattedPrice}</p>
}

7. ภาษาที่เขียนจากขวาไปซ้าย (RTL)

หากแอปพลิเคชันของคุณต้องการรองรับภาษาต่างๆ เช่น ภาษาอาหรับหรือฮิบรู (ภาษา RTL) ให้ออกแบบเลย์เอาต์ของคุณเพื่อรองรับสิ่งนี้ พิจารณาใช้คุณสมบัติ CSS เช่น `direction: rtl;` และปรับตำแหน่งขององค์ประกอบ UI

8. Content Delivery Networks (CDNs) และประสิทธิภาพ

ใช้ CDN เพื่อให้บริการแอสเซทแบบคงที่ของแอปพลิเคชันของคุณ (รูปภาพ, CSS, JavaScript) จากเซิร์ฟเวอร์ที่อยู่ใกล้กับผู้ใช้ของคุณทางภูมิศาสตร์ ซึ่งจะช่วยลดเวลาแฝงและปรับปรุงเวลาในการโหลดหน้าเว็บสำหรับผู้ใช้ต่างชาติ การปรับปรุงรูปภาพในตัวของ Next.js และการรวม CDN สามารถปรับปรุงประสิทธิภาพได้อย่างมีนัยสำคัญ

9. การปรับปรุง SEO สำหรับตลาดโลก

การปรับปรุงให้เหมาะสมกับเครื่องมือค้นหา (SEO) เป็นสิ่งสำคัญสำหรับการดึงดูดผู้ใช้ทั่วโลก ใช้เทคนิคต่อไปนี้:

ตัวอย่างแท็ก hreflang ใน `` ของคอมโพเนนต์ `Layout` ของคุณ:


<Head>
  <title>{t('layout.title', { title })}</title>
  <meta name="description" content={t('layout.description')} />
  <link rel="alternate" href="https://www.example.com/" hreflang="x-default" />  {
  <link rel="alternate" href="https://www.example.com/en/" hreflang="en" />
  <link rel="alternate" href="https://www.example.com/fr/" hreflang="fr" />
  // ตัวแปรภาษาเพิ่มเติม
</Head>

กลยุทธ์ Layout ขั้นสูง

1. Code Splitting กับ Layouts

Next.js ทำการแบ่งโค้ดโดยอัตโนมัติเพื่อปรับปรุงประสิทธิภาพ แต่คุณสามารถปรับแต่งพฤติกรรมนี้ได้โดยใช้ dynamic imports โดยเฉพาะภายในเลย์เอาต์ของคุณ ด้วยการนำเข้าคอมโพเนนต์ขนาดใหญ่แบบไดนามิก คุณสามารถลดขนาด JavaScript bundle เริ่มต้นได้ ซึ่งนำไปสู่เวลาในการโหลดเริ่มต้นที่เร็วขึ้น


import dynamic from 'next/dynamic';

const DynamicComponent = dynamic(() => import('../components/LargeComponent'));

function Layout({ children }) {
  return (
    <>
      <header>...</header>
      <main>
        {children}
        <DynamicComponent />  <!-- คอมโพเนนต์ที่โหลดแบบไดนามิก -->
      </main>
      <footer>...</footer>
    </>
  );
}

ในตัวอย่าง `LargeComponent` จะถูกโหลดแบบไดนามิก การนำเข้าแบบไดนามิกจะชะลอการดาวน์โหลดคอมโพเนนต์นี้จนกว่าจะจำเป็นต้องใช้จริงๆ

2. Layouts กับ Server-Side Rendering (SSR)

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

การใช้ `getServerSideProps` ภายในหน้า คุณสามารถส่งข้อมูลไปยังเลย์เอาต์ได้:


// pages/posts/[id].js
import Layout from '../../components/Layout';

export async function getServerSideProps(context) {
  const { id } = context.params;
  const res = await fetch(`https://api.example.com/posts/${id}`);
  const post = await res.json();

  return {
    props: {
      post,
    },
  };
}

function PostPage({ post }) {
  return (
    <Layout title={post.title}>
      <h1>{post.title}</h1>
      <p>{post.content}</p>
    </Layout>
  );
}

export default PostPage;

ฟังก์ชัน `getServerSideProps` จะดึงข้อมูลโพสต์ จากนั้นข้อมูล `post` จะถูกส่งเป็น prop ไปยัง `Layout`

3. Layouts กับ Static Site Generation (SSG)

สำหรับเนื้อหาที่ไม่เปลี่ยนแปลงบ่อยครั้ง SSG ให้ประโยชน์ด้านประสิทธิภาพอย่างมาก มันจะเรนเดอร์หน้าล่วงหน้าในขณะสร้าง (build time) สร้างไฟล์ HTML แบบคงที่ซึ่งจะถูกให้บริการโดยตรงแก่ผู้ใช้ หากต้องการใช้ SSG ให้ใช้ฟังก์ชัน `getStaticProps` ในคอมโพเนนต์หน้าของคุณ และข้อมูลสามารถส่งไปยังเลย์เอาต์ได้


// pages/about.js
import Layout from '../components/Layout';

export async function getStaticProps() {
  const aboutData = { title: 'About Us', content: 'Some information about our company.' };
  return {
    props: {
      aboutData,
    },
  };
}

function AboutPage({ aboutData }) {
  return (
    <Layout title={aboutData.title}>
      <h2>{aboutData.title}</h2>
      <p>{aboutData.content}</p>
    </Layout>
  );
}

export default AboutPage;

ในตัวอย่าง SSG นี้ `getStaticProps` จะดึงข้อมูลในขณะสร้าง จากนั้นส่งต่อไปยัง `AboutPage` ซึ่งจะถูกเรนเดอร์โดยใช้คอมโพเนนต์ `Layout`

4. Nested Layouts

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


// components/MainLayout.js
function MainLayout({ children }) {
  return (
    <>
      <header>Main Header</header>
      <main>{children}</main>
      <footer>Main Footer</footer>
    </>
  );
}

export default MainLayout;

// components/SectionLayout.js
function SectionLayout({ children }) {
  return (
    <div className="section-wrapper">
      <aside>Section Navigation</aside>
      <div className="section-content">{children}</div>
    </div>
  );
}

export default SectionLayout;

// pages/section/[page].js
import MainLayout from '../../components/MainLayout';
import SectionLayout from '../../components/SectionLayout';

function SectionPage({ page }) {
  return (
    <MainLayout>
      <SectionLayout>
        <h1>Section Page: {page}</h1>
        <p>Content for section page {page}.</p>
      </SectionLayout>
    </MainLayout>
  );
}

export async function getServerSideProps(context) {
  const { page } = context.query;
  return {
    props: {
      page,
    },
  };
}

export default SectionPage;

ในกรณีนี้ `SectionPage` จะถูกครอบด้วยทั้ง `MainLayout` และ `SectionLayout` เพื่อสร้างโครงสร้างเลย์เอาต์ซ้อน

แนวทางปฏิบัติที่ดีที่สุดและเคล็ดลับการปรับปรุงประสิทธิภาพ

1. Component Composition

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

2. การตรวจสอบประสิทธิภาพ

ตรวจสอบประสิทธิภาพของเลย์เอาต์และแอปพลิเคชันของคุณอย่างต่อเนื่องโดยใช้เครื่องมือเช่น Google Lighthouse หรือ WebPageTest เครื่องมือเหล่านี้สามารถช่วยคุณระบุปัญหาคอขวดด้านประสิทธิภาพและส่วนที่ต้องปรับปรุง

3. กลยุทธ์การแคช

นำกลยุทธ์การแคชมาใช้เพื่อลดภาระของเซิร์ฟเวอร์และปรับปรุงเวลาตอบสนอง พิจารณาการแคชข้อมูลที่เข้าถึงบ่อยครั้ง การใช้การแคชของเบราว์เซอร์สำหรับแอสเซทแบบคงที่ และการใช้ Content Delivery Network (CDN) เพื่อแคชเนื้อหาให้ใกล้กับผู้ใช้มากขึ้น

4. Lazy Loading

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

5. หลีกเลี่ยงการ Re-render ที่มากเกินไป

ปรับปรุงคอมโพเนนต์ของคุณเพื่อหลีกเลี่ยงการ re-render ที่ไม่จำเป็น ใช้ `React.memo`, `useMemo` และ `useCallback` เพื่อ memoize คอมโพเนนต์และฟังก์ชัน ใช้ prop `key` อย่างเหมาะสมเมื่อเรนเดอร์รายการคอมโพเนนต์เพื่อช่วยให้ React ระบุการเปลี่ยนแปลงได้อย่างมีประสิทธิภาพ

6. การทดสอบ

ทำการทดสอบคอมโพเนนต์เลย์เอาต์ของคุณอย่างละเอียด รวมถึงการทดสอบหน่วย (unit tests) และการทดสอบการรวม (integration tests) เพื่อให้แน่ใจว่าทำงานได้ตามที่คาดไว้และรักษพฤติกรรมที่สอดคล้องกัน ทดสอบเลย์เอาต์ในขนาดหน้าจอและท้องถิ่นที่แตกต่างกัน

บทสรุป

Next.js Layouts นำเสนอเครื่องมือที่มีประสิทธิภาพและหลากหลายเพื่อสร้างเว็บแอปพลิเคชันที่ยอดเยี่ยม ด้วยการเชี่ยวชาญเทคนิคที่กล่าวถึงในคู่มือนี้ คุณสามารถสร้าง UI ที่มีโครงสร้างดี บำรุงรักษาง่าย และมีประสิทธิภาพ อย่าลืมนำแนวทางปฏิบัติที่ดีที่สุดด้านการทำให้เป็นสากลและโลกาภิวัตน์มาใช้เพื่อให้แน่ใจว่าแอปพลิเคชันของคุณจะเข้าถึงผู้ชมทั่วโลก ด้วยการผสมผสานพลังของ Next.js เข้ากับแนวทางที่รอบคอบในการสร้างเลย์เอาต์ คุณจะพร้อมอย่างเต็มที่ในการสร้างประสบการณ์เว็บที่ทันสมัย ขยายขนาดได้ และเข้าถึงได้ในระดับสากล

Next.js Layouts: การเรียนรู้รูปแบบคอมโพเนนต์ UI ที่ใช้ร่วมกันสำหรับแอปพลิเคชันระดับโลก | MLOG