Part 3: Next.js Lazy Loading

Pozterz
Pozterz
Aug 24, 2017 · 2 min read

ความเดิมตอนที่แล้ว https://medium.com/@pozterz.jojo/part-2-next-js-fetching-data-e72c42814e7e

Lazy Loading คืออะไร

Lazy = ขี้เกียจ

Loading = โหลด

ตามนั้น !

จริงๆ Lazy loading ถูกเอามาใช้หลายๆอย่างเลยนะ แต่ใน Next.js ทำ Lazy Loading Modules และ Lazy Loading Component ได้ ทีละอย่างละกัน

Lazy Loading Module

เอาไว้ใช้กับ Module ที่ต้องใช้บ่อยๆ แต่ไม่อยาก import ใหม่ คือมันเปลือง ต้องโหลดอีกทำไม เสียเวลา ถ้า Module มันใหญ่ด้วยล่ะ

แถ่น แถ๊นนน Next.js ขอเสนอ Lazy Loading Module วันนี้เราจะใช้ firebase เป็นเคสตัวอย่างนะครับ

How it work

มันจะโหลด Module แค่ครั้งแรกที่ user พยายามที่จะไปหน้าไหนสักหน้า เมื่อความพยายามของมันสำเร็จ ครั้งต่อไปมันก็ไม่จำเป็นต้องพยายามแล้ว เพราะโหลดเสร็จตั้งแต่แรกแล้วไง อุ้ว ๆ สุดยอดไปเลยใช่มั้ยล่ะ

ทดสอบกับ index.js และ post.js

pages/index.js

import Layout from '../components/Layout'
import Link from 'next/link'
import loadDB from '../lib/load-db'
const PostLink = (props) => (
<li>
<Link as={`/p/${props.id}`} href={`/post?id=${props.id}`}>
<a>{props.title}</a>
</Link>
</li>
)
const Index = ({ stories }) => (
<Layout>
<h1>Hacker News — Latest</h1>
<ul>
{stories.map(story => (
<PostLink
key={story.id}
id={story.id}
title={story.title}
/>
))}
</ul>
</Layout>
)
Index.getInitialProps = async () => {
const db = await loadDB()
const ids = await db.child('topstories').once('value')
let stories = await Promise.all(
ids.val().slice(0, 10).map(id => db
.child('item')
.child(id)
.once('value')
)
)
stories = stories.map(s => s.val())
return { stories }
}
export default Index

pages/post.js

import Layout from '../components/Layout'
import loadDB from '../lib/load-db'
const Post = ({ item }) => (
<Layout>
<h1>{item.title}</h1>
<p>URL: <a target="_blank" href={item.url}>{item.url}</a></p>
</Layout>
)
Post.getInitialProps = async ({ query }) => {
console.log('id', query.id)
const db = await loadDB()
let item = await db.child('item').child(query.id).once('value')
item = item.val()
return { item }
}
export default Post

lib/load-db.js

ปกติ

export default async () => {
const firebase = require('firebase')
try {
firebase.initializeApp({
databaseURL: 'https://hacker-news.firebaseio.com'
})
} catch (err) {
if(!/already exists/.test(err.message)) {
console.error('Firebase init error ', err.stack);
}
}
return firebase.database().ref('v0')
}

ไม่ปกติ (Lazy Loading Module)

export default async () => {
const firebase = await import('firebase')
try {
firebase.initializeApp({
databaseURL: 'https://hacker-news.firebaseio.com'
})
} catch (err) {
if(!/already exists/.test(err.message)) {
console.error('Firebase init error ', err.stack);
}
}
return firebase.database().ref('v0')
}

เพียงแค่ await import เท่านั้น !!! ~

แบบปกติ

Lazy Loading Module

แล้วไอ firebase_[string] นี้มันถูกเรียกแค่ครั้งเดียวด้วยนะ กดหน้าอื่นไม่มีละ เร็วกว่าแบบปกติด้วย อุ้ว ๆ สุดยอดไปเลยย

Lazy Loading Component

คล้ายกับอันตะกี้เลย แต่เป็น Component ไงไงไงไง

วิธีทำหรอ

import dynamic from 'next/dynamic'
const Highlight = dynamic(import('react-highlight'))

แค่นี้แหละ จะให้มัน Lazy Loading ตรง Component ไหน (ที่มันใหญ่ๆ ต้องโหลดนานๆ) ก็ import dynamic มา ครอบ import มันซะ

จบ !!

มีวิธีทำ dynamic import อีกเพียบ ที่ https://github.com/zeit/next.js/#dynamic-import

หาของเล่นต่อ ไว้จะมาแชร์อีกนะครับ :D

)

Pozterz

Written by

Pozterz

Lv.25 Full Stack Pokemon @Pi R Square

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade