Skip to content

Commit 4cecdb8

Browse files
committed
update 04-static-site-generation
1 parent 70abb5e commit 4cecdb8

28 files changed

Lines changed: 103 additions & 131 deletions

04-frameworks/08-nextjs/03-boilerplate/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
},
99
"scripts": {
1010
"start": "next dev",
11-
"build": "next build",
11+
"build": "rimraf .next && next build",
1212
"start:prod": "next start -p 8080",
1313
"start:api-server": "cd api-server && npm run mock-server",
1414
"postinstall": "cd ./api-server && npm install"
@@ -27,6 +27,7 @@
2727
"@types/react": "^19.2.7",
2828
"@types/react-dom": "^19.2.3",
2929
"npm-run-all": "^4.1.5",
30+
"rimraf": "^6.1.2",
3031
"typescript": "^5.9.3"
3132
}
3233
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export const envConstants = {
1+
export const ENV = {
22
BASE_API_URL: process.env.BASE_API_URL,
33
BASE_PICTURES_URL: process.env.BASE_PICTURES_URL,
44
};

04-frameworks/08-nextjs/03-boilerplate/src/pods/car-list/api/car-list.api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { envConstants } from '#core/constants';
1+
import { ENV } from '#core/constants';
22
import { Car } from './car-list.api-model';
33

4-
const url = `${envConstants.BASE_API_URL}/cars`;
4+
const url = `${ENV.BASE_API_URL}/cars`;
55

66
export const getCarList = async (): Promise<Car[]> => {
77
return await fetch(url).then((response) => response.json());

04-frameworks/08-nextjs/03-boilerplate/src/pods/car-list/car-list.mappers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { mapToCollection } from '#common/mappers';
2-
import { envConstants } from '#core/constants';
2+
import { ENV } from '#core/constants';
33
import * as apiModel from './api';
44
import * as viewModel from './car-list.vm';
55

@@ -10,6 +10,6 @@ export const mapCarListFromApiToVm = (
1010
const mapCarFromApiToVm = (car: apiModel.Car): viewModel.Car => ({
1111
id: car.id,
1212
name: car.name,
13-
imageUrl: `${envConstants.BASE_PICTURES_URL}${car.imageUrl}`,
13+
imageUrl: `${ENV.BASE_PICTURES_URL}${car.imageUrl}`,
1414
isBooked: car.isBooked,
1515
});

04-frameworks/08-nextjs/03-boilerplate/src/pods/car-list/components/car-item.component.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import React from 'react';
2-
import Link from 'next/link';
31
import { routeConstants } from '#core/constants';
2+
import Link from 'next/link';
3+
import React from 'react';
44
import { Car } from '../car-list.vm';
55
import classes from './car-item.module.css';
66

@@ -25,7 +25,7 @@ export const CarItem: React.FC<Props> = (props) => {
2525
)}
2626
<span>{car.name}</span>
2727
</h2>
28-
<img src={car.imageUrl} alt={car.name} />
28+
<img className={classes.image} src={car.imageUrl} alt={car.name} />
2929
</Link>
3030
);
3131
};

04-frameworks/08-nextjs/03-boilerplate/src/pods/car-list/components/car-item.module.css

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
.root {
2-
box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2),
3-
0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
42
text-decoration: none;
53
}
64

@@ -15,3 +13,8 @@
1513
letter-spacing: 0.01071em;
1614
color: black;
1715
}
16+
17+
.image {
18+
box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2),
19+
0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12);
20+
}

04-frameworks/08-nextjs/03-boilerplate/src/pods/car/api/car.api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { envConstants } from '#core/constants';
1+
import { ENV } from '#core/constants';
22
import { Car } from './car.api-model';
33

4-
const url = `${envConstants.BASE_API_URL}/cars`;
4+
const url = `${ENV.BASE_API_URL}/cars`;
55

66
export const getCar = async (id: string): Promise<Car> => {
77
return await fetch(`${url}/${id}`).then((response) => response.json());
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { envConstants } from '#core/constants';
1+
import { ENV } from '#core/constants';
22
import * as apiModel from './api';
33
import * as viewModel from './car.vm';
44

@@ -7,7 +7,7 @@ export const mapCarFromApiToVm = (car: apiModel.Car): viewModel.Car =>
77
? {
88
id: car.id,
99
name: car.name,
10-
imageUrl: `${envConstants.BASE_PICTURES_URL}${car.imageUrl}`,
10+
imageUrl: `${ENV.BASE_PICTURES_URL}${car.imageUrl}`,
1111
features: car.features,
1212
isBooked: car.isBooked,
1313
}
@@ -16,7 +16,7 @@ export const mapCarFromApiToVm = (car: apiModel.Car): viewModel.Car =>
1616
export const mapCarFromVmToApi = (car: viewModel.Car): apiModel.Car => ({
1717
id: car.id,
1818
name: car.name,
19-
imageUrl: car.imageUrl.split(envConstants.BASE_PICTURES_URL)[1],
19+
imageUrl: car.imageUrl.split(ENV.BASE_PICTURES_URL)[1],
2020
features: car.features,
2121
isBooked: car.isBooked,
2222
});

04-frameworks/08-nextjs/03-boilerplate/tsconfig.json

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
{
22
"compilerOptions": {
33
"target": "ES2017",
4-
"lib": [
5-
"dom",
6-
"dom.iterable",
7-
"esnext"
8-
],
4+
"lib": ["dom", "dom.iterable", "esnext"],
95
"allowJs": true,
106
"skipLibCheck": true,
117
"strict": false,
@@ -21,7 +17,11 @@
2117
{
2218
"name": "next"
2319
}
24-
]
20+
],
21+
"baseUrl": ".",
22+
"paths": {
23+
"#*": ["./src/*"]
24+
}
2525
},
2626
"include": [
2727
"next-env.d.ts",
@@ -31,7 +31,5 @@
3131
"**/*.ts",
3232
"**/*.tsx"
3333
],
34-
"exclude": [
35-
"node_modules"
36-
]
34+
"exclude": ["node_modules"]
3735
}

