Compare commits
141 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4068b4493e | ||
|
|
0448535ef0 | ||
|
|
0df6aef3a3 | ||
|
|
5ba2989592 | ||
|
|
9240d86ed6 | ||
|
|
27e0dacdaf | ||
|
|
8dc1cd3ca8 | ||
|
|
413bc01676 | ||
|
|
7c025e9bd7 | ||
|
|
24e51c7ae5 | ||
|
|
b2f84f1224 | ||
|
|
8df18f24ad | ||
|
|
d480d84e46 | ||
|
|
f0a9fbeb14 | ||
|
|
fe8179b595 | ||
|
|
6eaed7a3b2 | ||
|
|
69e97017b1 | ||
|
|
1aa2d79ef4 | ||
|
|
194a3720ce | ||
|
|
e21b22d672 | ||
|
|
b634fe9587 | ||
|
|
9b35fcd018 | ||
|
|
d16ed02a50 | ||
|
|
bdec5cffbf | ||
|
|
be430e093d | ||
|
|
3deb0045f4 | ||
|
|
c19e71624e | ||
|
|
b6fcba1c01 | ||
|
|
dbdb6a4199 | ||
|
|
c151b3571e | ||
|
|
6198025ce5 | ||
|
|
c9dba04f56 | ||
|
|
a2c6c9ce23 | ||
|
|
b09c188113 | ||
|
|
cdd71af1cf | ||
|
|
54647d0054 | ||
|
|
1e39604ae1 | ||
|
|
2f890b72ca | ||
|
|
2a9125def5 | ||
|
|
2111ca6fae | ||
|
|
a640b1112f | ||
|
|
0243df5b6a | ||
|
|
4256f48fa6 | ||
|
|
1c256c9c11 | ||
|
|
e392a37985 | ||
|
|
e2b6dd2779 | ||
|
|
e4e3e757bc | ||
|
|
18438fb45c | ||
|
|
b80cf675b6 | ||
|
|
4db0f32156 | ||
|
|
a63e234ca4 | ||
|
|
5f2bf3ae55 | ||
|
|
da39eca564 | ||
|
|
9fc358b0df | ||
|
|
6e7111397f | ||
|
|
fc66d61f0c | ||
|
|
026d3d84a1 | ||
|
|
bd43af1ba5 | ||
|
|
86be2c122e | ||
|
|
e2a54b5904 | ||
|
|
2c3afcf407 | ||
|
|
f478f83e9d | ||
|
|
4e9968a2db | ||
|
|
5d0998ab84 | ||
|
|
b3f1598212 | ||
|
|
503ec19c66 | ||
|
|
f20d7cf8ec | ||
|
|
81118cd6a0 | ||
|
|
768562945e | ||
|
|
cac31cd1e6 | ||
|
|
3138fc5f6e | ||
|
|
2fa862ebf8 | ||
|
|
218bc15bd3 | ||
|
|
be9f70850c | ||
|
|
ef6a6dbcc7 | ||
|
|
afa6792b66 | ||
|
|
7d5f437c7b | ||
|
|
a81f4518ae | ||
|
|
1407ddd7ad | ||
|
|
a510bd079b | ||
|
|
ff85cf1c17 | ||
|
|
1ef378bff0 | ||
|
|
22a845e13a | ||
|
|
8eb1509b9a | ||
|
|
c46decbbe7 | ||
|
|
577206a404 | ||
|
|
8b245bef9a | ||
|
|
f2d41eff35 | ||
|
|
f8ce548f4a | ||
|
|
d8aeb6b18f | ||
|
|
f1de531124 | ||
|
|
9c54361cd6 | ||
|
|
ee939ac7b8 | ||
|
|
3cf7d399cd | ||
|
|
e4b788321b | ||
|
|
59272f7334 | ||
|
|
3416e097d8 | ||
|
|
49e7abbdfe | ||
|
|
a00f162bca | ||
|
|
31498e2d46 | ||
|
|
6b463fcdd1 | ||
|
|
e1785f97a9 | ||
|
|
d4dc932bc3 | ||
|
|
750ba2e429 | ||
|
|
a4e4cb2f64 | ||
|
|
c5b461c641 | ||
|
|
174bf32c84 | ||
|
|
cb432b6276 | ||
|
|
1ff0f00715 | ||
|
|
a3cf482e8f | ||
|
|
684b3f34c8 | ||
|
|
f547f311f7 | ||
|
|
e7dc1b8352 | ||
|
|
8fb8608e49 | ||
|
|
63e200e173 | ||
|
|
53bb153df8 | ||
|
|
3727385cd6 | ||
|
|
1de36fd8dd | ||
|
|
5e2dafe519 | ||
|
|
8f08f38d80 | ||
|
|
61b8c95be8 | ||
|
|
a429013360 | ||
|
|
01c609be9e | ||
|
|
7e333955aa | ||
|
|
0bfa5fdb7a | ||
|
|
27336d423a | ||
|
|
fa82ac913f | ||
|
|
65405b6f43 | ||
|
|
ada67b5aed | ||
|
|
3dcc885186 | ||
|
|
0ce552c90e | ||
|
|
ec3930ca46 | ||
|
|
e3a5420cea | ||
|
|
4156368b75 | ||
|
|
632df97342 | ||
|
|
eae332b0c7 | ||
|
|
7fdd07e598 | ||
|
|
a328b6c19c | ||
|
|
7e22f61079 | ||
|
|
719d867eea | ||
|
|
3501f29521 |
@@ -357,7 +357,8 @@
|
||||
"contributions": [
|
||||
"test",
|
||||
"code",
|
||||
"review"
|
||||
"review",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2374,7 +2375,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1357323?v=4",
|
||||
"profile": "http://twitter.com/_markeh",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2410,7 +2412,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1384885?v=4",
|
||||
"profile": "www.usertrack.net",
|
||||
"contributions": [
|
||||
"doc"
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2637,7 +2640,9 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3389914?v=4",
|
||||
"profile": "minaabadir.ca",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2646,7 +2651,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1476561?v=4",
|
||||
"profile": "https://github.com/frankiesardo",
|
||||
"contributions": [
|
||||
"doc"
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2693,6 +2699,177 @@
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "guoqqqi",
|
||||
"name": "guoqqqi",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/72343596?v=4",
|
||||
"profile": "https://github.com/guoqqqi",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "timbooker",
|
||||
"name": "Tim",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/612681?v=4",
|
||||
"profile": "https://github.com/timbooker",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ormarek",
|
||||
"name": "Marek Orłowski",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/16357457?v=4",
|
||||
"profile": "http://orlowski.me/",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "AntoineGuestin",
|
||||
"name": "Antoine G",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/70888750?v=4",
|
||||
"profile": "https://github.com/AntoineGuestin",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "swinner2",
|
||||
"name": "Sean Winner",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6707308?v=4",
|
||||
"profile": "https://github.com/swinner2",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "max-programming",
|
||||
"name": "Max Programming",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/51731966?v=4",
|
||||
"profile": "https://usman-s.me",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sebastianhoitz",
|
||||
"name": "Sebastian Hoitz",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/353768?v=4",
|
||||
"profile": "https://makemake.sh",
|
||||
"contributions": [
|
||||
"test",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "garnerp",
|
||||
"name": "garnerp",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/737307?v=4",
|
||||
"profile": "https://github.com/garnerp",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kivi",
|
||||
"name": "kivi",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/366163?v=4",
|
||||
"profile": "https://github.com/kivi",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dangreaves",
|
||||
"name": "Dan Greaves",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1036142?v=4",
|
||||
"profile": "http://dangreaves.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lksnmnn",
|
||||
"name": "Lukas Neumann",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/4983285?v=4",
|
||||
"profile": "lksnmnn.com",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dbachrach",
|
||||
"name": "Dustin Bachrach",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/45016?v=4",
|
||||
"profile": "dbachrach.com",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ashikka",
|
||||
"name": "Ashikka Gupta",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/58368421?v=4",
|
||||
"profile": "https://github.com/ashikka",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "deini",
|
||||
"name": "Daniel Almaguer",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2752665?v=4",
|
||||
"profile": "https://github.com/deini",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "igeligel",
|
||||
"name": "Kevin Peters",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/12736734?v=4",
|
||||
"profile": "https://www.kevinpeters.net/about/",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "prisis",
|
||||
"name": "Daniel Bannert",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2716058?v=4",
|
||||
"profile": "http://anolilab.de",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "benjakugler96",
|
||||
"name": "Benja Kugler",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/53273645?v=4",
|
||||
"profile": "https://benjakugler96.github.io/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "esemeniuc",
|
||||
"name": "Eric Semeniuc",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3838856?v=4",
|
||||
"profile": "https://semeniuc.ml/",
|
||||
"contributions": [
|
||||
"test",
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@@ -27,14 +27,16 @@ eslint.config.*
|
||||
/recipes/*/templates
|
||||
/packages/generator/templates
|
||||
/packages/cli/lib
|
||||
/packages/babel-preset/src/fix-node-file-trace/tests/**
|
||||
/test/integration/**/out/**
|
||||
/nextjs/packages/create-next-app
|
||||
|
||||
|
||||
// COPIED FROM nextjs/.eslintignore
|
||||
/nextjs/**/.next/**
|
||||
/nextjs/**/_next/**
|
||||
/nextjs/**/dist/**
|
||||
/nextjs/examples/with-typescript-eslint-jest/**
|
||||
/nextjs/examples/with-kea/**
|
||||
/nextjs/examples/**
|
||||
/nextjs/packages/next/bundles/webpack/packages/*.runtime.js
|
||||
/nextjs/packages/next/compiled/**/*
|
||||
/nextjs/packages/react-refresh-utils/**/*.js
|
||||
@@ -47,4 +49,5 @@ eslint.config.*
|
||||
/nextjs/packages/next-codemod/**/*.d.ts
|
||||
/nextjs/packages/next-env/**/*.d.ts
|
||||
/nextjs/test/integration/async-modules/**
|
||||
/nextjs/test/integration/eslint/**
|
||||
/nextjs/test-timings.json
|
||||
|
||||
13
.eslintrc.js
13
.eslintrc.js
@@ -80,6 +80,19 @@ module.exports = {
|
||||
"@typescript-eslint/no-floating-promises": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["examples/**"],
|
||||
plugins: ["cypress"],
|
||||
parserOptions: {
|
||||
project: null,
|
||||
},
|
||||
env: {
|
||||
"cypress/globals": true,
|
||||
},
|
||||
rules: {
|
||||
"simple-import-sort/imports": "off",
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ["packages/cli/src/commands/**/*"],
|
||||
rules: {
|
||||
|
||||
6
.github/workflows/compressed.yml
vendored
6
.github/workflows/compressed.yml
vendored
@@ -1,9 +1,13 @@
|
||||
name: CI
|
||||
name: Size Check
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, canary]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Compressed Size
|
||||
|
||||
122
.github/workflows/main.yml
vendored
122
.github/workflows/main.yml
vendored
@@ -3,11 +3,13 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [canary]
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
@@ -28,9 +30,9 @@ jobs:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v8-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v8-
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
env:
|
||||
@@ -39,6 +41,10 @@ jobs:
|
||||
run: yarn manypkg check
|
||||
env:
|
||||
CI: true
|
||||
- name: Build next.js
|
||||
run: yarn build:nextjs
|
||||
env:
|
||||
CI: true
|
||||
- name: yarn lint
|
||||
run: yarn lint
|
||||
env:
|
||||
@@ -70,9 +76,9 @@ jobs:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v8-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v8-
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
- name: Build Packages
|
||||
run: yarn build
|
||||
@@ -138,9 +144,9 @@ jobs:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v8-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v8-
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
# - run: yarn cpy node_modules/.blitz packages/core/node_modules/.blitz
|
||||
# if: matrix.os == 'windows-latest'
|
||||
@@ -239,7 +245,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
group: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
group: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
|
||||
steps:
|
||||
- run: echo ${{needs.build.outputs.docsChange}}
|
||||
working-directory: ./
|
||||
@@ -254,7 +260,7 @@ jobs:
|
||||
- run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
|
||||
- run: xvfb-run node run-tests.js --timings -g ${{ matrix.group }}/10 -c 3
|
||||
- run: xvfb-run node run-tests.js --timings -g ${{ matrix.group }}/20 -c 3
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
|
||||
testElectron:
|
||||
@@ -302,94 +308,6 @@ jobs:
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
testFutureDependencies:
|
||||
name: Nextjs - Webpack 5 (Basic, Production, Acceptance)
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
NEXT_PRIVATE_TEST_WEBPACK5_MODE: 1
|
||||
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
|
||||
- run: xvfb-run node run-tests.js test/integration/{fallback-modules,link-ref,production,basic,async-modules,font-optimization,ssr-ctx}/test/index.test.js test/acceptance/*.test.js
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
working-directory: nextjs
|
||||
|
||||
testLegacyReact:
|
||||
name: Nextjs - React 16 + Webpack 4 (Basic, Production, Acceptance)
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 25
|
||||
|
||||
- run: echo ::set-output name=DOCS_CHANGE::$(node skip-docs-change.js echo 'not-docs-only-change')
|
||||
id: docs-change
|
||||
|
||||
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: cat package.json | jq '.resolutions.react = "^16.14.0"' > package.json.tmp && mv package.json.tmp package.json
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: cat package.json | jq '.resolutions."react-dom" = "^16.14.0"' > package.json.tmp && mv package.json.tmp package.json
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- name: Use Node.js
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
- name: Get yarn cache directory path
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: Cache node_modules
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
id: yarn-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
C:\Users\runneradmin\AppData\Local\Cypress\Cache
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v8-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v8-
|
||||
|
||||
- run: yarn install --check-files
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: yarn list react react-dom
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: yarn build:nextjs
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: xvfb-run node run-tests.js test/integration/{link-ref,production,basic,async-modules,font-optimization,ssr-ctx,worker-loader}/test/index.test.js test/acceptance/*.test.js
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
working-directory: nextjs
|
||||
|
||||
testFirefox:
|
||||
name: Nextjs - Test Firefox (production)
|
||||
defaults:
|
||||
@@ -399,7 +317,7 @@ jobs:
|
||||
needs: build
|
||||
env:
|
||||
HEADLESS: true
|
||||
BROWSERNAME: "firefox"
|
||||
BROWSER_NAME: "firefox"
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
@@ -408,7 +326,7 @@ jobs:
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
- run: node run-tests.js test/integration/production/test/index.test.js
|
||||
- run: node run-tests.js -c 1 test/integration/production/test/index.test.js
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
|
||||
testSafari:
|
||||
@@ -420,7 +338,7 @@ jobs:
|
||||
needs: build
|
||||
env:
|
||||
BROWSERSTACK: true
|
||||
BROWSERNAME: "safari"
|
||||
BROWSER_NAME: "safari"
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
SKIP_LOCAL_SELENIUM_SERVER: true
|
||||
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
|
||||
@@ -432,7 +350,7 @@ jobs:
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
- run: '[[ -z "$BROWSERSTACK_ACCESS_KEY" ]] && echo "Skipping for PR" || node run-tests.js test/integration/production/test/index.test.js'
|
||||
- run: '[[ -z "$BROWSERSTACK_ACCESS_KEY" ]] && echo "Skipping for PR" || node run-tests.js -c 1 test/integration/production/test/index.test.js'
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
|
||||
testSafariOld:
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -29,3 +29,5 @@ examples/auth2
|
||||
.ultra.cache.json
|
||||
db.sqlite-journal
|
||||
test/integration/**/db.json
|
||||
test/**/*/out
|
||||
.blitz**
|
||||
|
||||
@@ -20,3 +20,6 @@ bin
|
||||
packages/generator/templates/**
|
||||
.github/ISSUE_TEMPLATE/bug_report.md
|
||||
nextjs/packages/next/compiled/**
|
||||
|
||||
// Because file from nextjs upstream isn't formatted properly
|
||||
nextjs/packages/next/build/webpack-config.ts
|
||||
|
||||
@@ -7,20 +7,29 @@
|
||||
### Syncing Next.js Fork
|
||||
|
||||
1. Run `yarn push-nextjs`
|
||||
- If it fails with an error of `git-subrepo: Can't commit: 'subrepo/nextjs' doesn't contain upstream HEAD:`, then run `yarn push-nextjs --force` (see https://github.com/ingydotnet/git-subrepo/issues/530)
|
||||
2. Create new git branch for the upgrade
|
||||
3. In the forked repo (https://github.com/blitz-js/next.js), run:
|
||||
1. `git pull`
|
||||
2. `git fetch --all`
|
||||
3. `git merge v10.2.0` (change the version to be the version you are updating to)
|
||||
4. Resolve all merge conflicts and complete merge
|
||||
5. `git push`
|
||||
4. Run `rm -rf examples && git add examples`
|
||||
5. To resolve conflict with their version for a path, like docs, run this:
|
||||
- `git checkout --theirs docs && git add docs`
|
||||
6. Resolve all merge conflicts and complete merge
|
||||
7. Run `yarn` and make sure all builds complete
|
||||
8. Run `yarn lint` and fix any issues
|
||||
9. `git push`
|
||||
4. Run `yarn pull next-nextjs`
|
||||
- If it fails, run `git subrepo clean nextjs` and try again
|
||||
5. Run `yarn`
|
||||
6. Run `yarn manypkg check` and optionally `yarn manypkg fix` to fix any issues
|
||||
7. Run `yarn lint` - fix any issues
|
||||
8. Run `yarn build` - fix any issues
|
||||
9. Under `nextjs/`, run `./check-pre-compiled.sh` and commit the changes
|
||||
10. Run `yarn test:nextjs-size` and update tests if there are any failures
|
||||
11. Open PR and fix any failing tests
|
||||
12. Any doc updates?
|
||||
7. Under `nextjs/`, run `./check-pre-compiled.sh` and commit the changes
|
||||
8. Run `yarn build:nextjs`
|
||||
9. Run `yarn lint` - fix any issues
|
||||
10. Run `yarn build` - fix any issues
|
||||
11. Run `yarn test:nextjs-size` and update tests if there are any failures
|
||||
12. Open PR and fix any failing tests
|
||||
13. Update any references to nextjs in new code including imports like `next/image`, etc.
|
||||
14. Any doc updates needed?
|
||||
15. Merge PR
|
||||
16. `yarn push-nextjs`
|
||||
|
||||
3
CONTRIBUTOR_STATS.md
Normal file
3
CONTRIBUTOR_STATS.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Contributor over time
|
||||
|
||||
[](https://www.apiseven.com/en/contributor-graph?chart=contributorOverTime&repo=blitz-js/blitz)
|
||||
44
README.md
44
README.md
@@ -6,7 +6,7 @@
|
||||
<img alt="" src="https://img.shields.io/badge/Join%20our%20community-6700EB.svg?style=for-the-badge&labelColor=000000&logoWidth=20&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQ9SURBVHgB7d3dVdtAEIbhcSpICUoH0IEogQqSVBBSAU4FSSpIOoAORAfQgSghHXzZ1U/YcMD4R9rZmf2ec3y448LyiNf27iLiGIAmPLrweC9Un3DhrzG6EarLNP09nlwJ1SOZ/lQr5N80/S/p2QMVCBf5N17XCfm1Y/rBHqjAG9PPHvBsz+mf9WAP+HLA9M/YA14cOP2payH7jpj+VCtk1wnTP+vj7xCy6cTpn7EHLMLp059iD1iD8eveJbVCNsSLheX1YA/YgOWnf8YeKB3Wmf7Ud6Fy4f/FHmtpxbl3YlC4MJ/Cj0bWdwPnPbARg+L0S54XQHS32WwuxClzd4CM0z9rPfeAuTtA5ulPXYQ7wZ04Y+oOoDD9KZc9YOoOoDj9s4dwFzgXR6w1wIPoOvPWA9buAHEJ173o3gWiy3AnuBUHLEbgmYwvAk1/wuM8vAgexThzbwPDkx7/DHwVXfFOxP2GmsKd4Ab6zPeAyU8CI7AHFmH2BRCBPXAyk18GzUrqAXCTiR4ssyj0VFw/oCU8+e+RZ33AWz6KMaYbIIWxB+JSLs1bsbkeMN0AqakHvoku9oA2sAfqBvbAQdw0QArsgb25aYBUQT3QgT2gB+yBuqGcHij2UCqXDZACe2Anlw2QYg/QAOyBuoE98CL3DZDCuK4/rh/Q7oGL6U+TOvcNkJoijN8X1C48+T+g75eQDrAH/qmqAVJgDwyqaoAUe4AGYA/UDZX3QLUNkEIZPRCd5+6BahsgVUgPROwBTSijB7jpVAvGHriHvmw9wAZ4BpX1ABvgmakHtPcbRuwBTWAPULgAV9D/jKDY9YRvwvgEaurD44uQHvAol7qBW7WKluVtIHiUS7GyvA0s6CiXDnxrpQfsgbqBS7GKk/2jYHCrVlGyfxTMrVo0ALdq1Q3sgSKofh0M9oA61a+D2QM0AHugbmAPqClmSRjK2apVVQ8UsySsoK1aHdgDesCtWnUDeyCrIpeFg1u3sylyWTi3btMA7IG6gT2wuuK3hoE9sKrit4YVslWLPaAN7IG6ocKt2zmY2h4O9sDiTG0PZw/QANy6XTewBxZj9ogYVHy025LMHhEz9cBn0We6B0yfERReBLfhx0/R1YQHPx/QBPbA0VwcEwf2wNFcHBPHHjiem3MC2QPHcXdSaJjA+KfgTPQ8hhfjBzHC40mhlzJ+Xq9lK4a4PCs43AVaGTed5mZq+iOXZwWHi3AnOj2wFWNcnxYe7gTxLtBKHuamP/J+Wnh8a5irB7ZC5Yk9gPX1QuXC+usHWqGyhYvUYR0a7zboUOFCNVhnk0krZAOW7wFOvzXhom2xnEbIHizTA1wEYhWW6YFGyC6c1gOcfg9wfA80Qj7g8B7g9HuCww+haIR8wf49wOn3Cvv9k8tGyC/s7gFOv3fY3QONkH+v9MBWqB7PeqDn9FcIT//kcitUn6kHOu/T/xfWzlQy3dEHhwAAAABJRU5ErkJggg==">
|
||||
</a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-286-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-304-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
<a aria-label="License" href="https://github.com/blitz-js/blitz/blob/canary/LICENSE">
|
||||
<img alt="" src="https://img.shields.io/npm/l/blitz.svg?style=for-the-badge&labelColor=000000&color=blue">
|
||||
@@ -221,6 +221,14 @@ _Issue triage, pull request triage, community encouragement and moderation, etc_
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://mina.ca">
|
||||
<img src="https://avatars.githubusercontent.com/mabadir" width="100px;" alt="Mina Abadir avatar" /><br />
|
||||
<sub>
|
||||
<b>Mina Abadir</b>
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
@@ -280,7 +288,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="https://mikeattara.com"><img src="https://avatars1.githubusercontent.com/u/31483629?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mike Perry Y Attara</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mikeattara" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://devanthe.dev"><img src="https://avatars0.githubusercontent.com/u/354652?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Devan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=DevanB" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/jclancy93"><img src="https://avatars2.githubusercontent.com/u/7850202?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jack Clancy</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jclancy93" title="Code">💻</a> <a href="#maintenance-jclancy93" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/ntgussoni"><img src="https://avatars0.githubusercontent.com/u/10161067?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nicolas Torres</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Antgussoni" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://github.com/ntgussoni"><img src="https://avatars0.githubusercontent.com/u/10161067?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nicolas Torres</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Antgussoni" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://simonknott.de"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Simon Knott</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Skn0tt" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Skn0tt" title="Tests">⚠️</a> <a href="#maintenance-Skn0tt" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=Skn0tt" title="Documentation">📖</a></td>
|
||||
@@ -558,13 +566,13 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="https://github.com/amdolan"><img src="https://avatars.githubusercontent.com/u/2552275?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alex Dolan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=amdolan" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=amdolan" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=amdolan" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/Maastrich"><img src="https://avatars.githubusercontent.com/u/58431775?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mathis Pinsault</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Maastrich" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/gstranger"><img src="https://avatars.githubusercontent.com/u/36181416?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gstranger</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gstranger" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=gstranger" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://twitter.com/_markeh"><img src="https://avatars.githubusercontent.com/u/1357323?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mark Hughes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=markhughes" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://twitter.com/_markeh"><img src="https://avatars.githubusercontent.com/u/1357323?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mark Hughes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=markhughes" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=markhughes" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="www.andrearizzello.work"><img src="https://avatars.githubusercontent.com/u/10348930?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrea Rizzello</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=andrearizzello" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="jahred.com.au"><img src="https://avatars.githubusercontent.com/u/13903378?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jahred Hope</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jahredhope" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="simonelnahas.github.io/"><img src="https://avatars.githubusercontent.com/u/29279201?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Simon El Nahas</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=simonelnahas" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="www.usertrack.net"><img src="https://avatars.githubusercontent.com/u/1384885?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Buleandra Cristian</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Cristy94" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="www.usertrack.net"><img src="https://avatars.githubusercontent.com/u/1384885?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Buleandra Cristian</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Cristy94" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Cristy94" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://palauisaac.me/"><img src="https://avatars.githubusercontent.com/u/12257885?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pedro Enrique Palau Isaac</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=peterpalau" title="Code">💻</a></td>
|
||||
<td align="center"><a href="www.seanbrydon.me"><img src="https://avatars.githubusercontent.com/u/55134778?v=4?s=100" width="100px;" alt=""/><br /><sub><b>sean-brydon</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sean-brydon" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="buonerba.dev"><img src="https://avatars.githubusercontent.com/u/28837891?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alessandro</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Dieman89" title="Documentation">📖</a></td>
|
||||
@@ -595,15 +603,39 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="http://www.fernvillasenor.com"><img src="https://avatars.githubusercontent.com/u/5857808?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fernando Villasenor</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fernvilla" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/swiftgaruda"><img src="https://avatars.githubusercontent.com/u/16741392?v=4?s=100" width="100px;" alt=""/><br /><sub><b>swiftgaruda</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=swiftgaruda" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://pplife.home.blog"><img src="https://avatars.githubusercontent.com/u/35653876?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pankaj Patil</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Patil2099" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="minaabadir.ca"><img src="https://avatars.githubusercontent.com/u/3389914?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mina Abadir</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mabadir" title="Code">💻</a></td>
|
||||
<td align="center"><a href="minaabadir.ca"><img src="https://avatars.githubusercontent.com/u/3389914?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mina Abadir</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mabadir" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=mabadir" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=mabadir" title="Tests">⚠️</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/frankiesardo"><img src="https://avatars.githubusercontent.com/u/1476561?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Francesco Sardo</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=frankiesardo" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/frankiesardo"><img src="https://avatars.githubusercontent.com/u/1476561?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Francesco Sardo</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=frankiesardo" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=frankiesardo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/enemycnt"><img src="https://avatars.githubusercontent.com/u/320313?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nikolay</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=enemycnt" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://dipeshwagle.com"><img src="https://avatars.githubusercontent.com/u/4191022?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dipesh Wagle</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Dipeshwagle" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://codepoet.de"><img src="https://avatars.githubusercontent.com/u/462455?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benjamin Bender</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=benbender" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://nima.sh"><img src="https://avatars.githubusercontent.com/u/3728170?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nima Shoghi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nimashoghi" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/chronark"><img src="https://avatars.githubusercontent.com/u/18246773?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andreas Thomas</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chronark" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/guoqqqi"><img src="https://avatars.githubusercontent.com/u/72343596?v=4?s=100" width="100px;" alt=""/><br /><sub><b>guoqqqi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=guoqqqi" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/timbooker"><img src="https://avatars.githubusercontent.com/u/612681?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tim</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=timbooker" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=timbooker" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="http://orlowski.me/"><img src="https://avatars.githubusercontent.com/u/16357457?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Marek Orłowski</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ormarek" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/AntoineGuestin"><img src="https://avatars.githubusercontent.com/u/70888750?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Antoine G</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=AntoineGuestin" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/swinner2"><img src="https://avatars.githubusercontent.com/u/6707308?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sean Winner</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=swinner2" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=swinner2" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=swinner2" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://usman-s.me"><img src="https://avatars.githubusercontent.com/u/51731966?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Max Programming</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=max-programming" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://makemake.sh"><img src="https://avatars.githubusercontent.com/u/353768?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sebastian Hoitz</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sebastianhoitz" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=sebastianhoitz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/garnerp"><img src="https://avatars.githubusercontent.com/u/737307?v=4?s=100" width="100px;" alt=""/><br /><sub><b>garnerp</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=garnerp" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/kivi"><img src="https://avatars.githubusercontent.com/u/366163?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kivi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kivi" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://dangreaves.com"><img src="https://avatars.githubusercontent.com/u/1036142?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dan Greaves</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dangreaves" title="Code">💻</a></td>
|
||||
<td align="center"><a href="lksnmnn.com"><img src="https://avatars.githubusercontent.com/u/4983285?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lukas Neumann</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lksnmnn" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=lksnmnn" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=lksnmnn" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="dbachrach.com"><img src="https://avatars.githubusercontent.com/u/45016?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dustin Bachrach</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dbachrach" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=dbachrach" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/ashikka"><img src="https://avatars.githubusercontent.com/u/58368421?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ashikka Gupta</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ashikka" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=ashikka" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/deini"><img src="https://avatars.githubusercontent.com/u/2752665?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Almaguer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=deini" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.kevinpeters.net/about/"><img src="https://avatars.githubusercontent.com/u/12736734?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Peters</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=igeligel" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://anolilab.de"><img src="https://avatars.githubusercontent.com/u/2716058?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Bannert</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=prisis" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://benjakugler96.github.io/"><img src="https://avatars.githubusercontent.com/u/53273645?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benja Kugler</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=benjakugler96" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://semeniuc.ml/"><img src="https://avatars.githubusercontent.com/u/3838856?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eric Semeniuc</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=esemeniuc" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=esemeniuc" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 30 KiB |
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod"
|
||||
import {z} from "zod"
|
||||
|
||||
const password = z.string().min(10).max(100)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, {ReactNode, PropsWithoutRef} from "react"
|
||||
import {Form as FinalForm, FormProps as FinalFormProps} from "react-final-form"
|
||||
import * as z from "zod"
|
||||
import {z} from "zod"
|
||||
import {validateZodSchema} from "blitz"
|
||||
export {FORM_ERROR} from "final-form"
|
||||
|
||||
export interface FormProps<S extends z.ZodType<any, any>>
|
||||
@@ -25,14 +26,7 @@ export function Form<S extends z.ZodType<any, any>>({
|
||||
return (
|
||||
<FinalForm
|
||||
initialValues={initialValues}
|
||||
validate={(values) => {
|
||||
if (!schema) return
|
||||
try {
|
||||
schema.parse(values)
|
||||
} catch (error) {
|
||||
return error.formErrors.fieldErrors
|
||||
}
|
||||
}}
|
||||
validate={validateZodSchema(schema)}
|
||||
onSubmit={onSubmit}
|
||||
render={({handleSubmit, submitting, submitError}) => (
|
||||
<form onSubmit={handleSubmit} className="form" {...props}>
|
||||
|
||||
@@ -1,28 +1,22 @@
|
||||
import {
|
||||
AppProps,
|
||||
ErrorBoundary,
|
||||
ErrorComponent,
|
||||
useRouter,
|
||||
AuthenticationError,
|
||||
AuthorizationError,
|
||||
ErrorFallbackProps,
|
||||
useQueryErrorResetBoundary,
|
||||
} from "blitz"
|
||||
import {ErrorBoundary} from "react-error-boundary"
|
||||
import LoginForm from "app/auth/components/LoginForm"
|
||||
import {ReactQueryDevtools} from "react-query/devtools"
|
||||
|
||||
export default function App({Component, pageProps}: AppProps) {
|
||||
const getLayout = Component.getLayout || ((page) => page)
|
||||
const router = useRouter()
|
||||
const {reset} = useQueryErrorResetBoundary()
|
||||
|
||||
return (
|
||||
<>
|
||||
<ErrorBoundary
|
||||
FallbackComponent={RootErrorFallback}
|
||||
resetKeys={[router.asPath]}
|
||||
onReset={reset}
|
||||
>
|
||||
<ErrorBoundary FallbackComponent={RootErrorFallback} onReset={reset}>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</ErrorBoundary>
|
||||
<ReactQueryDevtools />
|
||||
|
||||
@@ -10,7 +10,14 @@ import {Routes} from ".blitz"
|
||||
export const EditProject = () => {
|
||||
const router = useRouter()
|
||||
const projectId = useParam("projectId", "number")
|
||||
const [project, {setQueryData}] = useQuery(getProject, {id: projectId})
|
||||
const [project, {setQueryData}] = useQuery(
|
||||
getProject,
|
||||
{id: projectId},
|
||||
{
|
||||
// This ensures the query never refreshes and overwrites the form data while the user is editing.
|
||||
staleTime: Infinity,
|
||||
},
|
||||
)
|
||||
const [updateProjectMutation] = useMutation(updateProject)
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,7 +23,7 @@ const NewProjectPage: BlitzPage = () => {
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
const project = await createProjectMutation(values)
|
||||
router.push(`/projects/${project.id}`)
|
||||
router.push(Routes.ShowProjectPage({projectId: project.id}))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return {
|
||||
|
||||
@@ -12,16 +12,8 @@ import {
|
||||
} from "blitz"
|
||||
import getUser from "app/users/queries/getUser"
|
||||
import logout from "app/auth/mutations/logout"
|
||||
import path from "path"
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async ({req, res}) => {
|
||||
// Ensure these files are not eliminated by trace-based tree-shaking (like Vercel)
|
||||
// https://github.com/blitz-js/blitz/issues/794
|
||||
path.resolve("next.config.js")
|
||||
path.resolve("blitz.config.js")
|
||||
path.resolve(".next/blitz/db.js")
|
||||
// End anti-tree-shaking
|
||||
|
||||
const session = await getSession(req, res)
|
||||
console.log("Session id:", session.userId)
|
||||
try {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {Form, FormProps} from "app/core/components/Form"
|
||||
import {LabeledTextField} from "app/core/components/LabeledTextField"
|
||||
import * as z from "zod"
|
||||
import {ZodType} from "zod"
|
||||
export {FORM_ERROR} from "app/core/components/Form"
|
||||
|
||||
export function ProjectForm<S extends z.ZodType<any, any>>(props: FormProps<S>) {
|
||||
export function ProjectForm<S extends ZodType<any, any>>(props: FormProps<S>) {
|
||||
return (
|
||||
<Form<S> {...props}>
|
||||
<LabeledTextField name="name" label="Name" placeholder="Name" />
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import {resolver} from "blitz"
|
||||
import db from "db"
|
||||
import * as z from "zod"
|
||||
import {z} from "zod"
|
||||
|
||||
const CreateProject = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
})
|
||||
.nonstrict()
|
||||
const CreateProject = z.object({
|
||||
name: z.string(),
|
||||
})
|
||||
|
||||
export default resolver.pipe(resolver.zod(CreateProject), resolver.authorize(), async (input) => {
|
||||
// TODO: in multi-tenant app, you must add validation to ensure correct tenant
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import {resolver} from "blitz"
|
||||
import db from "db"
|
||||
import * as z from "zod"
|
||||
import {z} from "zod"
|
||||
|
||||
const DeleteProject = z
|
||||
.object({
|
||||
id: z.number(),
|
||||
})
|
||||
.nonstrict()
|
||||
const DeleteProject = z.object({
|
||||
id: z.number(),
|
||||
})
|
||||
|
||||
export default resolver.pipe(resolver.zod(DeleteProject), resolver.authorize(), async ({id}) => {
|
||||
// TODO: in multi-tenant app, you must add validation to ensure correct tenant
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import {resolver} from "blitz"
|
||||
import db from "db"
|
||||
import * as z from "zod"
|
||||
import {z} from "zod"
|
||||
|
||||
const UpdateProject = z
|
||||
.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
})
|
||||
.nonstrict()
|
||||
const UpdateProject = z.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
})
|
||||
|
||||
export default resolver.pipe(
|
||||
resolver.zod(UpdateProject),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {resolver, NotFoundError} from "blitz"
|
||||
import db from "db"
|
||||
import * as z from "zod"
|
||||
import {z} from "zod"
|
||||
|
||||
const GetProject = z.object({
|
||||
// This accepts type of undefined, but is required at runtime
|
||||
|
||||
@@ -28,18 +28,16 @@
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.19.0",
|
||||
"blitz": "0.35.0",
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"passport-auth0": "1.4.0",
|
||||
"passport-github2": "0.1.12",
|
||||
"passport-twitter": "1.0.4",
|
||||
"prisma": "2.19.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react-error-boundary": "3.1.1",
|
||||
"react-final-form": "6.5.2",
|
||||
"zod": "1.11.11"
|
||||
"prisma": "2.24.1",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/skip-test": "2.6.0",
|
||||
@@ -50,7 +48,7 @@
|
||||
"@types/passport-github2": "1.2.4",
|
||||
"@types/passport-twitter": "1.0.36",
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "6.2.1",
|
||||
"eslint": "7.21.0",
|
||||
@@ -59,8 +57,7 @@
|
||||
"prettier": "2.2.1",
|
||||
"pretty-quick": "3.1.0",
|
||||
"preview-email": "3.0.3",
|
||||
"start-server-and-test": "1.11.7",
|
||||
"typescript": "4.1.5"
|
||||
"start-server-and-test": "1.11.7"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod"
|
||||
import {z} from "zod"
|
||||
|
||||
export const SignupInput = z.object({
|
||||
email: z.string().email(),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, {ReactNode, PropsWithoutRef} from "react"
|
||||
import {Form as FinalForm, FormProps as FinalFormProps} from "react-final-form"
|
||||
import * as z from "zod"
|
||||
import {z} from "zod"
|
||||
import {validateZodSchema} from "blitz"
|
||||
export {FORM_ERROR} from "final-form"
|
||||
|
||||
type FormProps<S extends z.ZodType<any, any>> = {
|
||||
@@ -24,14 +25,7 @@ export function Form<S extends z.ZodType<any, any>>({
|
||||
return (
|
||||
<FinalForm
|
||||
initialValues={initialValues}
|
||||
validate={(values) => {
|
||||
if (!schema) return
|
||||
try {
|
||||
schema.parse(values)
|
||||
} catch (error) {
|
||||
return error.formErrors.fieldErrors
|
||||
}
|
||||
}}
|
||||
validate={validateZodSchema(schema)}
|
||||
onSubmit={onSubmit}
|
||||
render={({handleSubmit, submitting, submitError}) => (
|
||||
<form onSubmit={handleSubmit} className="form" {...props}>
|
||||
|
||||
@@ -1,31 +1,26 @@
|
||||
import {
|
||||
AppProps,
|
||||
ErrorBoundary,
|
||||
ErrorFallbackProps,
|
||||
ErrorComponent,
|
||||
useRouter,
|
||||
AuthenticationError,
|
||||
AuthorizationError,
|
||||
useQueryErrorResetBoundary,
|
||||
} from "blitz"
|
||||
import {ErrorBoundary, FallbackProps} from "react-error-boundary"
|
||||
import LoginForm from "app/auth/components/LoginForm"
|
||||
|
||||
export default function App({Component, pageProps}: AppProps) {
|
||||
const getLayout = Component.getLayout || ((page) => page)
|
||||
const router = useRouter()
|
||||
const {reset} = useQueryErrorResetBoundary()
|
||||
|
||||
return (
|
||||
<ErrorBoundary
|
||||
FallbackComponent={RootErrorFallback}
|
||||
resetKeys={[router.asPath]}
|
||||
onReset={reset}
|
||||
>
|
||||
<ErrorBoundary FallbackComponent={RootErrorFallback} onReset={reset}>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
function RootErrorFallback({error, resetErrorBoundary}: FallbackProps) {
|
||||
function RootErrorFallback({error, resetErrorBoundary}: ErrorFallbackProps) {
|
||||
if (error instanceof AuthenticationError) {
|
||||
return <LoginForm onSuccess={resetErrorBoundary} />
|
||||
} else if (error instanceof AuthorizationError) {
|
||||
|
||||
@@ -30,23 +30,20 @@
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.19.0",
|
||||
"blitz": "0.35.0",
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.19.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react-error-boundary": "3.1.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2",
|
||||
"secure-password": "4.0.0",
|
||||
"typescript": "4.1.5",
|
||||
"zod": "1.11.11"
|
||||
"secure-password": "4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/skip-test": "2.6.0",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"@types/secure-password": "3.1.0",
|
||||
"cypress": "6.2.1",
|
||||
"eslint": "7.21.0",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as z from "zod"
|
||||
import { z } from "zod"
|
||||
|
||||
export const SignupInput = z.object({
|
||||
email: z.string().email(),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ReactNode, PropsWithoutRef } from "react"
|
||||
import { Form as FinalForm, FormProps as FinalFormProps } from "react-final-form"
|
||||
import * as z from "zod"
|
||||
import { z } from "zod"
|
||||
import { validateZodSchema } from "blitz"
|
||||
export { FORM_ERROR } from "final-form"
|
||||
|
||||
type FormProps<S extends z.ZodType<any, any>> = {
|
||||
@@ -24,14 +25,7 @@ export function Form<S extends z.ZodType<any, any>>({
|
||||
return (
|
||||
<FinalForm
|
||||
initialValues={initialValues}
|
||||
validate={(values) => {
|
||||
if (!schema) return
|
||||
try {
|
||||
schema.parse(values)
|
||||
} catch (error) {
|
||||
return error.formErrors.fieldErrors
|
||||
}
|
||||
}}
|
||||
validate={validateZodSchema(schema)}
|
||||
onSubmit={onSubmit}
|
||||
render={({ handleSubmit, submitting, submitError }) => (
|
||||
<form onSubmit={handleSubmit} className="form" {...props}>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
import { AppProps, ErrorComponent, useRouter, useQueryErrorResetBoundary } from "blitz"
|
||||
import { ErrorBoundary, FallbackProps } from "react-error-boundary"
|
||||
import {
|
||||
AppProps,
|
||||
ErrorBoundary,
|
||||
ErrorFallbackProps,
|
||||
ErrorComponent,
|
||||
useQueryErrorResetBoundary,
|
||||
} from "blitz"
|
||||
import LoginForm from "app/auth/components/LoginForm"
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
const getLayout = Component.getLayout || ((page) => page)
|
||||
const router = useRouter()
|
||||
const { reset } = useQueryErrorResetBoundary()
|
||||
|
||||
return (
|
||||
<ErrorBoundary
|
||||
FallbackComponent={RootErrorFallback}
|
||||
resetKeys={[router.asPath]}
|
||||
onReset={reset}
|
||||
>
|
||||
<ErrorBoundary FallbackComponent={RootErrorFallback} onReset={reset}>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
function RootErrorFallback({ error, resetErrorBoundary }: FallbackProps) {
|
||||
function RootErrorFallback({ error, resetErrorBoundary }: ErrorFallbackProps) {
|
||||
if (error?.name === "AuthenticationError") {
|
||||
return <LoginForm onSuccess={resetErrorBoundary} />
|
||||
} else if (error?.name === "AuthorizationError") {
|
||||
|
||||
@@ -28,33 +28,29 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "0.35.0",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"graphql": "15.5.0",
|
||||
"graphql-request": "3.4.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react-error-boundary": "3.1.1",
|
||||
"react-final-form": "6.5.2",
|
||||
"secure-password": "4.0.0",
|
||||
"zod": "1.11.11"
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@testing-library/react-hooks": "^4.0.1",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"@types/secure-password": "3.1.0",
|
||||
"babel-eslint": "~10.1.0",
|
||||
"eslint": "7.21.0",
|
||||
"eslint-config-react-app": "~6.0.0",
|
||||
"eslint-plugin-flowtype": "~5.2.0",
|
||||
"eslint-plugin-import": "~2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "~6.4.1",
|
||||
"eslint-plugin-react": "~7.22.0",
|
||||
"eslint-plugin-react-hooks": "~4.2.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-react": "^7.23.1",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"husky": "5.1.2",
|
||||
"start-server-and-test": "1.11.7",
|
||||
"typescript": "4.1.5"
|
||||
"start-server-and-test": "1.11.7"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
||||
@@ -26,27 +26,26 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "0.35.0",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"knex": "0.21.16",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"sqlite3": "5.0.0"
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"sqlite3": "5.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"babel-eslint": "~10.1.0",
|
||||
"eslint": "7.21.0",
|
||||
"eslint-config-react-app": "~6.0.0",
|
||||
"eslint-plugin-flowtype": "~5.2.0",
|
||||
"eslint-plugin-import": "~2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "~6.4.1",
|
||||
"eslint-plugin-react": "~7.22.0",
|
||||
"eslint-plugin-react-hooks": "~4.2.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-react": "^7.23.1",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"husky": "5.1.2",
|
||||
"lint-staged": "10.5.4",
|
||||
"prettier": "2.2.1",
|
||||
"pretty-quick": "3.1.0",
|
||||
"typescript": "4.1.5"
|
||||
"pretty-quick": "3.1.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
||||
@@ -32,26 +32,25 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.19.0",
|
||||
"blitz": "0.35.0",
|
||||
"prisma": "2.19.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71"
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "~10.1.0",
|
||||
"eslint": "7.21.0",
|
||||
"eslint-config-react-app": "~6.0.0",
|
||||
"eslint-plugin-flowtype": "~5.2.0",
|
||||
"eslint-plugin-import": "~2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "~6.4.1",
|
||||
"eslint-plugin-react": "~7.22.0",
|
||||
"eslint-plugin-react-hooks": "~4.2.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-react": "^7.23.1",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"husky": "5.1.2",
|
||||
"lint-staged": "10.5.4",
|
||||
"prettier": "2.2.1",
|
||||
"pretty-quick": "3.1.0",
|
||||
"typescript": "4.1.5"
|
||||
"pretty-quick": "3.1.0"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
import {
|
||||
AppProps,
|
||||
ErrorBoundary,
|
||||
ErrorComponent,
|
||||
useRouter,
|
||||
ErrorFallbackProps,
|
||||
useQueryErrorResetBoundary,
|
||||
} from "blitz"
|
||||
import { ErrorBoundary } from "react-error-boundary"
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
const getLayout = Component.getLayout || ((page) => page)
|
||||
const router = useRouter()
|
||||
const { reset } = useQueryErrorResetBoundary()
|
||||
|
||||
return (
|
||||
<ErrorBoundary
|
||||
FallbackComponent={RootErrorFallback}
|
||||
resetKeys={[router.asPath]}
|
||||
onReset={reset}
|
||||
>
|
||||
<ErrorBoundary FallbackComponent={RootErrorFallback} onReset={reset}>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</ErrorBoundary>
|
||||
)
|
||||
|
||||
@@ -32,20 +32,17 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.19.0",
|
||||
"blitz": "0.35.0",
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.19.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react-error-boundary": "3.1.1",
|
||||
"react-final-form": "6.5.2",
|
||||
"typescript": "4.1.5",
|
||||
"zod": "1.11.11"
|
||||
"prisma": "2.24.1",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"eslint": "7.21.0",
|
||||
"husky": "5.1.2",
|
||||
"lint-staged": "10.5.4",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
extends: ["blitz"],
|
||||
}
|
||||
@@ -1,13 +1,5 @@
|
||||
import db, {Product} from "db"
|
||||
import db from "db"
|
||||
import {BlitzApiRequest, BlitzApiResponse} from "blitz"
|
||||
import {mean} from "lodash"
|
||||
|
||||
// this is here mainly as an integration test for
|
||||
// importing from api/
|
||||
export function meanPrice(products: Product[]) {
|
||||
const prices = products.map((p) => p.price).filter((p) => !!p) as number[]
|
||||
return mean(prices)
|
||||
}
|
||||
|
||||
export default async function users(_req: BlitzApiRequest, res: BlitzApiResponse) {
|
||||
const products = await db.product.findMany()
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import {Suspense, useState} from "react"
|
||||
import {useQuery, Link, useRouterQuery, invalidateQuery, setQueryData} from "blitz"
|
||||
import getProducts from "app/products/queries/getProducts"
|
||||
import {meanPrice} from "app/admin/api/users"
|
||||
import {mean} from "lodash"
|
||||
import {Product} from "@prisma/client"
|
||||
|
||||
// this is here mainly as an integration test for
|
||||
// importing from api/
|
||||
export function meanPrice(products: Product[]) {
|
||||
const prices = products.map((p) => p.price).filter((p) => !!p) as number[]
|
||||
return mean(prices)
|
||||
}
|
||||
|
||||
function reversedProductList(productsList) {
|
||||
return {...productsList, products: [...productsList.products].reverse()}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {AppProps, ErrorComponent, useQueryErrorResetBoundary} from "blitz"
|
||||
import {ErrorBoundary} from "react-error-boundary"
|
||||
import {AppProps, ErrorBoundary, ErrorComponent, useQueryErrorResetBoundary} from "blitz"
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
window["DEBUG_BLITZ"] = 1
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import {Link, BlitzPage, InferGetStaticPropsType} from "blitz"
|
||||
import getProducts, {averagePrice} from "../../queries/getProducts"
|
||||
import getProducts from "../../queries/getProducts"
|
||||
import {sum} from "lodash"
|
||||
import {Product} from "@prisma/client"
|
||||
|
||||
// regression test for #1646
|
||||
import {getMeSomeQualityHumor} from "../../api"
|
||||
console.log("Attention! Must read: " + getMeSomeQualityHumor())
|
||||
|
||||
export function averagePrice(products: Product[]) {
|
||||
const prices = products.map((p) => p.price ?? 0)
|
||||
return sum(prices) / prices.length
|
||||
}
|
||||
|
||||
export const getStaticProps = async () => {
|
||||
const {products} = await getProducts({orderBy: {id: "desc"}})
|
||||
return {
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import {Middleware, paginate} from "blitz"
|
||||
import db, {Prisma, Product} from "db"
|
||||
import {sum} from "lodash"
|
||||
|
||||
export function averagePrice(products: Product[]) {
|
||||
const prices = products.map((p) => p.price ?? 0)
|
||||
return sum(prices) / prices.length
|
||||
}
|
||||
import db, {Prisma} from "db"
|
||||
|
||||
type GetProductsInput = {
|
||||
where?: Prisma.ProductFindManyArgs["where"]
|
||||
|
||||
@@ -20,20 +20,17 @@
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.19.0",
|
||||
"blitz": "0.35.0",
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.19.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react-error-boundary": "3.1.1",
|
||||
"react-final-form": "6.5.2",
|
||||
"typescript": "4.1.5"
|
||||
"prisma": "2.24.1",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react": "17.0.13",
|
||||
"cypress": "6.2.1",
|
||||
"eslint-plugin-cypress": "~2.11.2",
|
||||
"start-server-and-test": "1.11.7"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.35.1",
|
||||
"version": "0.38.3-canary.1",
|
||||
"packages": ["packages/*"],
|
||||
"npmClient": "yarn",
|
||||
"useWorkspaces": true,
|
||||
|
||||
4
nextjs/.alexignore
Normal file
4
nextjs/.alexignore
Normal file
@@ -0,0 +1,4 @@
|
||||
CODE_OF_CONDUCT.md
|
||||
docs/
|
||||
errors/
|
||||
examples/
|
||||
@@ -2,6 +2,8 @@ node_modules
|
||||
**/.next/**
|
||||
**/_next/**
|
||||
**/dist/**
|
||||
e2e-tests/**
|
||||
examples/with-eslint/**
|
||||
examples/with-typescript-eslint-jest/**
|
||||
examples/with-kea/**
|
||||
packages/next/bundles/webpack/packages/*.runtime.js
|
||||
@@ -15,6 +17,7 @@ packages/next-codemod/transforms/__tests__/**/*
|
||||
packages/next-codemod/**/*.js
|
||||
packages/next-codemod/**/*.d.ts
|
||||
packages/next-env/**/*.d.ts
|
||||
packages/create-next-app/templates/**
|
||||
test/integration/async-modules/**
|
||||
test/integration/eslint/**
|
||||
test-timings.json
|
||||
packages/next/lib/regexr/**/*
|
||||
@@ -120,7 +120,7 @@
|
||||
"rules": {
|
||||
"no-shadow": ["warn", { "builtinGlobals": false }],
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
"off",
|
||||
{ "devDependencies": false }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
FROM node:10-buster
|
||||
FROM node:14-buster
|
||||
|
||||
LABEL com.github.actions.name="Next.js PR Stats"
|
||||
LABEL com.github.actions.description="Compares stats of a PR with the main branch"
|
||||
LABEL repository="https://github.com/zeit/next-stats-action"
|
||||
LABEL repository="https://github.com/vercel/next-stats-action"
|
||||
|
||||
COPY . /next-stats
|
||||
|
||||
|
||||
8
nextjs/.github/labeler.json
vendored
8
nextjs/.github/labeler.json
vendored
@@ -8,6 +8,14 @@
|
||||
"packages/react-dev-overlay/**",
|
||||
"packages/react-refresh-utils/**",
|
||||
"packages/next-codemod/**"
|
||||
],
|
||||
"type: chrome": [
|
||||
{ "type": "user", "pattern": "spanicker" },
|
||||
{ "type": "user", "pattern": "housseindjirdeh" },
|
||||
{ "type": "user", "pattern": "devknoll" },
|
||||
{ "type": "user", "pattern": "janicklas-ralph" },
|
||||
{ "type": "user", "pattern": "atcastle" },
|
||||
{ "type": "user", "pattern": "Joonpark13" }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
54
nextjs/.github/workflows/build_test_deploy.yml
vendored
54
nextjs/.github/workflows/build_test_deploy.yml
vendored
@@ -156,15 +156,15 @@ jobs:
|
||||
steps:
|
||||
- run: exit 0
|
||||
|
||||
testFutureDependencies:
|
||||
name: Webpack 5 (Basic, Production, Acceptance)
|
||||
testLegacyWebpack:
|
||||
name: Webpack 4 (Basic, Production, Acceptance)
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
NEXT_PRIVATE_TEST_WEBPACK5_MODE: 1
|
||||
NEXT_PRIVATE_TEST_WEBPACK4_MODE: 1
|
||||
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
@@ -174,50 +174,16 @@ jobs:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
|
||||
- run: xvfb-run node run-tests.js test/integration/{fallback-modules,link-ref,production,basic,async-modules,font-optimization,ssr-ctx}/test/index.test.js test/acceptance/*.test.js
|
||||
- run: xvfb-run node run-tests.js test/integration/{basic,fallback-modules,link-ref,production,async-modules,font-optimization,ssr-ctx}/test/index.test.js test/acceptance/*.test.js
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
|
||||
testLegacyReact:
|
||||
name: React 16 + Webpack 4 (Basic, Production, Acceptance)
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 25
|
||||
|
||||
- run: echo ::set-output name=DOCS_CHANGE::$(node skip-docs-change.js echo 'not-docs-only-change')
|
||||
id: docs-change
|
||||
|
||||
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: cat package.json | jq '.resolutions.react = "^16.14.0"' > package.json.tmp && mv package.json.tmp package.json
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: cat package.json | jq '.resolutions."react-dom" = "^16.14.0"' > package.json.tmp && mv package.json.tmp package.json
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: yarn install --check-files
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: yarn list react react-dom
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
- run: xvfb-run node run-tests.js test/integration/{link-ref,production,basic,async-modules,font-optimization,ssr-ctx,worker-loader}/test/index.test.js test/acceptance/*.test.js
|
||||
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}
|
||||
|
||||
testFirefox:
|
||||
name: Test Firefox (production)
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
env:
|
||||
HEADLESS: true
|
||||
BROWSERNAME: 'firefox'
|
||||
BROWSER_NAME: 'firefox'
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
@@ -226,7 +192,7 @@ jobs:
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
- run: node run-tests.js test/integration/production/test/index.test.js
|
||||
- run: node run-tests.js -c 1 test/integration/production/test/index.test.js
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
|
||||
testSafari:
|
||||
@@ -235,7 +201,7 @@ jobs:
|
||||
needs: build
|
||||
env:
|
||||
BROWSERSTACK: true
|
||||
BROWSERNAME: 'safari'
|
||||
BROWSER_NAME: 'safari'
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
SKIP_LOCAL_SELENIUM_SERVER: true
|
||||
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
|
||||
@@ -247,7 +213,7 @@ jobs:
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
- run: '[[ -z "$BROWSERSTACK_ACCESS_KEY" ]] && echo "Skipping for PR" || node run-tests.js test/integration/production/test/index.test.js'
|
||||
- run: '[[ -z "$BROWSERSTACK_ACCESS_KEY" ]] && echo "Skipping for PR" || node run-tests.js -c 1 test/integration/production/test/index.test.js'
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
|
||||
testSafariOld:
|
||||
@@ -257,7 +223,7 @@ jobs:
|
||||
env:
|
||||
BROWSERSTACK: true
|
||||
LEGACY_SAFARI: true
|
||||
BROWSERNAME: 'safari'
|
||||
BROWSER_NAME: 'safari'
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
SKIP_LOCAL_SELENIUM_SERVER: true
|
||||
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
|
||||
@@ -269,7 +235,7 @@ jobs:
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}
|
||||
- run: '[[ -z "$BROWSERSTACK_ACCESS_KEY" ]] && echo "Skipping for PR" || node run-tests.js test/integration/production-nav/test/index.test.js'
|
||||
- run: '[[ -z "$BROWSERSTACK_ACCESS_KEY" ]] && echo "Skipping for PR" || node run-tests.js -c 1 test/integration/production-nav/test/index.test.js'
|
||||
if: ${{needs.build.outputs.docsChange != 'docs only change'}}
|
||||
|
||||
publishRelease:
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
on:
|
||||
schedule:
|
||||
# * is a special character in YAML so you have to quote this string
|
||||
- cron: '0 0,12 * * *'
|
||||
|
||||
name: Test react@experimental
|
||||
|
||||
jobs:
|
||||
# build:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - uses: actions/checkout@v2
|
||||
|
||||
# - run: yarn install --frozen-lockfile --check-files
|
||||
# env:
|
||||
# NEXT_TELEMETRY_DISABLED: 1
|
||||
|
||||
# - run: yarn upgrade react@next react-dom@next -W --dev
|
||||
|
||||
# - uses: actions/cache@v2
|
||||
# id: cache-build
|
||||
# with:
|
||||
# path: ./*
|
||||
# key: ${{ github.sha }}
|
||||
|
||||
testAll:
|
||||
name: Test All
|
||||
runs-on: ubuntu-latest
|
||||
# needs: build
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
HEADLESS: true
|
||||
NEXT_PRIVATE_SKIP_SIZE_TESTS: true
|
||||
NEXT_PRIVATE_REACT_ROOT: 1
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
group: [1, 2, 3, 4, 5, 6]
|
||||
steps:
|
||||
# - uses: actions/cache@v2
|
||||
# id: restore-build
|
||||
# with:
|
||||
# path: ./*
|
||||
# key: ${{ github.sha }}
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
|
||||
- run: yarn upgrade react@experimental react-dom@experimental -W --dev
|
||||
|
||||
# TODO: remove after we fix watchpack watching too much
|
||||
- run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||
|
||||
- run: node run-tests.js --timings -g ${{ matrix.group }}/6 -c 3
|
||||
1
nextjs/.github/workflows/test_react_next.yml
vendored
1
nextjs/.github/workflows/test_react_next.yml
vendored
@@ -26,6 +26,7 @@ jobs:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
HEADLESS: true
|
||||
NEXT_PRIVATE_SKIP_SIZE_TESTS: true
|
||||
NEXT_PRIVATE_REACT_ROOT: 1
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = git@github.com:blitz-js/next.js.git
|
||||
branch = canary
|
||||
commit = f485e5670f466b8be3a85c5d8cc3fb487157bbc8
|
||||
parent = 9e96eaf6e729fb60e10c23c6643bced8dd0e479f
|
||||
commit = 4be32b7a54fa68dfcf66d4a5cc7744409c409c7f
|
||||
parent = 194a3720ce56aa3fabace4b07c5faeac1121b8d6
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
||||
|
||||
@@ -16,3 +16,6 @@ packages/next-codemod/**/*.js
|
||||
packages/next-codemod/**/*.d.ts
|
||||
packages/next-env/**/*.d.ts
|
||||
test-timings.json
|
||||
|
||||
// Because file from nextjs upstream isn't formatted properly
|
||||
nextjs/packages/next/build/webpack-config.ts
|
||||
|
||||
@@ -34,7 +34,7 @@ pr:
|
||||
variables:
|
||||
YARN_CACHE_FOLDER: $(Pipeline.Workspace)/.yarn
|
||||
NEXT_TELEMETRY_DISABLED: '1'
|
||||
node_version: ^10.10.0
|
||||
node_version: ^12.0.0
|
||||
|
||||
stages:
|
||||
- stage: Build
|
||||
@@ -86,7 +86,7 @@ stages:
|
||||
path: $(System.DefaultWorkingDirectory)
|
||||
displayName: Cache Build
|
||||
- script: |
|
||||
yarn testie --forceExit test/integration/production/ test/integration/css-client-nav/
|
||||
yarn testie --forceExit test/integration/production/ test/integration/css-client-nav/ test/integration/rewrites-has-condition/
|
||||
displayName: 'Run tests'
|
||||
|
||||
- job: test_unit
|
||||
@@ -117,13 +117,13 @@ stages:
|
||||
vmImage: 'windows-2019'
|
||||
strategy:
|
||||
matrix:
|
||||
node-10-1:
|
||||
nodejs-1:
|
||||
group: 1/4
|
||||
node-10-2:
|
||||
nodejs-2:
|
||||
group: 2/4
|
||||
node-10-3:
|
||||
nodejs-3:
|
||||
group: 3/4
|
||||
node-10-4:
|
||||
nodejs-4:
|
||||
group: 4/4
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const http = require('http')
|
||||
const fs = require('fs')
|
||||
import { createServer } from 'http'
|
||||
import { writeFileSync } from 'fs'
|
||||
|
||||
const PORT = 9411
|
||||
const HOST = '0.0.0.0'
|
||||
@@ -53,11 +53,11 @@ const main = () => {
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
console.log(`\nSaving to ${outFile}...`)
|
||||
fs.writeFileSync(outFile, JSON.stringify(traces, null, 2))
|
||||
writeFileSync(outFile, JSON.stringify(traces, null, 2))
|
||||
process.exit()
|
||||
})
|
||||
|
||||
const server = http.createServer(onRequest)
|
||||
const server = createServer(onRequest)
|
||||
server.listen(PORT, HOST, onReady)
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"bench:recursive-copy": "node recursive-copy/run"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "7.0.1",
|
||||
"recursive-copy": "2.0.10"
|
||||
"fs-extra": "10.0.0",
|
||||
"recursive-copy": "2.0.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const { join } = require('path')
|
||||
const { promisify } = require('util')
|
||||
const globMod = require('glob')
|
||||
import { join } from 'path'
|
||||
import { promisify } from 'util'
|
||||
import globMod from 'glob'
|
||||
|
||||
const glob = promisify(globMod)
|
||||
const resolveDataDir = join(__dirname, 'fixtures', '**/*')
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { join } = require('path')
|
||||
const { recursiveReadDir } = require('next/dist/lib/recursive-readdir')
|
||||
import { join } from 'path'
|
||||
import { recursiveReadDir } from 'next/dist/lib/recursive-readdir'
|
||||
const resolveDataDir = join(__dirname, 'fixtures')
|
||||
|
||||
async function test() {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
const { join } = require('path')
|
||||
const fs = require('fs-extra')
|
||||
|
||||
const recursiveCopyNpm = require('recursive-copy')
|
||||
|
||||
const {
|
||||
recursiveCopy: recursiveCopyCustom,
|
||||
} = require('next/dist/lib/recursive-copy')
|
||||
import { join } from 'path'
|
||||
import { ensureDir, outputFile, remove } from 'fs-extra'
|
||||
import recursiveCopyNpm from 'recursive-copy'
|
||||
import { recursiveCopy as recursiveCopyCustom } from 'next/dist/lib/recursive-copy'
|
||||
|
||||
const fixturesDir = join(__dirname, 'fixtures')
|
||||
const srcDir = join(fixturesDir, 'src')
|
||||
const destDir = join(fixturesDir, 'dest')
|
||||
|
||||
const createSrcFolder = async () => {
|
||||
await fs.ensureDir(srcDir)
|
||||
await ensureDir(srcDir)
|
||||
|
||||
const files = new Array(100)
|
||||
.fill(undefined)
|
||||
@@ -20,7 +16,7 @@ const createSrcFolder = async () => {
|
||||
join(srcDir, `folder${i % 5}`, `folder${i + (1 % 5)}`, `file${i}`)
|
||||
)
|
||||
|
||||
await Promise.all(files.map((file) => fs.outputFile(file, 'hello')))
|
||||
await Promise.all(files.map((file) => outputFile(file, 'hello')))
|
||||
}
|
||||
|
||||
async function run(fn) {
|
||||
@@ -38,7 +34,7 @@ async function run(fn) {
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const t = await test()
|
||||
await fs.remove(destDir)
|
||||
await remove(destDir)
|
||||
ts.push(t)
|
||||
}
|
||||
|
||||
@@ -57,7 +53,7 @@ async function main() {
|
||||
console.log('test recursive-copy custom implementation')
|
||||
await run(recursiveCopyCustom)
|
||||
|
||||
await fs.remove(fixturesDir)
|
||||
await remove(fixturesDir)
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const { join } = require('path')
|
||||
const { recursiveDelete } = require('next/dist/lib/recursive-delete')
|
||||
import { join } from 'path'
|
||||
import { recursiveDelete } from 'next/dist/lib/recursive-delete'
|
||||
const resolveDataDir = join(__dirname, `fixtures-${process.argv[2]}`)
|
||||
|
||||
async function test() {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
const { join } = require('path')
|
||||
const { promisify } = require('util')
|
||||
const rimrafMod = require('rimraf')
|
||||
const resolveDataDir = join(__dirname, `fixtures-${process.argv[2]}`, '**/*')
|
||||
import { join } from 'path'
|
||||
import { promisify } from 'util'
|
||||
import rimrafMod from 'rimraf'
|
||||
|
||||
const rimraf = promisify(rimrafMod)
|
||||
const resolveDataDir = join(__dirname, `fixtures-${process.argv[2]}`, '**/*')
|
||||
|
||||
async function test() {
|
||||
const time = process.hrtime()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Contributing to Next.js
|
||||
|
||||
Our Commitment to Open Source can be found [here](https://vercel.com/oss).
|
||||
Read about our [Commitment to Open Source](https://vercel.com/oss).
|
||||
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device.
|
||||
2. Create a new branch: `git checkout -b MY_BRANCH_NAME`
|
||||
@@ -46,7 +46,7 @@ Running a specific test suite inside of the `test/integration` directory:
|
||||
yarn testonly --testPathPattern "production"
|
||||
```
|
||||
|
||||
Running just one test in the `production` test suite:
|
||||
Running one test in the `production` test suite:
|
||||
|
||||
```sh
|
||||
yarn testonly --testPathPattern "production" -t "should allow etag header support"
|
||||
@@ -124,12 +124,19 @@ When you add an example to the [examples](examples) directory, don’t forget to
|
||||
- To add additional installation instructions, please add it where appropriate.
|
||||
- To add additional notes, add `## Notes` section at the end.
|
||||
- Remove the `Deploy your own` section if your example can’t be immediately deployed to Vercel.
|
||||
- Remove the `Preview` section if the example doesn't work on [StackBlitz](http://stackblitz.com/) and file an issue [here](https://github.com/stackblitz/webcontainer-core).
|
||||
|
||||
````markdown
|
||||
# Example Name
|
||||
|
||||
Description
|
||||
|
||||
## Preview
|
||||
|
||||
Preview the example live on [StackBlitz](http://stackblitz.com/):
|
||||
|
||||
[](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/DIRECTORY_NAME)
|
||||
|
||||
## Deploy your own
|
||||
|
||||
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example):
|
||||
|
||||
@@ -6,4 +6,4 @@ description: Using AMP with TypeScript? Extend your typings to allow AMP compone
|
||||
|
||||
AMP currently doesn't have built-in types for TypeScript, but it's in their roadmap ([#13791](https://github.com/ampproject/amphtml/issues/13791)).
|
||||
|
||||
As a workaround you can manually create a file called `amp.d.ts` inside your project and add the custom types described [here](https://stackoverflow.com/a/50601125).
|
||||
As a workaround you can manually create a file called `amp.d.ts` inside your project and add these [custom types](https://stackoverflow.com/a/50601125).
|
||||
|
||||
@@ -17,6 +17,14 @@ Codemods are transformations that run on your codebase programmatically. This al
|
||||
- `--dry` Do a dry-run, no code will be edited
|
||||
- `--print` Prints the changed output for comparison
|
||||
|
||||
## Next.js 11
|
||||
|
||||
### `cra-to-next` (experimental)
|
||||
|
||||
Migrates a Create React App project to Next.js; creating a pages directory and necessary config to match behavior. Client-side only rendering is leveraged initially to prevent breaking compatibility due to `window` usage during SSR and can be enabled seamlessly to allow gradual adoption of Next.js specific features.
|
||||
|
||||
Please share any feedback related to this transform [in this discussion](https://github.com/vercel/next.js/discussions/25858).
|
||||
|
||||
## Next.js 10
|
||||
|
||||
### `add-missing-react-import`
|
||||
|
||||
@@ -52,6 +52,9 @@ module.exports = {
|
||||
{
|
||||
domain: 'example.fr',
|
||||
defaultLocale: 'fr',
|
||||
// an optional http field can also be used to test
|
||||
// locale domains locally with http instead of https
|
||||
http: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -175,7 +175,7 @@ export function reportWebVitals(metric) {
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> Read more about sending results to Google Analytics [here](https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics).
|
||||
> Read more about [sending results to Google Analytics](https://github.com/GoogleChrome/web-vitals#send-the-results-to-google-analytics).
|
||||
|
||||
## TypeScript
|
||||
|
||||
|
||||
139
nextjs/docs/advanced-features/security-headers.md
Normal file
139
nextjs/docs/advanced-features/security-headers.md
Normal file
@@ -0,0 +1,139 @@
|
||||
---
|
||||
description: Improve the security of your Next.js application by adding HTTP response headers.
|
||||
---
|
||||
|
||||
# Security Headers
|
||||
|
||||
To improve the security of your application, you can use [`headers`](/docs/api-reference/next.config.js/headers.md) in `next.config.js` to apply HTTP response headers to all routes in your application.
|
||||
|
||||
```jsx
|
||||
// next.config.js
|
||||
|
||||
// You can choose which headers to add to the list
|
||||
// after learning more below.
|
||||
const securityHeaders = []
|
||||
|
||||
module.exports = {
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
// Apply these headers to all routes in your application.
|
||||
source: '/(.*)',
|
||||
headers: securityHeaders,
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
### [X-DNS-Prefetch-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control)
|
||||
|
||||
This header controls DNS prefetching, allowing browsers to proactively perform domain name resolution on external links, images, CSS, JavaScript, and more. This prefetching is performed in the background, so the [DNS](https://developer.mozilla.org/en-US/docs/Glossary/DNS) is more likely to be resolved by the time the referenced items are needed. This reduces latency when the user clicks a link.
|
||||
|
||||
```jsx
|
||||
{
|
||||
key: 'X-DNS-Prefetch-Control',
|
||||
value: 'on'
|
||||
}
|
||||
```
|
||||
|
||||
### [Strict-Transport-Security](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security)
|
||||
|
||||
This header informs browsers it should only be accessed using HTTPS, instead of using HTTP. Using the configuration below, all present and future subdomains will use HTTPS for a `max-age` of 2 years. This blocks access to pages or subdomains that can only be served over HTTP.
|
||||
|
||||
If you're deploying to [Vercel](https://vercel.com/docs/edge-network/headers#strict-transport-security), this header is not necessary as it's automatically added to all deployments.
|
||||
|
||||
```jsx
|
||||
{
|
||||
key: 'Strict-Transport-Security',
|
||||
value: 'max-age=31536000; includeSubDomains; preload'
|
||||
}
|
||||
```
|
||||
|
||||
### [X-XSS-Protection](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection)
|
||||
|
||||
This header stops pages from loading when they detect reflected cross-site scripting (XSS) attacks. Although this protection is not necessary when sites implement a strong [`Content-Security-Policy`](#content-security-policy) disabling the use of inline JavaScript (`'unsafe-inline'`), it can still provide protection for older web browsers that don't support CSP.
|
||||
|
||||
```jsx
|
||||
{
|
||||
key: 'X-XSS-Protection',
|
||||
value: '1; mode=block'
|
||||
}
|
||||
```
|
||||
|
||||
### [X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options)
|
||||
|
||||
This header indicates whether the site should be allowed to be displayed within an `iframe`. This can prevent against clickjacking attacks. This header has been superseded by CSP's `frame-ancestors` option, which has better support in modern browsers.
|
||||
|
||||
```jsx
|
||||
{
|
||||
key: 'X-Frame-Options',
|
||||
value: 'SAMEORIGIN'
|
||||
}
|
||||
```
|
||||
|
||||
### [Permissions-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy)
|
||||
|
||||
This header allows you to control which features and APIs can be used in the browser. It was previously named `Feature-Policy`. You can view the full list of permission options [here](https://www.w3.org/TR/permissions-policy-1/).
|
||||
|
||||
```jsx
|
||||
{
|
||||
key: 'Permissions-Policy',
|
||||
value: 'camera=(), microphone=(), geolocation=(), interest-cohort=()'
|
||||
}
|
||||
```
|
||||
|
||||
### [X-Content-Type-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options)
|
||||
|
||||
This header prevents the browser from attempting to guess the type of content if the `Content-Type` header is not explicitly set. This can prevent XSS exploits for websites that allow users to upload and share files. For example, a user trying to download an image, but having it treated as a different `Content-Type` like an executable, which could be malicious. This header also applies to downloading browser extensions. The only valid value for this header is `nosniff`.
|
||||
|
||||
```jsx
|
||||
{
|
||||
key: 'X-Content-Type-Options',
|
||||
value: 'nosniff'
|
||||
}
|
||||
```
|
||||
|
||||
### [Referrer-Policy](https://scotthelme.co.uk/a-new-security-header-referrer-policy/)
|
||||
|
||||
This header controls how much information the browser includes when navigating from the current website (origin) to another. You can read about the different options [here](https://scotthelme.co.uk/a-new-security-header-referrer-policy/).
|
||||
|
||||
```jsx
|
||||
{
|
||||
key: 'Referrer-Policy',
|
||||
value: 'origin-when-cross-origin'
|
||||
}
|
||||
```
|
||||
|
||||
### [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
|
||||
|
||||
This header helps prevent cross-site scripting (XSS), clickjacking and other code injection attacks. Content Security Policy (CSP) can specify allowed origins for content including scripts, stylesheets, images, fonts, objects, media (audio, video), iframes, and more.
|
||||
|
||||
You can read about the many different CSP options [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
|
||||
|
||||
```jsx
|
||||
{
|
||||
key: 'Content-Security-Policy',
|
||||
value: // Your CSP Policy
|
||||
}
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [MDN](https://developer.mozilla.org)
|
||||
- [Varun Naik](https://blog.vnaik.com/posts/web-attacks.html)
|
||||
- [Scott Helme](https://scotthelme.co.uk)
|
||||
- [Mozilla Observatory](https://observatory.mozilla.org/)
|
||||
|
||||
## Related
|
||||
|
||||
For more information, we recommend the following sections:
|
||||
|
||||
<div class="card">
|
||||
<a href="/docs/api-reference/next.config.js/headers.md">
|
||||
<b>Headers:</b>
|
||||
<small>Add custom HTTP headers to your Next.js app.</small>
|
||||
</a>
|
||||
</div>
|
||||
@@ -21,7 +21,7 @@ Usage
|
||||
$ next <command>
|
||||
|
||||
Available commands
|
||||
build, start, export, dev, telemetry
|
||||
build, start, export, dev, lint, telemetry
|
||||
|
||||
Options
|
||||
--version, -v Version number
|
||||
@@ -74,6 +74,20 @@ The application will start at `http://localhost:3000` by default. The default po
|
||||
npx next dev -p 4000
|
||||
```
|
||||
|
||||
Or using the `PORT` environment variable:
|
||||
|
||||
```bash
|
||||
PORT=4000 npx next dev
|
||||
```
|
||||
|
||||
> Note: `PORT` can not be set in `.env` as booting up the HTTP server happens before any other code is initialized.
|
||||
|
||||
You can also set the hostname to be different from the default of `0.0.0.0`, this can be useful for making the application available for other devices on the network. The default hostname can be changed with `-H`, like so:
|
||||
|
||||
```bash
|
||||
npx next dev -H 192.168.1.2
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
`next start` starts the application in production mode. The application should be compiled with [`next build`](#build) first.
|
||||
@@ -84,6 +98,27 @@ The application will start at `http://localhost:3000` by default. The default po
|
||||
npx next start -p 4000
|
||||
```
|
||||
|
||||
Or using the `PORT` environment variable:
|
||||
|
||||
```bash
|
||||
PORT=4000 npx next start
|
||||
```
|
||||
|
||||
> Note: `PORT` can not be set in `.env` as booting up the HTTP server happens before any other code is initialized.
|
||||
|
||||
## Lint
|
||||
|
||||
`next lint` runs ESLint for all files in the `pages`, `components`, and `lib` directories. It also
|
||||
provides a guided setup to install any required dependencies if ESLint is not already configured in
|
||||
your application.
|
||||
|
||||
If you have other directories that you would like to lint, you can specify them using the `--dir`
|
||||
flag:
|
||||
|
||||
```bash
|
||||
next lint --dir utils
|
||||
```
|
||||
|
||||
## Telemetry
|
||||
|
||||
Next.js collects **completely anonymous** telemetry data about general usage.
|
||||
|
||||
@@ -12,13 +12,22 @@ npx create-next-app
|
||||
yarn create next-app
|
||||
```
|
||||
|
||||
You can create a [TypeScript project](https://github.com/vercel/next.js/blob/canary/docs/basic-features/typescript.md) with the `--ts, --typescript` flag:
|
||||
|
||||
```bash
|
||||
npx create-next-app --ts
|
||||
# or
|
||||
yarn create next-app --typescript
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
`create-next-app` comes with the following options:
|
||||
|
||||
- **--ts, --typescript** - Initialize as a TypeScript project.
|
||||
- **-e, --example [name]|[github-url]** - An example to bootstrap the app with. You can use an example name from the [Next.js repo](https://github.com/vercel/next.js/tree/master/examples) or a GitHub URL. The URL can use any branch and/or subdirectory.
|
||||
- **--example-path [path-to-example]** - In a rare case, your GitHub URL might contain a branch name with a slash (e.g. bug/fix-1) and the path to the example (e.g. foo/bar). In this case, you must specify the path to the example separately: `--example-path foo/bar`
|
||||
- **--use-npm** - Explicitly tell the CLI to bootstrap the app using npm. Yarn will be used by default if it's installed
|
||||
- **--use-npm** - Explicitly tell the CLI to bootstrap the app using npm. To bootstrap using yarn we recommend running `yarn create next-app`
|
||||
|
||||
### Why use Create Next App?
|
||||
|
||||
|
||||
@@ -4,7 +4,14 @@ description: Learn more about setting a base path in Next.js
|
||||
|
||||
# Base Path
|
||||
|
||||
> This feature was introduced in [Next.js 9.5](https://nextjs.org/blog/next-9-5) and up. If you’re using older versions of Next.js, please upgrade before trying it out.
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
| Version | Changes |
|
||||
| -------- | ---------------- |
|
||||
| `v9.5.0` | Base Path added. |
|
||||
|
||||
</details>
|
||||
|
||||
To deploy a Next.js application under a sub-path of a domain you can use the `basePath` config option.
|
||||
|
||||
|
||||
@@ -24,9 +24,21 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
Next.js will automatically use your asset prefix for the JavaScript and CSS files it loads from the `/_next/` path (`.next/static/` folder).
|
||||
Next.js will automatically use your asset prefix for the JavaScript and CSS files it loads from the `/_next/` path (`.next/static/` folder). For example, with the above configuration, the following request for a JS chunk:
|
||||
|
||||
Asset prefix support does not influence the following paths:
|
||||
```
|
||||
/_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js
|
||||
```
|
||||
|
||||
Would instead become:
|
||||
|
||||
```
|
||||
https://cdn.mydomain.com/_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js
|
||||
```
|
||||
|
||||
The exact configuration for uploading your files to a given CDN will depend on your CDN of choice. The only folder you need to host on your CDN is the contents of `.next/static/`, which should be uploaded as `_next/static/` as the above URL request indicates. **Do not upload the rest of your `.next/` folder**, as you should not expose your server code and other configuration to the public.
|
||||
|
||||
While `assetPrefix` covers requests to `_next/static`, it does not influence the following paths:
|
||||
|
||||
- Files in the [public](/docs/basic-features/static-file-serving.md) folder; if you want to serve those assets over a CDN, you'll have to introduce the prefix yourself
|
||||
- `/_next/data/` requests for `getServerSideProps` pages. These requests will always be made against the main domain since they're not static.
|
||||
|
||||
@@ -15,7 +15,6 @@ Before continuing to add custom webpack configuration to your application make s
|
||||
|
||||
Some commonly asked for features are available as plugins:
|
||||
|
||||
- [@zeit/next-less](https://github.com/vercel/next-plugins/tree/master/packages/next-less)
|
||||
- [@next/mdx](https://github.com/vercel/next.js/tree/canary/packages/next-mdx)
|
||||
- [@next/bundle-analyzer](https://github.com/vercel/next.js/tree/canary/packages/next-bundle-analyzer)
|
||||
|
||||
@@ -24,10 +23,6 @@ In order to extend our usage of `webpack`, you can define a function that extend
|
||||
```js
|
||||
module.exports = {
|
||||
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
|
||||
// Note: we provide webpack above so you should not `require` it
|
||||
// Perform customizations to webpack config
|
||||
config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//))
|
||||
|
||||
// Important: return the modified config
|
||||
return config
|
||||
},
|
||||
|
||||
@@ -4,8 +4,6 @@ description: Add custom HTTP headers to your Next.js app.
|
||||
|
||||
# Headers
|
||||
|
||||
> This feature was introduced in [Next.js 9.5](https://nextjs.org/blog/next-9-5) and up. If you’re using older versions of Next.js, please upgrade before trying it out.
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
@@ -13,6 +11,16 @@ description: Add custom HTTP headers to your Next.js app.
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | -------------- |
|
||||
| `v10.2.0` | `has` added. |
|
||||
| `v9.5.0` | Headers added. |
|
||||
|
||||
</details>
|
||||
|
||||
Headers allow you to set custom HTTP headers for an incoming request path.
|
||||
|
||||
To set custom HTTP headers you can use the `headers` key in `next.config.js`:
|
||||
@@ -365,3 +373,14 @@ module.exports = {
|
||||
### Cache-Control
|
||||
|
||||
Cache-Control headers set in next.config.js will be overwritten in production to ensure that static assets can be cached effectively. If you need to revalidate the cache of a page that has been [statically generated](https://nextjs.org/docs/basic-features/pages#static-generation-recommended), you can do so by setting `revalidate` in the page's [`getStaticProps`](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) function.
|
||||
|
||||
## Related
|
||||
|
||||
For more information, we recommend the following sections:
|
||||
|
||||
<div class="card">
|
||||
<a href="/docs/advanced-features/security-headers.md">
|
||||
<b>Security Headers:</b>
|
||||
<small>Improve the security of your Next.js application by add HTTP response headers.</small>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
39
nextjs/docs/api-reference/next.config.js/ignoring-eslint.md
Normal file
39
nextjs/docs/api-reference/next.config.js/ignoring-eslint.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
description: Next.js reports ESLint errors and warnings during builds by default. Learn how to opt-out of this behavior here.
|
||||
---
|
||||
|
||||
# Ignoring ESLint
|
||||
|
||||
When ESLint is detected in your project, Next.js fails your **production build** (`next build`) when errors are present.
|
||||
|
||||
If you'd like Next.js to dangerously produce production code even when your application has ESLint errors, you can disable the built-in linting step completely.
|
||||
|
||||
> Be sure you have configured ESLint to run in a separate part of your workflow (for example, in CI or a pre-commit hook).
|
||||
|
||||
Open `next.config.js` and enable the `ignoreDuringBuilds` option in the `eslint` config:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
eslint: {
|
||||
// Warning: Dangerously allow production builds to successfully complete even if
|
||||
// your project has ESLint errors.
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
<div class="card">
|
||||
<a href="/docs/api-reference/next.config.js/introduction.md">
|
||||
<b>Introduction to next.config.js:</b>
|
||||
<small>Learn more about the configuration file used by Next.js.</small>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<a href="/docs/basic-features/eslint.md">
|
||||
<b>ESLint:</b>
|
||||
<small>Get started with ESLint in Next.js.</small>
|
||||
</a>
|
||||
</div>
|
||||
@@ -26,7 +26,7 @@ module.exports = (phase, { defaultConfig }) => {
|
||||
}
|
||||
```
|
||||
|
||||
`phase` is the current context in which the configuration is loaded. You can see the available phases [here](https://github.com/vercel/next.js/blob/canary/packages/next/next-server/lib/constants.ts#L1-L4). Phases can be imported from `next/constants`:
|
||||
`phase` is the current context in which the configuration is loaded. You can see the [available phases](https://github.com/vercel/next.js/blob/canary/packages/next/next-server/lib/constants.ts#L1-L4). Phases can be imported from `next/constants`:
|
||||
|
||||
```js
|
||||
const { PHASE_DEVELOPMENT_SERVER } = require('next/constants')
|
||||
@@ -44,7 +44,7 @@ module.exports = (phase, { defaultConfig }) => {
|
||||
}
|
||||
```
|
||||
|
||||
The commented lines are the place where you can put the configs allowed by `next.config.js`, which are defined [here](https://github.com/vercel/next.js/blob/canary/packages/next/next-server/server/config-shared.ts#L33).
|
||||
The commented lines are the place where you can put the configs allowed by `next.config.js`, which are [defined in this file](https://github.com/vercel/next.js/blob/canary/packages/next/next-server/server/config-shared.ts#L68).
|
||||
|
||||
However, none of the configs are required, and it's not necessary to understand what each config does. Instead, search for the features you need to enable or modify in this section and they will show you what to do.
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ description: Add redirects to your Next.js app.
|
||||
|
||||
# Redirects
|
||||
|
||||
> This feature was introduced in [Next.js 9.5](https://nextjs.org/blog/next-9-5) and up. If you’re using older versions of Next.js, please upgrade before trying it out.
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
@@ -13,6 +11,16 @@ description: Add redirects to your Next.js app.
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ---------------- |
|
||||
| `v10.2.0` | `has` added. |
|
||||
| `v9.5.0` | Redirects added. |
|
||||
|
||||
</details>
|
||||
|
||||
Redirects allow you to redirect an incoming request path to a different destination path.
|
||||
|
||||
Redirects are only available on the Node.js environment and do not affect client-side routing.
|
||||
@@ -132,7 +140,7 @@ module.exports = {
|
||||
// if the header `x-redirect-me` is present,
|
||||
// this redirect will be applied
|
||||
{
|
||||
source: '/:path*',
|
||||
source: '/:path((?!another-page$).*)',
|
||||
has: [
|
||||
{
|
||||
type: 'header',
|
||||
@@ -162,12 +170,12 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
permanent: false,
|
||||
destination: '/:path*/:page',
|
||||
destination: '/another/:path*',
|
||||
},
|
||||
// if the header `x-authorized` is present and
|
||||
// contains a matching value, this redirect will be applied
|
||||
{
|
||||
source: '/:path*',
|
||||
source: '/',
|
||||
has: [
|
||||
{
|
||||
type: 'header',
|
||||
@@ -181,7 +189,7 @@ module.exports = {
|
||||
// if the host is `example.com`,
|
||||
// this redirect will be applied
|
||||
{
|
||||
source: '/:path*',
|
||||
source: '/:path((?!another-page$).*)',,
|
||||
has: [
|
||||
{
|
||||
type: 'host',
|
||||
|
||||
@@ -4,8 +4,6 @@ description: Add rewrites to your Next.js app.
|
||||
|
||||
# Rewrites
|
||||
|
||||
> This feature was introduced in [Next.js 9.5](https://nextjs.org/blog/next-9-5) and up. If you’re using older versions of Next.js, please upgrade before trying it out.
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
@@ -13,9 +11,19 @@ description: Add rewrites to your Next.js app.
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | --------------- |
|
||||
| `v10.2.0` | `has` added. |
|
||||
| `v9.5.0` | Rewrites added. |
|
||||
|
||||
</details>
|
||||
|
||||
Rewrites allow you to map an incoming request path to a different destination path.
|
||||
|
||||
Rewrites are only available on the Node.js environment and do not affect client-side routing.
|
||||
Rewrites act as a URL proxy and mask the destination path, making it appear the user hasn't changed their location on the site. In contrast, [redirects](/docs/api-reference/next.config.js/redirects.md) will reroute to a new page and show the URL changes.
|
||||
|
||||
To use rewrites you can use the `rewrites` key in `next.config.js`:
|
||||
|
||||
@@ -32,6 +40,8 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
Rewrites are applied to client-side routing, a `<Link href="/about">` will have the rewrite applied in the above example.
|
||||
|
||||
`rewrites` is an async function that expects an array to be returned holding objects with `source` and `destination` properties:
|
||||
|
||||
- `source`: `String` - is the incoming request path pattern.
|
||||
@@ -48,8 +58,8 @@ module.exports = {
|
||||
return {
|
||||
beforeFiles: [
|
||||
// These rewrites are checked after headers/redirects
|
||||
// and before pages/public files which allows overriding
|
||||
// page files
|
||||
// and before all files including _next/public files which
|
||||
// allows overriding page files
|
||||
{
|
||||
source: '/some-page',
|
||||
destination: '/somewhere-else',
|
||||
@@ -69,7 +79,7 @@ module.exports = {
|
||||
// and dynamic routes are checked
|
||||
{
|
||||
source: '/:path*',
|
||||
destination: 'https://my-old-site.com',
|
||||
destination: `https://my-old-site.com/:path*`,
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -317,7 +327,7 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
See additional information on incremental adoption [in the docs here](https://nextjs.org/docs/migrating/incremental-adoption).
|
||||
See additional information on incremental adoption [in the docs here](/docs/migrating/incremental-adoption.md).
|
||||
|
||||
### Rewrites with basePath support
|
||||
|
||||
|
||||
@@ -4,7 +4,14 @@ description: Configure Next.js pages to resolve with or without a trailing slash
|
||||
|
||||
# Trailing Slash
|
||||
|
||||
> This feature was introduced in [Next.js 9.5](https://nextjs.org/blog/next-9-5) and up. If you’re using older versions of Next.js, please upgrade before trying it out.
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
| Version | Changes |
|
||||
| -------- | --------------------- |
|
||||
| `v9.5.0` | Trailing Slash added. |
|
||||
|
||||
</details>
|
||||
|
||||
By default Next.js will redirect urls with trailing slashes to their counterpart without a trailing slash. For example `/about/` will redirect to `/about`. You can configure this behavior to act the opposite way, where urls without trailing slashes are redirected to their counterparts with trailing slashes.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ description: Enable AMP in a page, and control the way Next.js adds AMP to the p
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
> AMP support is one of our advanced features, you can read more about it [here](/docs/advanced-features/amp-support/introduction.md).
|
||||
> AMP support is one of our advanced features, you can [read more about AMP here](/docs/advanced-features/amp-support/introduction.md).
|
||||
|
||||
To enable AMP, add the following config to your page:
|
||||
|
||||
|
||||
@@ -14,11 +14,12 @@ description: Enable Image Optimization with the built-in Image component.
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ------------------------ |
|
||||
| `v10.0.5` | `loader` prop added. |
|
||||
| `v10.0.1` | `layout` prop added. |
|
||||
| `v10.0.0` | `next/image` introduced. |
|
||||
| Version | Changes |
|
||||
| --------- | ------------------------------------------------------------------------------------------------- |
|
||||
| `v11.0.0` | `src` prop support for static import.<br/>`placeholder` prop added.<br/>`blurDataURL` prop added. |
|
||||
| `v10.0.5` | `loader` prop added. |
|
||||
| `v10.0.1` | `layout` prop added. |
|
||||
| `v10.0.0` | `next/image` introduced. |
|
||||
|
||||
</details>
|
||||
|
||||
@@ -39,17 +40,13 @@ We can serve an optimized image like so:
|
||||
|
||||
```jsx
|
||||
import Image from 'next/image'
|
||||
import profilePic from '../public/me.png'
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<>
|
||||
<h1>My Homepage</h1>
|
||||
<Image
|
||||
src="/me.png"
|
||||
alt="Picture of the author"
|
||||
width={500}
|
||||
height={500}
|
||||
/>
|
||||
<Image src={profilePic} alt="Picture of the author" />
|
||||
<p>Welcome to my homepage!</p>
|
||||
</>
|
||||
)
|
||||
@@ -64,7 +61,11 @@ The `<Image />` component requires the following properties.
|
||||
|
||||
### src
|
||||
|
||||
The path or URL to the source image. This is required.
|
||||
Required and must be one of the following:
|
||||
|
||||
1. A statically imported image file, as in the example code above, or
|
||||
2. A path string. This can be either an absolute external URL,
|
||||
or an internal path depending on the [loader](#loader).
|
||||
|
||||
When using an external URL, you must add it to
|
||||
[domains](/docs/basic-features/image-optimization.md#domains) in
|
||||
@@ -74,13 +75,13 @@ When using an external URL, you must add it to
|
||||
|
||||
The width of the image, in pixels. Must be an integer without a unit.
|
||||
|
||||
Required unless [`layout="fill"`](#layout).
|
||||
Required, except for statically imported images, or those with [`layout="fill"`](#layout).
|
||||
|
||||
### height
|
||||
|
||||
The height of the image, in pixels. Must be an integer without a unit.
|
||||
|
||||
Required unless [`layout="fill"`](#layout).
|
||||
Required, except for statically imported images, or those with [`layout="fill"`](#layout).
|
||||
|
||||
## Optional Props
|
||||
|
||||
@@ -101,8 +102,7 @@ When `responsive`, the image will scale the dimensions down for smaller
|
||||
viewports and scale up for larger viewports.
|
||||
|
||||
When `fill`, the image will stretch both width and height to the dimensions of
|
||||
the parent element, usually paired with
|
||||
[object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit).
|
||||
the parent element, usually paired with the [`objectFit`](#objectFit) property.
|
||||
|
||||
Try it out:
|
||||
|
||||
@@ -133,7 +133,7 @@ const MyImage = (props) => {
|
||||
return (
|
||||
<Image
|
||||
loader={myLoader}
|
||||
src="/me.png"
|
||||
src="me.png"
|
||||
alt="Picture of the author"
|
||||
width={500}
|
||||
height={500}
|
||||
@@ -163,6 +163,21 @@ When true, the image will be considered high priority and
|
||||
Should only be used when the image is visible above the fold. Defaults to
|
||||
`false`.
|
||||
|
||||
### placeholder
|
||||
|
||||
A placeholder to use while the image is loading, possible values are `blur` or `empty`. Defaults to `empty`.
|
||||
|
||||
When `blur`, the [`blurDataURL`](#blurdataurl) property will be used as the placeholder. If `src` is an object from a static import and the imported image is jpg, png, or webp, then `blurDataURL` will automatically be populated.
|
||||
|
||||
For dynamic images, you must provide the [`blurDataURL`](#blurdataurl) property. Solutions such as [Plaiceholder](https://github.com/joe-bell/plaiceholder) can help with `base64` generation.
|
||||
|
||||
When `empty`, there will be no placeholder while the image is loading, only empty space.
|
||||
|
||||
Try it out:
|
||||
|
||||
- [Demo the `blur` placeholder](https://image-component.nextjs.gallery/placeholder)
|
||||
- [Demo the shimmer effect with `blurDataURL` prop](https://image-component.nextjs.gallery/shimmer)
|
||||
|
||||
## Advanced Props
|
||||
|
||||
In some cases, you may need more advanced usage. The `<Image />` component
|
||||
@@ -197,6 +212,22 @@ When `eager`, load the image immediately.
|
||||
|
||||
[Learn more](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attr-loading)
|
||||
|
||||
### blurDataURL
|
||||
|
||||
A [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) to
|
||||
be used as a placeholder image before the `src` image successfully loads. Only takes effect when combined
|
||||
with [`placeholder="blur"`](#placeholder).
|
||||
|
||||
Must be a base64-encoded image. It will be enlarged and blurred, so a very small image (10px or
|
||||
less) is recommended. Including larger images as placeholders may harm your application performance.
|
||||
|
||||
Try it out:
|
||||
|
||||
- [Demo the default `blurDataURL` prop](https://image-component.nextjs.gallery/placeholder)
|
||||
- [Demo the shimmer effect with `blurDataURL` prop](https://image-component.nextjs.gallery/shimmer)
|
||||
|
||||
You can also [generate a solid color Data URL](https://png-pixel.com) to match the image.
|
||||
|
||||
### unoptimized
|
||||
|
||||
When true, the source image will be served as-is instead of changing quality,
|
||||
|
||||
@@ -41,7 +41,7 @@ export default ActiveLink
|
||||
|
||||
The following is the definition of the `router` object returned by both [`useRouter`](#useRouter) and [`withRouter`](#withRouter):
|
||||
|
||||
- `pathname`: `String` - Current route. That is the path of the page in `/pages`
|
||||
- `pathname`: `String` - Current route. That is the path of the page in `/pages`, the configured `basePath` or `locale` is not included.
|
||||
- `query`: `Object` - The query string parsed to an object. It will be an empty object during prerendering if the page doesn't have [data fetching requirements](/docs/basic-features/data-fetching.md). Defaults to `{}`
|
||||
- `asPath`: `String` - The path (including the query) shown in the browser without the configured `basePath` or `locale`.
|
||||
- `isFallback`: `boolean` - Whether the current page is in [fallback mode](/docs/basic-features/data-fetching.md#fallback-pages).
|
||||
@@ -49,6 +49,7 @@ The following is the definition of the `router` object returned by both [`useRou
|
||||
- `locale`: `String` - The active locale (if enabled).
|
||||
- `locales`: `String[]` - All supported locales (if enabled).
|
||||
- `defaultLocale`: `String` - The current default locale (if enabled).
|
||||
- `domainLocales`: `Array<{domain, defaultLocale, locales}>` - Any configured domain locales.
|
||||
- `isReady`: `boolean` - Whether the router fields are updated client-side and ready for use. Should only be used inside of `useEffect` methods and not for conditionally rendering on the server.
|
||||
- `isPreview`: `boolean` - Whether the application is currently in [preview mode](/docs/advanced-features/preview-mode.md).
|
||||
|
||||
@@ -74,6 +75,7 @@ router.push(url, as, options)
|
||||
- `options` - Optional object with the following configuration options:
|
||||
- `scroll` - Optional boolean, controls scrolling to the top of the page after navigation. Defaults to `true`
|
||||
- [`shallow`](/docs/routing/shallow-routing.md): Update the path of the current page without rerunning [`getStaticProps`](/docs/basic-features/data-fetching.md#getstaticprops-static-generation), [`getServerSideProps`](/docs/basic-features/data-fetching.md#getserversideprops-server-side-rendering) or [`getInitialProps`](/docs/api-reference/data-fetching/getInitialProps.md). Defaults to `false`
|
||||
- `locale` - Optional string, indicates locale of the new page
|
||||
|
||||
> You don't need to use `router.push` for external URLs. [window.location](https://developer.mozilla.org/en-US/docs/Web/API/Window/location) is better suited for those cases.
|
||||
|
||||
@@ -111,6 +113,8 @@ export default function Page() {
|
||||
}
|
||||
```
|
||||
|
||||
> **Note:** When navigating to the same page in Next.js, the page's state **will not** be reset by default, as the top-level React component is the same. You can manually ensure the state is updated using `useEffect`.
|
||||
|
||||
Redirecting the user to `pages/login.js`, useful for pages behind [authentication](/docs/authentication):
|
||||
|
||||
```jsx
|
||||
|
||||
@@ -29,8 +29,8 @@ export default function handler(req, res) {
|
||||
|
||||
For an API route to work, you need to export a function as default (a.k.a **request handler**), which then receives the following parameters:
|
||||
|
||||
- `req`: An instance of [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage), plus some pre-built middlewares you can see [here](/docs/api-routes/api-middlewares.md)
|
||||
- `res`: An instance of [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse), plus some helper functions you can see [here](/docs/api-routes/response-helpers.md)
|
||||
- `req`: An instance of [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage), plus some [pre-built middlewares](/docs/api-routes/api-middlewares.md)
|
||||
- `res`: An instance of [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse), plus some [helper functions](/docs/api-routes/response-helpers.md)
|
||||
|
||||
To handle different HTTP methods in an API route, you can use `req.method` in your request handler, like so:
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function handler(req, res) {
|
||||
The included helpers are:
|
||||
|
||||
- `res.status(code)` - A function to set the status code. `code` must be a valid [HTTP status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
|
||||
- `res.json(json)` - Sends a JSON response. `json` must be a valid JSON object
|
||||
- `res.json(body)` - Sends a JSON response. `body` must be a [serialiazable object](https://developer.mozilla.org/en-US/docs/Glossary/Serialization)
|
||||
- `res.send(body)` - Sends the HTTP response. `body` can be a `string`, an `object` or a `Buffer`
|
||||
- `res.redirect([status,] path)` - Redirects to a specified path or URL. `status` must be a valid [HTTP status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes). If not specified, `status` defaults to "307" "Temporary redirect".
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ const Profile = () => {
|
||||
export default Profile
|
||||
```
|
||||
|
||||
You can view this example in action [here](https://next-with-iron-session.vercel.app/). Check out the [`with-iron-session`](https://github.com/vercel/next.js/tree/canary/examples/with-iron-session) example to see how it works.
|
||||
You can view this [example in action](https://next-with-iron-session.vercel.app/). Check out the [`with-iron-session`](https://github.com/vercel/next.js/tree/canary/examples/with-iron-session) example to see how it works.
|
||||
|
||||
### Authenticating Server-Rendered Pages
|
||||
|
||||
@@ -127,77 +127,23 @@ Both of these libraries support either authentication pattern. If you're interes
|
||||
- [with-passport](https://github.com/vercel/next.js/tree/canary/examples/with-passport)
|
||||
- [with-passport-and-next-connect](https://github.com/vercel/next.js/tree/canary/examples/with-passport-and-next-connect)
|
||||
|
||||
### Firebase
|
||||
### Other Providers
|
||||
|
||||
To see examples with other authentication providers, check out the [examples folder](https://github.com/vercel/next.js/tree/canary/examples).
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/with-firebase-authentication">with-firebase-authentication</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
When using Firebase Authentication, we recommend using the static generation pattern.
|
||||
|
||||
It is possible to use the Firebase Client SDK to generate an ID token and forward it directly to Firebase's REST API on the server to log-in. However, requests to Firebase might take some time to resolve, depending on your user's location.
|
||||
|
||||
You can either use [FirebaseUI](https://github.com/firebase/firebaseui-web-react) for a drop-in UI, or create your own with a [custom React hook](https://usehooks.com/useAuth/).
|
||||
|
||||
### Magic (Passwordless)
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/with-magic">with-magic</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
[Magic](https://magic.link/), which uses [passwordless login](https://magic.link/), supports the static generation pattern. Similar to Firebase, a [unique identifier](https://w3c-ccg.github.io/did-primer/) has to be created on the client-side and then forwarded as a header to log-in. Then, Magic's Node SDK can be used to exchange the indentifier for a user's information.
|
||||
|
||||
### Auth0
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/auth0">auth0</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
[Auth0](https://auth0.com/) can support both authentication patterns. You can also utilize [API routes](/docs/api-routes/introduction.md) for logging in/out and retrieving user information. After logging in using the [Auth0 SDK](https://github.com/auth0/nextjs-auth0), you can utilize static generation or `getServerSideProps` for server-side rendering.
|
||||
|
||||
### Supabase
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/with-supabase-auth-realtime-db">with-supabase-auth-realtime-db</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
[Supabase](https://supabase.io/) is an open source Firebase alternative that supports many of its features, including authentication. It allows for row level security using JWT tokens and supports third party logins. Either authentication pattern is supported.
|
||||
|
||||
### Userbase
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/with-userbase">with-userbase</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
[Userbase](https://userbase.com/) supports the static generation pattern for authentication. It's open source and allows for a high level of security with end-to-end encryption. You can learn more about it in their [official site](https://userbase.com/).
|
||||
|
||||
### SuperTokens
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/with-supertokens">with-supertokens</a></li>
|
||||
<li><a href="https://github.com/vercel/next.js/tree/canary/examples/with-nhost-auth-realtime-graphql">with-nhost-auth-realtime-graphql</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
[SuperTokens](https://supertokens.io) is a highly customizable, open-source solution split into modules (so you only use what you need).
|
||||
SuperTokens currently supports credentials login, email verification, password reset flows, third-party logins, and cookie based sessions with rotating refresh tokens.
|
||||
|
||||
## Related
|
||||
|
||||
For more information on what to do next, we recommend the following sections:
|
||||
|
||||
@@ -181,19 +181,6 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
## Less and Stylus Support
|
||||
|
||||
To support importing `.less` or `.styl` files you can use the following plugins:
|
||||
|
||||
- [@zeit/next-less](https://github.com/vercel/next-plugins/tree/master/packages/next-less)
|
||||
- [@zeit/next-stylus](https://github.com/vercel/next-plugins/tree/master/packages/next-stylus)
|
||||
|
||||
If using the less plugin, don't forget to add a dependency on less as well, otherwise you'll see an error like:
|
||||
|
||||
```bash
|
||||
Error: Cannot find module 'less'
|
||||
```
|
||||
|
||||
## CSS-in-JS
|
||||
|
||||
<details>
|
||||
|
||||
@@ -72,8 +72,8 @@ The `context` parameter is an object containing the following keys:
|
||||
|
||||
`getStaticProps` should return an object with:
|
||||
|
||||
- `props` - A **required** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
|
||||
- `revalidate` - An **optional** amount in seconds after which a page re-generation can occur. More on [Incremental Static Regeneration](#incremental-static-regeneration)
|
||||
- `props` - An **optional** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
|
||||
- `revalidate` - An **optional** amount in seconds after which a page re-generation can occur (defaults to: `false` or no revalidating). More on [Incremental Static Regeneration](#incremental-static-regeneration)
|
||||
- `notFound` - An **optional** boolean value to allow the page to return a 404 status and page. Below is an example of how it works:
|
||||
|
||||
```js
|
||||
@@ -222,20 +222,27 @@ export default Blog
|
||||
|
||||
### Incremental Static Regeneration
|
||||
|
||||
> This feature was introduced in [Next.js 9.5](https://nextjs.org/blog/next-9-5#stable-incremental-static-regeneration) and up. If you’re using older versions of Next.js, please upgrade before trying Incremental Static Regeneration.
|
||||
|
||||
<details open>
|
||||
<summary><b>Examples</b></summary>
|
||||
<ul>
|
||||
<li><a href="https://reactions-demo.vercel.app/">Static Reactions Demo</a></li>
|
||||
<li><a href="https://nextjs.org/commerce">Next.js Commerce</a></li>
|
||||
<li><a href="https://reactions-demo.vercel.app/">GitHub Reactions Demo</a></li>
|
||||
<li><a href="https://static-tweet.vercel.app/">Static Tweet Demo</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
With [`getStaticProps`](#getstaticprops-static-generation) you don't have to stop relying on dynamic content, as **static content can also be dynamic**. Incremental Static Regeneration allows you to update _existing_ pages by re-rendering them in the background as traffic comes in.
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
Inspired by [stale-while-revalidate](https://tools.ietf.org/html/rfc5861), background regeneration ensures traffic is served uninterruptedly, always from static storage, and the newly built page is pushed only after it's done generating.
|
||||
| Version | Changes |
|
||||
| -------- | ---------------- |
|
||||
| `v9.5.0` | Base Path added. |
|
||||
|
||||
Consider our previous [`getStaticProps` example](#simple-example), but now with regeneration enabled:
|
||||
</details>
|
||||
|
||||
Next.js allows you to create or update static pages _after_ you’ve built your site. Incremental Static Regeneration (ISR) enables you to use static-generation on a per-page basis, **without needing to rebuild the entire site**. With ISR, you can retain the benefits of static while scaling to millions of pages.
|
||||
|
||||
Consider our previous [`getStaticProps` example](#simple-example), but now with Incremental Static Regeneration enabled through the `revalidate` property:
|
||||
|
||||
```jsx
|
||||
function Blog({ posts }) {
|
||||
@@ -261,25 +268,42 @@ export async function getStaticProps() {
|
||||
},
|
||||
// Next.js will attempt to re-generate the page:
|
||||
// - When a request comes in
|
||||
// - At most once every second
|
||||
revalidate: 1, // In seconds
|
||||
// - At most once every 10 seconds
|
||||
revalidate: 10, // In seconds
|
||||
}
|
||||
}
|
||||
|
||||
// This function gets called at build time on server-side.
|
||||
// It may be called again, on a serverless function, if
|
||||
// the path has not been generated.
|
||||
export async function getStaticPaths() {
|
||||
const res = await fetch('https://.../posts')
|
||||
const posts = await res.json()
|
||||
|
||||
// Get the paths we want to pre-render based on posts
|
||||
const paths = posts.map((post) => ({
|
||||
params: { id: post.id },
|
||||
}))
|
||||
|
||||
// We'll pre-render only these paths at build time.
|
||||
// { fallback: blocking } will server-render pages
|
||||
// on-demand if the path doesn't exist.
|
||||
return { paths, fallback: 'blocking' }
|
||||
}
|
||||
|
||||
export default Blog
|
||||
```
|
||||
|
||||
Now the list of blog posts will be revalidated once per second; if you add a new blog post it will be available almost immediately, without having to re-build your app or make a new deployment.
|
||||
When a request is made to a page that was pre-rendered at build time, it will initially show the cached page.
|
||||
|
||||
This works perfectly with [`fallback: true`](#fallback-true). Because now you can have a list of posts that's always up to date with the latest posts, and have a [blog post page](#fallback-pages) that generates blog posts on-demand, no matter how many posts you add or update.
|
||||
- Any requests to the page after the initial request and before 10 seconds are also cached and instantaneous.
|
||||
- After the 10-second window, the next request will still show the cached (stale) page
|
||||
- Next.js triggers a regeneration of the page in the background.
|
||||
- Once the page has been successfully generated, Next.js will invalidate the cache and show the updated product page. If the background regeneration fails, the old page remains unaltered.
|
||||
|
||||
#### Static content at scale
|
||||
When a request is made to a path that hasn’t been generated, Next.js will server-render the page on the first request. Future requests will serve the static file from the cache.
|
||||
|
||||
Unlike traditional SSR, [Incremental Static Regeneration](#incremental-static-regeneration) ensures you retain the benefits of static:
|
||||
|
||||
- No spikes in latency. Pages are served consistently fast
|
||||
- Pages never go offline. If the background page re-generation fails, the old page remains unaltered
|
||||
- Low database and backend load. Pages are re-computed at most once concurrently
|
||||
To learn how to persist the cache globally and handle rollbacks, learn more about [Incremental Static Regeneration](https://vercel.com/docs/next.js/incremental-static-regeneration).
|
||||
|
||||
### Reading files: Use `process.cwd()`
|
||||
|
||||
@@ -648,7 +672,7 @@ The `context` parameter is an object containing the following keys:
|
||||
|
||||
`getServerSideProps` should return an object with:
|
||||
|
||||
- `props` - A **required** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
|
||||
- `props` - An **optional** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
|
||||
- `notFound` - An **optional** boolean value to allow the page to return a 404 status and page. Below is an example of how it works:
|
||||
|
||||
```js
|
||||
|
||||
175
nextjs/docs/basic-features/eslint.md
Normal file
175
nextjs/docs/basic-features/eslint.md
Normal file
@@ -0,0 +1,175 @@
|
||||
---
|
||||
description: Next.js provides an integrated ESLint experience by default. These conformance rules help you use Next.js in the optimal way.
|
||||
---
|
||||
|
||||
# ESLint
|
||||
|
||||
Since version **11.0.0**, Next.js provides an integrated [ESLint](https://eslint.org/) experience out of the box. Add `next lint` as a script to `package.json`:
|
||||
|
||||
```json
|
||||
"scripts": {
|
||||
"lint": "next lint"
|
||||
}
|
||||
```
|
||||
|
||||
Then run `npm run lint` or `yarn lint`:
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
```
|
||||
|
||||
If you don't already have ESLint configured in your application, you will be guided through the installation of the required packages.
|
||||
|
||||
```bash
|
||||
yarn lint
|
||||
|
||||
# You'll see instructions like these:
|
||||
#
|
||||
# Please install eslint and eslint-config-next by running:
|
||||
#
|
||||
# yarn add --dev eslint eslint-config-next
|
||||
#
|
||||
# ...
|
||||
```
|
||||
|
||||
If no ESLint configuration is present, Next.js will create an `.eslintrc` file in the root of your project and automatically configure it with the base configuration:
|
||||
|
||||
```js
|
||||
{
|
||||
"extends": "next"
|
||||
}
|
||||
```
|
||||
|
||||
You can now run `next lint` every time you want to run ESLint to catch errors.
|
||||
|
||||
> The default base configuration (`"extends": "next"`) can be updated at any time and will only be included if no ESLint configuration is present.
|
||||
|
||||
We recommend using an appropriate [integration](https://eslint.org/docs/user-guide/integrations#editors) to view warnings and errors directly in your code editor during development.
|
||||
|
||||
## Linting During Builds
|
||||
|
||||
Once ESLint has been set up, it will automatically run during every build (`next build`). Errors will fail the build, while warnings will not.
|
||||
|
||||
If you do not want ESLint to run as a build step, refer to the documentation for [Ignoring ESLint](/docs/api-reference/next.config.js/ignoring-eslint.md):
|
||||
|
||||
## Linting Custom Directories
|
||||
|
||||
By default, Next.js will run ESLint for all files in the `pages/`, `components/`, and `lib/` directories. However, you can specify which directories using the `dirs` option in the `eslint` config in `next.config.js` for production builds:
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
eslint: {
|
||||
dirs: ['pages', 'utils'], // Only run ESLint on the 'pages' and 'utils' directories during production builds (next build)
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, the `--dir` flag can be used for `next lint`:
|
||||
|
||||
```bash
|
||||
yarn lint --dir pages --dir utils
|
||||
```
|
||||
|
||||
## ESLint Plugin
|
||||
|
||||
Next.js provides an ESLint plugin, [`eslint-plugin-next`](https://www.npmjs.com/package/@next/eslint-plugin-next), making it easier to catch common issues and problems in a Next.js application. The full set of rules is as follows:
|
||||
|
||||
| | Rule | Description |
|
||||
| :-: | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| ✔️ | [next/google-font-display](https://nextjs.org/docs/messages/google-font-display) | Enforce optional or swap font-display behavior with Google Fonts |
|
||||
| ✔️ | [next/google-font-preconnect](https://nextjs.org/docs/messages/google-font-preconnect) | Enforce preconnect usage with Google Fonts |
|
||||
| ✔️ | [next/link-passhref](https://nextjs.org/docs/messages/link-passhref) | Enforce passHref prop usage with custom Link components |
|
||||
| ✔️ | [next/no-css-tags](https://nextjs.org/docs/messages/no-css-tags) | Prevent manual stylesheet tags |
|
||||
| ✔️ | [next/no-document-import-in-page](https://nextjs.org/docs/messages/no-document-import-in-page) | Disallow importing next/document outside of pages/document.js |
|
||||
| ✔️ | [next/no-head-import-in-document](https://nextjs.org/docs/messages/no-head-import-in-document) | Disallow importing next/head in pages/document.js |
|
||||
| ✔️ | [next/no-html-link-for-pages](https://nextjs.org/docs/messages/no-html-link-for-pages) | Prohibit HTML anchor links to pages without a Link component |
|
||||
| ✔️ | [next/no-img-element](https://nextjs.org/docs/messages/no-img-element) | Prohibit usage of HTML <img> element |
|
||||
| ✔️ | [next/no-page-custom-font](https://nextjs.org/docs/messages/no-page-custom-font) | Prevent page-only custom fonts |
|
||||
| ✔️ | [next/no-sync-scripts](https://nextjs.org/docs/messages/no-sync-scripts) | Forbid synchronous scripts |
|
||||
| ✔️ | [next/no-title-in-document-head](https://nextjs.org/docs/messages/no-title-in-document-head) | Disallow using <title> with Head from next/document |
|
||||
| ✔️ | [next/no-unwanted-polyfillio](https://nextjs.org/docs/messages/no-unwanted-polyfillio) | Prevent duplicate polyfills from Polyfill.io |
|
||||
|
||||
- ✔: Enabled in the recommended configuration
|
||||
|
||||
## Base Configuration
|
||||
|
||||
The Next.js base ESLint configuration is automatically generated when `next lint` is run for the first time:
|
||||
|
||||
```js
|
||||
{
|
||||
"extends": "next"
|
||||
}
|
||||
```
|
||||
|
||||
This configuration extends recommended rule sets from various ESLint plugins:
|
||||
|
||||
- [`eslint-plugin-react`](https://www.npmjs.com/package/eslint-plugin-react)
|
||||
- [`eslint-plugin-react-hooks`](https://www.npmjs.com/package/eslint-plugin-react-hooks)
|
||||
- [`eslint-plugin-next`](https://www.npmjs.com/package/@next/eslint-plugin-next)
|
||||
|
||||
You can see the full details of the shareable configuration in the [`eslint-config-next`](https://www.npmjs.com/package/eslint-config-next) package.
|
||||
|
||||
## Disabling Rules
|
||||
|
||||
If you would like to modify or disable any rules provided by the supported plugins (`react`, `react-hooks`, `next`), you can directly change them using the `rules` property in your `.eslintrc`:
|
||||
|
||||
```js
|
||||
{
|
||||
"extends": "next",
|
||||
"rules": {
|
||||
"react/no-unescaped-entities": "off",
|
||||
"@next/next/no-page-custom-font": "off",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Note**: If you need to also include a separate, custom ESLint configuration, it is highly recommended that `eslint-config-next` is extended last after other configurations. For example:
|
||||
>
|
||||
> ```
|
||||
> {
|
||||
> "extends": ["eslint:recommended", "next"]
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> The `next` configuration already handles setting default values for the `parser`, `plugins` and `settings` properties.
|
||||
> There is no need to manually re-declare any of these properties unless you need a different configuration for your use case.
|
||||
> If you include any other shareable configurations, you will need to make sure that these properties are not overwritten or modified.
|
||||
|
||||
### Core Web Vitals
|
||||
|
||||
A stricter `next/core-web-vitals` rule set can also be added in `.eslintrc`:
|
||||
|
||||
```
|
||||
{
|
||||
"extends": ["next", "next/core-web-vitals"]
|
||||
}
|
||||
```
|
||||
|
||||
`next/core-web-vitals` updates `eslint-plugin-next` to error on a number of rules that are warnings by default if they affect [Core Web Vitals](https://web.dev/vitals/).
|
||||
|
||||
> Both `next` and `next/core-web-vitals` entry points are automatically included for new applications built with [Create Next App](/docs/api-reference/create-next-app.md).
|
||||
|
||||
## Usage with Prettier
|
||||
|
||||
ESLint also contains code formatting rules, which can conflict with your existing [Prettier](https://prettier.io/) setup. We recommend including [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) in your ESLint config to make ESLint and Prettier work together.
|
||||
|
||||
```js
|
||||
{
|
||||
"extends": ["next", "prettier"]
|
||||
}
|
||||
```
|
||||
|
||||
## Migrating Existing Config
|
||||
|
||||
If you already have ESLint configured in your application, we recommend extending directly from the Next.js ESLint plugin instead of the shareable configuration.
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
extends: [
|
||||
//...
|
||||
'plugin:@next/next/recommended',
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
This eliminates any risk of collisions that can occur due to importing the same plugin or parser across multiple configurations.
|
||||
100
nextjs/docs/basic-features/font-optimization.md
Normal file
100
nextjs/docs/basic-features/font-optimization.md
Normal file
@@ -0,0 +1,100 @@
|
||||
---
|
||||
description: Next.js supports built-in web font optimization to inline font CSS. Learn more here.
|
||||
---
|
||||
|
||||
# Font Optimization
|
||||
|
||||
Since version **10.2**, Next.js has built-in web font optimization.
|
||||
|
||||
By default, Next.js will automatically inline font CSS at build time, eliminating an extra round trip to fetch font declarations. This results in improvements to [First Contentful Paint (FCP)](https://web.dev/fcp/) and [Largest Contentful Paint (LCP)](https://vercel.com/blog/core-web-vitals#largest-contentful-paint). For example:
|
||||
|
||||
```js
|
||||
// Before
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
// After
|
||||
<style data-href="https://fonts.googleapis.com/css2?family=Inter">
|
||||
@font-face{font-family:'Inter';font-style:normal...
|
||||
</style>
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
To add a web font to your Next.js application, override `next/head`. For example, you can add a font to a specific page:
|
||||
|
||||
```js
|
||||
// pages/index.js
|
||||
|
||||
import Head from 'next/head'
|
||||
|
||||
export default function IndexPage() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</Head>
|
||||
<p>Hello world!</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
or to your entire application with a [Custom `Document`](/docs/advanced-features/custom-document.md).
|
||||
|
||||
```js
|
||||
// pages/_document.js
|
||||
|
||||
import Document, { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
||||
class MyDocument extends Document {
|
||||
render() {
|
||||
return (
|
||||
<Html>
|
||||
<Head>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</Head>
|
||||
<body>
|
||||
<Main />
|
||||
<NextScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument
|
||||
```
|
||||
|
||||
Automatic Webfont Optimization currently supports Google Fonts and Typekit with support for other font providers coming soon. We're also planning to add control over [loading strategies](https://github.com/vercel/next.js/issues/21555) and `font-display` values.
|
||||
|
||||
## Disabling Optimization
|
||||
|
||||
If you do not want Next.js to optimize your fonts, you can opt-out.
|
||||
|
||||
```js
|
||||
// next.config.js
|
||||
|
||||
module.exports = {
|
||||
optimizeFonts: false,
|
||||
}
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
For more information on what to do next, we recommend the following sections:
|
||||
|
||||
<div class="card">
|
||||
<a href="/docs/advanced-features/custom-document.md">
|
||||
<b>Custom Document</b>
|
||||
<small>Learn how to augment your application's html and body tags.</small>
|
||||
</a>
|
||||
</div>
|
||||
@@ -50,6 +50,39 @@ function Home() {
|
||||
export default Home
|
||||
```
|
||||
|
||||
## Image Imports
|
||||
|
||||
You can `import` images that live in your project. (Note that `require` is not supported—only `import`.)
|
||||
|
||||
With direct `import`s, `width`, `height`, and `blurDataURL` will be automatically provided to the image component. Alt text is still needed separately.
|
||||
|
||||
```js
|
||||
import Image from 'next/image'
|
||||
import profilePic from '../public/me.png'
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<>
|
||||
<h1>My Homepage</h1>
|
||||
<Image
|
||||
src={profilePic}
|
||||
alt="Picture of the author"
|
||||
// width={500} automatically provided
|
||||
// height={500} automatically provided
|
||||
// blurDataURL="data:..." automatically provided
|
||||
// Optionally allows to add a blurred version of the image while loading
|
||||
// placeholder="blur"
|
||||
/>
|
||||
<p>Welcome to my homepage!</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
For dynamic or remote images, you'll have to provide [`width`](/docs/api-reference/next/image#width), [`height`](/docs/api-reference/next/image#height) and [`blurDataURL`](/docs/api-reference/next/image#blurdataurl) manually.
|
||||
|
||||
## Properties
|
||||
|
||||
[View all properties](/docs/api-reference/next/image.md) available to the `next/image` component.
|
||||
|
||||
## Configuration
|
||||
@@ -138,6 +171,22 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
### Disable Static Imports
|
||||
|
||||
The default behavior allows you to import static files such as `import icon from './icon.png` and then pass that to the `src` property.
|
||||
|
||||
In some cases, you may wish to disable this feature if it conflicts with other plugins that expect the import to behave differently.
|
||||
|
||||
You can disable static image imports with the following configuration below.
|
||||
|
||||
```js
|
||||
module.exports = {
|
||||
images: {
|
||||
disableStaticImages: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
For more information on what to do next, we recommend the following sections:
|
||||
|
||||
129
nextjs/docs/basic-features/script.md
Normal file
129
nextjs/docs/basic-features/script.md
Normal file
@@ -0,0 +1,129 @@
|
||||
---
|
||||
description: Next.js helps you optimize loading third-party scripts with the built-in next/script component.
|
||||
---
|
||||
|
||||
# Script Component
|
||||
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ------------------------- |
|
||||
| `v11.0.0` | `next/script` introduced. |
|
||||
|
||||
</details>
|
||||
|
||||
The Next.js Script component enables developers to set the loading priority of third-party scripts to save developer time and improve loading performance.
|
||||
|
||||
Websites often need third parties for things like analytics, ads, customer support widgets, and consent management. However, these scripts tend to be heavy on loading performance and can drag down the user experience. Developers often struggle to decide where to place them in an application for optimal loading.
|
||||
|
||||
With `next/script`, you can define the `strategy` property and Next.js will optimize loading for the script:
|
||||
|
||||
- `beforeInteractive`: For critical scripts that need to be fetched and executed **before** the page is interactive, such as bot detection and consent management. These scripts are injected into the initial HTML from the server and run before self-bundled JavaScript is executed.
|
||||
- `afterInteractive` (**default**): For scripts that can fetch and execute **after** the page is interactive, such as tag managers and analytics. These scripts are injected on the client-side and will run after hydration.
|
||||
- `lazyOnload` For scripts that can wait to load during idle time, such as chat support and social media widgets.
|
||||
|
||||
> **Note:** These loading strategies work the same for inline scripts wrapped with `<Script>`. See the inline scripts example below.
|
||||
|
||||
## Usage
|
||||
|
||||
Previously, you needed to define `script` tags inside the `Head` of your Next.js page.
|
||||
|
||||
```js
|
||||
// Before
|
||||
|
||||
// pages/index.js
|
||||
import Head from 'next/head'
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<script async src="https://www.google-analytics.com/analytics.js" />
|
||||
</Head>
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
With `next/script`, you no longer need to wrap scripts in `next/head`. Further, `next/script` should **not** be used in `pages/_document.js` as `next/script` has client-side functionality to ensure loading order. For example:
|
||||
|
||||
```js
|
||||
// After
|
||||
|
||||
// pages/index.js
|
||||
import Script from 'next/script'
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<>
|
||||
<Script src="https://www.google-analytics.com/analytics.js" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Loading Polyfills
|
||||
|
||||
```js
|
||||
import Script from 'next/script'
|
||||
;<Script
|
||||
src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver"
|
||||
strategy="beforeInteractive"
|
||||
/>
|
||||
```
|
||||
|
||||
### Lazy-Loading
|
||||
|
||||
```js
|
||||
import Script from 'next/script'
|
||||
;<Script
|
||||
src="https://connect.facebook.net/en_US/sdk.js"
|
||||
strategy="lazyOnload"
|
||||
/>
|
||||
```
|
||||
|
||||
### Executing Code After Loading (`onLoad`)
|
||||
|
||||
```js
|
||||
import Script from 'next/script'
|
||||
;<Script
|
||||
id="stripe-js"
|
||||
src="https://js.stripe.com/v3/"
|
||||
onLoad={() => {
|
||||
this.setState({ stripe: window.Stripe('pk_test_12345') })
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Inline Scripts
|
||||
|
||||
```js
|
||||
import Script from 'next/script'
|
||||
|
||||
<Script strategy="lazyOnload">
|
||||
{`document.getElementById('banner').removeClass('hidden')`}
|
||||
</Script>
|
||||
|
||||
// or
|
||||
|
||||
<Script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `document.getElementById('banner').removeClass('hidden')`
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
### Forwarding Attributes
|
||||
|
||||
```js
|
||||
import Script from 'next/script'
|
||||
;<Script
|
||||
src="https://www.google-analytics.com/analytics.js"
|
||||
id="analytics"
|
||||
nonce="XUENAJFW"
|
||||
data-test="analytics"
|
||||
/>
|
||||
```
|
||||
@@ -11,9 +11,23 @@ description: Next.js supports TypeScript by default and has built-in types for p
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
Next.js provides an integrated [TypeScript](https://www.typescriptlang.org/) experience out of the box, similar to an IDE.
|
||||
Next.js provides an integrated [TypeScript](https://www.typescriptlang.org/)
|
||||
experience out of the box, similar to an IDE.
|
||||
|
||||
To get started, create an empty `tsconfig.json` file in the root of your project:
|
||||
## `create-next-app` support
|
||||
|
||||
You can create a TypeScript project with [`create-next-app`](https://nextjs.org/docs/api-reference/create-next-app) using the `--ts, --typescript` flag like so:
|
||||
|
||||
```
|
||||
npx create-next-app --ts
|
||||
# or
|
||||
yarn create next-app --typescript
|
||||
```
|
||||
|
||||
## Existing projects
|
||||
|
||||
To get started in an existing project, create an empty `tsconfig.json` file in
|
||||
the root folder:
|
||||
|
||||
```bash
|
||||
touch tsconfig.json
|
||||
@@ -127,3 +141,26 @@ export default MyApp
|
||||
Next.js automatically supports the `tsconfig.json` `"paths"` and `"baseUrl"` options.
|
||||
|
||||
You can learn more about this feature on the [Module Path aliases documentation](/docs/advanced-features/module-path-aliases.md).
|
||||
|
||||
## Type checking next.config.js
|
||||
|
||||
The `next.config.js` file must be a JavaScript file as it does not get parsed by Babel or TypeScript, however you can add some type checking in your IDE using JSDoc as below:
|
||||
|
||||
```js
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* @type {import('next/dist/next-server/server/config').NextConfig}
|
||||
**/
|
||||
const nextConfig = {
|
||||
/* config options here */
|
||||
}
|
||||
|
||||
module.exports = nextConfig
|
||||
```
|
||||
|
||||
## Incremental type checking
|
||||
|
||||
Since `v10.2.1` Next.js supports [incremental type checking](https://www.typescriptlang.org/tsconfig#incremental) when enabled in your `tsconfig.json`, this can help speed up type checking in larger applications.
|
||||
|
||||
It is highly recommended to be on at least `v4.3.2` of TypeScript to experience the [best performance](https://devblogs.microsoft.com/typescript/announcing-typescript-4-3/#lazier-incremental) when leveraging this feature.
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Get started with Next.js in the official documentation, and learn m
|
||||
|
||||
Welcome to the Next.js documentation!
|
||||
|
||||
If you're new to Next.js we recommend that you start with the [learn course](https://nextjs.org/learn/basics/getting-started).
|
||||
If you're new to Next.js we recommend that you start with the [learn course](https://nextjs.org/learn/basics/create-nextjs-app).
|
||||
|
||||
The interactive course with quizzes will guide you through everything you need to know to use Next.js.
|
||||
|
||||
@@ -27,6 +27,14 @@ npx create-next-app
|
||||
yarn create next-app
|
||||
```
|
||||
|
||||
If you want to start with a TypeScript project you can use the `--typescript` flag:
|
||||
|
||||
```bash
|
||||
npx create-next-app --typescript
|
||||
# or
|
||||
yarn create next-app --typescript
|
||||
```
|
||||
|
||||
After the installation is complete, follow the instructions to start the development server. Try editing `pages/index.js` and see the result on your browser.
|
||||
|
||||
For more information on how to use `create-next-app`, you can review the [`create-next-app` documentation](/docs/api-reference/create-next-app.md)
|
||||
@@ -47,7 +55,8 @@ Open `package.json` and add the following `scripts`:
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start"
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -56,6 +65,7 @@ These scripts refer to the different stages of developing an application:
|
||||
- `dev` - Runs [`next dev`](/docs/api-reference/cli.md#development) which starts Next.js in development mode
|
||||
- `build` - Runs [`next build`](/docs/api-reference/cli.md#build) which builds the application for production usage
|
||||
- `start` - Runs [`next start`](/docs/api-reference/cli.md#production) which starts a Next.js production server
|
||||
- `lint` - Runs [`next lint`](/docs/api-reference/cli.md#lint) which sets up Next.js' built-in ESLint configuration
|
||||
|
||||
Next.js is built around the concept of [pages](/docs/basic-features/pages.md). A page is a [React Component](https://reactjs.org/docs/components-and-props.html) exported from a `.js`, `.jsx`, `.ts`, or `.tsx` file in the `pages` directory.
|
||||
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
"title": "Image Optimization",
|
||||
"path": "/docs/basic-features/image-optimization.md"
|
||||
},
|
||||
{
|
||||
"title": "Font Optimization",
|
||||
"path": "/docs/basic-features/font-optimization.md"
|
||||
},
|
||||
{
|
||||
"title": "Static File Serving",
|
||||
"path": "/docs/basic-features/static-file-serving.md"
|
||||
@@ -33,6 +37,10 @@
|
||||
"title": "Fast Refresh",
|
||||
"path": "/docs/basic-features/fast-refresh.md"
|
||||
},
|
||||
{
|
||||
"title": "ESLint",
|
||||
"path": "/docs/basic-features/eslint.md"
|
||||
},
|
||||
{
|
||||
"title": "TypeScript",
|
||||
"path": "/docs/basic-features/typescript.md"
|
||||
@@ -44,6 +52,10 @@
|
||||
{
|
||||
"title": "Supported Browsers and Features",
|
||||
"path": "/docs/basic-features/supported-browsers-features.md"
|
||||
},
|
||||
{
|
||||
"title": "Script",
|
||||
"path": "/docs/basic-features/script.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -196,6 +208,10 @@
|
||||
{
|
||||
"title": "Internationalized Routing",
|
||||
"path": "/docs/advanced-features/i18n-routing.md"
|
||||
},
|
||||
{
|
||||
"title": "Security Headers",
|
||||
"path": "/docs/advanced-features/security-headers.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -336,6 +352,10 @@
|
||||
"title": "Configuring onDemandEntries",
|
||||
"path": "/docs/api-reference/next.config.js/configuring-onDemandEntries.md"
|
||||
},
|
||||
{
|
||||
"title": "Ignoring ESLint",
|
||||
"path": "/docs/api-reference/next.config.js/ignoring-eslint.md"
|
||||
},
|
||||
{
|
||||
"title": "Ignoring TypeScript Errors",
|
||||
"path": "/docs/api-reference/next.config.js/ignoring-typescript-errors.md"
|
||||
|
||||
@@ -236,4 +236,4 @@ If you've ejected Create React App, here are some things to consider:
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more about Next.js by completing our [starter tutorial](https://nextjs.org/learn/basics/getting-started). If you have questions or if this guide didn't work for you, feel free to reach out to our community on [GitHub Discussions](https://github.com/vercel/next.js/discussions).
|
||||
You can learn more about Next.js by completing our [starter tutorial](https://nextjs.org/learn/basics/create-nextjs-app). If you have questions or if this guide didn't work for you, feel free to reach out to our community on [GitHub Discussions](https://github.com/vercel/next.js/discussions).
|
||||
|
||||
@@ -4,6 +4,133 @@ description: Learn how to upgrade Next.js.
|
||||
|
||||
# Upgrade Guide
|
||||
|
||||
## Upgrading from version 10 to 11
|
||||
|
||||
### Upgrade React version to latest
|
||||
|
||||
Most applications already use the latest version of React, with Next.js 11 the minimum React version has been updated to 17.0.2.
|
||||
|
||||
To upgrade you can run the following command:
|
||||
|
||||
```
|
||||
npm install react@latest react-dom@latest
|
||||
```
|
||||
|
||||
Or using `yarn`:
|
||||
|
||||
```
|
||||
yarn add react@latest react-dom@latest
|
||||
```
|
||||
|
||||
### Upgrade Next.js version to latest
|
||||
|
||||
To upgrade you can run the following command in the terminal:
|
||||
|
||||
```
|
||||
npm install next@latest
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
yarn add next@latest
|
||||
```
|
||||
|
||||
### Webpack 5
|
||||
|
||||
Webpack 5 is now the default for all Next.js applications. If you did not have custom webpack configuration your application is already using webpack 5. If you do have custom webpack configuration you can refer to the [Next.js webpack 5 documentation](https://nextjs.org/docs/messages/webpack5) for upgrading guidance.
|
||||
|
||||
### Cleaning the `distDir` is now a default
|
||||
|
||||
The build output directory (defaults to `.next`) is now cleared by default except for the Next.js caches. You can refer to [the cleaning `distDir` RFC](https://github.com/vercel/next.js/discussions/6009) for more information.
|
||||
|
||||
If your application was relying on this behavior previously you can disable the new default behavior by adding the `cleanDistDir: false` flag in `next.config.js`.
|
||||
|
||||
### `PORT` is now supported for `next dev` and `next start`
|
||||
|
||||
Next.js 11 supports the `PORT` environment variable to set the port the application has to run on. Using `-p`/`--port` is still recommended but if you were prohibited from using `-p` in any way you can now use `PORT` as an alternative:
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
PORT=4000 next start
|
||||
```
|
||||
|
||||
### Remove `super.componentDidCatch()` from `pages/_app.js`
|
||||
|
||||
The `next/app` component's `componentDidCatch` has been deprecated since Next.js 9 as it's no longer needed and has since been a no-op, in Next.js 11 it has been removed.
|
||||
|
||||
If your `pages/_app.js` has a custom `componentDidCatch` method you can remove `super.componentDidCatch` as it is no longer needed.
|
||||
|
||||
### Remove `Container` from `pages/_app.js`
|
||||
|
||||
This export has been deprecated since Next.js 9 as it's no longer needed and has since been a no-op with a warning during development. In Next.js 11 it has been removed.
|
||||
|
||||
If your `pages/_app.js` imports `Container` from `next/app` you can remove `Container` as it has been removed. Learn more in [the documentation](https://nextjs.org/docs/messages/app-container-deprecated).
|
||||
|
||||
### Remove `props.url` usage from page components
|
||||
|
||||
This property has been deprecated since Next.js 4 and has since shown a warning during development. With the introduction of `getStaticProps` / `getServerSideProps` these methods already disallowed usage of `props.url`. In Next.js 11 it has been removed completely.
|
||||
|
||||
You can learn more in [the documentation](https://nextjs.org/docs/messages/url-deprecated).
|
||||
|
||||
### Remove `unsized` property on `next/image`
|
||||
|
||||
The `unsized` property on `next/image` was deprecated in Next.js 10.0.1. You can use `layout="fill"` instead. In Next.js 11 `unsized` was removed.
|
||||
|
||||
### Remove `modules` property on `next/dynamic`
|
||||
|
||||
The `modules` and `render` option for `next/dynamic` have been deprecated since Next.js 9.5 showing a warning that it has been deprecated. This was done in order to make `next/dynamic` close to `React.lazy` in API surface. In Next.js 11 the `modules` and `render` options have been removed.
|
||||
|
||||
This option hasn't been mentioned in the documentation since Next.js 8 so it's less likely that your application is using it.
|
||||
|
||||
If you application does use `modules` and `render` you can refer to [the documentation](https://nextjs.org/docs/messages/next-dynamic-modules).
|
||||
|
||||
### Remove `Head.rewind`
|
||||
|
||||
`Head.rewind` has been a no-op since Next.js 9.5, in Next.js 11 it was removed. You can safely remove your usage of `Head.rewind`.
|
||||
|
||||
### Moment.js locales excluded by default
|
||||
|
||||
Moment.js includes translations for a lot of locales by default. Next.js now automatically excludes these locales by default to optimize bundle size for applications using Moment.js.
|
||||
|
||||
To load a specific locale use this snippet:
|
||||
|
||||
```js
|
||||
import moment from 'moment'
|
||||
import 'moment/locale/ja'
|
||||
|
||||
moment.locale('ja')
|
||||
```
|
||||
|
||||
You can opt-out of this new default by adding `excludeDefaultMomentLocales: false` to `next.config.js` if you do not want the new behavior, do note it's highly recommended to not disable this new optimization as it significantly reduces the size of Moment.js.
|
||||
|
||||
### Update usage of `router.events`
|
||||
|
||||
In case you're accessing `router.events` during rendering, in Next.js 11 `router.events` is no longer provided during pre-rendering. Ensure you're accessing `router.events` in `useEffect`:
|
||||
|
||||
```js
|
||||
useEffect(() => {
|
||||
const handleRouteChange = (url, { shallow }) => {
|
||||
console.log(
|
||||
`App is changing to ${url} ${
|
||||
shallow ? 'with' : 'without'
|
||||
} shallow routing`
|
||||
)
|
||||
}
|
||||
|
||||
router.events.on('routeChangeStart', handleRouteChange)
|
||||
|
||||
// If the component is unmounted, unsubscribe
|
||||
// from the event with the `off` method:
|
||||
return () => {
|
||||
router.events.off('routeChangeStart', handleRouteChange)
|
||||
}
|
||||
}, [router])
|
||||
```
|
||||
|
||||
If your application uses `router.router.events` which was an internal property that was not public please make sure to use `router.events` as well.
|
||||
|
||||
## React 16 to 17
|
||||
|
||||
React 17 introduced a new [JSX Transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) that brings a long-time Next.js feature to the wider React ecosystem: Not having to `import React from 'react'` when using JSX. When using React 17 Next.js will automatically use the new transform. This transform does not make the `React` variable global, which was an unintended side-effect of the previous Next.js implementation. A [codemod is available](/docs/advanced-features/codemods.md#add-missing-react-import) to automatically fix cases where you accidentally used `React` without importing it.
|
||||
@@ -15,7 +142,13 @@ There were no breaking changes between version 9 and 10.
|
||||
To upgrade run the following command:
|
||||
|
||||
```
|
||||
npm install next@latest
|
||||
npm install next@10
|
||||
```
|
||||
|
||||
Or using `yarn`:
|
||||
|
||||
```
|
||||
yarn add next@10
|
||||
```
|
||||
|
||||
## Upgrading from version 8 to 9
|
||||
|
||||
14
nextjs/errors/client-side-exception-occurred.md
Normal file
14
nextjs/errors/client-side-exception-occurred.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Client-side Exception Occurred
|
||||
|
||||
#### Why This Error Occurred
|
||||
|
||||
In your production application a client-side error occurred that was not caught by an error boundary. Additional information should be visible in the console tab of your browser.
|
||||
|
||||
#### Possible Ways to Fix It
|
||||
|
||||
Add error boundaries in your React tree to gracefully handle client-side errors and render a fallback view when they occur.
|
||||
|
||||
### Useful Links
|
||||
|
||||
- [Error Boundaries Documentation](https://reactjs.org/docs/error-boundaries.html)
|
||||
- [Custom Error Page Documentation](https://nextjs.org/docs/advanced-features/custom-error-page#more-advanced-error-page-customizing)
|
||||
33
nextjs/errors/future-webpack5-moved-to-webpack5.md
Normal file
33
nextjs/errors/future-webpack5-moved-to-webpack5.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# `future.webpack5` has been moved to `webpack5`
|
||||
|
||||
#### Why This Error Occurred
|
||||
|
||||
The `future.webpack5` option has been moved to `webpack5` in `next.config.js`.
|
||||
|
||||
#### Possible Ways to Fix It
|
||||
|
||||
If you had the value `true` you can remove the option as webpack 5 is now the default for all Next.js apps unless opted out.
|
||||
|
||||
If you had he value `false` you can update `next.config.js`:
|
||||
|
||||
Change `future.webpack5` to `webpack5`.
|
||||
|
||||
Current `next.config.js`:
|
||||
|
||||
```js
|
||||
// next.config.js
|
||||
module.exports = {
|
||||
future: {
|
||||
webpack5: false,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Updated `next.config.js`:
|
||||
|
||||
```js
|
||||
// next.config.js
|
||||
module.exports = {
|
||||
webpack5: false,
|
||||
}
|
||||
```
|
||||
36
nextjs/errors/google-font-display.md
Normal file
36
nextjs/errors/google-font-display.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Google Font Display
|
||||
|
||||
### Why This Error Occurred
|
||||
|
||||
For a Google Font, the `display` descriptor was either not assigned or set to `auto`, `fallback`, or `block`.
|
||||
|
||||
### Possible Ways to Fix It
|
||||
|
||||
For most cases, the best font display strategy for custom fonts is `optional`.
|
||||
|
||||
```jsx
|
||||
import Head from 'next/head'
|
||||
|
||||
export default function IndexPage() {
|
||||
return (
|
||||
<div>
|
||||
<Head>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Krona+One&display=optional"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</Head>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Specifying `display=optional` minimizes the risk of invisible text or layout shift. If swapping to the custom font after it has loaded is important to you, then use `display=swap` instead.
|
||||
|
||||
### When Not To Use It
|
||||
|
||||
If you want to specifically display a font using a `block` or `fallback` strategy, then you can disable this rule.
|
||||
|
||||
### Useful Links
|
||||
|
||||
- [Font-display](https://font-display.glitch.me/)
|
||||
17
nextjs/errors/google-font-preconnect.md
Normal file
17
nextjs/errors/google-font-preconnect.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Google Font Preconnect
|
||||
|
||||
### Why This Error Occurred
|
||||
|
||||
A preconnect resource hint was not used with a request to the Google Fonts domain. Adding `preconnect` is recommended to initiate an early connection to the origin.
|
||||
|
||||
### Possible Ways to Fix It
|
||||
|
||||
Add `rel="preconnect"` to the Google Font domain `<link>` tag:
|
||||
|
||||
```jsx
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
```
|
||||
|
||||
### Useful Links
|
||||
|
||||
- [Preconnect to required origins](https://web.dev/uses-rel-preconnect/)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user