Part 3: Next.js Lazy Loading
ความเดิมตอนที่แล้ว 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
