Skip to content

Commit

Permalink
feat: implement middleware module
Browse files Browse the repository at this point in the history
  • Loading branch information
arichard-info committed Aug 30, 2024
1 parent 68a90fd commit c355bb3
Show file tree
Hide file tree
Showing 20 changed files with 498 additions and 0 deletions.
3 changes: 3 additions & 0 deletions docs/markdown/07-middleware/00-title.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<!-- .slide: class="transition bg-pink" -->

# Lifecycles & Middleware
12 changes: 12 additions & 0 deletions docs/markdown/07-middleware/01-intro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!-- .slide: class="two-column with-code " -->

# http request lifecycle on Next.js

1. headers - next.config.js
2. redirects - next.config.js
3. middleware
4. rewrites | beforeFiles - next.config.js
5. routes (/public, /\_next/..., /app...)
6. rewrites | afterFiles - next.config.js
7. dynamic routes (/[slug]/page.tsx ...)
8. rewrites | fallback - next.config.js
9 changes: 9 additions & 0 deletions docs/markdown/07-middleware/10-next-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- .slide: class="two-column with-code " -->

# next.config.js

**next.config.js** can be used to affect the request on various things :

- headers
- rewrites
- redirects
81 changes: 81 additions & 0 deletions docs/markdown/07-middleware/11-headers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!-- .slide: class="two-column with-code " -->

# next.config.js

## headers

```js
module.exports = {
async headers() {
return [
{
source: '/employees',
headers: [
{
key: 'x-some-custom-header',
value: 'hello im a custom header value',
},
],
},
{
source: '/employees/:id(\\d{1,})', // will match /employees/123 (not /employees/abc)
headers: [
{
key: 'x-custom-regex-header',
value: 'header value based on regex',
},
],
},
];
},
};
```

##--##

Advanced matching :

```js
module.exports = {
async headers() {
return [
{
source: '/:path*', // match everything except home
has: [
{
type: 'header',
key: 'x-existing-header', // match based on existing header
},
],
headers: [
{
key: 'x-another-header',
value: 'hello',
},
],
},
{
source: '/employees',
has: [
{
type: 'query',
key: 'search',
value: 'some-value',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
headers: [
{
key: 'x-authorized',
value: ':authorized', // reference value of cookie
},
],
},
];
},
};
```
26 changes: 26 additions & 0 deletions docs/markdown/07-middleware/12-matching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!-- .slide: class="two-column with-code " -->

# next.config.js

## matching request

Regex based matching :

```js
module.exports = {
async headers() {
return [
// Regex based matching :
{
source: '/employees/:id(\\d{1,})', // will match /employees/123 (not /employees/abc)
headers: [
{
key: 'x-custom-regex-header',
value: 'header value based on regex',
},
],
},
];
},
};
```
63 changes: 63 additions & 0 deletions docs/markdown/07-middleware/13-matching-attribute.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<!-- .slide: class="two-column with-code " -->

# next.config.js

## matching request

Request attribute matching :

- **has** : check if request has a specified attribute / value
- **missing** : check if request is missing attribute / value

Has and missing objects can have the following fields :

- type : header |cookie | host | query
- key
- value

##--##

```js
module.exports = {
async headers() {
return [
{
source: '/:path*', // match everything except home
has: [
{
type: 'header',
key: 'x-existing-header', // match based on existing header
},
],
headers: [
{
key: 'x-another-header',
value: 'hello',
},
],
},
{
source: '/employees',
has: [
{
type: 'query',
key: 'search',
value: 'some-value',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
headers: [
{
key: 'x-authorized',
value: ':authorized', // reference value of cookie
},
],
},
];
},
};
```
22 changes: 22 additions & 0 deletions docs/markdown/07-middleware/14-redirects.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!-- .slide: class="two-column with-code " -->

# next.config.js

## redirects

