Chúng tôi có thể dễ dàng tạo các trang do Khách hàng hiển thị (CSR) và các trang được tạo tĩnh (SG) bằng cách sử dụng Next.js. Tuy nhiên, đôi khi, bạn sẽ muốn trang của mình sử dụng kết hợp các phương pháp hiển thị khác nhau đó. Giống như, bạn muốn trang tĩnh của mình được tạo bằng một số dữ liệu từ api, sau đó khi trình duyệt của người dùng đã hydrat hóa trang tĩnh, bạn muốn CSR bắt đầu. Có một cách chúng ta có thể sử dụng điều này, bằng cách sử dụng plugin SWR
tuyệt vời từ Vercel (`người tạo ra Next.js). Hãy cùng tìm hiểu sơ qua về nó trong bài viết này.
Trước tiên, hãy tạo một ứng dụng tiếp theo bằng cách chạy
1 2 | npx create-next-app blog-swr-demo -y |
Bây giờ chúng ta cần tạo một api giả để phục vụ cho các bài viết / bài viết của chúng ta. Hãy tạo một tệp mới trong pages/posts.js
và dán vào
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">(</span> <span class="token parameter">req <span class="token punctuation">,</span> res</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> res <span class="token punctuation">.</span> <span class="token function">status</span> <span class="token punctuation">(</span> <span class="token number">200</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">json</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> posts <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> title <span class="token operator">:</span> <span class="token string">"A"</span> <span class="token punctuation">,</span> content <span class="token operator">:</span> <span class="token string">"asdf"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> title <span class="token operator">:</span> <span class="token string">"B"</span> <span class="token punctuation">,</span> content <span class="token operator">:</span> <span class="token string">"qwert"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> title <span class="token operator">:</span> <span class="token string">"C"</span> <span class="token punctuation">,</span> content <span class="token operator">:</span> <span class="token string">"zxcv"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> title <span class="token operator">:</span> <span class="token string">"D"</span> <span class="token punctuation">,</span> content <span class="token operator">:</span> <span class="token string">"mnopq"</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> title <span class="token operator">:</span> <span class="token string">"E"</span> <span class="token punctuation">,</span> content <span class="token operator">:</span> <span class="token string">"aeiou"</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Bây giờ, chúng tôi sẽ cài đặt plugin SWR
1 2 | npm i swr |
Và tạo thành phần blog của chúng tôi và cũng nhập hook useSWR
từ plugin mà chúng tôi vừa cài đặt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <span class="token keyword">import</span> useSWR <span class="token keyword">from</span> <span class="token string">"swr"</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Blog</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> Demo blog <span class="token punctuation">{</span> posts <span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">post</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token operator"><</span> h4 <span class="token operator">></span> <span class="token punctuation">{</span> post <span class="token punctuation">.</span> title <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> h4 <span class="token operator">></span> <span class="token operator"><</span> p <span class="token operator">></span> <span class="token punctuation">{</span> post <span class="token punctuation">.</span> content <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> p <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Bây giờ, hãy kết xuất các bài đăng trên blog bằng cách sử dụng useSWR
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <span class="token keyword">import</span> useSWR <span class="token keyword">from</span> <span class="token string">"swr"</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetcherFunc</span> <span class="token punctuation">(</span> <span class="token parameter">url</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span> <span class="token punctuation">(</span> url <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> res <span class="token punctuation">.</span> <span class="token function">json</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Blog</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> url <span class="token operator">=</span> <span class="token string">"http://localhost:3000/api/posts"</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> data <span class="token punctuation">,</span> error <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useSWR</span> <span class="token punctuation">(</span> url <span class="token punctuation">,</span> fetcherFunc <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> data <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> div <span class="token operator">></span> fetching <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token keyword">const</span> <span class="token punctuation">{</span> posts <span class="token punctuation">}</span> <span class="token operator">=</span> data <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> Demo blog <span class="token punctuation">{</span> posts <span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">post</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token operator"><</span> div <span class="token operator">></span> <span class="token operator"><</span> h4 <span class="token operator">></span> Article <span class="token operator">:</span> <span class="token punctuation">{</span> post <span class="token punctuation">.</span> title <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> h4 <span class="token operator">></span> <span class="token operator"><</span> p <span class="token operator">></span> <span class="token punctuation">{</span> post <span class="token punctuation">.</span> content <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> p <span class="token operator">></span> <span class="token operator"><</span> br <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Bây giờ, hãy tạo tệp được tạo tĩnh cho trang của chúng tôi, vì điều này, chúng tôi sẽ sửa đổi mã của mình như
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Blog</span> <span class="token punctuation">(</span> <span class="token parameter">props</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// <<<<<<< changed here</span> <span class="token comment">// const url = "http://localhost:3000/api/posts";</span> <span class="token comment">// const {data, error} = useSWR(url, fetcherFunc);</span> <span class="token comment">// if (!data) return <div>fetching</div></span> <span class="token keyword">const</span> <span class="token punctuation">{</span> posts <span class="token punctuation">}</span> <span class="token operator">=</span> props <span class="token punctuation">;</span> <span class="token comment">// <<<<<<<< Also here</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> Demo blog <span class="token punctuation">{</span> posts <span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">post</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token operator"><</span> div <span class="token operator">></span> <span class="token operator"><</span> h4 <span class="token operator">></span> Article <span class="token operator">:</span> <span class="token punctuation">{</span> post <span class="token punctuation">.</span> title <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> h4 <span class="token operator">></span> <span class="token operator"><</span> p <span class="token operator">></span> <span class="token punctuation">{</span> post <span class="token punctuation">.</span> content <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> p <span class="token operator">></span> <span class="token operator"><</span> br <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getStaticProps</span> <span class="token punctuation">(</span> <span class="token parameter">context</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token function">fetch</span> <span class="token punctuation">(</span> <span class="token string">"http://localhost:3000/api/posts"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> posts <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token punctuation">(</span> <span class="token keyword">await</span> res <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">json</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> props <span class="token operator">:</span> <span class="token punctuation">{</span> posts <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Hãy tạo trang. Đối với cuộc chạy đó
1 2 | npm run build |
Bạn sẽ thấy điều này sau khi nó được xây dựng thành công
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | > <a href="/cdn-cgi/l/email-protection" class="__cf_email__">[email protected]</a> build > next build info - Creating an optimized production build info - Compiled successfully info - Collecting page data info - Generating static pages (4/4) info - Finalizing page optimization Page Size First Load JS ┌ ○ / 3.46 kB 66.9 kB ├ └ css/c50ddf22b716c7b6b76d.css 660 B ├ /_app 0 B 63.4 kB ├ ○ /404 3.46 kB 66.9 kB ├ λ /api/hello 0 B 63.4 kB ├ λ /api/posts 0 B 63.4 kB └ ● /blog 1.96 kB 65.4 kB + First Load JS shared by all 63.4 kB ├ chunks/e82d01500e11e0131e78851aa17fd9f5e63d6c88.ebefd9.js 2.47 kB ├ chunks/f6078781a05fe1bcb0902d23dbbb2662c8d200b3.519eb7.js 11.3 kB ├ chunks/framework.e2fe4a.js 41.8 kB ├ chunks/main.1a4cca.js 6.67 kB ├ chunks/pages/_app.6b4817.js 531 B ├ chunks/webpack.50bee0.js 751 B └ css/6e9ef204d6fd7ac61493.css 194 B λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps) ○ (Static) automatically rendered as static HTML (uses no initial props) ● (SSG) automatically generated as static HTML + JSON (uses getStaticProps) (ISR) incremental static regeneration (uses revalidate in getStaticProps) |
Lưu ý, nếu chúng tôi tiếp tục thêm các bài đăng vào api giả của mình trong khi blog của chúng tôi đang chạy, thì dữ liệu sẽ không được làm mới. Chúng tôi cần tải lại trang để làm điều đó
Hãy khắc phục điều đó ngay bây giờ. Đối với điều đó, chúng tôi sẽ chuyển tùy chọn revalidateOnMount
trong móc useSWR
của chúng tôi Vì vậy, mã cuối cùng sẽ là
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <span class="token keyword">import</span> useSWR <span class="token keyword">from</span> <span class="token string">"swr"</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fetcherFunc</span> <span class="token punctuation">(</span> <span class="token parameter">url</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span> <span class="token punctuation">(</span> url <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> res <span class="token punctuation">.</span> <span class="token function">json</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">Blog</span> <span class="token punctuation">(</span> <span class="token parameter">props</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> url <span class="token operator">=</span> <span class="token string">"http://localhost:3000/api/posts"</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> data <span class="token punctuation">,</span> error <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">useSWR</span> <span class="token punctuation">(</span> url <span class="token punctuation">,</span> fetcherFunc <span class="token punctuation">,</span> <span class="token punctuation">{</span> initialData <span class="token operator">:</span> props <span class="token punctuation">,</span> revalidateOnMount <span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> posts <span class="token punctuation">}</span> <span class="token operator">=</span> data <span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> posts <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator"><</span> div <span class="token operator">></span> fetching <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> div <span class="token operator">></span> Demo blog <span class="token punctuation">{</span> posts <span class="token punctuation">.</span> <span class="token function">map</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">post</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token operator"><</span> div <span class="token operator">></span> <span class="token operator"><</span> h4 <span class="token operator">></span> Article <span class="token operator">:</span> <span class="token punctuation">{</span> post <span class="token punctuation">.</span> title <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> h4 <span class="token operator">></span> <span class="token operator"><</span> p <span class="token operator">></span> <span class="token punctuation">{</span> post <span class="token punctuation">.</span> content <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> p <span class="token operator">></span> <span class="token operator"><</span> br <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getStaticProps</span> <span class="token punctuation">(</span> <span class="token parameter">context</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token function">fetch</span> <span class="token punctuation">(</span> <span class="token string">"http://localhost:3000/api/posts"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> posts <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token punctuation">(</span> <span class="token keyword">await</span> res <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">json</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> props <span class="token operator">:</span> <span class="token punctuation">{</span> posts <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Hãy kiểm tra
Mã nguồn
https://github.com/Salekin-1169/blog-swr-demo