04-frameworks/08-nextjs/04-static-site-generation/README.md

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Pages are generated at build time, it means that it will fetch all necessary dat
2929
- Recommended whenever possible because it's much faster than having server render the page on every request.
3030
- The build time will be larger than SSR mode.
3131
- Only available on `Server Components`.
32-
- [More about static data fetching](https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic-rendering#static-data-fetching-default)
32+
- [More about SSG](https://nextjs.org/docs/app/api-reference/file-conventions/route#static-generation-with-generatestaticparams)
3333

3434
We will fetch data from an API (`api-server`), so let's start this server on `start` command:
3535

@@ -137,43 +137,6 @@ import classes from './layout.module.css';
137137

138138
```
139139

140-
Fix the `car details` page:
141-
142-
_./src/app/cars/\[carId\]/page.tsx_
143-
144-
```diff
145-
import React from 'react';
146-
import { Metadata } from 'next';
147-
148-
interface Props {
149-
- params: { carId: string };
150-
+ params: Promise<{ carId: string }>;
151-
}
152-
153-
export const generateMetadata = async (props: Props): Promise<Metadata> => {
154-
- const { params } = props;
155-
+ const params = await props.params;
156-
return {
157-
title: `Rent a car - Car ${params.carId} details`,
158-
};
159-
};
160-
161-
- const CarPage = (props: Props) => {
162-
+ const CarPage = async (props: Props) => {
163-
- const { params } = props;
164-
+ const params = await props.params;
165-
return (
166-
<>
167-
<h2>Car detail page</h2>
168-
<p>{params.carId}</p>
169-
</>
170-
);
171-
};
172-
173-
export default CarPage;
174-
175-
```
176-
177140
Run in `prod` mode (two terminals):
178141

179142
```bash
@@ -362,7 +325,7 @@ export const generateMetadata = async (props: Props): Promise<Metadata> => {
362325

363326
> It will fetch the car details data only once.
364327
>
365-
> [Automatic fetch request deduping](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching#reusing-data-across-multiple-functions)
328+
> [Automatic fetch request deduping](https://nextjs.org/docs/app/getting-started/fetching-data#deduplicate-requests-and-cache-data)
366329
367330
Run again:
368331

@@ -372,7 +335,7 @@ npm run build
372335
npm run start:prod
373336
```
374337

375-
What's if `api-server` has new data, let's use [Incremental Static Regeneration or Revalidating Data](https://nextjs.org/docs/app/building-your-application/data-fetching/revalidating):
338+
What's if `api-server` has new data, let's use [Incremental Static Regeneration or Revalidating Data](https://nextjs.org/docs/app/guides/incremental-static-regeneration):
376339

377340
_./src/pods/car-list/api/car-list.api.ts_
378341

@@ -414,7 +377,7 @@ export default CarListPage;
414377

415378
```
416379

417-
> It also have other [on-demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration#time-based-revalidation) options
380+
> It also have other [on-demand revalidation](https://nextjs.org/docs/app/building-your-application/data-fetching/incremental-static-regeneration#time-based-revalidation) options
418381
419382
Run again:
420383

@@ -471,11 +434,14 @@ BASE_PICTURES_URL=http://localhost:3001
471434

472435
```
473436

474-
_./next.config.js_
437+
_./next.config.ts_
475438

476439
```javascript
477-
module.exports = {
440+
import type { NextConfig } from 'next';
441+
442+
const nextConfig: NextConfig = {
478443
images: {
444+
dangerouslyAllowLocalIP: true, // only for local development
479445
remotePatterns: [
480446
{
481447
hostname: process.env.IMAGES_DOMAIN,
@@ -484,6 +450,7 @@ module.exports = {
484450
},
485451
};
486452

453+
export default nextConfig;
487454
```
488455

489456
> [Remote Images](https://nextjs.org/docs/app/building-your-application/optimizing/images#remote-images)

0 commit comments

Comments
 (0)