Skip to content

Commit

Permalink
Merge branch 'canary' of https://github.com/zeit/next.js into font-op…
Browse files Browse the repository at this point in the history
…tims
  • Loading branch information
prateekbh committed Jul 30, 2020
2 parents 52ed9ce + dcb69ee commit b478785
Show file tree
Hide file tree
Showing 49 changed files with 725 additions and 219 deletions.
22 changes: 19 additions & 3 deletions .github/workflows/build_test_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,8 @@ jobs:
- run: exit 0

testMacOS:
name: macOS ( Basic, Production, Acceptance )
name: macOS (Basic, Production, Acceptance)
runs-on: macos-latest
needs: build
env:
NEXT_TELEMETRY_DISABLED: 1
NEXT_TEST_JOB: 1
Expand All @@ -90,7 +89,24 @@ jobs:
- uses: actions/checkout@v2
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
# Installing dependencies again since OS changed
- run: yarn install --frozen-lockfile --check-files
- run: yarn install --frozen-lockfile --check-files || yarn install --frozen-lockfile --check-files
- run: node run-tests.js test/integration/production/test/index.test.js
- run: node run-tests.js test/integration/basic/test/index.test.js
- run: node run-tests.js test/acceptance/*

testWebpack5:
name: webpack 5 (Basic, Production, Acceptance)
runs-on: ubuntu-latest
env:
NEXT_TELEMETRY_DISABLED: 1
NEXT_TEST_JOB: 1
HEADLESS: true

steps:
- uses: actions/checkout@v2
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
- run: cat package.json | jq '.resolutions.webpack = "^5.0.0-beta.22"' > package.json.tmp && mv package.json.tmp package.json
- run: yarn install --check-files
- run: node run-tests.js test/integration/production/test/index.test.js
- run: node run-tests.js test/integration/basic/test/index.test.js
- run: node run-tests.js test/acceptance/*
Expand Down
75 changes: 74 additions & 1 deletion docs/basic-features/data-fetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ The `context` parameter is an object containing the following keys:
- `preview` is `true` if the page is in the preview mode and `false` otherwise. See the [Preview Mode documentation](/docs/advanced-features/preview-mode.md).
- `previewData` contains the preview data set by `setPreviewData`. See the [Preview Mode documentation](/docs/advanced-features/preview-mode.md).

`getStaticProps` should return an object with:

- `props` - A **required** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization)
- `revalidate` - An **optional** amount in seconds after which a page re-generation can occur. More on [Incremental Static Regeneration](#incremental-static-regeneration)

> **Note**: You can import modules in top-level scope for use in `getStaticProps`.
> Imports used in `getStaticProps` will not be bundled for the client-side, as [explained below](#write-server-side-code-directly).
Expand Down Expand Up @@ -143,6 +148,67 @@ function Blog({ posts }: InferGetStaticPropsType<typeof getStaticProps>) {
export default Blog
```

### Incremental Static Regeneration

> This feature was introduced in [Next.js 9.5](https://nextjs.org/blog/next-9-5#stable-incremental-static-regeneration) and up. If you’re using older versions of Next.js, please upgrade before trying Incremental Static Regeneration.
<details open>
<summary><b>Examples</b></summary>
<ul>
<li><a href="https://reactions-demo.now.sh/">Static Reactions Demo</a></li>
</ul>
</details>

With [`getStaticProps`](#getstaticprops-static-generation) you don't have to stop relying in dynamic content, as **static content can also be dynamic**. Incremental Static Regeneration allows you to update _existing_ pages by re-rendering them in the background as traffic comes in.

Inspired by [stale-while-revalidate](https://tools.ietf.org/html/rfc5861), background regeneration ensures traffic is served uninterruptedly, always from static storage, and the newly built page is pushed only after it's done generating.

Consider our previous [`getStaticProps` example](#simple-example), but now with regeneration enabled:

```jsx
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
)
}

// This function gets called at build time on server-side.
// It may be called again, on a serverless function, if
// revalidation is enabled and a new request comes in
export async function getStaticProps() {
const res = await fetch('https://.../posts')
const posts = await res.json()

return {
props: {
posts,
},
// Next.js will attempt to re-generate the page:
// - When a request comes in
// - At most once every second
revalidate: 1, // In seconds
}
}

export default Blog
```

Now the list of blog posts will be revalidated once per second; if you add a new blog post it will be available almost immediately, without having to re-build your app or make a new deployment.

This works perfectly with [`fallback: true`](#fallback-true). Because now you can have a list of posts that's always up to date with the latest posts, and have a [blog post page](#fallback-pages) that generates blog posts on-demand, no matter how many posts you add or update.

#### Static content at scale

Unlike traditional SSR, [Incremental Static Regeneration](#incremental-static-regeneration) ensures you retain the benefits of static:

- No spikes in latency. Pages are served consistently fast
- Pages never go offline. If the background page re-generation fails, the old page remains unaltered
- Low database and backend load. Pages are re-computed at most once concurrently

### Reading files: Use `process.cwd()`

Files can be read directly from the filesystem in `getStaticProps`.
Expand Down Expand Up @@ -387,7 +453,12 @@ export async function getStaticProps({ params }) {
const post = await res.json()

// Pass post data to the page via props
return { props: { post } }
return {
props: { post },
// Re-generate the post at most once per second
// if a request comes in
revalidate: 1,
}
}

export default Post
Expand All @@ -401,6 +472,8 @@ Instead, you may statically generate a small subset of pages and use `fallback:

This ensures that users always have a fast experience while preserving fast builds and the benefits of Static Generation.

`fallback: true` will not _update_ generated pages, for that take a look at [Incremental Static Regeneration](#incremental-static-regeneration).

### When should I use `getStaticPaths`?

You should use `getStaticPaths` if you’re statically pre-rendering pages that use dynamic routes.
Expand Down
8 changes: 0 additions & 8 deletions examples/with-sentry/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,6 @@ const Index = () => (
Open in a new tab
</a>
</li>
<li>
There is a top-of-module Promise that rejects, but its result is not
awaited. Sentry should record Error('Server Test 4'). Note this will
also be recorded on the client side, once the page is hydrated.{' '}
<a href="/server/test4" target="_blank">
Open in a new tab
</a>
</li>
</ul>

<li>Client exceptions</li>
Expand Down
12 changes: 0 additions & 12 deletions examples/with-sentry/pages/server/test4.js

This file was deleted.

2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@
"registry": "https://registry.npmjs.org/"
}
},
"version": "9.5.1-canary.2"
"version": "9.5.2-canary.0"
}
2 changes: 1 addition & 1 deletion packages/create-next-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-next-app",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"keywords": [
"react",
"next",
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/eslint-plugin-next",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"description": "ESLint plugin for NextJS.",
"main": "lib/index.js",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion packages/next-bundle-analyzer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/bundle-analyzer",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"main": "index.js",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-mdx/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"main": "index.js",
"license": "MIT",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-google-analytics/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-google-analytics",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-google-analytics"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-sentry/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-sentry",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-sentry"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-plugin-storybook/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-storybook",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-storybook"
Expand Down
2 changes: 1 addition & 1 deletion packages/next-polyfill-nomodule/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-nomodule",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"description": "A polyfill for non-dead, nomodule browsers.",
"main": "dist/polyfill-nomodule.js",
"license": "MIT",
Expand Down
9 changes: 7 additions & 2 deletions packages/next/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import WebpackConformancePlugin, {
ReactSyncScriptsConformanceCheck,
} from './webpack/plugins/webpack-conformance-plugin'
import { WellKnownErrorsPlugin } from './webpack/plugins/wellknown-errors-plugin'
import FontStylesheetGatheringPlugin from './webpack/plugins/font-stylesheet-gathering-plugin'

type ExcludesFalse = <T>(x: T | false) => x is T

const isWebpack5 = parseInt(webpack.version!) === 5
Expand Down Expand Up @@ -984,7 +984,12 @@ export default async function getBaseWebpackConfig(
config.experimental.optimizeFonts &&
!dev &&
isServer &&
new FontStylesheetGatheringPlugin(),
(function () {
const {
FontStylesheetGatheringPlugin,
} = require('./webpack/plugins/font-stylesheet-gathering-plugin')
return new FontStylesheetGatheringPlugin()
})(),
config.experimental.conformance &&
!isWebpack5 &&
!dev &&
Expand Down
1 change: 1 addition & 0 deletions packages/next/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ if (
!(
page === '/_error' &&
hydrateProps &&
hydrateProps.pageProps &&
hydrateProps.pageProps.statusCode === '404'
)
) {
Expand Down
8 changes: 4 additions & 4 deletions packages/next/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"description": "The React Framework",
"main": "./dist/server/next.js",
"license": "MIT",
Expand Down Expand Up @@ -76,8 +76,8 @@
"@babel/preset-typescript": "7.9.0",
"@babel/runtime": "7.9.6",
"@babel/types": "7.9.6",
"@next/react-dev-overlay": "9.5.1-canary.2",
"@next/react-refresh-utils": "9.5.1-canary.2",
"@next/react-dev-overlay": "9.5.2-canary.0",
"@next/react-refresh-utils": "9.5.2-canary.0",
"ast-types": "0.13.2",
"babel-plugin-syntax-jsx": "6.18.0",
"babel-plugin-transform-define": "2.0.0",
Expand Down Expand Up @@ -119,7 +119,7 @@
"react-dom": "^16.6.0"
},
"devDependencies": {
"@next/polyfill-nomodule": "9.5.1-canary.2",
"@next/polyfill-nomodule": "9.5.2-canary.0",
"@taskr/clear": "1.1.0",
"@taskr/esnext": "1.1.0",
"@taskr/watch": "1.1.0",
Expand Down
32 changes: 28 additions & 4 deletions packages/next/server/hot-reloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,10 @@ export default class HotReloader {
private pagesDir: string
private webpackHotMiddleware: (NextHandleFunction & any) | null
private config: any
private stats: any
private serverStats: any
private stats: webpack.Stats | null
private serverStats: webpack.Stats | null
private clientError: Error | null = null
private serverError: Error | null = null
private serverPrevDocumentHash: string | null
private prevChunkNames?: Set<any>
private onDemandEntries: any
Expand Down Expand Up @@ -349,9 +351,17 @@ export default class HotReloader {
watchCompilers(multiCompiler.compilers[0], multiCompiler.compilers[1])

// This plugin watches for changes to _document.js and notifies the client side that it should reload the page
multiCompiler.compilers[1].hooks.failed.tap(
'NextjsHotReloaderForServer',
(err: Error) => {
this.serverError = err
this.serverStats = null
}
)
multiCompiler.compilers[1].hooks.done.tap(
'NextjsHotReloaderForServer',
(stats) => {
this.serverError = null
this.serverStats = stats

const { compilation } = stats
Expand Down Expand Up @@ -384,9 +394,19 @@ export default class HotReloader {
}
)

multiCompiler.compilers[0].hooks.failed.tap(
'NextjsHotReloaderForClient',
(err: Error) => {
this.clientError = err
this.stats = null
}
)
multiCompiler.compilers[0].hooks.done.tap(
'NextjsHotReloaderForClient',
(stats) => {
this.clientError = null
this.stats = stats

const { compilation } = stats
const chunkNames = new Set(
compilation.chunks
Expand Down Expand Up @@ -415,7 +435,6 @@ export default class HotReloader {
}
}

this.stats = stats
this.prevChunkNames = chunkNames
}
)
Expand Down Expand Up @@ -471,7 +490,9 @@ export default class HotReloader {
public async getCompilationErrors(page: string) {
const normalizedPage = normalizePathSep(page)

if (this.stats.hasErrors()) {
if (this.clientError || this.serverError) {
return [this.clientError || this.serverError]
} else if (this.stats?.hasErrors()) {
const { compilation } = this.stats
const failedPages = erroredPages(compilation)

Expand Down Expand Up @@ -499,6 +520,9 @@ export default class HotReloader {
if (page !== '/_error' && BLOCKED_PAGES.indexOf(page) !== -1) {
return
}
if (this.serverError || this.clientError) {
return Promise.reject(this.serverError || this.clientError)
}
return this.onDemandEntries.ensurePage(page)
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/react-dev-overlay/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@next/react-dev-overlay",
"version": "9.5.1-canary.2",
"version": "9.5.2-canary.0",
"description": "A development-only overlay for developing React applications.",
"repository": {
"url": "vercel/next.js",
Expand Down
Loading

0 comments on commit b478785

Please sign in to comment.