next.js　ページのレンダリングについて CSR SSG ISR SSRの実装方法と動きの確認

# 概要
nextjsの各レンダリング方法（CSR、SSG、ISR SSR）の実装方法、動きを確認します。
dynamic routingのような難しいことはしないで　初歩的な確認をします。

# 開発環境
フロントエンド：
IDE:VScode

├── @types/node@18.11.15
├── @types/react-dom@18.0.9
├── @types/react@18.0.26
├── axios@1.2.1
├── eslint-config-next@13.0.6
├── eslint@8.29.0
├── next-auth@4.18.7
├── next@13.0.6
├── react-bootstrap@2.7.0
├── react-dom@18.2.0
├── react@18.2.0
├── styled-components@5.3.6
├── styled-jsx@5.1.1
└── typescript@4.9.4

# 実装
## CSR-Client Sever Rendering
Reactベースの手法です。nextjsの要素はないです。

### ソースコード
```tsx:csr.tsx
import { useEffect, useState } from "react";

function Csr(){
	const[products, setProducts] = useState([]);
	useEffect(() => {
		fetch('/dummy-backend.json')
		.then((response) => {
			return response.json();
		})
		.then((data) => {
			setProducts(data.products);
		});
}, []);

return(
	<div>
		<h1>CSR例</h1>
		<ul>
			{products.map((product : any) =>(
				<li key={product.id}>{product.title}</li>	
			))}		
		</ul>
	</div>
)
}

export default Csr;

```

ダミーデータを作成。クライアントサイドからアクセスできるようにpublicフォルダーに置きます
```json:root/public/dummy-backend.json
{
	"products": [
	  { "id": "p1", "title": "Product 1", "description": "This is product 1" },
	  { "id": "p2", "title": "Product 2", "description": "This is product 2" },
	  { "id": "p3", "title": "Product 3", "description": "This is product 3" }
	]
  }
```


### 確認方法
以下コマンドを実行
```
npm run dev
```


ページを開きCtrl+Uを押してソースを表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/32beae70-be8c-c2a4-183b-cd002e854fa7.png)
データの取得はクライアントで行われるから、データの部分が入ってないですね。（赤線部分）

## SSG-Static Side Rendering
ビルド時にデータを取得して、htmlに組み込む手法です。

### ソースコード
```tsx:ssg.tsx
import path from "path";
import fs from 'fs/promises';
import Link from "next/link";

function Ssg(props : any){
	const {products} = props;
	return(
		<div>
			<Link href="/ssg">SSG実装例</Link>

			<ul>
				{products.map((product : any) =>( 
				<li key ={product.id}>{product.title}</li>))}
			</ul>
		</div>
	);
}

export async function getStaticProps(){
	console.log('Regenerating...')
	const filePath = path.join(process.cwd(),'data','dummy-backend.json');
	const jsonData = await fs.readFile(filePath);
	const data =JSON.parse(jsonData as any);
	return{
		props:{
			products: data.products
		},
	};
}
export default Ssg;
```

データ
```json:root/data/dummy-backend.json
{
	"products": [
	  { "id": "p1", "title": "Product 1", "description": "This is product 1" },
	  { "id": "p2", "title": "Product 2", "description": "This is product 2" },
	  { "id": "p3", "title": "Product 3", "description": "This is product 3" }
	]
  }
```
### 確認方法



buildコマンドを実行する
```
npm run build
``` 
ビルド結果　コンソールからSSGが作成されていることを確認。赤線部分注目
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/f2ae339f-7a62-5541-bde3-68d76b7b2a6d.png)

以下コマンドを実行してビルド結果を確認します。（一応npm run devでも確認はできます）
```
npm start
```

ページを開いてCtrl+Uを押してソースを表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/d97f4c0e-6c6b-6c60-efc8-2222f8737dda.png)
赤線部分からhtmlにデータが入っています。サーバー側でデータを取得しhtmlに組み込んでいることを確認できます。




## ISR-Incremental Static Regeneration
SSGの発展で一定間隔でデータの取得します。

### ソースコード
SSGができれば簡単に実装できます。
revalidateを追加するだけです。

```diff_typescript
import path from "path";
import fs from 'fs/promises';
import Link from "next/link";

function Isr(props : any){
	const {products} = props;
	return(
		<div>
			<Link href="/ssg">ISR実装例</Link>
			
			<ul>
				{products.map((product : any) =>( 
				<li key ={product.id}>{product.title}</li>))}
			</ul>
		</div>
	);
}

export async function getStaticProps(){
	console.log('Regenerating...')
	const filePath = path.join(process.cwd(),'data','dummy-backend.json');
	const jsonData = await fs.readFile(filePath);
	const data =JSON.parse(jsonData as any);	
	if(!data){
		return{
	return{
		props:{
			products: data.products
		},
+		revalidate:10,
	};
}
export default ISR;
```
### 確認方法
ビルドしてログを確認
``` 
npm run build
```
ログの結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/ae53d213-2a07-9161-c692-6d6e3219d882.png)
赤線部分からISRになったことが確認できます。10秒おきにデータの再取得を行います。
以下コマンドを実行してサーバーを起動する

``` 
npm start
```
htmlソースコードの画像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/d91778e5-ceb7-07ca-b652-6f8b8c4348c8.png)
赤線部からしてデータ入ってますね。

データ取得頻度の値を変えて比較

下gifアニメはISRのページに対して更新を連打している様子です。
データの取得が行われるとvscodeのコンソールに文字が出力されます。
１枚目は5秒 2枚目は１秒にしました。

間隔が5秒の時
![ISR_take1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/8bf64194-1edd-d5a6-bced-0ae261bfa866.gif)


間隔が1秒の時
![ISR_take2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a921b7d2-76b3-e333-38f3-d9c0f87ee168.gif)

SSGよりは使い勝手が良さそう

## SSR Server Side Rendering
### ソースコード
``` tsx:user-profile.tsx

function UserProfilePage(props : any) {
	console.log("Page")
	return <h1>{props.username}</h1>
  }
  
  export default UserProfilePage;
  
  export async function getServerSideProps(context: any) {
	console.log("SSR")
	const { params, req, res } = context;
	
	return {
	  props: {
		username: 'Max'
	  }
	};
  }
```

### 動きの確認
以下コマンドを押してビルド
```
npm run build
```
下の画像はビルド結果です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/51d7f93a-7305-8192-62da-e23f829386c0.png)

htmlの結果　データ入ってますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/a2b547a9-8e93-f9ac-0afe-7b3b63c5131d.png)

下gifアニメは更新ボタンを連打している時の様子です。
押すごとにconsole.log('SSR')が実行されデータを取得していることを確認できます。

![SSR _samole.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/046bfc1b-ef8d-e2f6-cc8f-1adaa90a914e.gif)



# 参考
Section5 

https://www.udemy.com/course/nextjs-react-the-complete-guide/learn/lecture/25145656#content