diff --git a/.github/workflows/build_native.yml b/.github/workflows/build_native.yml
index 4f660a10ff74b..9f22bedf98cea 100644
--- a/.github/workflows/build_native.yml
+++ b/.github/workflows/build_native.yml
@@ -63,6 +63,17 @@ jobs:
export CXX=$(xcrun -f clang++);
SYSROOT=$(xcrun --sdk macosx --show-sdk-path);
export CFLAGS="-isysroot $SYSROOT -isystem $SYSROOT";
+ # We use restore-key to pick latest cache.
+ # We will not get exact match, but doc says
+ # "If there are multiple partial matches for a restore key, the action returns the most recently created cache."
+ # So we get latest cache
+ - name: Cache built files
+ uses: actions/cache@v2
+ with:
+ path: ./packages/next/build/swc/target
+ key: next-swc-cargo-cache-${{ matrix.os }}--${{ hashFiles('**/Cargo.lock') }}
+ restore-keys: |
+ next-swc-cargo-cache-${{ matrix.os }}
- name: 'Build'
if: steps.binary-cache.outputs.cache-hit != true
run: yarn build-native --target ${{ matrix.target }}
diff --git a/docs/api-reference/next/image.md b/docs/api-reference/next/image.md
index fffaa86980448..3b0c6ec05048d 100644
--- a/docs/api-reference/next/image.md
+++ b/docs/api-reference/next/image.md
@@ -318,12 +318,13 @@ The following describes the caching algorithm for the default [loader](#loader).
Images are optimized dynamically upon request and stored in the `/cache/images` directory. The optimized image file will be served for subsequent requests until the expiration is reached. When a request is made that matches a cached but expired file, the cached file is deleted before generating a new optimized image and caching the new file.
-The expiration (or rather Max Age) is defined by the upstream server's `Cache-Control` header.
+The expiration (or rather Max Age) is defined by either the [`minimumCacheTTL`](#minimum-cache-ttl) configuration or the upstream server's `Cache-Control` header, whichever is larger. Specifically, the `max-age` value of the `Cache-Control` header is used. If both `s-maxage` and `max-age` are found, then `s-maxage` is preferred.
-- If `s-maxage` is found in `Cache-Control`, it is used. If no `s-maxage` is found, then `max-age` is used. If no `max-age` is found, then [`minimumCacheTTL`](#minimum-cache-ttl) is used.
-- You can configure [`minimumCacheTTL`](#minimum-cache-ttl) to increase the cache duration when the upstream image does not include `max-age`.
-- You can also configure [`deviceSizes`](#device-sizes) and [`imageSizes`](#device-sizes) to reduce the total number of possible generated images.
-- You can also configure [formats](/docs/basic-features/image-optimization.md#acceptable-formats) to disable multiple formats in favor of a single image format.
+- You can configure [`minimumCacheTTL`](#minimum-cache-ttl) to increase the cache duration when the upstream image does not include `Cache-Control` header or the value is very low.
+- You can configure [`deviceSizes`](#device-sizes) and [`imageSizes`](#device-sizes) to reduce the total number of possible generated images.
+- You can configure [formats](/docs/basic-features/image-optimization.md#acceptable-formats) to disable multiple formats in favor of a single image format.
+
+### Minimum Cache TTL
You can configure the Time to Live (TTL) in seconds for cached optimized images. In many cases, it's better to use a [Static Image Import](/docs/basic-features/image-optimization.md#local-images) which will automatically hash the file contents and cache the image forever with a `Cache-Control` header of `immutable`.
diff --git a/lerna.json b/lerna.json
index c23e2b0c19ec3..cd10658835d4e 100644
--- a/lerna.json
+++ b/lerna.json
@@ -17,5 +17,5 @@
"registry": "https://registry.npmjs.org/"
}
},
- "version": "11.1.3-canary.67"
+ "version": "11.1.3-canary.68"
}
diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json
index 82b87f5decfbf..37c542bc80005 100644
--- a/packages/create-next-app/package.json
+++ b/packages/create-next-app/package.json
@@ -1,6 +1,6 @@
{
"name": "create-next-app",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"keywords": [
"react",
"next",
diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json
index 09e15342ea9af..bcc53288774c7 100644
--- a/packages/eslint-config-next/package.json
+++ b/packages/eslint-config-next/package.json
@@ -1,6 +1,6 @@
{
"name": "eslint-config-next",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"description": "ESLint configuration used by NextJS.",
"main": "index.js",
"license": "MIT",
@@ -9,7 +9,7 @@
"directory": "packages/eslint-config-next"
},
"dependencies": {
- "@next/eslint-plugin-next": "11.1.3-canary.67",
+ "@next/eslint-plugin-next": "11.1.3-canary.68",
"@rushstack/eslint-patch": "^1.0.8",
"@typescript-eslint/parser": "^5.0.0",
"eslint-import-resolver-node": "^0.3.4",
diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json
index 8693ac93b68fa..245dfbc2c355b 100644
--- a/packages/eslint-plugin-next/package.json
+++ b/packages/eslint-plugin-next/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/eslint-plugin-next",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"description": "ESLint plugin for NextJS.",
"main": "lib/index.js",
"license": "MIT",
diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json
index 1452c6be5089f..ca813b18b4b94 100644
--- a/packages/next-bundle-analyzer/package.json
+++ b/packages/next-bundle-analyzer/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/bundle-analyzer",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"main": "index.js",
"license": "MIT",
"repository": {
diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json
index db2238aaa0961..c8e8c95e74485 100644
--- a/packages/next-codemod/package.json
+++ b/packages/next-codemod/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/codemod",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"license": "MIT",
"dependencies": {
"chalk": "4.1.0",
diff --git a/packages/next-env/package.json b/packages/next-env/package.json
index 997a9f77db0fe..ff188acf783d6 100644
--- a/packages/next-env/package.json
+++ b/packages/next-env/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/env",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"keywords": [
"react",
"next",
diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json
index f43e3546bdc69..64e6b7f0df004 100644
--- a/packages/next-mdx/package.json
+++ b/packages/next-mdx/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/mdx",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"main": "index.js",
"license": "MIT",
"repository": {
diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json
index 084bc5d4e98a1..0d30c39258ae1 100644
--- a/packages/next-plugin-storybook/package.json
+++ b/packages/next-plugin-storybook/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/plugin-storybook",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"repository": {
"url": "vercel/next.js",
"directory": "packages/next-plugin-storybook"
diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json
index d781b92391c0b..2dea887d9e1d5 100644
--- a/packages/next-polyfill-module/package.json
+++ b/packages/next-polyfill-module/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-module",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"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",
diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json
index c790fddbb089a..b931a76aa1b23 100644
--- a/packages/next-polyfill-nomodule/package.json
+++ b/packages/next-polyfill-nomodule/package.json
@@ -1,6 +1,6 @@
{
"name": "@next/polyfill-nomodule",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"description": "A polyfill for non-dead, nomodule browsers.",
"main": "dist/polyfill-nomodule.js",
"license": "MIT",
diff --git a/packages/next/build/swc/Cargo.lock b/packages/next/build/swc/Cargo.lock
index 43adfbf4f884f..bb33d24fe7615 100644
--- a/packages/next/build/swc/Cargo.lock
+++ b/packages/next/build/swc/Cargo.lock
@@ -1612,9 +1612,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "swc"
-version = "0.68.0"
+version = "0.68.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db528ae495b10d365a4e46fc84a34ba79556ab9001e6524cfd7abac7da6273ef"
+checksum = "9f6dd80aa3787665ab1560af56722140b1a1435b56b240dc4253b57491cb3a9a"
dependencies = [
"ahash",
"anyhow",
@@ -2163,9 +2163,9 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_typescript"
-version = "0.49.0"
+version = "0.49.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9828b88136fc8b947d894fcf49d237b75ee80ffe7e5cb39813403ee714c02b4c"
+checksum = "cf92d054c7f5c4d8e26143ad04a60329afb8d7cf3111578ce0433d60be78b88f"
dependencies = [
"serde",
"swc_atoms",
diff --git a/packages/next/native/next-swc.darwin-arm64.node b/packages/next/native/next-swc.darwin-arm64.node
index e2b4d08382c2c..3324d2802bec4 100644
Binary files a/packages/next/native/next-swc.darwin-arm64.node and b/packages/next/native/next-swc.darwin-arm64.node differ
diff --git a/packages/next/native/next-swc.darwin-x64.node b/packages/next/native/next-swc.darwin-x64.node
index 5401c84ddfbc5..c6beff09c6475 100644
Binary files a/packages/next/native/next-swc.darwin-x64.node and b/packages/next/native/next-swc.darwin-x64.node differ
diff --git a/packages/next/native/next-swc.linux-x64-gnu.node b/packages/next/native/next-swc.linux-x64-gnu.node
index e8ea7855b057f..cc5573aa87551 100644
Binary files a/packages/next/native/next-swc.linux-x64-gnu.node and b/packages/next/native/next-swc.linux-x64-gnu.node differ
diff --git a/packages/next/native/next-swc.win32-x64-msvc.node b/packages/next/native/next-swc.win32-x64-msvc.node
index e82d94a51b905..b1d76bea72d3b 100644
Binary files a/packages/next/native/next-swc.win32-x64-msvc.node and b/packages/next/native/next-swc.win32-x64-msvc.node differ
diff --git a/packages/next/package.json b/packages/next/package.json
index e1431256535eb..5d3da0957ab76 100644
--- a/packages/next/package.json
+++ b/packages/next/package.json
@@ -1,6 +1,6 @@
{
"name": "next",
- "version": "11.1.3-canary.67",
+ "version": "11.1.3-canary.68",
"description": "The React Framework",
"main": "./dist/server/next.js",
"license": "MIT",
@@ -66,10 +66,10 @@
"dependencies": {
"@babel/runtime": "7.15.4",
"@hapi/accept": "5.0.2",
- "@next/env": "11.1.3-canary.67",
- "@next/polyfill-module": "11.1.3-canary.67",
- "@next/react-dev-overlay": "11.1.3-canary.67",
- "@next/react-refresh-utils": "11.1.3-canary.67",
+ "@next/env": "11.1.3-canary.68",
+ "@next/polyfill-module": "11.1.3-canary.68",
+ "@next/react-dev-overlay": "11.1.3-canary.68",
+ "@next/react-refresh-utils": "11.1.3-canary.68",
"@node-rs/helper": "1.2.1",
"assert": "2.0.0",
"browserify-zlib": "0.2.0",
@@ -152,7 +152,7 @@
"@babel/traverse": "7.15.0",
"@babel/types": "7.15.0",
"@napi-rs/cli": "1.1.0",
- "@next/polyfill-nomodule": "11.1.3-canary.67",
+ "@next/polyfill-nomodule": "11.1.3-canary.68",
"@taskr/clear": "1.1.0",
"@taskr/esnext": "1.1.0",
"@taskr/watch": "1.1.0",
diff --git a/packages/next/pages/_document.tsx b/packages/next/pages/_document.tsx
index 61f4fda081bcd..c6093d7760188 100644
--- a/packages/next/pages/_document.tsx
+++ b/packages/next/pages/_document.tsx
@@ -481,6 +481,7 @@ export class Head extends Component<
unstable_runtimeJS,
unstable_JsPreload,
disableOptimizedLoading,
+ useMaybeDeferContent,
} = this.context
const disableRuntimeJS = unstable_runtimeJS === false
@@ -597,98 +598,36 @@ export class Head extends Component<
inAmpMode
)
- return (
-
- {this.context.isDevelopment && (
- <>
-
-
- >
- )}
- {children}
- {process.env.__NEXT_OPTIMIZE_FONTS && (
-
- )}
- {head}
-
- {inAmpMode && (
+ // Must use nested component to allow use of a custom hook
+ const DeferrableHead = () => {
+ const getDynamicHeadContent = () => {
+ return (
<>
+ {head}
- {!hasCanonicalRel && (
-
- )}
- {/* https://www.ampproject.org/docs/fundamentals/optimize_amp#optimize-the-amp-runtime-loading */}
-
-
-
-
-
>
- )}
- {!inAmpMode && (
+ )
+ }
+
+ const getDynamicScriptPreloads = () => {
+ return (
<>
- {!hasAmphtmlRel && hybridAmp && (
-
- )}
- {!process.env.__NEXT_OPTIMIZE_CSS && this.getCssLinks(files)}
- {!process.env.__NEXT_OPTIMIZE_CSS && (
-
- )}
- {process.env.__NEXT_OPTIMIZE_IMAGES && (
-
- )}
{!disableRuntimeJS &&
!disableJsPreload &&
this.getPreloadDynamicChunks()}
{!disableRuntimeJS &&
!disableJsPreload &&
this.getPreloadMainLinks(files)}
- {!disableOptimizedLoading &&
- !disableRuntimeJS &&
- this.getPolyfillScripts()}
+ >
+ )
+ }
+
+ const getDynamicScriptContent = () => {
+ return (
+ <>
{!disableOptimizedLoading &&
!disableRuntimeJS &&
this.getPreNextScripts()}
@@ -698,22 +637,129 @@ export class Head extends Component<
{!disableOptimizedLoading &&
!disableRuntimeJS &&
this.getScripts(files)}
- {process.env.__NEXT_OPTIMIZE_CSS && this.getCssLinks(files)}
- {process.env.__NEXT_OPTIMIZE_CSS && (
-
- )}
- {this.context.isDevelopment && (
- // this element is used to mount development styles so the
- // ordering matches production
- // (by default, style-loader injects at the bottom of )
-
- )}
- {styles || null}
>
- )}
- {React.createElement(React.Fragment, {}, ...(headTags || []))}
-
- )
+ )
+ }
+
+ const [isDeferred] = useMaybeDeferContent('HEAD', () => {
+ return (
+ <>
+ {getDynamicHeadContent()}
+ {getDynamicScriptPreloads()}
+ {getDynamicScriptContent()}
+ >
+ )
+ })
+
+ return (
+
+ {this.context.isDevelopment && (
+ <>
+
+
+ >
+ )}
+ {children}
+ {process.env.__NEXT_OPTIMIZE_FONTS && (
+
+ )}
+
+ {!isDeferred && getDynamicHeadContent()}
+
+ {inAmpMode && (
+ <>
+
+ {!hasCanonicalRel && (
+
+ )}
+ {/* https://www.ampproject.org/docs/fundamentals/optimize_amp#optimize-the-amp-runtime-loading */}
+
+
+
+
+
+ >
+ )}
+ {!inAmpMode && (
+ <>
+ {!hasAmphtmlRel && hybridAmp && (
+
+ )}
+ {!process.env.__NEXT_OPTIMIZE_CSS && this.getCssLinks(files)}
+ {!process.env.__NEXT_OPTIMIZE_CSS && (
+
+ )}
+ {process.env.__NEXT_OPTIMIZE_IMAGES && (
+
+ )}
+
+ {!isDeferred && getDynamicScriptPreloads()}
+
+ {!disableOptimizedLoading &&
+ !disableRuntimeJS &&
+ this.getPolyfillScripts()}
+
+ {!isDeferred && getDynamicScriptContent()}
+
+ {process.env.__NEXT_OPTIMIZE_CSS && this.getCssLinks(files)}
+ {process.env.__NEXT_OPTIMIZE_CSS && (
+
+ )}
+ {this.context.isDevelopment && (
+ // this element is used to mount development styles so the
+ // ordering matches production
+ // (by default, style-loader injects at the bottom of