Compare commits
40 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 |
@@ -357,7 +357,8 @@
|
||||
"contributions": [
|
||||
"test",
|
||||
"code",
|
||||
"review"
|
||||
"review",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2411,7 +2412,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1384885?v=4",
|
||||
"profile": "www.usertrack.net",
|
||||
"contributions": [
|
||||
"doc"
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2831,6 +2833,43 @@
|
||||
"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,
|
||||
|
||||
12
.github/workflows/main.yml
vendored
12
.github/workflows/main.yml
vendored
@@ -30,9 +30,9 @@ jobs:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v12-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v12-
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
env:
|
||||
@@ -76,9 +76,9 @@ jobs:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v12-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v12-
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
- name: Build Packages
|
||||
run: yarn build
|
||||
@@ -144,9 +144,9 @@ jobs:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v12-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v12-
|
||||
${{ 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'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -30,3 +30,4 @@ examples/auth2
|
||||
db.sqlite-journal
|
||||
test/integration/**/db.json
|
||||
test/**/*/out
|
||||
.blitz**
|
||||
|
||||
@@ -13,11 +13,14 @@
|
||||
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
|
||||
- Run `rm -rf examples && git add examples`
|
||||
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. Under `nextjs/`, run `./check-pre-compiled.sh` and commit the changes
|
||||
@@ -26,7 +29,7 @@
|
||||
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. Any new features?
|
||||
14. Any doc updates?
|
||||
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`
|
||||
|
||||
12
README.md
12
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-300-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">
|
||||
@@ -288,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>
|
||||
@@ -572,7 +572,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<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>
|
||||
@@ -630,6 +630,12 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<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 |
@@ -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 {
|
||||
|
||||
@@ -29,14 +29,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.37.0",
|
||||
"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.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-final-form": "6.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -48,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",
|
||||
|
||||
@@ -31,11 +31,11 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.37.0",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"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"
|
||||
},
|
||||
@@ -43,7 +43,7 @@
|
||||
"@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",
|
||||
|
||||
@@ -28,18 +28,18 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "0.37.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": "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",
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"blitz": "0.37.0",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"knex": "0.21.16",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"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",
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.37.0",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71"
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "~10.1.0",
|
||||
|
||||
@@ -33,16 +33,16 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.37.0",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"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",
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.37.0",
|
||||
"blitz": "0.38.3-canary.1",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"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",
|
||||
"start-server-and-test": "1.11.7"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "0.37.0",
|
||||
"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/
|
||||
@@ -6,7 +6,7 @@
|
||||
[subrepo]
|
||||
remote = git@github.com:blitz-js/next.js.git
|
||||
branch = canary
|
||||
commit = 8d1a527b8f32fbbc1fde06ce64d3ffd0206acc5d
|
||||
parent = e4e3e757bccea5361c6d986ad09a085e5bed0cf3
|
||||
commit = 4be32b7a54fa68dfcf66d4a5cc7744409c409c7f
|
||||
parent = 194a3720ce56aa3fabace4b07c5faeac1121b8d6
|
||||
method = merge
|
||||
cmdver = 0.4.3
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
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>
|
||||
@@ -27,8 +27,7 @@ yarn create next-app --typescript
|
||||
- **--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. To bootstrap using yarn we recommend to run `yarn create next-app`
|
||||
- **--typescript or --ts** - Creates the default template with TypeScript instead of JavaScript.
|
||||
- **--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?
|
||||
|
||||
|
||||
@@ -373,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>
|
||||
|
||||
@@ -14,12 +14,12 @@ description: Enable Image Optimization with the built-in Image component.
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
| Version | Changes |
|
||||
| --------- | ---------------------------------------------------------------------------- |
|
||||
| `v11.0.0` | Added static imports for `src`. Added `placeholder` and `blurDataURL` props. |
|
||||
| `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>
|
||||
|
||||
@@ -40,7 +40,7 @@ We can serve an optimized image like so:
|
||||
|
||||
```jsx
|
||||
import Image from 'next/image'
|
||||
import profilePic from '../me.png'
|
||||
import profilePic from '../public/me.png'
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
@@ -166,7 +166,17 @@ Should only be used when the image is visible above the fold. Defaults to
|
||||
### placeholder
|
||||
|
||||
A placeholder to use while the image is loading, possible values are `blur` or `empty`. Defaults to `empty`.
|
||||
When `placeholder="blur"`, the `blurDataURL` will be used as the placeholder. If the `src` is an object from a static import, then `blurDataURL` will automatically be populated. If the `src` is a string, then you must provide the [`blurDataURL` property](#blurdataurl).
|
||||
|
||||
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
|
||||
|
||||
@@ -211,6 +221,13 @@ 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,
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -112,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
|
||||
|
||||
@@ -149,6 +149,16 @@ A stricter `next/core-web-vitals` rule set can also be added in `.eslintrc`:
|
||||
|
||||
> 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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -4,89 +4,126 @@ description: Next.js helps you optimize loading third-party scripts with the bui
|
||||
|
||||
# Script Component
|
||||
|
||||
Since version **11**, Next.js has a built-in Script component.
|
||||
<details>
|
||||
<summary><b>Version History</b></summary>
|
||||
|
||||
Example of usage
|
||||
| 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'
|
||||
|
||||
// Before
|
||||
<Script
|
||||
async
|
||||
src="https://www.google-analytics.com/analytics.js"
|
||||
/>
|
||||
|
||||
// After
|
||||
<Script
|
||||
src="https://www.google-analytics.com/analytics.js"
|
||||
;<Script
|
||||
src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver"
|
||||
strategy="beforeInteractive"
|
||||
/>
|
||||
```
|
||||
|
||||
Three loading strategies will be initially supported for wrapping third-party scripts:
|
||||
### Lazy-Loading
|
||||
|
||||
- beforeInteractive
|
||||
- script is fetched and executed _before_ page is interactive (i.e. before self-bundled javascript is executed)
|
||||
- script is injected in SSR’s HTML - similar to self-bundled JS
|
||||
- afterInteractive (**default**)
|
||||
- script is fetched and executed _after_ page is interactive (i.e. after self-bundled javascript is executed)
|
||||
- script is injected during hydration and will execute soon after hydration
|
||||
- lazyOnload
|
||||
- script is injected at onload, and will execute in a subsequent idle period (using `requestIdleCallback`)
|
||||
```js
|
||||
import Script from 'next/script'
|
||||
;<Script
|
||||
src="https://connect.facebook.net/en_US/sdk.js"
|
||||
strategy="lazyOnload"
|
||||
/>
|
||||
```
|
||||
|
||||
NOTE: above strategies work the same for inline scripts wrapped with ScriptLoader.
|
||||
### Executing Code After Loading (`onLoad`)
|
||||
|
||||
Example scenarios
|
||||
```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'
|
||||
|
||||
|
||||
// Loading polyfills before-interactive
|
||||
<Script
|
||||
src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver"
|
||||
strategy="beforeInteractive"
|
||||
></Script>
|
||||
|
||||
// Lazy load FB scripts
|
||||
<Script
|
||||
src="https://connect.facebook.net/en_US/sdk.js"
|
||||
strategy="lazyOnload"
|
||||
></Script>
|
||||
|
||||
// Use the onLoad callback to execute code on script load
|
||||
<Script id="stripe-js" src="https://js.stripe.com/v3/" onLoad={() => {
|
||||
this.setState({stripe: window.Stripe('pk_test_12345')});
|
||||
}}></Script>
|
||||
|
||||
// Loading strategy works for inline scripts too
|
||||
<Script strategy="lazyOnload">
|
||||
{`document.getElementById('banner').removeClass('hidden')`}
|
||||
</Script>
|
||||
|
||||
// or
|
||||
|
||||
<Script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `document.getElementById('banner').removeClass('hidden')`,
|
||||
__html: `document.getElementById('banner').removeClass('hidden')`
|
||||
}}
|
||||
>
|
||||
</Script>
|
||||
/>
|
||||
```
|
||||
|
||||
// All script attributes are forwarded to the final element
|
||||
<Script
|
||||
### Forwarding Attributes
|
||||
|
||||
```js
|
||||
import Script from 'next/script'
|
||||
;<Script
|
||||
src="https://www.google-analytics.com/analytics.js"
|
||||
id="analytics"
|
||||
nonce="XUENAJFW"
|
||||
data-test="analytics"
|
||||
></Script>
|
||||
/>
|
||||
```
|
||||
|
||||
## Which third-party scripts to wrap with Script Loader
|
||||
|
||||
We recommend the following Script Loader strategies for these categories of third-party scripts
|
||||
|
||||
| Loading strategy | third-party categories |
|
||||
| ----------------- | -------------------------------------------------------------------------------------------- |
|
||||
| beforeInteractive | polyfill.io<br>Bot detection, security & authentication<br>User consent management (GDPR) |
|
||||
| afterInteractive | Tag-managers<br>Analytics |
|
||||
| lazyOnload | customer relationship management eg. Google feedback, chat support widget<br>social networks |
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
{
|
||||
"title": "Supported Browsers and Features",
|
||||
"path": "/docs/basic-features/supported-browsers-features.md"
|
||||
},
|
||||
{
|
||||
"title": "Script",
|
||||
"path": "/docs/basic-features/script.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -204,6 +208,10 @@
|
||||
{
|
||||
"title": "Internationalized Routing",
|
||||
"path": "/docs/advanced-features/i18n-routing.md"
|
||||
},
|
||||
{
|
||||
"title": "Security Headers",
|
||||
"path": "/docs/advanced-features/security-headers.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Learn how to upgrade Next.js.
|
||||
|
||||
## Upgrading from version 10 to 11
|
||||
|
||||
## Upgrade React version to latest
|
||||
### 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.
|
||||
|
||||
@@ -22,6 +22,20 @@ 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.
|
||||
@@ -128,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
|
||||
|
||||
@@ -6,7 +6,7 @@ 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 removed the option as webpack 5 is now the default for all Next.js apps unless opted out.
|
||||
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`:
|
||||
|
||||
|
||||
@@ -373,7 +373,28 @@
|
||||
"path": "/errors/undefined-webpack-config.md"
|
||||
},
|
||||
{ "title": "url-deprecated", "path": "/errors/url-deprecated.md" },
|
||||
{ "title": "webpack5", "path": "/errors/webpack5.md" }
|
||||
{ "title": "webpack5", "path": "/errors/webpack5.md" },
|
||||
{
|
||||
"title": "client-side-exception-occurred",
|
||||
"path": "/errors/client-side-exception-occurred.md"
|
||||
},
|
||||
{
|
||||
"title": "future-webpack5-moved-to-webpack5",
|
||||
"path": "/errors/future-webpack5-moved-to-webpack5.md"
|
||||
},
|
||||
{
|
||||
"title": "link-multiple-children",
|
||||
"path": "/errors/link-multiple-children.md"
|
||||
},
|
||||
{ "title": "no-img-element", "path": "/errors/no-img-element.md" },
|
||||
{
|
||||
"title": "non-dynamic-getstaticpaths-usage",
|
||||
"path": "/errors/non-dynamic-getstaticpaths-usage.md"
|
||||
},
|
||||
{
|
||||
"title": "placeholder-blur-data-url",
|
||||
"path": "/errors/placeholder-blur-data-url.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -9,7 +9,7 @@ An HTML `<img>` element was used to display an image. For better performance and
|
||||
Import and use the `<Image />` component:
|
||||
|
||||
```jsx
|
||||
import { Image } from 'next/image'
|
||||
import Image from 'next/image'
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
|
||||
@@ -11,7 +11,7 @@ A synchronous script was used which can impact your webpage's performance.
|
||||
Use the Script component with the right loading strategy to defer loading of the script until necessary.
|
||||
|
||||
```jsx
|
||||
import Script from 'next/experimental-script'
|
||||
import Script from 'next/script'
|
||||
|
||||
const Home = () => {
|
||||
return (
|
||||
@@ -25,8 +25,6 @@ const Home = () => {
|
||||
export default Home
|
||||
```
|
||||
|
||||
Note: This is still an experimental feature and needs to be enabled via the `experimental.scriptLoader` flag in `next.config.js`.
|
||||
|
||||
### Useful Links
|
||||
|
||||
- [Efficiently load third-party JavaScript](https://web.dev/efficiently-load-third-party-javascript/)
|
||||
|
||||
@@ -17,5 +17,5 @@
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
}
|
||||
},
|
||||
"version": "11.0.0"
|
||||
"version": "11.0.1"
|
||||
}
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
"lint-typescript": "lerna run typescript",
|
||||
"lint-eslint": "eslint . --ext js,jsx,ts,tsx --max-warnings=0",
|
||||
"lint-no-typescript": "run-p prettier-check lint-eslint",
|
||||
"lint": "run-p lint-typescript prettier-check lint-eslint",
|
||||
"lint": "run-p lint-typescript prettier-check lint-eslint lint-language",
|
||||
"lint-fix": "yarn prettier-fix && eslint . --ext js,jsx,ts,tsx --fix --max-warnings=0",
|
||||
"lint-language": "alex .",
|
||||
"prettier-check": "prettier --check .",
|
||||
"prettier-fix": "prettier --write .",
|
||||
"types": "lerna run types --stream",
|
||||
@@ -44,6 +45,7 @@
|
||||
"@babel/preset-react": "7.12.10",
|
||||
"@fullhuman/postcss-purgecss": "1.3.0",
|
||||
"@mdx-js/loader": "0.18.0",
|
||||
"@svgr/webpack": "5.5.0",
|
||||
"@testing-library/react": "11.2.5",
|
||||
"@types/cheerio": "0.22.16",
|
||||
"@types/fs-extra": "8.1.0",
|
||||
@@ -56,6 +58,7 @@
|
||||
"@zeit/next-sass": "1.0.2-canary.2",
|
||||
"@zeit/next-typescript": "1.1.2-canary.0",
|
||||
"abort-controller": "3.0.0",
|
||||
"alex": "9.1.0",
|
||||
"amphtml-validator": "1.0.33",
|
||||
"async-sema": "3.0.1",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
@@ -80,6 +83,7 @@
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"execa": "2.0.3",
|
||||
"express": "4.17.0",
|
||||
"faker": "5.5.3",
|
||||
"faunadb": "2.6.1",
|
||||
"firebase": "7.14.5",
|
||||
"fs-extra": "^9.1.0",
|
||||
@@ -112,8 +116,8 @@
|
||||
"prettier": "2.2.1",
|
||||
"pretty-bytes": "5.3.0",
|
||||
"pretty-ms": "7.0.0",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-dom": "18.0.0-alpha-ed6c091fe-20210701",
|
||||
"react-ssr-prepass": "1.0.8",
|
||||
"release": "6.3.0",
|
||||
"request-promise-core": "1.1.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Create Next App
|
||||
|
||||
The easiest way to get started with Next.js is by using `create-next-app`. This simple CLI tool enables you to quickly start building a new Next.js application, with everything set up for you. You can create a new app using the default Next.js template, or by using one of the [official Next.js examples](https://github.com/vercel/next.js/tree/canary/examples). To get started, use the following command:
|
||||
The easiest way to get started with Next.js is by using `create-next-app`. This CLI tool enables you to quickly start building a new Next.js application, with everything set up for you. You can create a new app using the default Next.js template, or by using one of the [official Next.js examples](https://github.com/vercel/next.js/tree/canary/examples). To get started, use the following command:
|
||||
|
||||
```bash
|
||||
npx create-next-app
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "create-next-app",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"keywords": [
|
||||
"react",
|
||||
"next",
|
||||
@@ -44,7 +44,7 @@
|
||||
"prompts": "2.1.0",
|
||||
"rimraf": "3.0.0",
|
||||
"tar": "4.4.10",
|
||||
"typescript": "4.1.5",
|
||||
"typescript": "4.3.4",
|
||||
"update-check": "1.5.4",
|
||||
"validate-npm-package-name": "3.0.0"
|
||||
},
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 25 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 25 KiB |
@@ -58,6 +58,9 @@ module.exports = {
|
||||
[require.resolve('eslint-import-resolver-node')]: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
},
|
||||
[require.resolve('eslint-import-resolver-typescript')]: {
|
||||
alwaysTryTypes: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "eslint-config-next",
|
||||
"private": "true",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"description": "ESLint configuration used by NextJS.",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
@@ -10,10 +10,11 @@
|
||||
"directory": "packages/eslint-config-next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@next/eslint-plugin-next": "11.0.0",
|
||||
"@next/eslint-plugin-next": "11.0.1",
|
||||
"@rushstack/eslint-patch": "^1.0.6",
|
||||
"@typescript-eslint/parser": "^4.20.0",
|
||||
"eslint-import-resolver-node": "^0.3.4",
|
||||
"eslint-import-resolver-typescript": "^2.4.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
"eslint-plugin-react": "^7.23.1",
|
||||
|
||||
@@ -44,9 +44,7 @@ module.exports = {
|
||||
|
||||
const hasAnchorChild = children.some(
|
||||
(attr) =>
|
||||
attr.type === 'JSXElement' &&
|
||||
attr.openingElement.name.name === 'a' &&
|
||||
attr.closingElement.name.name === 'a'
|
||||
attr.type === 'JSXElement' && attr.openingElement.name.name === 'a'
|
||||
)
|
||||
|
||||
if (!hasAnchorChild && !hasPassHref) {
|
||||
@@ -56,7 +54,7 @@ module.exports = {
|
||||
attributes.value('passHref') !== true
|
||||
? 'must be set to true'
|
||||
: 'is missing'
|
||||
}. See https://nextjs.org/docs/messages/link-passhref.`,
|
||||
}. See https://nextjs.org/docs/messages/link-passhref`,
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
@@ -21,7 +21,7 @@ module.exports = {
|
||||
|
||||
context.report({
|
||||
node,
|
||||
message: `Do not use <img>. Use Image from 'next/image' instead. See https://nextjs.org/docs/messages/no-img-element.`,
|
||||
message: `Do not use <img>. Use <Image> from 'blitz' instead. See https://nextjs.org/docs/messages/no-img-element.`,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@next/eslint-plugin-next",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"description": "ESLint plugin for NextJS.",
|
||||
"main": "lib/index.js",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@next/bundle-analyzer",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
34
nextjs/packages/next-codemod/lib/cra-to-next/gitignore
Normal file
34
nextjs/packages/next-codemod/lib/cra-to-next/gitignore
Normal file
@@ -0,0 +1,34 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
@@ -1,5 +1,5 @@
|
||||
// @ts-ignore internal module
|
||||
import Runner from 'jscodeshift/src/runner'
|
||||
import Runner from 'jscodeshift/src/Runner'
|
||||
|
||||
export default function runJscodeshift(
|
||||
transformerPath: string,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@next/codemod",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "4.1.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@next/env",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"keywords": [
|
||||
"react",
|
||||
"next",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@next/mdx",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@next/plugin-storybook",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"repository": {
|
||||
"url": "vercel/next.js",
|
||||
"directory": "packages/next-plugin-storybook"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@next/polyfill-module",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)",
|
||||
"main": "dist/polyfill-module.js",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "@next/polyfill-nomodule",
|
||||
"version": "11.0.0",
|
||||
"version": "11.0.1",
|
||||
"description": "A polyfill for non-dead, nomodule browsers.",
|
||||
"main": "dist/polyfill-nomodule.js",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { readFileSync } from 'fs'
|
||||
import JSON5 from 'next/dist/compiled/json5'
|
||||
|
||||
import { createConfigItem, loadOptions } from 'next/dist/compiled/babel/core'
|
||||
import loadConfig from 'next/dist/compiled/babel/core-lib-config'
|
||||
|
||||
import { NextBabelLoaderOptions, NextJsLoaderContext } from './types'
|
||||
import { consumeIterator } from './util'
|
||||
import { isPageFile as isPageFileFn } from '../../utils'
|
||||
|
||||
const nextDistPath = /(next[\\/]dist[\\/]next-server[\\/]lib)|(next[\\/]dist[\\/]client)|(next[\\/]dist[\\/]pages)/
|
||||
|
||||
@@ -42,8 +44,8 @@ function getCacheCharacteristics(
|
||||
filename: string
|
||||
): CharacteristicsGermaneToCaching {
|
||||
const { isServer, pagesDir } = loaderOptions
|
||||
const isPageFile = filename.startsWith(pagesDir)
|
||||
const isNextDist = nextDistPath.test(filename)
|
||||
const isPageFile = !isNextDist && isPageFileFn(filename.replace(pagesDir, ''))
|
||||
const hasModuleExports = source.indexOf('module.exports') !== -1
|
||||
const fileExt = fileExtensionRegex.exec(filename)?.[1] || 'unknown'
|
||||
|
||||
@@ -151,7 +153,7 @@ const isJsFile = /\.js$/
|
||||
function getCustomBabelConfig(configFilePath: string) {
|
||||
if (isJsonFile.exec(configFilePath)) {
|
||||
const babelConfigRaw = readFileSync(configFilePath, 'utf8')
|
||||
return JSON.parse(babelConfigRaw)
|
||||
return JSON5.parse(babelConfigRaw)
|
||||
} else if (isJsFile.exec(configFilePath)) {
|
||||
return require(configFilePath)
|
||||
}
|
||||
|
||||
@@ -35,30 +35,39 @@ export default function NoAnonymousDefaultExport({
|
||||
|
||||
switch (def.type) {
|
||||
case 'ArrowFunctionExpression': {
|
||||
warn(
|
||||
[
|
||||
chalk.yellow.bold(
|
||||
'Anonymous arrow functions cause Fast Refresh to not preserve local component state.'
|
||||
),
|
||||
'Please add a name to your function, for example:',
|
||||
'',
|
||||
chalk.bold('Before'),
|
||||
chalk.cyan('export default () => <div />;'),
|
||||
'',
|
||||
chalk.bold('After'),
|
||||
chalk.cyan('const Named = () => <div />;'),
|
||||
chalk.cyan('export default Named;'),
|
||||
'',
|
||||
`A codemod is available to fix the most common cases: ${chalk.cyan(
|
||||
'https://nextjs.link/codemod-ndc'
|
||||
)}`,
|
||||
].join('\n')
|
||||
)
|
||||
if (
|
||||
!process.env.__NEXT_TEST_MODE ||
|
||||
!!process.env.__NEXT_TEST_ANON_EXPORT
|
||||
) {
|
||||
warn(
|
||||
[
|
||||
chalk.yellow.bold(
|
||||
'Anonymous arrow functions cause Fast Refresh to not preserve local component state.'
|
||||
),
|
||||
'Please add a name to your function, for example:',
|
||||
'',
|
||||
chalk.bold('Before'),
|
||||
chalk.cyan('export default () => <div />;'),
|
||||
'',
|
||||
chalk.bold('After'),
|
||||
chalk.cyan('const Named = () => <div />;'),
|
||||
chalk.cyan('export default Named;'),
|
||||
'',
|
||||
`A codemod is available to fix the most common cases: ${chalk.cyan(
|
||||
'https://nextjs.link/codemod-ndc'
|
||||
)}`,
|
||||
].join('\n')
|
||||
)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'FunctionDeclaration': {
|
||||
const isAnonymous = !Boolean(def.id)
|
||||
if (isAnonymous) {
|
||||
if (
|
||||
isAnonymous &&
|
||||
(!process.env.__NEXT_TEST_MODE ||
|
||||
!!process.env.__NEXT_TEST_ANON_EXPORT)
|
||||
) {
|
||||
warn(
|
||||
[
|
||||
chalk.yellow.bold(
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ClientPagesLoaderOptions } from './webpack/loaders/next-client-pages-lo
|
||||
import { ServerlessLoaderQuery } from './webpack/loaders/next-serverless-loader'
|
||||
import { LoadedEnvFiles } from '@next/env'
|
||||
import { NextConfig } from '../next-server/server/config'
|
||||
import { convertPageFilePathToRoutePath } from './utils'
|
||||
|
||||
type PagesMapping = {
|
||||
[page: string]: string
|
||||
@@ -22,19 +23,19 @@ export function createPagesMapping(
|
||||
const previousPages: PagesMapping = {}
|
||||
const pages: PagesMapping = pagePaths.reduce(
|
||||
(result: PagesMapping, pagePath): PagesMapping => {
|
||||
let page = `${pagePath
|
||||
let page = `${convertPageFilePathToRoutePath(pagePath)
|
||||
.replace(new RegExp(`\\.+(${extensions.join('|')})$`), '')
|
||||
.replace(/\\/g, '/')}`.replace(/\/index$/, '')
|
||||
|
||||
const pageKey = page === '' ? '/' : page
|
||||
let pageKey = page === '' ? '/' : page
|
||||
|
||||
if (pageKey in result) {
|
||||
warn(
|
||||
`Duplicate page detected. ${chalk.cyan(
|
||||
join('pages', previousPages[pageKey])
|
||||
)} and ${chalk.cyan(
|
||||
join('pages', pagePath)
|
||||
)} both resolve to ${chalk.cyan(pageKey)}.`
|
||||
previousPages[pageKey]
|
||||
)} and ${chalk.cyan(pagePath)} both resolve to ${chalk.cyan(
|
||||
pageKey
|
||||
)}.`
|
||||
)
|
||||
} else {
|
||||
previousPages[pageKey] = pagePath
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
PUBLIC_DIR_MIDDLEWARE_CONFLICT,
|
||||
} from '../lib/constants'
|
||||
import { fileExists } from '../lib/file-exists'
|
||||
import { findPagesDir } from '../lib/find-pages-dir'
|
||||
import loadCustomRoutes, {
|
||||
CustomRoutes,
|
||||
getRedirectStatus,
|
||||
@@ -125,7 +124,7 @@ export default async function build(
|
||||
const nextBuildSpan = trace('next-build')
|
||||
|
||||
return nextBuildSpan.traceAsyncFn(async () => {
|
||||
// attempt to load global env values so they are available in next.config.js
|
||||
// attempt to load global env values so they are available in blitz.config.js
|
||||
const { loadedEnvFiles } = nextBuildSpan
|
||||
.traceChild('load-dotenv')
|
||||
.traceFn(() => loadEnvConfig(dir, false, Log))
|
||||
@@ -162,7 +161,7 @@ export default async function build(
|
||||
setGlobal('telemetry', telemetry)
|
||||
|
||||
const publicDir = path.join(dir, 'public')
|
||||
const pagesDir = findPagesDir(dir)
|
||||
const pagesDir = dir
|
||||
const hasPublicDir = await fileExists(publicDir)
|
||||
|
||||
telemetry.record(
|
||||
@@ -192,7 +191,13 @@ export default async function build(
|
||||
const verifyResult = await nextBuildSpan
|
||||
.traceChild('verify-typescript-setup')
|
||||
.traceAsyncFn(() =>
|
||||
verifyTypeScriptSetup(dir, pagesDir, !ignoreTypeScriptErrors, cacheDir)
|
||||
verifyTypeScriptSetup(
|
||||
dir,
|
||||
pagesDir,
|
||||
!ignoreTypeScriptErrors,
|
||||
!config.images.disableStaticImages,
|
||||
cacheDir
|
||||
)
|
||||
)
|
||||
|
||||
const typeCheckEnd = process.hrtime(typeCheckStart)
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
SERVER_PROPS_SSG_CONFLICT,
|
||||
} from '../lib/constants'
|
||||
import prettyBytes from '../lib/pretty-bytes'
|
||||
import { recursiveReadDir } from '../lib/recursive-readdir'
|
||||
import { recursiveFindPages } from '../lib/recursive-readdir'
|
||||
import { getRouteMatcher, getRouteRegex } from '../next-server/lib/router/utils'
|
||||
import { isDynamicRoute } from '../next-server/lib/router/utils/is-dynamic'
|
||||
import escapePathDelimiters from '../next-server/lib/router/utils/escape-path-delimiters'
|
||||
@@ -49,14 +49,35 @@ const fsStat = (file: string) => {
|
||||
return (fileStats[file] = fileSize(file))
|
||||
}
|
||||
|
||||
export const topLevelFoldersThatMayContainPages = [
|
||||
'pages',
|
||||
'src',
|
||||
'app',
|
||||
'integrations',
|
||||
]
|
||||
|
||||
export function convertPageFilePathToRoutePath(filePath: string) {
|
||||
return filePath
|
||||
.replace(/^.*?[\\/]pages[\\/]/, '/')
|
||||
.replace(/^.*?[\\/]api[\\/]/, '/api/')
|
||||
}
|
||||
|
||||
export function isPageFile(filePathFromAppRoot: string) {
|
||||
return (
|
||||
/[\\/]pages[\\/]/.test(filePathFromAppRoot) ||
|
||||
/[\\/]api[\\/]/.test(filePathFromAppRoot)
|
||||
)
|
||||
}
|
||||
|
||||
export function buildPageExtensionRegex(pageExtensions: string[]) {
|
||||
return new RegExp(`(?<!\\.test|\\.spec)\\.(?:${pageExtensions.join('|')})$`)
|
||||
}
|
||||
|
||||
export function collectPages(
|
||||
directory: string,
|
||||
pageExtensions: string[]
|
||||
): Promise<string[]> {
|
||||
return recursiveReadDir(
|
||||
directory,
|
||||
new RegExp(`\\.(?:${pageExtensions.join('|')})$`)
|
||||
)
|
||||
return recursiveFindPages(directory, buildPageExtensionRegex(pageExtensions))
|
||||
}
|
||||
|
||||
export interface PageInfo {
|
||||
|
||||
@@ -3,6 +3,7 @@ import chalk from 'chalk'
|
||||
import crypto from 'crypto'
|
||||
import { readFileSync } from 'fs'
|
||||
import { codeFrameColumns } from 'next/dist/compiled/babel/code-frame'
|
||||
import semver from 'next/dist/compiled/semver'
|
||||
import { isWebpack5, webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
import path, { join as pathJoin, relative as relativePath } from 'path'
|
||||
import {
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
PAGES_DIR_ALIAS,
|
||||
} from '../lib/constants'
|
||||
import { fileExists } from '../lib/file-exists'
|
||||
import { getPackageVersion } from '../lib/get-package-version'
|
||||
import { CustomRoutes } from '../lib/load-custom-routes.js'
|
||||
import { getTypeScriptConfiguration } from '../lib/typescript/getTypeScriptConfiguration'
|
||||
import {
|
||||
@@ -50,20 +52,7 @@ import WebpackConformancePlugin, {
|
||||
} from './webpack/plugins/webpack-conformance-plugin'
|
||||
import { WellKnownErrorsPlugin } from './webpack/plugins/wellknown-errors-plugin'
|
||||
import { regexLikeCss } from './webpack/config/blocks/css'
|
||||
|
||||
import fs from 'fs'
|
||||
import { getProjectRoot } from '../server/lib/utils'
|
||||
|
||||
/* ------ Blitz.js ------- */
|
||||
function doesDbModuleExist() {
|
||||
const projectRoot = getProjectRoot()
|
||||
return (
|
||||
fs.existsSync(path.join(projectRoot, 'db/index.js')) ||
|
||||
fs.existsSync(path.join(projectRoot, 'db/index.ts')) ||
|
||||
fs.existsSync(path.join(projectRoot, 'db/index.tsx'))
|
||||
)
|
||||
}
|
||||
/* ------ Blitz.js ------- */
|
||||
import { existsSync } from 'fs'
|
||||
|
||||
type ExcludesFalse = <T>(x: T | false) => x is T
|
||||
|
||||
@@ -244,6 +233,18 @@ export default async function getBaseWebpackConfig(
|
||||
rewrites.afterFiles.length > 0 ||
|
||||
rewrites.fallback.length > 0
|
||||
const hasReactRefresh: boolean = dev && !isServer
|
||||
const reactDomVersion = await getPackageVersion({
|
||||
cwd: dir,
|
||||
name: 'react-dom',
|
||||
})
|
||||
const hasReactExperimental: boolean =
|
||||
Boolean(reactDomVersion) && reactDomVersion!.includes('experimental') // blitz
|
||||
const hasReact18: boolean =
|
||||
(Boolean(reactDomVersion) &&
|
||||
(semver.gte(reactDomVersion!, '18.0.0') ||
|
||||
semver.coerce(reactDomVersion)?.version === '18.0.0')) ||
|
||||
hasReactExperimental // blitz
|
||||
const hasReactRoot: boolean = config.experimental.reactRoot || hasReact18
|
||||
|
||||
const babelConfigFile = await [
|
||||
'.babelrc',
|
||||
@@ -265,6 +266,12 @@ export default async function getBaseWebpackConfig(
|
||||
|
||||
const distDir = path.join(dir, config.distDir)
|
||||
|
||||
/* ------ Blitz.js ------- */
|
||||
const hasDbModule =
|
||||
existsSync(path.join(dir, 'db/index.js')) ||
|
||||
existsSync(path.join(dir, 'db/index.ts'))
|
||||
/* ------ Blitz.js ------- */
|
||||
|
||||
// Webpack 5 can use the faster babel loader, webpack 5 has built-in caching for loaders
|
||||
// For webpack 4 the old loader is used as it has external caching
|
||||
const babelLoader = isWebpack5
|
||||
@@ -498,7 +505,7 @@ export default async function getBaseWebpackConfig(
|
||||
|
||||
// Contains various versions of the Webpack SplitChunksPlugin used in different build types
|
||||
const splitChunksConfigs: {
|
||||
[propName: string]: webpack.Options.SplitChunksOptions
|
||||
[propName: string]: webpack.Options.SplitChunksOptions | false
|
||||
} = {
|
||||
dev: {
|
||||
cacheGroups: {
|
||||
@@ -599,9 +606,9 @@ export default async function getBaseWebpackConfig(
|
||||
}
|
||||
|
||||
// Select appropriate SplitChunksPlugin config for this build
|
||||
let splitChunksConfig: webpack.Options.SplitChunksOptions
|
||||
let splitChunksConfig: webpack.Options.SplitChunksOptions | false
|
||||
if (dev) {
|
||||
splitChunksConfig = splitChunksConfigs.dev
|
||||
splitChunksConfig = isWebpack5 ? false : splitChunksConfigs.dev
|
||||
} else {
|
||||
splitChunksConfig = splitChunksConfigs.prodGranular
|
||||
}
|
||||
@@ -899,9 +906,7 @@ export default async function getBaseWebpackConfig(
|
||||
entry: async () => {
|
||||
return {
|
||||
...(clientEntries ? clientEntries : {}),
|
||||
...(isServer && doesDbModuleExist()
|
||||
? { 'blitz-db': './db/index' }
|
||||
: {}),
|
||||
...(isServer && hasDbModule ? { 'blitz-db': './db/index' } : {}),
|
||||
...entrypoints,
|
||||
}
|
||||
},
|
||||
@@ -931,7 +936,7 @@ export default async function getBaseWebpackConfig(
|
||||
: {}),
|
||||
// we must set publicPath to an empty value to override the default of
|
||||
// auto which doesn't work in IE11
|
||||
publicPath: '',
|
||||
publicPath: `${config.assetPrefix || ''}/_next/`,
|
||||
path:
|
||||
isServer && isWebpack5 && !dev
|
||||
? path.join(outputPath, 'chunks')
|
||||
@@ -950,7 +955,7 @@ export default async function getBaseWebpackConfig(
|
||||
? 'static/webpack/[id].[fullhash].hot-update.js'
|
||||
: 'static/webpack/[id].[hash].hot-update.js',
|
||||
hotUpdateMainFilename: isWebpack5
|
||||
? 'static/webpack/[fullhash].hot-update.json'
|
||||
? 'static/webpack/[fullhash].[runtime].hot-update.json'
|
||||
: 'static/webpack/[hash].hot-update.json',
|
||||
// This saves chunks with the name given via `import()`
|
||||
chunkFilename: isServer
|
||||
@@ -1039,16 +1044,6 @@ export default async function getBaseWebpackConfig(
|
||||
use: { loader: require.resolve('null-loader') },
|
||||
},
|
||||
]),
|
||||
...(!config.images.disableStaticImages && isWebpack5
|
||||
? [
|
||||
{
|
||||
test: /\.(png|svg|jpg|jpeg|gif|webp|ico|bmp)$/i,
|
||||
loader: 'next-image-loader',
|
||||
issuer: { not: regexLikeCss },
|
||||
dependency: { not: ['url'] },
|
||||
},
|
||||
]
|
||||
: []),
|
||||
].filter(Boolean),
|
||||
},
|
||||
plugins: [
|
||||
@@ -1111,9 +1106,7 @@ export default async function getBaseWebpackConfig(
|
||||
'process.env.__NEXT_STRICT_MODE': JSON.stringify(
|
||||
config.reactStrictMode
|
||||
),
|
||||
'process.env.__NEXT_REACT_ROOT': JSON.stringify(
|
||||
config.experimental.reactRoot
|
||||
),
|
||||
'process.env.__NEXT_REACT_ROOT': JSON.stringify(hasReactRoot),
|
||||
'process.env.__NEXT_OPTIMIZE_FONTS': JSON.stringify(
|
||||
config.optimizeFonts && !dev
|
||||
),
|
||||
@@ -1371,12 +1364,13 @@ export default async function getBaseWebpackConfig(
|
||||
type: 'filesystem',
|
||||
// Includes:
|
||||
// - Next.js version
|
||||
// - next.config.js keys that affect compilation
|
||||
// - blitz.config.js keys that affect compilation
|
||||
version: `${process.env.__NEXT_VERSION}|${configVars}`,
|
||||
cacheDirectory: path.join(distDir, 'cache', 'webpack'),
|
||||
}
|
||||
|
||||
// Adds `next.config.js` as a buildDependency when custom webpack config is provided
|
||||
// TODO - can we remove this?
|
||||
// Adds `blitz.config.js` as a buildDependency when custom webpack config is provided
|
||||
if (config.webpack && config.configFile) {
|
||||
cache.buildDependencies = {
|
||||
config: [config.configFile],
|
||||
@@ -1479,6 +1473,30 @@ export default async function getBaseWebpackConfig(
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.images.disableStaticImages && isWebpack5) {
|
||||
if (!webpackConfig.module) {
|
||||
webpackConfig.module = { rules: [] }
|
||||
}
|
||||
|
||||
const hasSvg = webpackConfig.module.rules.some(
|
||||
(rule) =>
|
||||
'test' in rule && rule.test instanceof RegExp && rule.test.test('.svg')
|
||||
)
|
||||
|
||||
// Exclude svg if the user already defined it in custom
|
||||
// webpack config such as `@svgr/webpack` plugin or
|
||||
// the `babel-plugin-inline-react-svg` plugin.
|
||||
webpackConfig.module.rules.push({
|
||||
test: hasSvg
|
||||
? /\.(png|jpg|jpeg|gif|webp|ico|bmp)$/i
|
||||
: /\.(png|svg|jpg|jpeg|gif|webp|ico|bmp)$/i,
|
||||
loader: 'next-image-loader',
|
||||
dependency: { not: ['url'] },
|
||||
// @ts-ignore
|
||||
issuer: { not: regexLikeCss },
|
||||
})
|
||||
}
|
||||
|
||||
if (
|
||||
config.experimental.craCompat &&
|
||||
webpackConfig.module?.rules &&
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { join } from 'path'
|
||||
import * as Log from '../../output/log'
|
||||
import babelLoader from './babel-loader/src/index'
|
||||
import { isPageFile as isPageFileFn } from '../../utils'
|
||||
|
||||
// increment 'p' to invalidate cache
|
||||
// eslint-disable-next-line no-useless-concat
|
||||
@@ -81,7 +82,7 @@ const customBabelLoader = babelLoader((babel) => {
|
||||
) {
|
||||
const filename = this.resourcePath
|
||||
const options = Object.assign({}, cfg.options)
|
||||
const isPageFile = filename.startsWith(pagesDir)
|
||||
const isPageFile = isPageFileFn(filename.replace(pagesDir, ''))
|
||||
|
||||
if (cfg.hasFilesystemConfig()) {
|
||||
for (const file of [cfg.babelrc, cfg.config]) {
|
||||
|
||||
@@ -351,10 +351,15 @@ export function getUtils({
|
||||
|
||||
let defaultLocale = i18n.defaultLocale
|
||||
let detectedLocale = detectLocaleCookie(req, i18n.locales)
|
||||
let acceptPreferredLocale =
|
||||
i18n.localeDetection !== false
|
||||
? accept.language(req.headers['accept-language'], i18n.locales)
|
||||
: detectedLocale
|
||||
let acceptPreferredLocale
|
||||
try {
|
||||
acceptPreferredLocale =
|
||||
i18n.localeDetection !== false
|
||||
? accept.language(req.headers['accept-language'], i18n.locales)
|
||||
: detectedLocale
|
||||
} catch (_) {
|
||||
acceptPreferredLocale = detectedLocale
|
||||
}
|
||||
|
||||
const { host } = req.headers || {}
|
||||
// remove port from host and remove port if present
|
||||
|
||||
@@ -28,7 +28,6 @@ const eslintOptions = (args: arg.Spec) => ({
|
||||
args['--report-unused-disable-directives'] || null,
|
||||
cache: args['--cache'] ?? false,
|
||||
cacheLocation: args['--cache-location'] || '.eslintcache',
|
||||
cacheStrategy: args['--cache-strategy'] || 'metadata',
|
||||
errorOnUnmatchedPattern: !Boolean(args['--no-error-on-unmatched-pattern']),
|
||||
})
|
||||
|
||||
@@ -55,11 +54,11 @@ const nextLint: cliCommand = (argv) => {
|
||||
'--fix-type': [String],
|
||||
'--ignore-path': String,
|
||||
'--no-ignore': Boolean,
|
||||
'--quiet': Boolean,
|
||||
'--no-inline-config': Boolean,
|
||||
'--report-unused-disable-directives': String,
|
||||
'--cache': Boolean,
|
||||
'--cache-location': String,
|
||||
'--cache-strategy': String,
|
||||
'--no-error-on-unmatched-pattern': Boolean,
|
||||
|
||||
// Aliases
|
||||
@@ -107,6 +106,9 @@ const nextLint: cliCommand = (argv) => {
|
||||
--ignore-path path::String Specify path of ignore file
|
||||
--no-ignore Disable use of ignore files and patterns
|
||||
|
||||
Handling warnings:
|
||||
--quiet Report errors only - default: false
|
||||
|
||||
Inline configuration comments:
|
||||
--no-inline-config Prevent comments from changing config or rules
|
||||
--report-unused-disable-directives Adds reported errors for unused eslint-disable directives ("error" | "warn" | "off")
|
||||
@@ -114,7 +116,6 @@ const nextLint: cliCommand = (argv) => {
|
||||
Caching:
|
||||
--cache Only check changed files - default: false
|
||||
--cache-location path::String Path to the cache file or directory - default: .eslintcache
|
||||
--cache-strategy String Strategy to use for detecting changed files - either: metadata or content - default: metadata
|
||||
|
||||
Miscellaneous:
|
||||
--no-error-on-unmatched-pattern Prevent errors when pattern is unmatched - default: false
|
||||
@@ -140,7 +141,10 @@ const nextLint: cliCommand = (argv) => {
|
||||
},
|
||||
[]
|
||||
)
|
||||
runLintCheck(baseDir, lintDirs, false, eslintOptions(args))
|
||||
|
||||
const reportErrorsOnly = Boolean(args['--quiet'])
|
||||
|
||||
runLintCheck(baseDir, lintDirs, false, eslintOptions(args), reportErrorsOnly)
|
||||
.then(async (lintResults) => {
|
||||
const lintOutput =
|
||||
typeof lintResults === 'string' ? lintResults : lintResults?.output
|
||||
|
||||
@@ -37,7 +37,12 @@ async function tryApplyUpdates() {
|
||||
return
|
||||
}
|
||||
try {
|
||||
const res = await fetch(`${hotUpdatePath}${curHash}.hot-update.json`)
|
||||
const res = await fetch(
|
||||
typeof __webpack_runtime_id__ !== 'undefined'
|
||||
? // eslint-disable-next-line no-undef
|
||||
`${hotUpdatePath}${curHash}.${__webpack_runtime_id__}.hot-update.json`
|
||||
: `${hotUpdatePath}${curHash}.hot-update.json`
|
||||
)
|
||||
const jsonData = await res.json()
|
||||
const curPage = page === '/' ? 'index' : page
|
||||
// webpack 5 uses an array instead
|
||||
|
||||
@@ -173,16 +173,20 @@ function handleErrors(errors) {
|
||||
}
|
||||
}
|
||||
|
||||
let startLatency = undefined
|
||||
|
||||
function onFastRefresh(hasUpdates) {
|
||||
DevOverlay.onBuildOk()
|
||||
if (hasUpdates) {
|
||||
DevOverlay.onRefresh()
|
||||
}
|
||||
|
||||
const latency = Date.now() - startLatency
|
||||
console.log(`[Fast Refresh] done in ${latency}ms`)
|
||||
if (self.__NEXT_HMR_LATENCY_CB) {
|
||||
self.__NEXT_HMR_LATENCY_CB(latency)
|
||||
if (startLatency) {
|
||||
const latency = Date.now() - startLatency
|
||||
console.log(`[Fast Refresh] done in ${latency}ms`)
|
||||
if (self.__NEXT_HMR_LATENCY_CB) {
|
||||
self.__NEXT_HMR_LATENCY_CB(latency)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,8 +196,6 @@ function handleAvailableHash(hash) {
|
||||
mostRecentCompilationHash = hash
|
||||
}
|
||||
|
||||
let startLatency = undefined
|
||||
|
||||
// Handle messages from the server.
|
||||
function processMessage(e) {
|
||||
const obj = JSON.parse(e.data)
|
||||
|
||||
@@ -348,7 +348,7 @@ export function Image({
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!src) {
|
||||
throw new Error(
|
||||
`Image is missing required "src" property. Make sure you pass "src" in props to the \`next/image\` component. Received: ${JSON.stringify(
|
||||
`Image is missing required "src" property. Make sure you pass "src" in props to the \`<Image>\` component. Received: ${JSON.stringify(
|
||||
{ width, height, quality }
|
||||
)}`
|
||||
)
|
||||
@@ -360,6 +360,14 @@ export function Image({
|
||||
).join(',')}.`
|
||||
)
|
||||
}
|
||||
if (
|
||||
(typeof widthInt !== 'undefined' && isNaN(widthInt)) ||
|
||||
(typeof heightInt !== 'undefined' && isNaN(heightInt))
|
||||
) {
|
||||
throw new Error(
|
||||
`Image with src "${src}" has invalid "width" or "height" property. These should be numeric values.`
|
||||
)
|
||||
}
|
||||
if (!VALID_LOADING_VALUES.includes(loading)) {
|
||||
throw new Error(
|
||||
`Image with src "${src}" has invalid "loading" property. Provided "${loading}" should be one of ${VALID_LOADING_VALUES.map(
|
||||
@@ -373,7 +381,7 @@ export function Image({
|
||||
)
|
||||
}
|
||||
if (placeholder === 'blur') {
|
||||
if ((widthInt || 0) * (heightInt || 0) < 1600) {
|
||||
if (layout !== 'fill' && (widthInt || 0) * (heightInt || 0) < 1600) {
|
||||
console.warn(
|
||||
`Image with src "${src}" is smaller than 40x40. Consider removing the "placeholder='blur'" property to improve performance.`
|
||||
)
|
||||
@@ -569,9 +577,7 @@ export function Image({
|
||||
sizes,
|
||||
loader,
|
||||
})}
|
||||
src={src}
|
||||
decoding="async"
|
||||
sizes={sizes}
|
||||
style={imgStyle}
|
||||
className={className}
|
||||
/>
|
||||
@@ -676,7 +682,7 @@ function defaultLoader({
|
||||
throw new Error(
|
||||
`Next Image Optimization requires ${missingValues.join(
|
||||
', '
|
||||
)} to be provided. Make sure you pass them as props to the \`next/image\` component. Received: ${JSON.stringify(
|
||||
)} to be provided. Make sure you pass them as props to the \`<Image>\` component. Received: ${JSON.stringify(
|
||||
{ src, width, quality }
|
||||
)}`
|
||||
)
|
||||
@@ -684,7 +690,7 @@ function defaultLoader({
|
||||
|
||||
if (src.startsWith('//')) {
|
||||
throw new Error(
|
||||
`Failed to parse src "${src}" on \`next/image\`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)`
|
||||
`Failed to parse src "${src}" on \`<Image>\`, protocol-relative URL (//) must be changed to an absolute URL (http:// or https://)`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -695,13 +701,13 @@ function defaultLoader({
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
throw new Error(
|
||||
`Failed to parse src "${src}" on \`next/image\`, if using relative image it must start with a leading slash "/" or be an absolute URL (http:// or https://)`
|
||||
`Failed to parse src "${src}" on \`<Image>\`, if using relative image it must start with a leading slash "/" or be an absolute URL (http:// or https://)`
|
||||
)
|
||||
}
|
||||
|
||||
if (!configDomains.includes(parsedSrc.hostname)) {
|
||||
throw new Error(
|
||||
`Invalid src prop (${src}) on \`next/image\`, hostname "${parsedSrc.hostname}" is not configured under images in your \`blitz.config.js\`\n` +
|
||||
`Invalid src prop (${src}) on \`<Image>\`, hostname "${parsedSrc.hostname}" is not configured under images in your \`blitz.config.js\`\n` +
|
||||
`See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host`
|
||||
)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ import PageLoader, { StyleSheetTuple } from './page-loader'
|
||||
import measureWebVitals from './performance-relayer'
|
||||
import { RouteAnnouncer } from './route-announcer'
|
||||
import { createRouter, makePublicRouterInstance } from './router'
|
||||
import {
|
||||
AuthenticationError,
|
||||
AuthorizationError,
|
||||
NotFoundError,
|
||||
RedirectError,
|
||||
} from '../stdlib/errors'
|
||||
|
||||
/// <reference types="react-dom/experimental" />
|
||||
|
||||
@@ -96,6 +102,22 @@ if (hasBasePath(asPath)) {
|
||||
asPath = delBasePath(asPath)
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
function onUnhandledError(ev: ErrorEvent) {
|
||||
if (
|
||||
ev.error instanceof RedirectError ||
|
||||
ev.error instanceof AuthenticationError ||
|
||||
ev.error instanceof AuthorizationError ||
|
||||
ev.error instanceof NotFoundError
|
||||
) {
|
||||
// This prevents 'Uncaught error' logs in the console.
|
||||
// This doesn't change how React or error boundaries handle errors
|
||||
ev.preventDefault()
|
||||
}
|
||||
}
|
||||
window.addEventListener('error', onUnhandledError)
|
||||
}
|
||||
|
||||
if (process.env.__NEXT_I18N_SUPPORT) {
|
||||
const {
|
||||
normalizeLocalePath,
|
||||
@@ -259,7 +281,7 @@ class Container extends React.Component<{
|
||||
}
|
||||
}
|
||||
|
||||
export const emitter: MittEmitter = mitt()
|
||||
export const emitter: MittEmitter<string> = mitt()
|
||||
let CachedComponent: React.ComponentType
|
||||
|
||||
export default async (opts: { webpackHMR?: any } = {}) => {
|
||||
@@ -508,7 +530,7 @@ function renderReactElement(
|
||||
const reactEl = fn(shouldHydrate ? markHydrateComplete : markRenderComplete)
|
||||
if (process.env.__NEXT_REACT_ROOT) {
|
||||
if (!reactRoot) {
|
||||
const createRootName =
|
||||
const createRootName = // blitz
|
||||
typeof (ReactDOM as any).unstable_createRoot === 'function'
|
||||
? 'unstable_createRoot'
|
||||
: 'createRoot'
|
||||
|
||||
@@ -7,7 +7,7 @@ export function removePathTrailingSlash(path: string): string {
|
||||
|
||||
/**
|
||||
* Normalizes the trailing slash of a path according to the `trailingSlash` option
|
||||
* in `next.config.js`.
|
||||
* in `blitz.config.js`.
|
||||
*/
|
||||
export const normalizePathTrailingSlash = process.env.__NEXT_TRAILING_SLASH
|
||||
? (path: string): string => {
|
||||
|
||||
@@ -43,6 +43,7 @@ const urlPropertyFields = [
|
||||
'isReady',
|
||||
'isPreview',
|
||||
'isLocaleDomain',
|
||||
'domainLocales',
|
||||
]
|
||||
const routerEvents = [
|
||||
'routeChangeStart',
|
||||
@@ -51,7 +52,9 @@ const routerEvents = [
|
||||
'routeChangeError',
|
||||
'hashChangeStart',
|
||||
'hashChangeComplete',
|
||||
]
|
||||
] as const
|
||||
export type RouterEvent = typeof routerEvents[number]
|
||||
|
||||
const coreMethodFields = [
|
||||
'push',
|
||||
'replace',
|
||||
@@ -89,7 +92,7 @@ coreMethodFields.forEach((field: string) => {
|
||||
}
|
||||
})
|
||||
|
||||
routerEvents.forEach((event: string) => {
|
||||
routerEvents.forEach((event) => {
|
||||
singletonRouter.ready(() => {
|
||||
Router.events.on(event, (...args) => {
|
||||
const eventField = `on${event.charAt(0).toUpperCase()}${event.substring(
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22319,7 +22319,7 @@ module.exports = isAccessorDescriptor;
|
||||
/***/ 21008:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var isBuffer = __webpack_require__(95310);
|
||||
var isBuffer = __webpack_require__(16597);
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
@@ -22437,6 +22437,34 @@ module.exports = function kindOf(val) {
|
||||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 16597:
|
||||
/***/ (function(module) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 6284:
|
||||
@@ -22505,7 +22533,7 @@ module.exports = isDataDescriptor;
|
||||
/***/ 13360:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var isBuffer = __webpack_require__(95310);
|
||||
var isBuffer = __webpack_require__(16597);
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
@@ -31299,12 +31327,40 @@ module.exports = function hasValue(val) {
|
||||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 45305:
|
||||
/***/ (function(module) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 58839:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var isBuffer = __webpack_require__(95310);
|
||||
var isBuffer = __webpack_require__(45305);
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
@@ -31552,34 +31608,6 @@ function has(obj, key) {
|
||||
module.exports = isAccessorDescriptor;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 95310:
|
||||
/***/ (function(module) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1734:
|
||||
@@ -31718,12 +31746,40 @@ module.exports = function isNumber(num) {
|
||||
};
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 51247:
|
||||
/***/ (function(module) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 1005:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var isBuffer = __webpack_require__(95310);
|
||||
var isBuffer = __webpack_require__(51247);
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
@@ -35797,12 +35853,40 @@ module.exports = copy;
|
||||
module.exports.has = has;
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 92541:
|
||||
/***/ (function(module) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 73988:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var isBuffer = __webpack_require__(95310);
|
||||
var isBuffer = __webpack_require__(92541);
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
@@ -41643,12 +41727,40 @@ function assert(val, message) {
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 12633:
|
||||
/***/ (function(module) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 31042:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var isBuffer = __webpack_require__(95310);
|
||||
var isBuffer = __webpack_require__(12633);
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
@@ -45760,12 +45872,40 @@ function filter(arr) {
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 41722:
|
||||
/***/ (function(module) {
|
||||
|
||||
/*!
|
||||
* Determine if an object is a Buffer
|
||||
*
|
||||
* @author Feross Aboukhadijeh <https://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
// The _isBuffer check is for Safari 5-7 support, because it's missing
|
||||
// Object.prototype.constructor. Remove this eventually
|
||||
module.exports = function (obj) {
|
||||
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
|
||||
}
|
||||
|
||||
function isBuffer (obj) {
|
||||
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
|
||||
}
|
||||
|
||||
// For Node v0.10 support. Remove this eventually.
|
||||
function isSlowBuffer (obj) {
|
||||
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 17728:
|
||||
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
|
||||
|
||||
var isBuffer = __webpack_require__(95310);
|
||||
var isBuffer = __webpack_require__(41722);
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,6 @@ import {
|
||||
BUILD_ID_FILE,
|
||||
CLIENT_PUBLIC_FILES_PATH,
|
||||
CLIENT_STATIC_FILES_PATH,
|
||||
CONFIG_FILE,
|
||||
EXPORT_DETAIL,
|
||||
EXPORT_MARKER,
|
||||
PAGES_MANIFEST,
|
||||
@@ -143,7 +142,7 @@ export default async function exportApp(
|
||||
return nextExportSpan.traceAsyncFn(async () => {
|
||||
dir = resolve(dir)
|
||||
|
||||
// attempt to load global env values so they are available in next.config.js
|
||||
// attempt to load global env values so they are available in blitz.config.js
|
||||
nextExportSpan
|
||||
.traceChild('load-dotenv')
|
||||
.traceFn(() => loadEnvConfig(dir, false, Log))
|
||||
@@ -308,7 +307,7 @@ export default async function exportApp(
|
||||
if (typeof nextConfig.exportPathMap !== 'function') {
|
||||
if (!options.silent) {
|
||||
Log.info(
|
||||
`No "exportPathMap" found in "${CONFIG_FILE}". Generating map from "./pages"`
|
||||
`No "exportPathMap" found in "blitz.config.js". Generating map from "./pages"`
|
||||
)
|
||||
}
|
||||
nextConfig.exportPathMap = async (defaultMap: ExportPathMap) => {
|
||||
@@ -356,7 +355,7 @@ export default async function exportApp(
|
||||
- Use \`blitz start\` to run a server, which includes the Image Optimization API.
|
||||
- Use any provider which supports Image Optimization (like Vercel).
|
||||
- Configure a third-party loader in \`blitz.config.js\`.
|
||||
- Use the \`loader\` prop for \`next/image\`.
|
||||
- Use the \`loader\` prop for \`blitz\`.
|
||||
Read more: https://nextjs.org/docs/messages/export-image-api`
|
||||
)
|
||||
}
|
||||
|
||||
62
nextjs/packages/next/image-types/global.d.ts
vendored
Normal file
62
nextjs/packages/next/image-types/global.d.ts
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// this file is conditionally added/removed to next-env.d.ts
|
||||
// if the static image import handling is enabled
|
||||
|
||||
interface StaticImageData {
|
||||
src: string
|
||||
height: number
|
||||
width: number
|
||||
placeholder?: string
|
||||
}
|
||||
|
||||
declare module '*.png' {
|
||||
const content: StaticImageData
|
||||
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.svg' {
|
||||
/**
|
||||
* Use `any` to avoid conflicts with
|
||||
* `@svgr/webpack` plugin or
|
||||
* `babel-plugin-inline-react-svg` plugin.
|
||||
*/
|
||||
const content: any
|
||||
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.jpg' {
|
||||
const content: StaticImageData
|
||||
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.jpeg' {
|
||||
const content: StaticImageData
|
||||
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.gif' {
|
||||
const content: StaticImageData
|
||||
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.webp' {
|
||||
const content: StaticImageData
|
||||
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.ico' {
|
||||
const content: StaticImageData
|
||||
|
||||
export default content
|
||||
}
|
||||
|
||||
declare module '*.bmp' {
|
||||
const content: StaticImageData
|
||||
|
||||
export default content
|
||||
}
|
||||
@@ -28,7 +28,8 @@ async function lint(
|
||||
lintDirs: string[],
|
||||
eslintrcFile: string | null,
|
||||
pkgJsonPath: string | null,
|
||||
eslintOptions: any = null
|
||||
eslintOptions: any = null,
|
||||
reportErrorsOnly: boolean = false
|
||||
): Promise<
|
||||
| string
|
||||
| null
|
||||
@@ -42,7 +43,7 @@ async function lint(
|
||||
const mod = await import(deps.resolved.get('eslint')!)
|
||||
|
||||
const { ESLint } = mod
|
||||
let eslintVersion = ESLint.version
|
||||
let eslintVersion = ESLint?.version
|
||||
|
||||
if (!ESLint) {
|
||||
eslintVersion = mod?.CLIEngine?.version
|
||||
@@ -59,7 +60,6 @@ async function lint(
|
||||
'error'
|
||||
)} - ESLint class not found. Please upgrade to ESLint version 7 or later`
|
||||
}
|
||||
|
||||
let options: any = {
|
||||
useEslintrc: true,
|
||||
baseConfig: {},
|
||||
@@ -85,7 +85,7 @@ async function lint(
|
||||
}
|
||||
}
|
||||
|
||||
const pagesDir = findPagesDir(baseDir)
|
||||
const pagesDir = baseDir
|
||||
|
||||
if (nextEslintPluginIsEnabled) {
|
||||
let updatedPagesDir = false
|
||||
@@ -111,8 +111,9 @@ async function lint(
|
||||
}
|
||||
const lintStart = process.hrtime()
|
||||
|
||||
const results = await eslint.lintFiles(lintDirs)
|
||||
let results = await eslint.lintFiles(lintDirs)
|
||||
if (options.fix) await ESLint.outputFixes(results)
|
||||
if (reportErrorsOnly) results = await ESLint.getErrorResults(results) // Only return errors if --quiet flag is used
|
||||
|
||||
const formattedResult = formatResults(baseDir, results)
|
||||
const lintEnd = process.hrtime(lintStart)
|
||||
@@ -142,7 +143,8 @@ export async function runLintCheck(
|
||||
baseDir: string,
|
||||
lintDirs: string[],
|
||||
lintDuringBuild: boolean = false,
|
||||
eslintOptions: any = null
|
||||
eslintOptions: any = null,
|
||||
reportErrorsOnly: boolean = false
|
||||
): ReturnType<typeof lint> {
|
||||
try {
|
||||
// Find user's .eslintrc file
|
||||
@@ -203,7 +205,8 @@ export async function runLintCheck(
|
||||
lintDirs,
|
||||
eslintrcFile,
|
||||
pkgJsonPath,
|
||||
eslintOptions
|
||||
eslintOptions,
|
||||
reportErrorsOnly
|
||||
)
|
||||
} catch (err) {
|
||||
throw err
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function fileExists(
|
||||
}
|
||||
return true
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
if (err.code === 'ENOENT' || err.code === 'ENAMETOOLONG') {
|
||||
return false
|
||||
}
|
||||
throw err
|
||||
|
||||
@@ -11,7 +11,9 @@ export const existsSync = (f: string): boolean => {
|
||||
}
|
||||
|
||||
export function findPagesDir(dir: string): string {
|
||||
throw new Error('findPagesDir is deprecated in Blitz.js')
|
||||
// prioritize ./pages over ./src/pages
|
||||
// eslint-disable-next-line no-unreachable -- disabled in Blitz.js
|
||||
let curDir = path.join(dir, 'pages')
|
||||
if (existsSync(curDir)) return curDir
|
||||
|
||||
|
||||
122
nextjs/packages/next/lib/has-necessary-dependencies.js
Normal file
122
nextjs/packages/next/lib/has-necessary-dependencies.js
Normal file
@@ -0,0 +1,122 @@
|
||||
exports.__esModule = true
|
||||
exports.hasNecessaryDependencies = hasNecessaryDependencies
|
||||
|
||||
var _chalk = _interopRequireDefault(require('chalk'))
|
||||
|
||||
var _path = require('path')
|
||||
|
||||
var _fileExists = require('./file-exists')
|
||||
|
||||
var _oxfordCommaList = require('./oxford-comma-list')
|
||||
|
||||
var _fatalError = require('./fatal-error')
|
||||
|
||||
function _interopRequireDefault(obj) {
|
||||
return obj && obj.__esModule ? obj : { default: obj }
|
||||
}
|
||||
|
||||
const requiredTSPackages = [
|
||||
{
|
||||
file: 'typescript',
|
||||
pkg: 'typescript',
|
||||
},
|
||||
{
|
||||
file: '@types/react/index.d.ts',
|
||||
pkg: '@types/react',
|
||||
},
|
||||
{
|
||||
file: '@types/node/index.d.ts',
|
||||
pkg: '@types/node',
|
||||
},
|
||||
]
|
||||
const requiredLintPackages = [
|
||||
{
|
||||
file: 'eslint/lib/api.js',
|
||||
pkg: 'eslint',
|
||||
},
|
||||
{
|
||||
file: 'eslint-config-next',
|
||||
pkg: 'eslint-config-next',
|
||||
},
|
||||
]
|
||||
|
||||
async function hasNecessaryDependencies(
|
||||
baseDir,
|
||||
checkTSDeps,
|
||||
checkESLintDeps,
|
||||
lintDuringBuild = false
|
||||
) {
|
||||
if (!checkTSDeps && !checkESLintDeps) {
|
||||
return {
|
||||
resolved: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
let resolutions = new Map()
|
||||
let requiredPackages = checkESLintDeps
|
||||
? requiredLintPackages
|
||||
: requiredTSPackages
|
||||
const missingPackages = requiredPackages.filter((p) => {
|
||||
try {
|
||||
resolutions.set(
|
||||
p.pkg,
|
||||
require.resolve(p.file, {
|
||||
paths: [baseDir],
|
||||
})
|
||||
)
|
||||
return false
|
||||
} catch (_) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
if (missingPackages.length < 1) {
|
||||
return {
|
||||
resolved: resolutions,
|
||||
}
|
||||
}
|
||||
|
||||
const packagesHuman = (0, _oxfordCommaList.getOxfordCommaList)(
|
||||
missingPackages.map((p) => p.pkg)
|
||||
)
|
||||
const packagesCli = missingPackages.map((p) => p.pkg).join(' ')
|
||||
const yarnLockFile = (0, _path.join)(baseDir, 'yarn.lock')
|
||||
const isYarn = await (0, _fileExists.fileExists)(yarnLockFile).catch(
|
||||
() => false
|
||||
)
|
||||
|
||||
const removalTSMsg =
|
||||
'\n\n' +
|
||||
_chalk.default.bold(
|
||||
'If you are not trying to use TypeScript, please remove the ' +
|
||||
_chalk.default.cyan('tsconfig.json') +
|
||||
' file from your package root (and any TypeScript files in your pages directory).'
|
||||
)
|
||||
|
||||
const removalLintMsg =
|
||||
`\n\n` +
|
||||
(lintDuringBuild
|
||||
? `If you do not want to run ESLint during builds, disable it in blitz.config.js. See https://blitzjs.com/docs/eslint-config#during-builds`
|
||||
: `Once installed, run ${_chalk.default.bold.cyan('next lint')} again.`)
|
||||
const removalMsg = checkTSDeps ? removalTSMsg : removalLintMsg
|
||||
throw new _fatalError.FatalError(
|
||||
_chalk.default.bold.red(
|
||||
checkTSDeps
|
||||
? `It looks like you're trying to use TypeScript but do not have the required package(s) installed.`
|
||||
: `To use ESLint, additional required package(s) must be installed.`
|
||||
) +
|
||||
'\n\n' +
|
||||
_chalk.default.bold(
|
||||
`Please install ${_chalk.default.bold(packagesHuman)} by running:`
|
||||
) +
|
||||
'\n\n' +
|
||||
`\t${_chalk.default.bold.cyan(
|
||||
(isYarn ? 'yarn add --dev' : 'npm install --save-dev') +
|
||||
' ' +
|
||||
packagesCli
|
||||
)}` +
|
||||
removalMsg +
|
||||
'\n'
|
||||
)
|
||||
}
|
||||
//# sourceMappingURL=has-necessary-dependencies.js.map
|
||||
@@ -66,7 +66,7 @@ export async function hasNecessaryDependencies(
|
||||
const removalLintMsg =
|
||||
`\n\n` +
|
||||
(lintDuringBuild
|
||||
? `If you do not want to run ESLint during builds, disable it in blitz.config.js. See https://nextjs.org/docs/api-reference/next.config.js/ignoring-eslint.`
|
||||
? `If you do not want to run ESLint during builds, disable it in blitz.config.js. See https://blitzjs.com/docs/eslint-config#during-builds`
|
||||
: `Once installed, run ${chalk.bold.cyan('next lint')} again.`)
|
||||
const removalMsg = checkTSDeps ? removalTSMsg : removalLintMsg
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { promises } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { isPageFile, topLevelFoldersThatMayContainPages } from '../build/utils'
|
||||
|
||||
/**
|
||||
* Recursively read directory
|
||||
@@ -40,3 +41,45 @@ export async function recursiveReadDir(
|
||||
|
||||
return arr.sort()
|
||||
}
|
||||
|
||||
export async function recursiveFindPages(
|
||||
dir: string,
|
||||
filter: RegExp,
|
||||
ignore?: RegExp,
|
||||
arr: string[] = [],
|
||||
rootDir: string = dir
|
||||
): Promise<string[]> {
|
||||
let folders = await promises.readdir(dir)
|
||||
|
||||
if (dir === rootDir) {
|
||||
folders = folders.filter((folder) =>
|
||||
topLevelFoldersThatMayContainPages.includes(folder)
|
||||
)
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
folders.map(async (part: string) => {
|
||||
const absolutePath = join(dir, part)
|
||||
if (ignore && ignore.test(part)) return
|
||||
|
||||
const pathStat = await promises.stat(absolutePath)
|
||||
|
||||
if (pathStat.isDirectory()) {
|
||||
await recursiveFindPages(absolutePath, filter, ignore, arr, rootDir)
|
||||
return
|
||||
}
|
||||
|
||||
if (!filter.test(part)) {
|
||||
return
|
||||
}
|
||||
|
||||
const relativeFromRoot = absolutePath.replace(rootDir, '')
|
||||
if (isPageFile(relativeFromRoot)) {
|
||||
arr.push(relativeFromRoot)
|
||||
return
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
return arr.sort()
|
||||
}
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import { promises as fs } from 'fs'
|
||||
import os from 'os'
|
||||
import path from 'path'
|
||||
import { fileExists } from '../file-exists'
|
||||
|
||||
export async function writeAppTypeDeclarations(baseDir: string): Promise<void> {
|
||||
export async function writeAppTypeDeclarations(
|
||||
baseDir: string,
|
||||
imageImportsEnabled: boolean
|
||||
): Promise<void> {
|
||||
// Reference `next` types
|
||||
const appTypeDeclarations = path.join(baseDir, 'next-env.d.ts')
|
||||
const hasAppTypeDeclarations = await fileExists(appTypeDeclarations)
|
||||
if (!hasAppTypeDeclarations) {
|
||||
await fs.writeFile(
|
||||
appTypeDeclarations,
|
||||
'/// <reference types="next" />' +
|
||||
os.EOL +
|
||||
'/// <reference types="next/types/global" />' +
|
||||
os.EOL
|
||||
)
|
||||
}
|
||||
|
||||
await fs.writeFile(
|
||||
appTypeDeclarations,
|
||||
'/// <reference types="next" />' +
|
||||
os.EOL +
|
||||
'/// <reference types="next/types/global" />' +
|
||||
os.EOL +
|
||||
(imageImportsEnabled
|
||||
? '/// <reference types="next/image-types/global" />' + os.EOL
|
||||
: '')
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ export async function verifyTypeScriptSetup(
|
||||
dir: string,
|
||||
pagesDir: string,
|
||||
typeCheckPreflight: boolean,
|
||||
imageImportsEnabled: boolean,
|
||||
cacheDir?: string
|
||||
): Promise<{ result?: TypeCheckResult; version: string | null }> {
|
||||
const tsConfigPath = path.join(dir, 'tsconfig.json')
|
||||
@@ -42,7 +43,10 @@ export async function verifyTypeScriptSetup(
|
||||
deps.resolved.get('typescript')!
|
||||
)) as typeof import('typescript')
|
||||
|
||||
if (semver.lt(ts.version, '4.3.2')) {
|
||||
if (
|
||||
semver.lt(ts.version, '4.3.2') &&
|
||||
!Boolean(process.env.BLITZ_TEST_ENVIRONMENT)
|
||||
) {
|
||||
log.warn(
|
||||
`Minimum recommended TypeScript version is v4.3.2, older versions can potentially be incompatible with Blitz.js. Detected: ${ts.version}`
|
||||
)
|
||||
@@ -52,7 +56,7 @@ export async function verifyTypeScriptSetup(
|
||||
await writeConfigurationDefaults(ts, tsConfigPath, firstTimeSetup)
|
||||
// Write out the necessary `next-env.d.ts` file to correctly register
|
||||
// Next.js' types:
|
||||
await writeAppTypeDeclarations(dir)
|
||||
await writeAppTypeDeclarations(dir, imageImportsEnabled)
|
||||
|
||||
let result
|
||||
if (typeCheckPreflight) {
|
||||
|
||||
@@ -15,7 +15,7 @@ export const REACT_LOADABLE_MANIFEST = 'react-loadable-manifest.json'
|
||||
export const FONT_MANIFEST = 'font-manifest.json'
|
||||
export const SERVER_DIRECTORY = 'server'
|
||||
export const SERVERLESS_DIRECTORY = 'serverless'
|
||||
export const CONFIG_FILE = 'next.config.js'
|
||||
export const CONFIG_FILE = '.blitz.config.compiled.js'
|
||||
export const BUILD_ID_FILE = 'BUILD_ID'
|
||||
export const BLOCKED_PAGES = ['/_document', '/_app']
|
||||
export const CLIENT_PUBLIC_FILES_PATH = 'public'
|
||||
|
||||
@@ -16,13 +16,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
type Handler = (...evts: any[]) => void
|
||||
|
||||
export type MittEmitter = {
|
||||
on(type: string, handler: Handler): void
|
||||
off(type: string, handler: Handler): void
|
||||
emit(type: string, ...evts: any[]): void
|
||||
export type MittEmitter<T> = {
|
||||
on(type: T, handler: Handler): void
|
||||
off(type: T, handler: Handler): void
|
||||
emit(type: T, ...evts: any[]): void
|
||||
}
|
||||
|
||||
export default function mitt(): MittEmitter {
|
||||
export default function mitt(): MittEmitter<string> {
|
||||
const all: { [s: string]: Handler[] } = Object.create(null)
|
||||
|
||||
return {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
isAssetError,
|
||||
markAssetError,
|
||||
} from '../../../client/route-loader'
|
||||
import { RouterEvent } from '../../../client/router'
|
||||
import { DomainLocales } from '../../server/config'
|
||||
import { denormalizePagePath } from '../../server/denormalize-page-path'
|
||||
import { normalizeLocalePath } from '../i18n/normalize-locale-path'
|
||||
@@ -522,7 +523,7 @@ export default class Router implements BaseRouter {
|
||||
clc: ComponentLoadCancel
|
||||
pageLoader: any
|
||||
_bps: BeforePopStateCallback | undefined
|
||||
events: MittEmitter
|
||||
events: MittEmitter<RouterEvent>
|
||||
_wrapApp: (App: AppComponent) => any
|
||||
isSsr: boolean
|
||||
isFallback: boolean
|
||||
@@ -538,7 +539,7 @@ export default class Router implements BaseRouter {
|
||||
|
||||
private _idx: number = 0
|
||||
|
||||
static events: MittEmitter = mitt()
|
||||
static events: MittEmitter<RouterEvent> = mitt()
|
||||
|
||||
constructor(
|
||||
pathname: string,
|
||||
@@ -1112,14 +1113,12 @@ export default class Router implements BaseRouter {
|
||||
pages
|
||||
)
|
||||
|
||||
if (pages.includes(parsedHref.pathname)) {
|
||||
const { url: newUrl, as: newAs } = prepareUrlAs(
|
||||
this,
|
||||
destination,
|
||||
destination
|
||||
)
|
||||
return this.change(method, newUrl, newAs, options)
|
||||
}
|
||||
const { url: newUrl, as: newAs } = prepareUrlAs(
|
||||
this,
|
||||
destination,
|
||||
destination
|
||||
)
|
||||
return this.change(method, newUrl, newAs, options)
|
||||
}
|
||||
|
||||
window.location.href = destination
|
||||
|
||||
@@ -31,6 +31,17 @@ export function matchHas(
|
||||
query: Params
|
||||
): false | Params {
|
||||
const params: Params = {}
|
||||
let initialQueryValues: string[] = []
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
initialQueryValues = Object.values((req as any).__NEXT_INIT_QUERY)
|
||||
}
|
||||
if (typeof window !== 'undefined') {
|
||||
initialQueryValues = Array.from(
|
||||
new URLSearchParams(location.search).values()
|
||||
)
|
||||
}
|
||||
|
||||
const allMatch = has.every((hasItem) => {
|
||||
let value: undefined | string
|
||||
let key = hasItem.key
|
||||
@@ -46,7 +57,12 @@ export function matchHas(
|
||||
break
|
||||
}
|
||||
case 'query': {
|
||||
// preserve initial encoding of query values
|
||||
value = query[key!]
|
||||
|
||||
if (initialQueryValues.includes(value || '')) {
|
||||
value = encodeURIComponent(value!)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'host': {
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { existsSync, readFileSync } from 'fs'
|
||||
import { build as esbuild } from 'esbuild'
|
||||
import findUp from 'next/dist/compiled/find-up'
|
||||
import os from 'os'
|
||||
import { join } from 'path'
|
||||
import { Header, Redirect, Rewrite } from '../../lib/load-custom-routes'
|
||||
import { imageConfigDefault } from './image-config'
|
||||
import { CONFIG_FILE } from '../lib/constants'
|
||||
import { copy, remove } from 'fs-extra'
|
||||
const debug = require('debug')('blitz:config')
|
||||
|
||||
export type DomainLocales = Array<{
|
||||
http?: true
|
||||
@@ -115,7 +122,7 @@ export const defaultConfig: NextConfig = {
|
||||
scrollRestoration: false,
|
||||
stats: false,
|
||||
externalDir: false,
|
||||
reactRoot: true,
|
||||
reactRoot: Number(process.env.NEXT_PRIVATE_REACT_ROOT) > 0,
|
||||
disableOptimizedLoading: false,
|
||||
gzipSize: true,
|
||||
craCompat: false,
|
||||
@@ -143,3 +150,116 @@ export function normalizeConfig(phase: string, config: any) {
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
export async function getConfigSrcPath(dir: string | null) {
|
||||
if (!dir) return null
|
||||
|
||||
let tsPath = join(dir, 'blitz.config.ts')
|
||||
let jsPath = join(dir, 'blitz.config.js')
|
||||
let legacyPath = join(dir, 'next.config.js')
|
||||
|
||||
if (existsSync(tsPath)) {
|
||||
return tsPath
|
||||
} else if (existsSync(jsPath)) {
|
||||
return jsPath
|
||||
} else if (existsSync(legacyPath)) {
|
||||
const isInternalDevelopment = __dirname.includes(
|
||||
'packages/next/dist/next-server'
|
||||
)
|
||||
if (isInternalDevelopment || process.env.VERCEL_BUILDER) {
|
||||
// We read from next.config.js that Vercel automatically adds
|
||||
debug(
|
||||
'Using next.config.js because isInternalDevelopment or VERCEL_BUILDER...'
|
||||
)
|
||||
return legacyPath
|
||||
} else {
|
||||
console.log('') // newline
|
||||
throw new Error(
|
||||
'Blitz does not support next.config.js. Please rename it to blitz.config.js'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.__NEXT_TEST_MODE) {
|
||||
let tsPath2 = join(dir, '..', 'blitz.config.ts')
|
||||
let jsPath2 = join(dir, '..', 'blitz.config.js')
|
||||
let legacyPath2 = join(dir, '..', 'next.config.js')
|
||||
if (existsSync(tsPath2)) {
|
||||
return tsPath2
|
||||
} else if (existsSync(jsPath2)) {
|
||||
return jsPath2
|
||||
} else if (existsSync(legacyPath2)) {
|
||||
return legacyPath2
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function getCompiledConfigPath(dir: string) {
|
||||
return join(dir, CONFIG_FILE)
|
||||
}
|
||||
|
||||
export async function compileConfig(dir: string | null) {
|
||||
debug('Starting compileConfig...')
|
||||
|
||||
if (!dir) {
|
||||
debug('compileConfig given empty dir argument')
|
||||
return
|
||||
}
|
||||
|
||||
const srcPath = await getConfigSrcPath(dir)
|
||||
debug('srcPath:', srcPath)
|
||||
const compiledPath = getCompiledConfigPath(dir)
|
||||
debug('compiledPath:', compiledPath)
|
||||
|
||||
// Remove compiled file. This is important for example when user
|
||||
// had a config file but then removed it
|
||||
remove(compiledPath)
|
||||
|
||||
if (!srcPath) {
|
||||
debug('Did not find a config file')
|
||||
return
|
||||
}
|
||||
|
||||
if (readFileSync(srcPath, 'utf8').includes('tsconfig-paths/register')) {
|
||||
// User is manually handling their own typescript stuff
|
||||
debug(
|
||||
"Config contains 'tsconfig-paths/register', so skipping build and just copying the file"
|
||||
)
|
||||
await copy(srcPath, compiledPath)
|
||||
return
|
||||
}
|
||||
|
||||
const pkgJsonPath = await findUp('package.json', { cwd: dir })
|
||||
|
||||
if (!pkgJsonPath) {
|
||||
// This will happen when running blitz no inside a blitz app
|
||||
debug('Unable to find package directory')
|
||||
return
|
||||
}
|
||||
|
||||
debug('Building config...')
|
||||
const pkg = require(pkgJsonPath)
|
||||
|
||||
await esbuild({
|
||||
entryPoints: [srcPath],
|
||||
outfile: compiledPath,
|
||||
format: 'cjs',
|
||||
bundle: true,
|
||||
platform: 'node',
|
||||
external: [
|
||||
'*.json',
|
||||
'@blitzjs',
|
||||
'@next',
|
||||
'@zeit',
|
||||
'blitz',
|
||||
'next',
|
||||
'webpack',
|
||||
...Object.keys(require('blitz/package').dependencies),
|
||||
...Object.keys(pkg?.dependencies ?? {}),
|
||||
...Object.keys(pkg?.devDependencies ?? {}),
|
||||
],
|
||||
})
|
||||
debug('Config built.')
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ export async function shouldLoadWithWebpack5(
|
||||
}
|
||||
}
|
||||
|
||||
// Use webpack 5 by default in apps that do not have next.config.js
|
||||
// Use webpack 5 by default in apps that do not have blitz.config.js
|
||||
if (!path?.length) {
|
||||
return {
|
||||
enabled: true,
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import chalk from 'chalk'
|
||||
import findUp from 'next/dist/compiled/find-up'
|
||||
import { basename, extname } from 'path'
|
||||
import { basename, extname, join } from 'path'
|
||||
import * as Log from '../../build/output/log'
|
||||
import { hasNextSupport } from '../../telemetry/ci-info'
|
||||
import { CONFIG_FILE, PHASE_DEVELOPMENT_SERVER } from '../lib/constants'
|
||||
import { execOnce } from '../lib/utils'
|
||||
import { defaultConfig, normalizeConfig } from './config-shared'
|
||||
import { compileConfig, defaultConfig, normalizeConfig } from './config-shared'
|
||||
import { loadWebpackHook } from './config-utils'
|
||||
import { ImageConfig, imageConfigDefault, VALID_LOADERS } from './image-config'
|
||||
import { loadEnvConfig } from '@next/env'
|
||||
const debug = require('debug')('blitz:config')
|
||||
|
||||
export { DomainLocales, NextConfig, normalizeConfig } from './config-shared'
|
||||
|
||||
@@ -412,6 +413,10 @@ export default async function loadConfig(
|
||||
customConfig?: object | null
|
||||
) {
|
||||
await loadEnvConfig(dir, phase === PHASE_DEVELOPMENT_SERVER, Log)
|
||||
if (!['start', 's'].includes(process.argv[2])) {
|
||||
// Do not compile config for blitz start because it was already compiled during blitz build
|
||||
await compileConfig(dir)
|
||||
}
|
||||
await loadWebpackHook(phase, dir)
|
||||
|
||||
if (customConfig) {
|
||||
@@ -423,11 +428,20 @@ export default async function loadConfig(
|
||||
// If config file was found
|
||||
if (path?.length) {
|
||||
const userConfigModule = require(path)
|
||||
const userConfig = normalizeConfig(
|
||||
let userConfig = normalizeConfig(
|
||||
phase,
|
||||
userConfigModule.default || userConfigModule
|
||||
)
|
||||
|
||||
if (process.env.VERCEL_BUILDER) {
|
||||
debug("Loading Vercel's next.config.js...")
|
||||
const nextConfig = require(join('dir', 'next.config.js'))
|
||||
debug("Vercel's next.config.js contents:", nextConfig)
|
||||
for (const [key, value] of Object.entries(nextConfig)) {
|
||||
userConfig[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(userConfig).length === 0) {
|
||||
Log.warn(
|
||||
'Detected blitz.config.js, no exported configuration found. https://nextjs.org/docs/messages/empty-configuration'
|
||||
@@ -461,21 +475,23 @@ export default async function loadConfig(
|
||||
...userConfig,
|
||||
})
|
||||
} else {
|
||||
const configBaseName = basename(CONFIG_FILE, extname(CONFIG_FILE))
|
||||
const nonJsPath = findUp.sync(
|
||||
const unsupportedPath = findUp.sync(
|
||||
[
|
||||
`${configBaseName}.jsx`,
|
||||
`${configBaseName}.ts`,
|
||||
`${configBaseName}.tsx`,
|
||||
`${configBaseName}.json`,
|
||||
`blitz.config.jsx`,
|
||||
`blitz.config.tsx`,
|
||||
`blitz.config.json`,
|
||||
`next.config.jsx`,
|
||||
`next.config.ts`,
|
||||
`next.config.tsx`,
|
||||
`next.config.json`,
|
||||
],
|
||||
{ cwd: dir }
|
||||
)
|
||||
if (nonJsPath?.length) {
|
||||
if (unsupportedPath?.length) {
|
||||
throw new Error(
|
||||
`Configuring Blitz.js via '${basename(
|
||||
nonJsPath
|
||||
)}' is not supported. Please replace the file with 'blitz.config.js'.`
|
||||
unsupportedPath
|
||||
)}' is not supported. Please replace the file with 'blitz.config.(js|ts)'`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ export type ServerConstructor = {
|
||||
*/
|
||||
quiet?: boolean
|
||||
/**
|
||||
* Object what you would use in next.config.js - @default {}
|
||||
* Object what you would use in blitz.config.js - @default {}
|
||||
*/
|
||||
conf?: NextConfig | null
|
||||
dev?: boolean
|
||||
@@ -432,11 +432,15 @@ export default class Server {
|
||||
|
||||
let defaultLocale = i18n.defaultLocale
|
||||
let detectedLocale = detectLocaleCookie(req, i18n.locales)
|
||||
let acceptPreferredLocale =
|
||||
i18n.localeDetection !== false
|
||||
? accept.language(req.headers['accept-language'], i18n.locales)
|
||||
: detectedLocale
|
||||
|
||||
let acceptPreferredLocale
|
||||
try {
|
||||
acceptPreferredLocale =
|
||||
i18n.localeDetection !== false
|
||||
? accept.language(req.headers['accept-language'], i18n.locales)
|
||||
: detectedLocale
|
||||
} catch (_) {
|
||||
acceptPreferredLocale = detectedLocale
|
||||
}
|
||||
const { host } = req?.headers || {}
|
||||
// remove port from host if present
|
||||
const hostname = host?.split(':')[0].toLowerCase()
|
||||
@@ -602,7 +606,7 @@ export default class Server {
|
||||
let rewrites: CustomRoutes['rewrites']
|
||||
|
||||
// rewrites can be stored as an array when an array is
|
||||
// returned in next.config.js so massage them into
|
||||
// returned in blitz.config.js so massage them into
|
||||
// the expected object format
|
||||
if (Array.isArray(customRoutes.rewrites)) {
|
||||
rewrites = {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "next",
|
||||
"version": "0.37.0",
|
||||
"nextjsVersion": "11.0.0",
|
||||
"version": "0.38.3-canary.1",
|
||||
"nextjsVersion": "11.0.1",
|
||||
"description": "The React Framework",
|
||||
"main": "./dist/server/next.js",
|
||||
"license": "MIT",
|
||||
@@ -41,8 +41,11 @@
|
||||
"router.d.ts",
|
||||
"amp.js",
|
||||
"amp.d.ts",
|
||||
"stdlib.js",
|
||||
"stdlib.d.ts",
|
||||
"types/index.d.ts",
|
||||
"types/global.d.ts"
|
||||
"types/global.d.ts",
|
||||
"image-types/global.d.ts"
|
||||
],
|
||||
"bin": {
|
||||
"next": "./dist/bin/next"
|
||||
@@ -65,10 +68,10 @@
|
||||
"dependencies": {
|
||||
"@babel/runtime": "7.12.5",
|
||||
"@hapi/accept": "5.0.2",
|
||||
"@next/env": "11.0.0",
|
||||
"@next/polyfill-module": "11.0.0",
|
||||
"@next/react-dev-overlay": "11.0.0",
|
||||
"@next/react-refresh-utils": "11.0.0",
|
||||
"@next/env": "11.0.1",
|
||||
"@next/polyfill-module": "11.0.1",
|
||||
"@next/react-dev-overlay": "11.0.1",
|
||||
"@next/react-refresh-utils": "11.0.1",
|
||||
"assert": "2.0.0",
|
||||
"ast-types": "0.13.2",
|
||||
"browserify-zlib": "0.2.0",
|
||||
@@ -80,9 +83,12 @@
|
||||
"constants-browserify": "1.0.0",
|
||||
"crypto-browserify": "3.12.0",
|
||||
"cssnano-simple": "2.0.0",
|
||||
"debug": "4.3.1",
|
||||
"domain-browser": "4.19.0",
|
||||
"encoding": "0.1.13",
|
||||
"esbuild": "^0.11.12",
|
||||
"etag": "1.8.1",
|
||||
"fs-extra": "^9.1.0",
|
||||
"get-orientation": "1.1.2",
|
||||
"https-browserify": "1.0.0",
|
||||
"image-size": "1.0.0",
|
||||
@@ -107,6 +113,7 @@
|
||||
"stream-http": "3.1.1",
|
||||
"string_decoder": "1.3.0",
|
||||
"styled-jsx": "3.3.2",
|
||||
"superjson": "1.7.2",
|
||||
"timers-browserify": "2.0.12",
|
||||
"tty-browserify": "0.0.1",
|
||||
"use-subscription": "1.5.1",
|
||||
@@ -150,7 +157,7 @@
|
||||
"@babel/preset-typescript": "7.12.7",
|
||||
"@babel/traverse": "^7.12.10",
|
||||
"@babel/types": "7.12.12",
|
||||
"@next/polyfill-nomodule": "11.0.0",
|
||||
"@next/polyfill-nomodule": "11.0.1",
|
||||
"@taskr/clear": "1.1.0",
|
||||
"@taskr/esnext": "1.1.0",
|
||||
"@taskr/watch": "1.1.0",
|
||||
@@ -173,8 +180,8 @@
|
||||
"@types/lru-cache": "5.1.0",
|
||||
"@types/node-fetch": "2.5.8",
|
||||
"@types/path-to-regexp": "1.7.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/react-dom": "16.9.4",
|
||||
"@types/react": "17.0.13",
|
||||
"@types/react-dom": "17.0.8",
|
||||
"@types/react-is": "16.7.1",
|
||||
"@types/semver": "7.3.1",
|
||||
"@types/send": "0.14.4",
|
||||
@@ -199,7 +206,6 @@
|
||||
"content-type": "1.0.4",
|
||||
"cookie": "0.4.1",
|
||||
"css-loader": "4.3.0",
|
||||
"debug": "4.3.1",
|
||||
"devalue": "2.0.1",
|
||||
"escape-string-regexp": "2.0.0",
|
||||
"file-loader": "6.0.0",
|
||||
|
||||
@@ -166,7 +166,7 @@ export default class HotReloader {
|
||||
this.buildId = buildId
|
||||
this.dir = dir
|
||||
this.middlewares = []
|
||||
this.pagesDir = pagesDir
|
||||
this.pagesDir = dir
|
||||
this.webpackHotMiddleware = null
|
||||
this.stats = null
|
||||
this.serverStats = null
|
||||
|
||||
@@ -3,7 +3,9 @@ import chalk from 'chalk'
|
||||
import { warn } from '../../build/output/log'
|
||||
import { promises } from 'fs'
|
||||
import { denormalizePagePath } from '../../next-server/server/normalize-page-path'
|
||||
import { fileExists } from '../../lib/file-exists'
|
||||
// import { fileExists } from '../../lib/file-exists'
|
||||
import { recursiveFindPages } from '../../lib/recursive-readdir'
|
||||
import { buildPageExtensionRegex } from '../../build/utils'
|
||||
|
||||
async function isTrueCasePagePath(pagePath: string, pagesDir: string) {
|
||||
const pageSegments = normalize(pagePath).split(pathSeparator).filter(Boolean)
|
||||
@@ -22,27 +24,60 @@ export async function findPageFile(
|
||||
normalizedPagePath: string,
|
||||
pageExtensions: string[]
|
||||
): Promise<string | null> {
|
||||
const foundPagePaths: string[] = []
|
||||
// console.log('[findPageFile]', { rootDir, normalizedPagePath })
|
||||
|
||||
const page = denormalizePagePath(normalizedPagePath)
|
||||
|
||||
for (const extension of pageExtensions) {
|
||||
if (!normalizedPagePath.endsWith('/index')) {
|
||||
const relativePagePath = `${page}.${extension}`
|
||||
const pagePath = join(rootDir, relativePagePath)
|
||||
const allPages = await recursiveFindPages(
|
||||
rootDir,
|
||||
buildPageExtensionRegex(pageExtensions)
|
||||
)
|
||||
// console.log('allPages', allPages)
|
||||
|
||||
if (await fileExists(pagePath)) {
|
||||
foundPagePaths.push(relativePagePath)
|
||||
}
|
||||
}
|
||||
|
||||
const relativePagePathWithIndex = join(page, `index.${extension}`)
|
||||
const pagePathWithIndex = join(rootDir, relativePagePathWithIndex)
|
||||
if (await fileExists(pagePathWithIndex)) {
|
||||
foundPagePaths.push(relativePagePathWithIndex)
|
||||
}
|
||||
let prefix: string
|
||||
if (normalizedPagePath.startsWith('/api/')) {
|
||||
prefix = ''
|
||||
} else {
|
||||
prefix = '/pages'
|
||||
}
|
||||
|
||||
let nameMatch: string
|
||||
if (page === '/') {
|
||||
nameMatch = normalizedPagePath
|
||||
} else if (page.endsWith('/index')) {
|
||||
nameMatch = `${page}/index`
|
||||
} else {
|
||||
nameMatch = `(${page}|${page}/index)`
|
||||
}
|
||||
|
||||
nameMatch = nameMatch.replace(/[[\]\\]/g, '\\$&')
|
||||
const foundPagePaths = allPages.filter((path) =>
|
||||
path.match(
|
||||
new RegExp(`${prefix}${nameMatch}\\.(?:${pageExtensions.join('|')})$`)
|
||||
)
|
||||
)
|
||||
// console.log(
|
||||
// new RegExp(`${prefix}${nameMatch}\\.(?:${pageExtensions.join('|')})$`)
|
||||
// )
|
||||
// console.log('FOUND', foundPagePaths)
|
||||
|
||||
// for (const extension of pageExtensions) {
|
||||
// if (!normalizedPagePath.endsWith('/index')) {
|
||||
// const relativePagePath = `${page}.${extension}`
|
||||
// const pagePath = join(rootDir, relativePagePath)
|
||||
//
|
||||
// if (await fileExists(pagePath)) {
|
||||
// foundPagePaths.push(relativePagePath)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// const relativePagePathWithIndex = join(page, `index.${extension}`)
|
||||
// const pagePathWithIndex = join(rootDir, relativePagePathWithIndex)
|
||||
// if (await fileExists(pagePathWithIndex)) {
|
||||
// foundPagePaths.push(relativePagePathWithIndex)
|
||||
// }
|
||||
// }
|
||||
|
||||
if (foundPagePaths.length < 1) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import findUp from 'next/dist/compiled/find-up'
|
||||
import { dirname } from 'path'
|
||||
|
||||
export function printAndExit(message: string, code = 1) {
|
||||
if (code === 0) {
|
||||
@@ -16,16 +16,14 @@ export function getNodeOptionsWithoutInspect() {
|
||||
return (process.env.NODE_OPTIONS || '').replace(NODE_INSPECT_RE, '')
|
||||
}
|
||||
|
||||
export function getProjectRoot() {
|
||||
return path.dirname(getConfigSrcPath())
|
||||
}
|
||||
export async function getProjectRoot(dir: string) {
|
||||
const pkgJsonPath = await findUp('package.json', { cwd: dir })
|
||||
|
||||
export function getConfigSrcPath() {
|
||||
const tsPath = path.resolve(path.join(process.cwd(), 'blitz.config.ts'))
|
||||
if (fs.existsSync(tsPath)) {
|
||||
return tsPath
|
||||
} else {
|
||||
const jsPath = path.resolve(path.join(process.cwd(), 'blitz.config.js'))
|
||||
return jsPath
|
||||
if (!pkgJsonPath) {
|
||||
throw new Error(
|
||||
'Unable to find project root by looking for your package.json'
|
||||
)
|
||||
}
|
||||
|
||||
return dirname(pkgJsonPath)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import { ampValidation } from '../build/output/index'
|
||||
import * as Log from '../build/output/log'
|
||||
import { PUBLIC_DIR_MIDDLEWARE_CONFLICT } from '../lib/constants'
|
||||
import { fileExists } from '../lib/file-exists'
|
||||
import { findPagesDir } from '../lib/find-pages-dir'
|
||||
import loadCustomRoutes, { CustomRoutes } from '../lib/load-custom-routes'
|
||||
import { verifyTypeScriptSetup } from '../lib/verifyTypeScriptSetup'
|
||||
import {
|
||||
@@ -39,6 +38,12 @@ import { findPageFile } from './lib/find-page-file'
|
||||
import { getNodeOptionsWithoutInspect } from './lib/utils'
|
||||
import { withCoalescedInvoke } from '../lib/coalesced-function'
|
||||
import { NextConfig } from '../next-server/server/config'
|
||||
import {
|
||||
buildPageExtensionRegex,
|
||||
convertPageFilePathToRoutePath,
|
||||
isPageFile,
|
||||
topLevelFoldersThatMayContainPages,
|
||||
} from '../build/utils'
|
||||
|
||||
if (typeof React.Suspense === 'undefined') {
|
||||
throw new Error(
|
||||
@@ -107,7 +112,7 @@ export default class DevServer extends Server {
|
||||
)
|
||||
}
|
||||
this.isCustomServer = !options.isNextDevCommand
|
||||
this.pagesDir = findPagesDir(this.dir)
|
||||
this.pagesDir = this.dir
|
||||
this.staticPathsWorker = new Worker(
|
||||
require.resolve('./static-paths-worker'),
|
||||
{
|
||||
@@ -187,8 +192,8 @@ export default class DevServer extends Server {
|
||||
return
|
||||
}
|
||||
|
||||
const regexPageExtension = new RegExp(
|
||||
`\\.+(?:${this.nextConfig.pageExtensions.join('|')})$`
|
||||
const regexPageExtension = buildPageExtensionRegex(
|
||||
this.nextConfig.pageExtensions
|
||||
)
|
||||
|
||||
let resolved = false
|
||||
@@ -208,18 +213,31 @@ export default class DevServer extends Server {
|
||||
})
|
||||
|
||||
let wp = (this.webpackWatcher = new Watchpack())
|
||||
wp.watch([], [pagesDir!], 0)
|
||||
wp.watch(
|
||||
[],
|
||||
topLevelFoldersThatMayContainPages.map((dir) =>
|
||||
pathJoin(pagesDir!, dir)
|
||||
),
|
||||
0
|
||||
)
|
||||
|
||||
wp.on('aggregated', () => {
|
||||
const routedPages = []
|
||||
const knownFiles = wp.getTimeInfoEntries()
|
||||
for (const [fileName, { accuracy }] of knownFiles) {
|
||||
if (accuracy === undefined || !regexPageExtension.test(fileName)) {
|
||||
for (const [filePath, { accuracy }] of knownFiles) {
|
||||
const relativePath = '/' + relative(pagesDir!, filePath)
|
||||
|
||||
if (
|
||||
accuracy === undefined ||
|
||||
!isPageFile(relativePath) ||
|
||||
!regexPageExtension.test(filePath)
|
||||
) {
|
||||
continue
|
||||
}
|
||||
|
||||
let pageName =
|
||||
'/' + relative(pagesDir!, fileName).replace(/\\+/g, '/')
|
||||
let pageName = relativePath.replace(/\\+/g, '/')
|
||||
|
||||
pageName = convertPageFilePathToRoutePath(pageName)
|
||||
pageName = pageName.replace(regexPageExtension, '')
|
||||
pageName = pageName.replace(/\/index$/, '') || '/'
|
||||
|
||||
@@ -275,7 +293,12 @@ export default class DevServer extends Server {
|
||||
}
|
||||
|
||||
async prepare(): Promise<void> {
|
||||
await verifyTypeScriptSetup(this.dir, this.pagesDir!, false)
|
||||
await verifyTypeScriptSetup(
|
||||
this.dir,
|
||||
this.pagesDir!,
|
||||
false,
|
||||
!this.nextConfig.images.disableStaticImages
|
||||
)
|
||||
|
||||
this.customRoutes = await loadCustomRoutes(this.nextConfig)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { pageNotFoundError } from '../next-server/server/require'
|
||||
import { findPageFile } from './lib/find-page-file'
|
||||
import getRouteFromEntrypoint from '../next-server/server/get-route-from-entrypoint'
|
||||
import { convertPageFilePathToRoutePath } from '../build/utils'
|
||||
|
||||
export const ADDED = Symbol('added')
|
||||
export const BUILDING = Symbol('building')
|
||||
@@ -158,7 +159,7 @@ export default function onDemandEntryHandler(
|
||||
throw pageNotFoundError(normalizedPagePath)
|
||||
}
|
||||
|
||||
let pageUrl = pagePath.replace(/\\/g, '/')
|
||||
let pageUrl = convertPageFilePathToRoutePath(pagePath.replace(/\\/g, '/'))
|
||||
|
||||
pageUrl = `${pageUrl[0] !== '/' ? '/' : ''}${pageUrl
|
||||
.replace(new RegExp(`\\.+(?:${pageExtensions.join('|')})$`), '')
|
||||
|
||||
2
nextjs/packages/next/stdlib.d.ts
vendored
Normal file
2
nextjs/packages/next/stdlib.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './dist/stdlib/index'
|
||||
export { default } from './dist/stdlib/index'
|
||||
1
nextjs/packages/next/stdlib.js
Normal file
1
nextjs/packages/next/stdlib.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('./dist/stdlib/index')
|
||||
@@ -1,15 +1,15 @@
|
||||
import SuperJson from "superjson"
|
||||
import type {UrlObject} from "url"
|
||||
import SuperJson from 'superjson'
|
||||
import type { UrlObject } from 'url'
|
||||
|
||||
const errorProps = ["name", "message", "code", "statusCode", "meta"]
|
||||
const errorProps = ['name', 'message', 'code', 'statusCode', 'meta']
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
SuperJson.allowErrorProps(...errorProps)
|
||||
}
|
||||
|
||||
export class AuthenticationError extends Error {
|
||||
name = "AuthenticationError"
|
||||
name = 'AuthenticationError'
|
||||
statusCode = 401
|
||||
constructor(message = "You must be logged in to access this") {
|
||||
constructor(message = 'You must be logged in to access this') {
|
||||
super(message)
|
||||
}
|
||||
get _clearStack() {
|
||||
@@ -18,13 +18,13 @@ export class AuthenticationError extends Error {
|
||||
}
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
SuperJson.registerClass(AuthenticationError, {
|
||||
identifier: "BlitzAuthenticationError",
|
||||
identifier: 'BlitzAuthenticationError',
|
||||
allowProps: errorProps,
|
||||
})
|
||||
}
|
||||
|
||||
export class CSRFTokenMismatchError extends Error {
|
||||
name = "CSRFTokenMismatchError"
|
||||
name = 'CSRFTokenMismatchError'
|
||||
statusCode = 401
|
||||
get _clearStack() {
|
||||
return true
|
||||
@@ -32,15 +32,15 @@ export class CSRFTokenMismatchError extends Error {
|
||||
}
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
SuperJson.registerClass(CSRFTokenMismatchError, {
|
||||
identifier: "BlitzCSRFTokenMismatchError",
|
||||
identifier: 'BlitzCSRFTokenMismatchError',
|
||||
allowProps: errorProps,
|
||||
})
|
||||
}
|
||||
|
||||
export class AuthorizationError extends Error {
|
||||
name = "AuthorizationError"
|
||||
name = 'AuthorizationError'
|
||||
statusCode = 403
|
||||
constructor(message = "You are not authorized to access this") {
|
||||
constructor(message = 'You are not authorized to access this') {
|
||||
super(message)
|
||||
}
|
||||
get _clearStack() {
|
||||
@@ -49,15 +49,15 @@ export class AuthorizationError extends Error {
|
||||
}
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
SuperJson.registerClass(AuthorizationError, {
|
||||
identifier: "BlitzAuthorizationError",
|
||||
identifier: 'BlitzAuthorizationError',
|
||||
allowProps: errorProps,
|
||||
})
|
||||
}
|
||||
|
||||
export class NotFoundError extends Error {
|
||||
name = "NotFoundError"
|
||||
name = 'NotFoundError'
|
||||
statusCode = 404
|
||||
constructor(message = "This could not be found") {
|
||||
constructor(message = 'This could not be found') {
|
||||
super(message)
|
||||
}
|
||||
get _clearStack() {
|
||||
@@ -65,29 +65,32 @@ export class NotFoundError extends Error {
|
||||
}
|
||||
}
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
SuperJson.registerClass(NotFoundError, {identifier: "BlitzNotFoundError", allowProps: errorProps})
|
||||
SuperJson.registerClass(NotFoundError, {
|
||||
identifier: 'BlitzNotFoundError',
|
||||
allowProps: errorProps,
|
||||
})
|
||||
}
|
||||
|
||||
export class PaginationArgumentError extends Error {
|
||||
name = "PaginationArgumentError"
|
||||
name = 'PaginationArgumentError'
|
||||
statusCode = 422
|
||||
constructor(message = "The pagination arguments are invalid") {
|
||||
constructor(message = 'The pagination arguments are invalid') {
|
||||
super(message)
|
||||
}
|
||||
}
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
SuperJson.registerClass(PaginationArgumentError, {
|
||||
identifier: "BlitzPaginationArgumentError",
|
||||
identifier: 'BlitzPaginationArgumentError',
|
||||
allowProps: errorProps,
|
||||
})
|
||||
}
|
||||
|
||||
export class RedirectError extends Error {
|
||||
name = "RedirectError"
|
||||
name = 'RedirectError'
|
||||
statusCode = 302
|
||||
url: UrlObject | string
|
||||
constructor(url: UrlObject | string) {
|
||||
super(typeof url === "object" ? url.href! : url)
|
||||
super(typeof url === 'object' ? url.href! : url)
|
||||
this.url = url
|
||||
}
|
||||
get _clearStack() {
|
||||
@@ -95,5 +98,8 @@ export class RedirectError extends Error {
|
||||
}
|
||||
}
|
||||
if (process.env.JEST_WORKER_ID === undefined) {
|
||||
SuperJson.registerClass(NotFoundError, {identifier: "BlitzRedirectError", allowProps: errorProps})
|
||||
SuperJson.registerClass(NotFoundError, {
|
||||
identifier: 'BlitzRedirectError',
|
||||
allowProps: errorProps,
|
||||
})
|
||||
}
|
||||
1
nextjs/packages/next/stdlib/index.ts
Normal file
1
nextjs/packages/next/stdlib/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './errors'
|
||||
@@ -807,6 +807,7 @@ export async function compile(task, opts) {
|
||||
'pages',
|
||||
'lib',
|
||||
'client',
|
||||
'stdlib',
|
||||
'telemetry',
|
||||
'nextserver',
|
||||
'nextserver_wasm',
|
||||
@@ -866,6 +867,14 @@ export async function client(task, opts) {
|
||||
notify('Compiled client files')
|
||||
}
|
||||
|
||||
export async function stdlib(task, opts) {
|
||||
await task
|
||||
.source(opts.src || 'stdlib/**/*.+(js|ts|tsx)')
|
||||
.babel('stdlib', { dev: opts.dev })
|
||||
.target('dist/stdlib')
|
||||
notify('Compiled stdlib files')
|
||||
}
|
||||
|
||||
// export is a reserved keyword for functions
|
||||
export async function nextbuildstatic(task, opts) {
|
||||
await task
|
||||
@@ -922,6 +931,7 @@ export default async function (task) {
|
||||
await task.watch('build/**/*.+(js|ts|tsx)', 'nextbuild', opts)
|
||||
await task.watch('export/**/*.+(js|ts|tsx)', 'nextbuildstatic', opts)
|
||||
await task.watch('client/**/*.+(js|ts|tsx)', 'client', opts)
|
||||
await task.watch('stdlib/**/*.+(js|ts|tsx)', 'stdlib', opts)
|
||||
await task.watch('lib/**/*.+(js|ts|tsx)', 'lib', opts)
|
||||
await task.watch('cli/**/*.+(js|ts|tsx)', 'cli', opts)
|
||||
await task.watch('telemetry/**/*.+(js|ts|tsx)', 'telemetry', opts)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user