```js
module.exports = {
async redirects() {
return [
{
source: '/about',
destination: '/',
permanent: true,
},
];
},
};
```

- permanent **true** : redirects with 308 status code indicating caches to store the redirect permenatly
- permanent **false** : redirects with 307 status code (temporary, not cached)
18 changes: 18 additions & 0 deletions docs/markdown/07-middleware/15-rewrite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!-- .slide: class="two-column with-code " -->

# next.config.js

## rewrites

```js
module.exports = {
async rewrites() {
return [
{
source: '/about',
destination: '/',
},
];
},
};
```
45 changes: 45 additions & 0 deletions docs/markdown/07-middleware/16-rewrite-advanced.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!-- .slide: class="two-column with-code " -->

# next.config.js

## rewrites

Detailed configuration :

1. headers - next.config.js
2. redirects - next.config.js
3. middleware
4. <strong>rewrites | beforeFiles - next.config.js</strong>
5. <strong>routes (/public, /\_next/..., /app...)</strong>
6. rewrites | afterFiles - next.config.js
7. dynamic routes (/[slug]/page.tsx ...)
8. <strong>rewrites | fallback - next.config.js</strong>

##--##

```js
module.exports = {
async rewrites() {
return {
beforeFiles: [
{
source: '/some-page',
destination: '/somewhere-else',
},
],
afterFiles: [
{
source: '/non-existent',
destination: '/somewhere-else',
},
],
fallback: [
{
source: '/:path*',
destination: `https://my-old-site.com/:path*`,
},
],
};
},
};
```
11 changes: 11 additions & 0 deletions docs/markdown/07-middleware/20-lab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- .slide: class="exercice" -->

# next.config.js lifecycles

## Lab

<small>

TODO

</small>
9 changes: 9 additions & 0 deletions docs/markdown/07-middleware/30-middleware.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- .slide: class="two-column with-code " -->

# middleware

Limits of next.config.js :

- build time
- limited conditional rules
- not possible to return early
28 changes: 28 additions & 0 deletions docs/markdown/07-middleware/31-definition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!-- .slide: class="two-column with-code " -->

# middleware

What is next.js middleware ? <br/>

allows to catch the incoming request and :

- modify the request / response :
- rewrite
- redirect
- modify request headers
- modify response headers
- return early
- produce and return an early response

##--##

Runs before caching content / route matching :

1. headers - next.config.js
2. redirects - next.config.js
3. **middleware**
4. rewrites | beforeFiles - next.config.js
5. routes (/public, /\_next/..., /app...)
6. rewrites | afterFiles - next.config.js
7. dynamic routes (/[slug]/page.tsx ...)
8. rewrites | fallback - next.config.js
9 changes: 9 additions & 0 deletions docs/markdown/07-middleware/32-use-cases.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- .slide: class="two-column with-code " -->

# middleware

- Authentication
- Localization (ex : redirect user to the right locale)
- Bot detection
- Complex URL rewriting
- Logging / Analytics
14 changes: 14 additions & 0 deletions docs/markdown/07-middleware/33-convention.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!-- .slide: class="two-column with-code " -->

# middleware

## conventions

Create a **/middleware.ts|js** file in the root directory <br/>
export a **middleware** function :

```js
export const middleware = (request) => {
// Some server operations on the request
};
```
28 changes: 28 additions & 0 deletions docs/markdown/07-middleware/34-url-matching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!-- .slide: class="two-column with-code " -->

# request matching

There are two ways to filter the requests : <br/>
Exporting the **matcher** configuration :

```js
export const config = {
matcher: ['/employee/:path*', '/expenses/:path*'],
};
```

##--##

Conditional statements :

```js
export function middleware(request) {
if (request.nextUrl.pathname.startsWith('/employee')) {
// do something
}

if (request.nextUrl.pathname.startsWith('/expenses')) {
// do something
}
}
```
Loading

0 comments on commit c355bb3

Please sign in to comment.