- Next.js คืออะไร? + มาหัดเขียนเว็บด้วย Next.js กันดีกว่า
- ตอนที่ 1 - Hello Next.js เริ่มสร้างโปรเจ็ค
- ตอนที่ 2 - สร้าง Page และการ navigate ระหว่าง Pages
- ตอนที่ 3 - การจัดการ Assets, Metadata และ CSS
- ตอนที่ 4 - เรื่องของ Pre Rendering
- ตอนที่ 5 - Data Fetching และการดึงข้อมูลจาก API
- ตอนที่ 6 - การทำ Dynamic Routes
- ตอนที่ 7 - API Routes การทำ API ด้วย Next.js
ตอนที่ 3 - การจัดการ Assets, Metadata และ CSS
เขียนวันที่ : Jun 18, 2022
มาต่อกันที่บทที่ 3 ครับ บทนี้ก็ยังใช้ source code ที่ได้จาก create-next-app
นะครับ วันนี้ต่อด้วยเรื่องของ Assets และการจัดการ CSS โดย Assets ก็หมายถึงพวก static files ทั้งหลาย เช่น images
หรือไฟล์ pdf
, .mp4
เป็นต้น การจัดการ Meta tag ต่างๆ พวก SEO tag ต่างๆ
Assets
Next.js นั้นจะมองโฟลเดอร์ public
ที่อยู่ในโปรเจ็คของเรา เป็น static assets ครับ เช่นไฟล์ robots.txt
ก็คือไฟล์ public ที่ให้ Google bot มาอ่าน
ตัวอย่างเช่น เราจะเก็บรูปที่เราจะใช้ในเว็บ เราก็เก็บไว้ในโฟลเดอร์ public
อาจจะแตกโฟลเดอร์ย่อยข้างในก็ได้ เช่น images
สมมติ เรามีไฟล์ public/images/logo.png
เวลาเราเรียกใช้ใน Component เราก็จะเรียกใช้งานแบบนี้
<img src="/images/logo.png" alt="My Logo" />
next/image
Next.js นั้นมี next/image
ที่มาช่วยจัดการเรื่องของ Image Optimization ให้เราครับ เช่น resize รูป, แปลงรูปเป็น WebP, รองรับขนาดรูปตาม size ของ viewport เป็นต้น
การใช้งาน next/image
ก็คล้ายๆกับ <img>
ของ HTML ปกติ ต่างกันที่มองเป็น Component และก็มี option คือ props นั่นเอง
วิธีใช้งาน ก็ตามตัวอย่างด้านล่าง การเพิ่มรูป โดยกำหนด ความกว้าง ความยาว = 144px
import Image from 'next/image'
const YourComponent = () => {
return (
<Image
src="/images/logo.png"
height={144}
width={144}
alt="My Logo"
/>
)
}
ซึ่งสามารถดูโค๊ดไฟล์ pages/index.js
ตรงส่วน <footer>
ดูได้ครับ จะมีการใช้งาน <Image>
โดยเรียกไฟล์ vercel.svg
<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
</footer>
อ่านเรื่องของ next/image เพิ่มเติม
Metadata
ปกติ Metadata ในหน้าเว็บ HTML ของเรา เช่น <title>
ใน <head>
เราสามารถปรับแต่งได้ โดยใช้ next/head
นั่นเอง (จริงๆ คือทั้งหมดที่อยู่ในแท็ก <head>
เช่นปรับ meta tag เพื่อ SEO ต่างๆ หรือแทรก script ลงไป)
ลองสังเกตที่ไฟล์ pages/index.js
ครับ จะเห็นส่วนนี้
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
... ...
</div>
);
}
ก็คือเป็นการกำหนด Title ให้หน้า Index นั่นเอง ตัวอย่้างดูได้จาก pages/index.js
เช่นเดิม
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
CSS Styling
ในการจัดการ CSS ของ Next.js เราสามารถเลือกเขียน CSS ได้หลากหลายมากครับ ทั้ง css ปกติ, css modules, CSS-in-JS หรือ Sass เป็นต้น
อย่าง CSS-in-JS ตัวที่เป็น built-in ของ Next.js เลย คือใช้ styled-jsx จะคล้ายๆกับ styled-component หรือ emotion
ตัวอย่างการใช้งาน
export default () => (
<div>
<p>only this paragraph will get the style :)</p>
{/* you can include <Component />s here that include
other <p>s that don't get unexpected styles! */}
<style jsx>{`
p {
color: red;
}
`}</style>
</div>
);
เราจะเห็นว่า <p>
ถูกกำหนดให้มี color: red
โดยที่มีผลแค่ component นี้ ไม่มีผลกับ <p>
ใน component อื่นๆ นั่นเอง
CSS Modules
นอกจากนี้เรื่องการจัดการ CSS แต่ละ component ไม่ให้ selector
มันชนกัน ก็คือการใช้ CSS Modules ครับ
สังเกตจากไฟล์ styles/global.css
และไฟล์ Home.module.css
ที่ถูกสร้างมา default จากตอนเราสร้างโปรเจ็ค naming convention จะเป็น [name].module.css
ส่วนไฟล์ pages/index.js
ก็จะมีการ import มาใช้งานอยู่ครับ
import styles from '../styles/Home.module.css'
export default function Home() {
return (
<div className={styles.container}>
</div>
)
}
ข้อดีของ CSS Module คือ class จะถูก generate ทำให้ selector ที่เราตั้งไว้ จะไม่โดน override ครับ ลองเปิดหน้าเว็บ แล้ว inspect ดู
Sass
ตัว Next.js ก็รองรับการเขียนด้วย Sass ครับ เพียงแค่ตั้งชื่อไฟล์ให้ลงท้ายด้วย .scss
และก็ติดตั้ง node-sass
ครับ
yarn add sass -D
# หรือ npm install sass --save-dev
Global Styles
นอกจากเราจะใช้ CSS Module เพื่อสำหรับการจัด style แบบ component-level แล้ว เรายังสามารถใช้ CSS แบบ global (พวก common, helper css) ที่ต้องใช้ทุกๆ หน้า ซึ่ง Next.js ก็รองรับ
เงื่อนไข คือไฟล์ _app.js
ในโฟลเดอร์ pages
มันจะโหลดทุกๆ หน้านั่นเอง เราก็แค่ import global styles ลงไป
ลองดูไฟล์ pages/_app.js
ที่ตัว create-next-app มัน generate มาให้ครับ
import '../styles/globals.css'
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
ทดลองปรับแก้ เพิ่ม selector ใน globals.css
ดูครับ
นอกจากนี้ เรายังสามารถ import CSS จาก node_modules
ได้ เช่นกัน เช่น ถ้าเราติดตั้ง bootstrap ไว้ ก็ import ได้เลย
import 'bootstrap/dist/css/bootstrap.css'
global css ไม่สามารถ import ที่อื่นได้ นอกจากไฟล์
pages/_app.js
เพื่อให้มันมีผล css กับทุกๆ element ในหน้า page
🎉 จบแล้วครับ สำหรับตอนที่ 3 - ตอนต่อไปจะมาพูดถึงเรื่องของ Pre-rendering กันครับ
แบบฝึกหัด
- ลองใช้งาน Style Component หรือ Emotion ปรับแต่งหน้าเว็บ
- ลอง import CSS Framework/Library อื่นๆ มาใช้ เช่น bootstrap, bulma, tailwind
- ลองใช้ classNames เพื่อจัดการกับ style