Skip to content

Commit

Permalink
Merge branch 'canary' into i18n/api-rewrite
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] authored Jan 6, 2021
2 parents 2bbb162 + 1a3adaa commit db37015
Show file tree
Hide file tree
Showing 93 changed files with 1,767 additions and 158 deletions.
19 changes: 15 additions & 4 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ trigger:
include:
- '*'
exclude:
- bench/*
- docs/*
- errors/*
- examples/*
- bench
- docs
- errors
- examples
# Do not run Azure on `canary`, `master`, or release tags. This unnecessarily
# increases the backlog, and the change was already tested on the PR.
branches:
Expand All @@ -20,6 +20,17 @@ trigger:
- master
- refs/tags/*

pr:
# Do not run Azure CI for docs-only/example-only changes:
paths:
include:
- '*'
exclude:
- bench
- docs
- errors
- examples

variables:
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn
NEXT_TELEMETRY_DISABLED: '1'
Expand Down
50 changes: 50 additions & 0 deletions docs/api-reference/next.config.js/rewrites.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,56 @@ module.exports = {
- `source` is the incoming request path pattern.
- `destination` is the path you want to route to.

## Rewrite parameters

When using parameters in a rewrite the parameters will be passed in the query by default when none of the parameters are used in the `destination`.

```js
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // The :path parameter isn't used here so will be automatically passed in the query
},
]
},
}
```

If a parameter is used in the destination none of the parameters will be automatically passed in the query.

```js
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // The :path parameter is used here so will not be automatically passed in the query
},
]
},
}
```

You can still pass the parameters manually in the query if one is already used in the destination by specifying the query in the `destination`.

```js
module.exports = {
async rewrites() {
return [
{
source: '/:first/:second',
destination: '/:first?second=:second',
// Since the :first parameter is used in the destination the :second parameter
// will not automatically be added in the query although we can manually add it
// as shown above
},
]
},
}
```

## Path Matching

Path matches are allowed, for example `/blog/:slug` will match `/blog/hello-world` (no nested paths):
Expand Down
21 changes: 21 additions & 0 deletions docs/api-reference/next.config.js/static-optimization-indicator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
description: Optimized pages include an indicator to let you know if it's being statically optimized. You can opt-out of it here.
---

# Static Optimization Indicator

> **Note:** This indicator was removed in Next.js version 10.0.1. We recommend upgrading to the latest version of Next.js.
When a page qualifies for [Automatic Static Optimization](/docs/advanced-features/automatic-static-optimization.md) we show an indicator to let you know.

This is helpful since automatic static optimization can be very beneficial and knowing immediately in development if the page qualifies can be useful.

In some cases this indicator might not be useful, like when working on electron applications. To remove it open `next.config.js` and disable the `autoPrerender` config in `devIndicators`:

```js
module.exports = {
devIndicators: {
autoPrerender: false,
},
}
```
31 changes: 31 additions & 0 deletions docs/api-reference/next/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ description: Enable Image Optimization with the built-in Image component.

| Version | Changes |
| --------- | ------------------------ |
| `v10.0.5` | `loader` prop added. |
| `v10.0.1` | `layout` prop added. |
| `v10.0.0` | `next/image` introduced. |

Expand Down Expand Up @@ -111,6 +112,36 @@ Try it out:
- [Demo the `fill` layout](https://image-component.nextjs.gallery/layout-fill)
- [Demo background image](https://image-component.nextjs.gallery/background)

### loader

A custom function used to resolve URLs. Defaults to [`images` object in `next.config.js`](/docs/basic-features/image-optimization.md#loader).

`loader` is a function returning a string, given the following parameters:

- [`src`](#src)
- [`width`](#width)
- [`quality`](#quality)

```js
import Image from 'next/image'

const myLoader = ({ src, width, quality }) => {
return `https://example.com/${src}?w=${width}&q=${quality || 75}`
}

const MyImage = (props) => {
return (
<Image
loader={myLoader}
src="/me.png"
alt="Picture of the author"
width={500}
height={500}
/>
)
}
```

### sizes

A string mapping media queries to device sizes. Defaults to `100vw`.
Expand Down
2 changes: 1 addition & 1 deletion docs/basic-features/data-fetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ The `context` parameter is an object containing the following keys:
- `params`: If this page uses a dynamic route, `params` contains the route parameters. If the page name is `[id].js` , then `params` will look like `{ id: ... }`. To learn more, take a look at the [Dynamic Routing documentation](/docs/routing/dynamic-routes.md).
- `req`: [The HTTP IncomingMessage object](https://nodejs.org/api/http.html#http_class_http_incomingmessage).
- `res`: [The HTTP response object](https://nodejs.org/api/http.html#http_class_http_serverresponse).
- `query`: The query string.
- `query`: An object representing the query string.
- `preview`: `preview` is `true` if the page is in the preview mode and `false` otherwise. See the [Preview Mode documentation](/docs/advanced-features/preview-mode.md).
- `previewData`: The preview data set by `setPreviewData`. See the [Preview Mode documentation](/docs/advanced-features/preview-mode.md).
- `resolvedUrl`: A normalized version of the request URL that strips the `_next/data` prefix for client transitions and includes original query values.
Expand Down
4 changes: 3 additions & 1 deletion docs/basic-features/image-optimization.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,16 @@ module.exports = {
}
```

The following Image Optimization cloud providers are supported:
The following Image Optimization cloud providers are included:

- [Vercel](https://vercel.com): Works automatically when you deploy on Vercel, no configuration necessary. [Learn more](https://vercel.com/docs/next.js/image-optimization)
- [Imgix](https://www.imgix.com): `loader: 'imgix'`
- [Cloudinary](https://cloudinary.com): `loader: 'cloudinary'`
- [Akamai](https://www.akamai.com): `loader: 'akamai'`
- Default: Works automatically with `next dev`, `next start`, or a custom server

If you need a different provider, you can use the [`loader`](/docs/api-reference/next/image.md#loader) prop with `next/image`.

## Caching

The following describes the caching algorithm for the default [loader](#loader). For all other loaders, please refer to your cloud provider's documentation.
Expand Down
34 changes: 34 additions & 0 deletions examples/api-routes-rate-limit/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel
35 changes: 35 additions & 0 deletions examples/api-routes-rate-limit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# API Routes Rate Limiting Example

This example uses `lru-cache` to implement a simple rate limiter for API routes ([Serverless Functions](https://vercel.com/docs/serverless-functions/introduction)).

**Demo: https://nextjs-rate-limit.vercel.app/**

```bash
curl http://localhost:3000/api/user -I
HTTP/1.1 200 OK
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 9

curl http://localhost:3000/api/user -I
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
```

## Deploy your own

Deploy the example using [Vercel](https://vercel.com):

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/vercel/next.js/tree/canary/examples/api-routes-rate-limit)

## How to use

Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:

```bash
npx create-next-app --example api-routes api-routes-rate-limit
# or
yarn create next-app --example api-routes api-routes-rate-limit
```

Deploy it to the cloud with [Vercel](https://vercel.com/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
17 changes: 17 additions & 0 deletions examples/api-routes-rate-limit/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "nextjs-rate-limit",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"lru-cache": "^6.0.0",
"next": "10.0.3",
"react": "17.0.1",
"react-dom": "17.0.1",
"uuid": "^8.3.1"
}
}
16 changes: 16 additions & 0 deletions examples/api-routes-rate-limit/pages/api/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as uuid from 'uuid'
import rateLimit from '../../utils/rate-limit'

const limiter = rateLimit({
interval: 60 * 1000, // 60 seconds
uniqueTokenPerInterval: 500, // Max 500 users per second
})

export default async function handler(req, res) {
try {
await limiter.check(res, 10, 'CACHE_TOKEN') // 10 requests per minute
res.status(200).json({ id: uuid.v4() })
} catch {
res.status(429).json({ error: 'Rate limit exceeded' })
}
}
52 changes: 52 additions & 0 deletions examples/api-routes-rate-limit/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useState } from 'react'
import styles from '../styles.module.css'

export default function Index() {
const [response, setResponse] = useState()

const makeRequest = async () => {
const res = await fetch('/api/user')

setResponse({
status: res.status,
body: await res.json(),
limit: res.headers.get('X-RateLimit-Limit'),
remaining: res.headers.get('X-RateLimit-Remaining'),
})
}

return (
<main className={styles.container}>
<h1>Next.js API Routes Rate Limiting</h1>
<p>
This example uses <code className={styles.inlineCode}>lru-cache</code>{' '}
to implement a simple rate limiter for API routes (Serverless
Functions).
</p>
<button onClick={() => makeRequest()}>Make Request</button>
<code className={styles.code}>
<div>
<b>Status Code: </b>
{response?.status || 'None'}
</div>
<div>
<b>Request Limit: </b>
{response?.limit || 'None'}
</div>
<div>
<b>Remaining Requests: </b>
{response?.remaining || 'None'}
</div>
<div>
<b>Body: </b>
{JSON.stringify(response?.body) || 'None'}
</div>
</code>
<div className={styles.links}>
<a href="#">View Source</a>
{' | '}
<a href="#">Deploy You Own ▲</a>
</div>
</main>
)
}
Loading

0 comments on commit db37015

Please sign in to comment.