Convert middleware-matcher
example to TypeScript (#42520)
Converted example to TypeScript to match Contribution docs. - Set cookies using `NextResponse` instead of the `Set-Cookie` header ## Documentation / Examples - [X] Make sure the linting passes by running `pnpm build && pnpm lint` - [X] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
This commit is contained in:
parent
257835569c
commit
6290689281
7 changed files with 60 additions and 32 deletions
|
@ -2,9 +2,9 @@
|
|||
|
||||
This example shows how to configure your [Next.js Middleware](https://nextjs.org/docs/advanced-features/middleware) to only match specific pages.
|
||||
|
||||
The index page ([`pages/index.js`](pages/index.js)) has a list of links to dynamic pages, which will tell whether they were matched or not.
|
||||
The index page ([`pages/index.ts`](pages/index.ts)) has a list of links to dynamic pages, which will tell whether they were matched or not.
|
||||
|
||||
The Middleware file ([`middleware.js`](middleware.js)) has a special `matcher` configuration key, allowing you to fine-grained control [matched pages](https://nextjs.org/docs/advanced-features/middleware#matcher).
|
||||
The Middleware file ([`middleware.ts`](middleware.ts)) has a special `matcher` configuration key, allowing you to fine-grained control [matched pages](https://nextjs.org/docs/advanced-features/middleware#matcher).
|
||||
|
||||
Please keep in mind that:
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
import { NextResponse } from 'next/server'
|
||||
|
||||
export default function middleware(req) {
|
||||
const { pathname } = new URL(req.url)
|
||||
const response = NextResponse.next()
|
||||
response.headers.set(
|
||||
'set-cookie',
|
||||
`middleware-slug=${pathname.slice(1)}; Path=${pathname}`
|
||||
)
|
||||
return response
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
'/disclaimer', // match a single, specific page
|
||||
'/((?!public|static).*)', // match all paths not starting with 'public' or 'static'
|
||||
],
|
||||
}
|
24
examples/middleware-matcher/middleware.ts
Normal file
24
examples/middleware-matcher/middleware.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { NextResponse } from 'next/server'
|
||||
import type { NextRequest } from 'next/server'
|
||||
|
||||
export default function middleware(req: NextRequest) {
|
||||
const path = req.nextUrl.pathname
|
||||
const slug = path.slice(1)
|
||||
|
||||
// Set a cookie on the response using the `ResponseCookies` API
|
||||
const response = NextResponse.next()
|
||||
response.cookies.set({
|
||||
name: 'middleware-slug',
|
||||
value: slug,
|
||||
path,
|
||||
})
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
'/disclaimer', // match a single, specific page
|
||||
'/((?!public|static).*)', // match all paths not starting with 'public' or 'static'
|
||||
],
|
||||
}
|
|
@ -7,7 +7,13 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"next": "latest",
|
||||
"react": "latest",
|
||||
"react-dom": "latest"
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/react": "^18.0.25",
|
||||
"@types/react-dom": "^18.0.8",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useRouter } from 'next/router'
|
||||
|
||||
function hasMiddlewareMatched(slug) {
|
||||
function hasMiddlewareMatched(slug?: string[]) {
|
||||
const values =
|
||||
(typeof document !== 'undefined' ? document.cookie : '')
|
||||
.split(';')
|
||||
|
@ -10,10 +10,10 @@ function hasMiddlewareMatched(slug) {
|
|||
return values.some((value) => value === slug?.join('/'))
|
||||
}
|
||||
|
||||
export const ContentPage = (props) => {
|
||||
const {
|
||||
query: { slug }, // slug is an array of path segments
|
||||
} = useRouter()
|
||||
export default function ContentPage() {
|
||||
const router = useRouter()
|
||||
const slug = router.query.slug as string[] // slug is an array of path segments
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>
|
||||
|
@ -25,5 +25,3 @@ export const ContentPage = (props) => {
|
|||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default ContentPage
|
4
examples/middleware-matcher/pages/index.jsx → examples/middleware-matcher/pages/index.tsx
Executable file → Normal file
4
examples/middleware-matcher/pages/index.jsx → examples/middleware-matcher/pages/index.tsx
Executable file → Normal file
|
@ -1,4 +1,4 @@
|
|||
const Home = () => {
|
||||
export default function Home() {
|
||||
const matching = ['/about', '/about/topic/cats', '/public/disclaimer']
|
||||
const notMatching = ['/public', '/public/disclaimer/nested', '/static']
|
||||
return (
|
||||
|
@ -26,5 +26,3 @@ const Home = () => {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
20
examples/middleware-matcher/tsconfig.json
Normal file
20
examples/middleware-matcher/tsconfig.json
Normal file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
Loading…
Reference in a new issue