diff --git a/docs/advanced-features/custom-document.md b/docs/advanced-features/custom-document.md index 2ef135fa783a..97d427fbec1b 100644 --- a/docs/advanced-features/custom-document.md +++ b/docs/advanced-features/custom-document.md @@ -41,7 +41,7 @@ Or add a `className` to the `body` tag: ## Caveats - The `` component used in `_document` is not the same as [`next/head`](/docs/api-reference/next/head.md). The `` component used here should only be used for any `` code that is common for all pages. For all other cases, such as `` tags, we recommend using [`next/head`](/docs/api-reference/next/head.md) in your pages or components. -- React components outside of `<Main />` will not be initialized by the browser. Do _not_ add application logic here or custom CSS (like `styled-jsx`). If you need shared components in all your pages (like a menu or a toolbar), read [Layouts](/docs/basic-features/layouts.md) intead. +- React components outside of `<Main />` will not be initialized by the browser. Do _not_ add application logic here or custom CSS (like `styled-jsx`). If you need shared components in all your pages (like a menu or a toolbar), read [Layouts](/docs/basic-features/layouts.md) instead. - `Document` currently does not support Next.js [Data Fetching methods](/docs/basic-features/data-fetching/overview.md) like [`getStaticProps`](/docs/basic-features/data-fetching/get-static-props.md) or [`getServerSideProps`](/docs/basic-features/data-fetching/get-server-side-props.md). ## Customizing `renderPage` diff --git a/examples/with-redis/lib/redis.js b/examples/with-redis/lib/redis.ts similarity index 100% rename from examples/with-redis/lib/redis.js rename to examples/with-redis/lib/redis.ts diff --git a/examples/with-redis/next-env.d.ts b/examples/with-redis/next-env.d.ts new file mode 100644 index 000000000000..4f11a03dc6cc --- /dev/null +++ b/examples/with-redis/next-env.d.ts @@ -0,0 +1,5 @@ +/// <reference types="next" /> +/// <reference types="next/image-types/global" /> + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/examples/with-redis/package.json b/examples/with-redis/package.json index 3323648bba82..bae8c5799aed 100644 --- a/examples/with-redis/package.json +++ b/examples/with-redis/package.json @@ -19,6 +19,11 @@ "uuid": "^8.3.2" }, "devDependencies": { - "@tailwindcss/jit": "0.1.1" + "@tailwindcss/jit": "0.1.1", + "@types/ioredis": "4.28.8", + "@types/node": "^16.11.25", + "@types/react": "^17.0.2", + "@types/uuid": "8.3.4", + "typescript": "^4.5.5" } } diff --git a/examples/with-redis/pages/_app.js b/examples/with-redis/pages/_app.tsx similarity index 81% rename from examples/with-redis/pages/_app.js rename to examples/with-redis/pages/_app.tsx index 8e5dce4cce7e..77e5950f7944 100644 --- a/examples/with-redis/pages/_app.js +++ b/examples/with-redis/pages/_app.tsx @@ -1,7 +1,9 @@ +import type { AppProps } from 'next/app' + import '../styles/globals.css' import { Toaster } from 'react-hot-toast' -function MyApp({ Component, pageProps }) { +function MyApp({ Component, pageProps }: AppProps) { return ( <> <Component {...pageProps} /> diff --git a/examples/with-redis/pages/api/create.js b/examples/with-redis/pages/api/create.ts similarity index 79% rename from examples/with-redis/pages/api/create.js rename to examples/with-redis/pages/api/create.ts index df777bce298a..1a73a03efb88 100644 --- a/examples/with-redis/pages/api/create.js +++ b/examples/with-redis/pages/api/create.ts @@ -1,8 +1,12 @@ +import type { NextApiRequest, NextApiResponse } from 'next' import { v4 as uuidv4 } from 'uuid' import redis from '../../lib/redis' -export default async function create(req, res) { +export default async function create( + req: NextApiRequest, + res: NextApiResponse +) { const { title } = req.body if (!title) { diff --git a/examples/with-redis/pages/api/features.js b/examples/with-redis/pages/api/features.ts similarity index 56% rename from examples/with-redis/pages/api/features.js rename to examples/with-redis/pages/api/features.ts index afa8546703e7..2f00e991fb07 100644 --- a/examples/with-redis/pages/api/features.js +++ b/examples/with-redis/pages/api/features.ts @@ -1,6 +1,11 @@ +import type { NextApiRequest, NextApiResponse } from 'next' + import redis from '../../lib/redis' -export default async function getAllFeatures(req, res) { +export default async function getAllFeatures( + req: NextApiRequest, + res: NextApiResponse +) { const features = (await redis.hvals('features')) .map((entry) => JSON.parse(entry)) .sort((a, b) => b.score - a.score) diff --git a/examples/with-redis/pages/api/subscribe.js b/examples/with-redis/pages/api/subscribe.ts similarity index 72% rename from examples/with-redis/pages/api/subscribe.js rename to examples/with-redis/pages/api/subscribe.ts index 436ff17642cd..544558c36df3 100644 --- a/examples/with-redis/pages/api/subscribe.js +++ b/examples/with-redis/pages/api/subscribe.ts @@ -1,6 +1,11 @@ +import type { NextApiRequest, NextApiResponse } from 'next' + import redis from '../../lib/redis' -export default async function subscribe(req, res) { +export default async function subscribe( + req: NextApiRequest, + res: NextApiResponse +) { const { email } = req.body if (email && validateEmail(email)) { @@ -15,7 +20,7 @@ export default async function subscribe(req, res) { } } -function validateEmail(email) { +function validateEmail(email: string) { const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ return re.test(String(email).toLowerCase()) diff --git a/examples/with-redis/pages/api/vote.js b/examples/with-redis/pages/api/vote.ts similarity index 80% rename from examples/with-redis/pages/api/vote.js rename to examples/with-redis/pages/api/vote.ts index 60879587b18e..8d58246521a8 100644 --- a/examples/with-redis/pages/api/vote.js +++ b/examples/with-redis/pages/api/vote.ts @@ -1,6 +1,11 @@ +import type { NextApiRequest, NextApiResponse } from 'next' + import redis from '../../lib/redis' -export default async function upvote(req, res) { +export default async function upvote( + req: NextApiRequest, + res: NextApiResponse +) { const { title, id } = req.body const ip = req.headers['x-forwarded-for'] || req.headers['Remote_Addr'] || 'NA' diff --git a/examples/with-redis/pages/index.js b/examples/with-redis/pages/index.tsx similarity index 86% rename from examples/with-redis/pages/index.js rename to examples/with-redis/pages/index.tsx index a53fd9895c0a..a4d5c2defa66 100644 --- a/examples/with-redis/pages/index.js +++ b/examples/with-redis/pages/index.tsx @@ -1,13 +1,22 @@ import { useState, useRef } from 'react' +import type { NextApiRequest } from 'next' +import type { MouseEvent } from 'react' import Head from 'next/head' import clsx from 'clsx' import useSWR, { mutate } from 'swr' import toast from 'react-hot-toast' import redis from '../lib/redis' -const fetcher = (url) => fetch(url).then((res) => res.json()) +type Feature = { + id: string + title: string + score: number + ip: string +} + +const fetcher = (url: string) => fetch(url).then((res) => res.json()) -function LoadingSpinner({ invert }) { +function LoadingSpinner({ invert }: { invert?: boolean }) { return ( <svg className={clsx( @@ -35,8 +44,20 @@ function LoadingSpinner({ invert }) { ) } -function Item({ isFirst, isLast, isReleased, hasVoted, feature }) { - const upvote = async (e) => { +function Item({ + isFirst, + isLast, + isReleased, + hasVoted, + feature, +}: { + isFirst: boolean + isLast: boolean + isReleased: boolean + hasVoted: boolean + feature: Feature +}) { + const upvote = async (e: MouseEvent<HTMLButtonElement>) => { e.preventDefault() const res = await fetch('/api/vote', { @@ -85,11 +106,17 @@ function Item({ isFirst, isLast, isReleased, hasVoted, feature }) { ) } -export default function Roadmap({ features, ip }) { +export default function Roadmap({ + features, + ip, +}: { + features: Feature[] + ip: string +}) { const [isCreateLoading, setCreateLoading] = useState(false) const [isEmailLoading, setEmailLoading] = useState(false) - const featureInputRef = useRef(null) - const subscribeInputRef = useRef(null) + const featureInputRef = useRef<HTMLInputElement>(null) + const subscribeInputRef = useRef<HTMLInputElement>(null) const { data, error } = useSWR('/api/features', fetcher, { initialData: { features }, @@ -99,13 +126,13 @@ export default function Roadmap({ features, ip }) { toast.error(error) } - const addFeature = async (e) => { + const addFeature = async (e: MouseEvent<HTMLFormElement>) => { e.preventDefault() setCreateLoading(true) const res = await fetch('/api/create', { body: JSON.stringify({ - title: featureInputRef.current.value, + title: featureInputRef?.current?.value ?? '', }), headers: { 'Content-Type': 'application/json', @@ -122,16 +149,18 @@ export default function Roadmap({ features, ip }) { } mutate('/api/features') - featureInputRef.current.value = '' + if (featureInputRef.current) { + featureInputRef.current.value = '' + } } - const subscribe = async (e) => { + const subscribe = async (e: MouseEvent<HTMLFormElement>) => { e.preventDefault() setEmailLoading(true) const res = await fetch('/api/subscribe', { body: JSON.stringify({ - email: subscribeInputRef.current.value, + email: subscribeInputRef?.current?.value ?? '', }), headers: { 'Content-Type': 'application/json', @@ -147,7 +176,10 @@ export default function Roadmap({ features, ip }) { } toast.success('You are now subscribed to feature updates!') - subscribeInputRef.current.value = '' + + if (subscribeInputRef.current) { + subscribeInputRef.current.value = '' + } } return ( @@ -189,7 +221,7 @@ export default function Roadmap({ features, ip }) { </form> </div> <div className="w-full"> - {data.features.map((feature, index) => ( + {data.features.map((feature: Feature, index: number) => ( <Item key={index} isFirst={index === 0} @@ -254,7 +286,7 @@ export default function Roadmap({ features, ip }) { ) } -export async function getServerSideProps({ req }) { +export async function getServerSideProps({ req }: { req: NextApiRequest }) { const ip = req.headers['x-forwarded-for'] || req.headers['Remote_Addr'] || 'NA' const features = (await redis.hvals('features')) diff --git a/examples/with-redis/tsconfig.json b/examples/with-redis/tsconfig.json new file mode 100644 index 000000000000..de46a2951991 --- /dev/null +++ b/examples/with-redis/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "baseUrl": ".", + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "incremental": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +} diff --git a/lerna.json b/lerna.json index 486aa0517869..380efb77df5b 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "12.1.1-canary.1" + "version": "12.1.1-canary.2" } diff --git a/packages/create-next-app/create-app.ts b/packages/create-next-app/create-app.ts index 1620ee65a0f7..c8cc31f36f04 100644 --- a/packages/create-next-app/create-app.ts +++ b/packages/create-next-app/create-app.ts @@ -127,7 +127,6 @@ export async function createApp({ console.log(`Creating a new Next.js app in ${chalk.green(root)}.`) console.log() - await makeDir(root) process.chdir(root) if (example) { diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index b961aed66b02..3baf95996676 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index 19ff3b85f728..0077e7a23e41 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "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": "12.1.1-canary.1", + "@next/eslint-plugin-next": "12.1.1-canary.2", "@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 6db6d1aa79ae..c2eda9f80ac2 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": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "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 39200cd66ce0..a398a6d66cb0 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index b74eac767ca8..7c44dd220423 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "license": "MIT", "dependencies": { "chalk": "4.1.0", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index e07576c1a98f..db48adc5cb07 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index f4996fbeb4f1..4fa3207d8897 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index 64745c06f561..9edae31b9bc6 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "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 92f8b50f373b..eb79cd2b01cc 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "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 c0e2b35bd6fe..abba99ca751c 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index ef251f821e0c..350e0a7a64b1 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "private": true, "scripts": { "build-native": "napi build --platform --cargo-name next_swc_napi native", diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts index f030cf3139e4..abd2b01a0829 100644 --- a/packages/next/build/webpack-config.ts +++ b/packages/next/build/webpack-config.ts @@ -1848,11 +1848,11 @@ export default async function getBaseWebpackConfig( } const fileNames = [ - '/tmp/test.css', - '/tmp/test.scss', - '/tmp/test.sass', - '/tmp/test.less', - '/tmp/test.styl', + '/tmp/NEXTJS_CSS_DETECTION_FILE.css', + '/tmp/NEXTJS_CSS_DETECTION_FILE.scss', + '/tmp/NEXTJS_CSS_DETECTION_FILE.sass', + '/tmp/NEXTJS_CSS_DETECTION_FILE.less', + '/tmp/NEXTJS_CSS_DETECTION_FILE.styl', ] if (rule instanceof RegExp && fileNames.some((input) => rule.test(input))) { diff --git a/packages/next/compiled/@napi-rs/triples/index.js b/packages/next/compiled/@napi-rs/triples/index.js index 262525745b42..99561f1eee72 100644 --- a/packages/next/compiled/@napi-rs/triples/index.js +++ b/packages/next/compiled/@napi-rs/triples/index.js @@ -1 +1 @@ -(()=>{var a={757:a=>{a.exports.platformArchTriples={darwin:{arm64:[{platform:"darwin",arch:"arm64",abi:null,platformArchABI:"darwin-arm64",raw:"aarch64-apple-darwin"}],x64:[{platform:"darwin",arch:"x64",abi:null,platformArchABI:"darwin-x64",raw:"x86_64-apple-darwin"}]},ios:{arm64:[{platform:"ios",arch:"arm64",abi:null,platformArchABI:"ios-arm64",raw:"aarch64-apple-ios"}],x64:[{platform:"ios",arch:"x64",abi:null,platformArchABI:"ios-x64",raw:"x86_64-apple-ios"}]},android:{arm64:[{platform:"android",arch:"arm64",abi:null,platformArchABI:"android-arm64",raw:"aarch64-linux-android"}],ia32:[{platform:"android",arch:"ia32",abi:null,platformArchABI:"android-ia32",raw:"i686-linux-android"}],x64:[{platform:"android",arch:"x64",abi:null,platformArchABI:"android-x64",raw:"x86_64-linux-android"}]},win32:{arm64:[{platform:"win32",arch:"arm64",abi:"msvc",platformArchABI:"win32-arm64-msvc",raw:"aarch64-pc-windows-msvc"}],i586:[{platform:"win32",arch:"i586",abi:"msvc",platformArchABI:"win32-i586-msvc",raw:"i586-pc-windows-msvc"}],ia32:[{platform:"win32",arch:"ia32",abi:"gnu",platformArchABI:"win32-ia32-gnu",raw:"i686-pc-windows-gnu"},{platform:"win32",arch:"ia32",abi:"msvc",platformArchABI:"win32-ia32-msvc",raw:"i686-pc-windows-msvc"}],x64:[{platform:"win32",arch:"x64",abi:"gnu",platformArchABI:"win32-x64-gnu",raw:"x86_64-pc-windows-gnu"},{platform:"win32",arch:"x64",abi:"msvc",platformArchABI:"win32-x64-msvc",raw:"x86_64-pc-windows-msvc"}]},linux:{arm64:[{platform:"linux",arch:"arm64",abi:"gnu",platformArchABI:"linux-arm64-gnu",raw:"aarch64-unknown-linux-gnu"},{platform:"linux",arch:"arm64",abi:"musl",platformArchABI:"linux-arm64-musl",raw:"aarch64-unknown-linux-musl"}],arm:[{platform:"linux",arch:"arm",abi:"gnueabi",platformArchABI:"linux-arm-gnueabi",raw:"arm-unknown-linux-gnueabi"},{platform:"linux",arch:"arm",abi:"gnueabihf",platformArchABI:"linux-arm-gnueabihf",raw:"arm-unknown-linux-gnueabihf"},{platform:"linux",arch:"arm",abi:"musleabi",platformArchABI:"linux-arm-musleabi",raw:"arm-unknown-linux-musleabi"},{platform:"linux",arch:"arm",abi:"musleabihf",platformArchABI:"linux-arm-musleabihf",raw:"arm-unknown-linux-musleabihf"},{platform:"linux",arch:"arm",abi:"gnueabi",platformArchABI:"linux-arm-gnueabi",raw:"armv7-unknown-linux-gnueabi"},{platform:"linux",arch:"arm",abi:"gnueabihf",platformArchABI:"linux-arm-gnueabihf",raw:"armv7-unknown-linux-gnueabihf"},{platform:"linux",arch:"arm",abi:"musleabi",platformArchABI:"linux-arm-musleabi",raw:"armv7-unknown-linux-musleabi"},{platform:"linux",arch:"arm",abi:"musleabihf",platformArchABI:"linux-arm-musleabihf",raw:"armv7-unknown-linux-musleabihf"}],armv5te:[{platform:"linux",arch:"armv5te",abi:"gnueabi",platformArchABI:"linux-armv5te-gnueabi",raw:"armv5te-unknown-linux-gnueabi"},{platform:"linux",arch:"armv5te",abi:"musleabi",platformArchABI:"linux-armv5te-musleabi",raw:"armv5te-unknown-linux-musleabi"}],i586:[{platform:"linux",arch:"i586",abi:"gnu",platformArchABI:"linux-i586-gnu",raw:"i586-unknown-linux-gnu"},{platform:"linux",arch:"i586",abi:"musl",platformArchABI:"linux-i586-musl",raw:"i586-unknown-linux-musl"}],ia32:[{platform:"linux",arch:"ia32",abi:"gnu",platformArchABI:"linux-ia32-gnu",raw:"i686-unknown-linux-gnu"},{platform:"linux",arch:"ia32",abi:"musl",platformArchABI:"linux-ia32-musl",raw:"i686-unknown-linux-musl"}],mips:[{platform:"linux",arch:"mips",abi:"gnu",platformArchABI:"linux-mips-gnu",raw:"mips-unknown-linux-gnu"},{platform:"linux",arch:"mips",abi:"musl",platformArchABI:"linux-mips-musl",raw:"mips-unknown-linux-musl"}],mips64:[{platform:"linux",arch:"mips64",abi:"gnuabi64",platformArchABI:"linux-mips64-gnuabi64",raw:"mips64-unknown-linux-gnuabi64"},{platform:"linux",arch:"mips64",abi:"muslabi64",platformArchABI:"linux-mips64-muslabi64",raw:"mips64-unknown-linux-muslabi64"}],mips64el:[{platform:"linux",arch:"mips64el",abi:"gnuabi64",platformArchABI:"linux-mips64el-gnuabi64",raw:"mips64el-unknown-linux-gnuabi64"},{platform:"linux",arch:"mips64el",abi:"muslabi64",platformArchABI:"linux-mips64el-muslabi64",raw:"mips64el-unknown-linux-muslabi64"}],mipsel:[{platform:"linux",arch:"mipsel",abi:"gnu",platformArchABI:"linux-mipsel-gnu",raw:"mipsel-unknown-linux-gnu"},{platform:"linux",arch:"mipsel",abi:"musl",platformArchABI:"linux-mipsel-musl",raw:"mipsel-unknown-linux-musl"}],powerpc:[{platform:"linux",arch:"powerpc",abi:"gnu",platformArchABI:"linux-powerpc-gnu",raw:"powerpc-unknown-linux-gnu"}],powerpc64:[{platform:"linux",arch:"powerpc64",abi:"gnu",platformArchABI:"linux-powerpc64-gnu",raw:"powerpc64-unknown-linux-gnu"}],powerpc64le:[{platform:"linux",arch:"powerpc64le",abi:"gnu",platformArchABI:"linux-powerpc64le-gnu",raw:"powerpc64le-unknown-linux-gnu"}],riscv64gc:[{platform:"linux",arch:"riscv64gc",abi:"gnu",platformArchABI:"linux-riscv64gc-gnu",raw:"riscv64gc-unknown-linux-gnu"}],s390x:[{platform:"linux",arch:"s390x",abi:"gnu",platformArchABI:"linux-s390x-gnu",raw:"s390x-unknown-linux-gnu"}],sparc64:[{platform:"linux",arch:"sparc64",abi:"gnu",platformArchABI:"linux-sparc64-gnu",raw:"sparc64-unknown-linux-gnu"}],thumbv7neon:[{platform:"linux",arch:"thumbv7neon",abi:"gnueabihf",platformArchABI:"linux-thumbv7neon-gnueabihf",raw:"thumbv7neon-unknown-linux-gnueabihf"}],x64:[{platform:"linux",arch:"x64",abi:"gnu",platformArchABI:"linux-x64-gnu",raw:"x86_64-unknown-linux-gnu"},{platform:"linux",arch:"x64",abi:"gnux32",platformArchABI:"linux-x64-gnux32",raw:"x86_64-unknown-linux-gnux32"},{platform:"linux",arch:"x64",abi:"musl",platformArchABI:"linux-x64-musl",raw:"x86_64-unknown-linux-musl"}]},freebsd:{ia32:[{platform:"freebsd",arch:"ia32",abi:null,platformArchABI:"freebsd-ia32",raw:"i686-unknown-freebsd"}],x64:[{platform:"freebsd",arch:"x64",abi:null,platformArchABI:"freebsd-x64",raw:"x86_64-unknown-freebsd"}]}}}};var r={};function __nccwpck_require__(n){var i=r[n];if(i!==undefined){return i.exports}var l=r[n]={exports:{}};var u=true;try{a[n](l,l.exports,__nccwpck_require__);u=false}finally{if(u)delete r[n]}return l.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var n=__nccwpck_require__(757);module.exports=n})(); \ No newline at end of file +(()=>{var a={757:a=>{a.exports.platformArchTriples={darwin:{arm64:[{platform:"darwin",arch:"arm64",abi:null,platformArchABI:"darwin-arm64",raw:"aarch64-apple-darwin"}],x64:[{platform:"darwin",arch:"x64",abi:null,platformArchABI:"darwin-x64",raw:"x86_64-apple-darwin"}]},ios:{arm64:[{platform:"ios",arch:"arm64",abi:null,platformArchABI:"ios-arm64",raw:"aarch64-apple-ios"}],x64:[{platform:"ios",arch:"x64",abi:null,platformArchABI:"ios-x64",raw:"x86_64-apple-ios"}]},android:{arm64:[{platform:"android",arch:"arm64",abi:null,platformArchABI:"android-arm64",raw:"aarch64-linux-android"}],arm:[{platform:"android",arch:"arm",abi:"eabi",platformArchABI:"android-arm-eabi",raw:"armv7-linux-androideabi"}],ia32:[{platform:"android",arch:"ia32",abi:null,platformArchABI:"android-ia32",raw:"i686-linux-android"}],x64:[{platform:"android",arch:"x64",abi:null,platformArchABI:"android-x64",raw:"x86_64-linux-android"}]},win32:{arm64:[{platform:"win32",arch:"arm64",abi:"msvc",platformArchABI:"win32-arm64-msvc",raw:"aarch64-pc-windows-msvc"}],ia32:[{platform:"win32",arch:"ia32",abi:"gnu",platformArchABI:"win32-ia32-gnu",raw:"i686-pc-windows-gnu"},{platform:"win32",arch:"ia32",abi:"msvc",platformArchABI:"win32-ia32-msvc",raw:"i686-pc-windows-msvc"}],x64:[{platform:"win32",arch:"x64",abi:"gnu",platformArchABI:"win32-x64-gnu",raw:"x86_64-pc-windows-gnu"},{platform:"win32",arch:"x64",abi:"msvc",platformArchABI:"win32-x64-msvc",raw:"x86_64-pc-windows-msvc"}]},linux:{arm64:[{platform:"linux",arch:"arm64",abi:"gnu",platformArchABI:"linux-arm64-gnu",raw:"aarch64-unknown-linux-gnu"},{platform:"linux",arch:"arm64",abi:"musl",platformArchABI:"linux-arm64-musl",raw:"aarch64-unknown-linux-musl"}],arm:[{platform:"linux",arch:"arm",abi:"gnueabihf",platformArchABI:"linux-arm-gnueabihf",raw:"arm-unknown-linux-gnueabihf"},{platform:"linux",arch:"arm",abi:"musleabihf",platformArchABI:"linux-arm-musleabihf",raw:"arm-unknown-linux-musleabihf"},{platform:"linux",arch:"arm",abi:"gnueabihf",platformArchABI:"linux-arm-gnueabihf",raw:"armv7-unknown-linux-gnueabihf"},{platform:"linux",arch:"arm",abi:"musleabihf",platformArchABI:"linux-arm-musleabihf",raw:"armv7-unknown-linux-musleabihf"}],ia32:[{platform:"linux",arch:"ia32",abi:"gnu",platformArchABI:"linux-ia32-gnu",raw:"i686-unknown-linux-gnu"},{platform:"linux",arch:"ia32",abi:"musl",platformArchABI:"linux-ia32-musl",raw:"i686-unknown-linux-musl"}],mips:[{platform:"linux",arch:"mips",abi:"gnu",platformArchABI:"linux-mips-gnu",raw:"mips-unknown-linux-gnu"},{platform:"linux",arch:"mips",abi:"musl",platformArchABI:"linux-mips-musl",raw:"mips-unknown-linux-musl"}],mips64:[{platform:"linux",arch:"mips64",abi:"gnuabi64",platformArchABI:"linux-mips64-gnuabi64",raw:"mips64-unknown-linux-gnuabi64"},{platform:"linux",arch:"mips64",abi:"muslabi64",platformArchABI:"linux-mips64-muslabi64",raw:"mips64-unknown-linux-muslabi64"}],mips64el:[{platform:"linux",arch:"mips64el",abi:"gnuabi64",platformArchABI:"linux-mips64el-gnuabi64",raw:"mips64el-unknown-linux-gnuabi64"},{platform:"linux",arch:"mips64el",abi:"muslabi64",platformArchABI:"linux-mips64el-muslabi64",raw:"mips64el-unknown-linux-muslabi64"}],mipsel:[{platform:"linux",arch:"mipsel",abi:"gnu",platformArchABI:"linux-mipsel-gnu",raw:"mipsel-unknown-linux-gnu"},{platform:"linux",arch:"mipsel",abi:"musl",platformArchABI:"linux-mipsel-musl",raw:"mipsel-unknown-linux-musl"}],powerpc:[{platform:"linux",arch:"powerpc",abi:"gnu",platformArchABI:"linux-powerpc-gnu",raw:"powerpc-unknown-linux-gnu"}],powerpc64:[{platform:"linux",arch:"powerpc64",abi:"gnu",platformArchABI:"linux-powerpc64-gnu",raw:"powerpc64-unknown-linux-gnu"}],powerpc64le:[{platform:"linux",arch:"powerpc64le",abi:"gnu",platformArchABI:"linux-powerpc64le-gnu",raw:"powerpc64le-unknown-linux-gnu"}],riscv64gc:[{platform:"linux",arch:"riscv64gc",abi:"gnu",platformArchABI:"linux-riscv64gc-gnu",raw:"riscv64gc-unknown-linux-gnu"}],s390x:[{platform:"linux",arch:"s390x",abi:"gnu",platformArchABI:"linux-s390x-gnu",raw:"s390x-unknown-linux-gnu"}],sparc64:[{platform:"linux",arch:"sparc64",abi:"gnu",platformArchABI:"linux-sparc64-gnu",raw:"sparc64-unknown-linux-gnu"}],x64:[{platform:"linux",arch:"x64",abi:"gnu",platformArchABI:"linux-x64-gnu",raw:"x86_64-unknown-linux-gnu"},{platform:"linux",arch:"x64",abi:"gnux32",platformArchABI:"linux-x64-gnux32",raw:"x86_64-unknown-linux-gnux32"},{platform:"linux",arch:"x64",abi:"musl",platformArchABI:"linux-x64-musl",raw:"x86_64-unknown-linux-musl"}]},freebsd:{ia32:[{platform:"freebsd",arch:"ia32",abi:null,platformArchABI:"freebsd-ia32",raw:"i686-unknown-freebsd"}],x64:[{platform:"freebsd",arch:"x64",abi:null,platformArchABI:"freebsd-x64",raw:"x86_64-unknown-freebsd"}]}}}};var r={};function __nccwpck_require__(n){var i=r[n];if(i!==undefined){return i.exports}var l=r[n]={exports:{}};var u=true;try{a[n](l,l.exports,__nccwpck_require__);u=false}finally{if(u)delete r[n]}return l.exports}if(typeof __nccwpck_require__!=="undefined")__nccwpck_require__.ab=__dirname+"/";var n=__nccwpck_require__(757);module.exports=n})(); \ No newline at end of file diff --git a/packages/next/package.json b/packages/next/package.json index 6942656b6535..6170b8a955e5 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -69,7 +69,7 @@ ] }, "dependencies": { - "@next/env": "12.1.1-canary.1", + "@next/env": "12.1.1-canary.2", "caniuse-lite": "^1.0.30001283", "postcss": "8.4.5", "styled-jsx": "5.0.0", @@ -116,12 +116,12 @@ "@babel/types": "7.15.0", "@hapi/accept": "5.0.2", "@napi-rs/cli": "2.4.4", - "@napi-rs/triples": "1.0.3", - "@next/polyfill-module": "12.1.1-canary.1", - "@next/polyfill-nomodule": "12.1.1-canary.1", - "@next/react-dev-overlay": "12.1.1-canary.1", - "@next/react-refresh-utils": "12.1.1-canary.1", - "@next/swc": "12.1.1-canary.1", + "@napi-rs/triples": "1.1.0", + "@next/polyfill-module": "12.1.1-canary.2", + "@next/polyfill-nomodule": "12.1.1-canary.2", + "@next/react-dev-overlay": "12.1.1-canary.2", + "@next/react-refresh-utils": "12.1.1-canary.2", + "@next/swc": "12.1.1-canary.2", "@peculiar/webcrypto": "1.1.7", "@taskr/clear": "1.1.0", "@taskr/esnext": "1.1.0", diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index a19c4477d793..69d30e7357d4 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -9,6 +9,7 @@ import type { PrerenderManifest } from '../build' import type { Rewrite } from '../lib/load-custom-routes' import type { BaseNextRequest, BaseNextResponse } from './base-http' import type { PagesManifest } from '../build/webpack/plugins/pages-manifest-plugin' +import type { PayloadOptions } from './send-payload' import { execOnce } from '../shared/lib/utils' import { @@ -43,7 +44,7 @@ import { route } from './router' import { run } from './web/sandbox' import { NodeNextRequest, NodeNextResponse } from './base-http/node' -import { PayloadOptions, sendRenderResult } from './send-payload' +import { sendRenderResult } from './send-payload' import { getExtension, serveStatic } from './serve-static' import { ParsedUrlQuery } from 'querystring' import { apiResolver } from './api-utils/node' @@ -584,6 +585,12 @@ export default class NextNodeServer extends BaseServer { protected streamResponseChunk(res: NodeNextResponse, chunk: any) { res.originalResponse.write(chunk) + + // When both compression and streaming are enabled, we need to explicitly + // flush the response to avoid it being buffered by gzip. + if (this.compression && 'flush' in res.originalResponse) { + ;(res.originalResponse as any).flush() + } } protected async imageOptimizer( diff --git a/packages/next/server/web-server.ts b/packages/next/server/web-server.ts index b3e11bc0bf4a..cb0c8b5eba47 100644 --- a/packages/next/server/web-server.ts +++ b/packages/next/server/web-server.ts @@ -148,6 +148,20 @@ export default class NextWebServer extends BaseServer { options?: PayloadOptions | undefined } ): Promise<void> { + // Add necessary headers. + // @TODO: Share the isomorphic logic with server/send-payload.ts. + if (options.poweredByHeader && options.type === 'html') { + res.setHeader('X-Powered-By', 'Next.js') + } + if (!res.getHeader('Content-Type')) { + res.setHeader( + 'Content-Type', + options.type === 'json' + ? 'application/json' + : 'text/html; charset=utf-8' + ) + } + // @TODO const writer = res.transformStream.writable.getWriter() diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index c087bfefef7d..0526861e0376 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-dev-overlay", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "description": "A development-only overlay for developing React applications.", "repository": { "url": "vercel/next.js", diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index 9adbbecf61d0..8f8037891a8f 100644 --- a/packages/react-refresh-utils/package.json +++ b/packages/react-refresh-utils/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-refresh-utils", - "version": "12.1.1-canary.1", + "version": "12.1.1-canary.2", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/test/integration/react-streaming-and-server-components/test/index.test.js b/test/integration/react-streaming-and-server-components/test/index.test.js index 826ca4d5d142..d93f233a1aab 100644 --- a/test/integration/react-streaming-and-server-components/test/index.test.js +++ b/test/integration/react-streaming-and-server-components/test/index.test.js @@ -69,16 +69,7 @@ export default function Page500() { } ` -describe('Edge runtime - basic', () => { - it('should warn user for experimental risk with server components', async () => { - const edgeRuntimeWarning = - 'You are using the experimental Edge Runtime with `experimental.runtime`.' - const rscWarning = `You have experimental React Server Components enabled. Continue at your own risk.` - const { stderr } = await nextBuild(appDir) - expect(stderr).toContain(edgeRuntimeWarning) - expect(stderr).toContain(rscWarning) - }) - +describe('Edge runtime - errors', () => { it('should warn user that native node APIs are not supported', async () => { const fsImportedErrorMessage = 'Native Node.js APIs are not supported in the Edge Runtime. Found `dns` imported.' @@ -93,7 +84,8 @@ describe('Edge runtime - prod', () => { beforeAll(async () => { error500Page.write(page500) context.appPort = await findPort() - await nextBuild(context.appDir) + const { stderr } = await nextBuild(context.appDir) + context.stderr = stderr context.server = await nextStart(context.appDir, context.appPort) }) afterAll(async () => { @@ -101,6 +93,14 @@ describe('Edge runtime - prod', () => { await killApp(context.server) }) + it('should warn user for experimental risk with edge runtime and server components', async () => { + const edgeRuntimeWarning = + 'You are using the experimental Edge Runtime with `experimental.runtime`.' + const rscWarning = `You have experimental React Server Components enabled. Continue at your own risk.` + expect(context.stderr).toContain(edgeRuntimeWarning) + expect(context.stderr).toContain(rscWarning) + }) + it('should generate middleware SSR manifests for edge runtime', async () => { const distServerDir = join(distDir, 'server') const files = [ @@ -177,6 +177,12 @@ describe('Edge runtime - dev', () => { expect(content).toMatchInlineSnapshot('"foo.client"') }) + it('should have content-type and content-encoding headers', async () => { + const res = await fetchViaHTTP(context.appPort, '/') + expect(res.headers.get('content-type')).toBe('text/html; charset=utf-8') + expect(res.headers.get('content-encoding')).toBe('gzip') + }) + basic(context, { env: 'dev' }) streaming(context) rsc(context, { runtime: 'edge', env: 'dev' }) diff --git a/yarn.lock b/yarn.lock index abf324d8eafc..ca61c9eb0e6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4060,10 +4060,10 @@ resolved "https://registry.yarnpkg.com/@napi-rs/cli/-/cli-2.4.4.tgz#878a38f0fba1709d89d66eba706745ce728a61a5" integrity sha512-f+tvwCv1ka24dBqI2DgBhR7Oxl3DKHOp4onxLXwyBFt6iCADnr3YZIr1/2Iq5r3uqxFgaf01bfPsRQZPkEp0kQ== -"@napi-rs/triples@1.0.3", "@napi-rs/triples@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.0.3.tgz#76d6d0c3f4d16013c61e45dfca5ff1e6c31ae53c" - integrity sha512-jDJTpta+P4p1NZTFVLHJ/TLFVYVcOqv6l8xwOeBKNPMgY/zDYH/YH7SJbvrr/h1RcS9GzbPcLKGzpuK9cV56UA== +"@napi-rs/triples@^1.0.3", "@napi-rs/triples@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.1.0.tgz#88c35b72e79a20b79bb4c9b3e2817241a1c9f4f9" + integrity sha512-XQr74QaLeMiqhStEhLn1im9EOMnkypp7MZOwQhGzqp2Weu5eQJbpPxWxixxlYRKWPOmJjsk6qYfYH9kq43yc2w== "@node-rs/helper@^1.0.0": version "1.2.1"