diff --git a/docs/deployment.md b/docs/deployment.md index 591ea8aab8a5ee8..f6c14f12436c41a 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -28,9 +28,9 @@ All JavaScript code inside `.next` has been **compiled** and browser bundles hav ## Managed Next.js with Vercel -[Vercel](https://vercel.com/) is a frontend cloud platform from the creators of Next.js. It's the fastest way to deploy your managed Next.js application with zero configuration. +[Vercel](https://vercel.com?utm_source=github.com&utm_medium=referral&utm_campaign=deployment) is the fastest way to deploy your Next.js application with zero configuration. -When deploying to Vercel, the platform automatically detects Next.js, runs `next build`, and optimizes the build output for you, including: +When deploying to Vercel, the platform [automatically detects Next.js](https://vercel.com/solutions/nextjs?utm_source=github.com&utm_medium=referral&utm_campaign=deployment), runs `next build`, and optimizes the build output for you, including: - Persisting cached assets across deployments if unchanged - [Immutable deployments](https://vercel.com/features/previews) with a unique URL for every commit @@ -49,9 +49,7 @@ In addition, Vercel provides features like: - Support for [Image Optimization](/docs/basic-features/image-optimization.md) with `next/image` - Instant global deployments via `git push` -You can start using Vercel (for free) through a personal hobby account, or create a team to start the next big thing. Learn more about [Next.js on Vercel](https://vercel.com/solutions/nextjs) or read the [Vercel Documentation](https://vercel.com/docs). - -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/hello-world&project-name=hello-world&repository-name=hello-world&utm_source=github.com&utm_medium=referral&utm_campaign=deployment) +[Deploy a Next.js application to Vercel](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/hello-world&project-name=hello-world&repository-name=hello-world&utm_source=github.com&utm_medium=referral&utm_campaign=deployment) for free to try it out. ## Self-Hosting diff --git a/errors/invalid-api-status-body.md b/errors/invalid-api-status-body.md index b0d5fd60fd99d52..0c3a7b0ab011d26 100644 --- a/errors/invalid-api-status-body.md +++ b/errors/invalid-api-status-body.md @@ -22,7 +22,7 @@ After ```js export default function handler(req, res) { - res.status(204).send() + res.status(204).end() } ``` diff --git a/lerna.json b/lerna.json index 92a574e20e5abb9..e862f0819406b0f 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "12.0.11-canary.2" + "version": "12.0.11-canary.3" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 4f21702d68cc99b..f60cdd42dfaecf8 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.0.11-canary.2", + "version": "12.0.11-canary.3", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index b4b9730ce04f2a1..d704b0ef9e194ce 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.0.11-canary.2", + "version": "12.0.11-canary.3", "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.0.11-canary.2", + "@next/eslint-plugin-next": "12.0.11-canary.3", "@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/lib/rules/inline-script-id.js b/packages/eslint-plugin-next/lib/rules/inline-script-id.js index 099b12de8edaede..20322f913c22d47 100644 --- a/packages/eslint-plugin-next/lib/rules/inline-script-id.js +++ b/packages/eslint-plugin-next/lib/rules/inline-script-id.js @@ -27,15 +27,22 @@ module.exports = { return } - const attributes = node.openingElement.attributes + const attributeNames = new Set() + node.openingElement.attributes.forEach((attribute) => { + if (attribute.type === 'JSXAttribute') { + attributeNames.add(attribute.name.name) + } else if (attribute.type === 'JSXSpreadAttribute') { + attribute.argument.properties.forEach((property) => { + attributeNames.add(property.key.name) + }) + } + }) if ( node.children.length > 0 || - attributes.some( - (attribute) => attribute.name.name === 'dangerouslySetInnerHTML' - ) + attributeNames.has('dangerouslySetInnerHTML') ) { - if (!attributes.some((attribute) => attribute.name.name === 'id')) { + if (!attributeNames.has('id')) { context.report({ node, message: diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index ef565eb566062f1..41572a18353cb36 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.0.11-canary.2", + "version": "12.0.11-canary.3", "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 07001ed279ff73c..51a8da9d34fac7d 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.0.11-canary.2", + "version": "12.0.11-canary.3", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 266b046c6806834..272d1275c917cd0 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "12.0.11-canary.2", + "version": "12.0.11-canary.3", "license": "MIT", "dependencies": { "chalk": "4.1.0", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index fbd83b636ddff65..e27264e3244b4ee 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "12.0.11-canary.2", + "version": "12.0.11-canary.3", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index 62fae1a3f3bc434..fbb003ae93e9f42 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "12.0.11-canary.2", + "version": "12.0.11-canary.3", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index 04ed8b67a6c3ee9..b689c048372594b 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.0.11-canary.2", + "version": "12.0.11-canary.3", "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 c45137879f96304..8c6404cce773361 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.0.11-canary.2", + "version": "12.0.11-canary.3", "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 7504ba7cb4c986e..5c174b4621a3d2b 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.0.11-canary.2", + "version": "12.0.11-canary.3", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/crates/core/src/lib.rs b/packages/next-swc/crates/core/src/lib.rs index 03b77e8ea85ffea..ece7465796d6661 100644 --- a/packages/next-swc/crates/core/src/lib.rs +++ b/packages/next-swc/crates/core/src/lib.rs @@ -112,7 +112,7 @@ pub fn custom_before_pass( #[cfg(not(target_arch = "wasm32"))] let relay_plugin = { if let Some(config) = &opts.relay { - Either::Left(relay::relay(config, file.name.clone())) + Either::Left(relay::relay(config, file.name.clone(), opts.pages_dir.clone())) } else { Either::Right(noop()) } diff --git a/packages/next-swc/crates/core/src/relay.rs b/packages/next-swc/crates/core/src/relay.rs index 76c7298eee913fb..b9035197bbb2b6d 100644 --- a/packages/next-swc/crates/core/src/relay.rs +++ b/packages/next-swc/crates/core/src/relay.rs @@ -24,6 +24,7 @@ impl Default for RelayLanguageConfig { struct Relay<'a> { root_dir: PathBuf, + pages_dir: PathBuf, file_name: FileName, config: &'a Config, } @@ -85,36 +86,44 @@ impl<'a> Fold for Relay<'a> { #[derive(Debug)] enum BuildRequirePathError { FileNameNotReal, - ArtifactDirectoryExpected, + ArtifactDirectoryExpected { file_name: String }, } -fn path_for_artifact( - root_dir: &Path, - config: &Config, - definition_name: &str, -) -> Result { - let filename = match &config.language { - RelayLanguageConfig::Flow => format!("{}.graphql.js", definition_name), - RelayLanguageConfig::TypeScript => { - format!("{}.graphql.ts", definition_name) - } - }; +impl<'a> Relay<'a> { + fn path_for_artifact( + &self, + real_file_name: &Path, + definition_name: &str, + ) -> Result { + let filename = match &self.config.language { + RelayLanguageConfig::Flow => format!("{}.graphql.js", definition_name), + RelayLanguageConfig::TypeScript => { + format!("{}.graphql.ts", definition_name) + } + }; - if let Some(artifact_directory) = &config.artifact_directory { - Ok(root_dir.join(artifact_directory).join(filename)) - } else { - Err(BuildRequirePathError::ArtifactDirectoryExpected) + if let Some(artifact_directory) = &self.config.artifact_directory { + Ok(self.root_dir.join(artifact_directory).join(filename)) + } else if real_file_name.starts_with(&self.pages_dir) { + Err(BuildRequirePathError::ArtifactDirectoryExpected { + file_name: real_file_name.display().to_string(), + }) + } else { + Ok(real_file_name + .parent() + .unwrap() + .join("__generated__") + .join(filename)) + } } -} -impl<'a> Relay<'a> { fn build_require_path( &mut self, operation_name: &str, ) -> Result { match &self.file_name { - FileName::Real(_real_file_name) => { - path_for_artifact(&self.root_dir, self.config, operation_name) + FileName::Real(real_file_name) => { + self.path_for_artifact(real_file_name, operation_name) } _ => Err(BuildRequirePathError::FileNameNotReal), } @@ -140,10 +149,14 @@ impl<'a> Relay<'a> { file. This is likely a bug and \ should be reported to Next.js" .to_string(), - BuildRequirePathError::ArtifactDirectoryExpected => { - "The `artifactDirectory` is expected to be set in the Relay config \ - file to work correctly with Next.js." - .to_string() + BuildRequirePathError::ArtifactDirectoryExpected { file_name } => { + format!( + "The generated file for `{}` will be created in `pages` \ + directory, which will break production builds. Try moving the \ + file outside of `pages` or set the `artifactDirectory` in the \ + Relay config file.", + file_name + ) } }; @@ -161,10 +174,15 @@ impl<'a> Relay<'a> { } } -pub fn relay<'a>(config: &'a Config, file_name: FileName) -> impl Fold + '_ { +pub fn relay<'a>( + config: &'a Config, + file_name: FileName, + pages_dir: Option, +) -> impl Fold + '_ { Relay { root_dir: std::env::current_dir().unwrap(), file_name, + pages_dir: pages_dir.unwrap_or_else(|| panic!("pages_dir is expected.")), config, } } diff --git a/packages/next-swc/crates/core/tests/fixture.rs b/packages/next-swc/crates/core/tests/fixture.rs index 332f35d15fbf891..e8f25d44273e721 100644 --- a/packages/next-swc/crates/core/tests/fixture.rs +++ b/packages/next-swc/crates/core/tests/fixture.rs @@ -160,7 +160,13 @@ fn relay_no_artifact_dir_fixture(input: PathBuf) { }; test_fixture( syntax(), - &|_tr| relay(&config, FileName::Real(PathBuf::from("input.tsx"))), + &|_tr| { + relay( + &config, + FileName::Real(PathBuf::from("input.tsx")), + Some(PathBuf::from("src/pages")), + ) + }, &input, &output, ); diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index b23de7d61f9a42d..3f48c7baa72604d 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "12.0.11-canary.2", + "version": "12.0.11-canary.3", "private": true, "scripts": { "build-native": "napi build --platform --cargo-name next_swc_napi native", diff --git a/packages/next/package.json b/packages/next/package.json index e418e4e1ed79e7c..b584afacf201baf 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "12.0.11-canary.2", + "version": "12.0.11-canary.3", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -69,7 +69,7 @@ ] }, "dependencies": { - "@next/env": "12.0.11-canary.2", + "@next/env": "12.0.11-canary.3", "caniuse-lite": "^1.0.30001283", "postcss": "8.4.5", "styled-jsx": "5.0.0", @@ -117,11 +117,11 @@ "@hapi/accept": "5.0.2", "@napi-rs/cli": "1.2.1", "@napi-rs/triples": "1.0.3", - "@next/polyfill-module": "12.0.11-canary.2", - "@next/polyfill-nomodule": "12.0.11-canary.2", - "@next/react-dev-overlay": "12.0.11-canary.2", - "@next/react-refresh-utils": "12.0.11-canary.2", - "@next/swc": "12.0.11-canary.2", + "@next/polyfill-module": "12.0.11-canary.3", + "@next/polyfill-nomodule": "12.0.11-canary.3", + "@next/react-dev-overlay": "12.0.11-canary.3", + "@next/react-refresh-utils": "12.0.11-canary.3", + "@next/swc": "12.0.11-canary.3", "@peculiar/webcrypto": "1.1.7", "@taskr/clear": "1.1.0", "@taskr/esnext": "1.1.0", diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 497e4cd232b35bc..36fcece3639f564 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.0.11-canary.2", + "version": "12.0.11-canary.3", "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 97952afcf203b2e..b3395d414d65db8 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.0.11-canary.2", + "version": "12.0.11-canary.3", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/test/integration/relay-graphql-swc-single-project/pages/index.tsx b/test/integration/relay-graphql-swc-single-project/pages/index.tsx index 5b586d43dbd96c3..d1c1bb83ad1fe5f 100644 --- a/test/integration/relay-graphql-swc-single-project/pages/index.tsx +++ b/test/integration/relay-graphql-swc-single-project/pages/index.tsx @@ -2,13 +2,13 @@ import { Environment, FetchFunction, fetchQuery, - graphql, Network, RecordSource, Store, } from 'relay-runtime' import { GetServerSideProps } from 'next' -import { pagesQuery } from '../__generated__/pagesQuery.graphql' +import { pagesQuery as pagesQueryType } from '../queries/__generated__/pagesQuery.graphql' +import pagesQuery from '../queries/pagesQuery' type Props = { greeting: string } @@ -41,13 +41,9 @@ export const getServerSideProps: GetServerSideProps = async ({ req }) => { network: Network.create(createGraphQLFetcher(req.headers.host)), }) - const result = await fetchQuery( + const result = await fetchQuery( environment, - graphql` - query pagesQuery { - greeting - } - `, + pagesQuery, {} ).toPromise() diff --git a/test/integration/relay-graphql-swc-single-project/__generated__/pagesQuery.graphql.ts b/test/integration/relay-graphql-swc-single-project/queries/__generated__/pagesQuery.graphql.ts similarity index 100% rename from test/integration/relay-graphql-swc-single-project/__generated__/pagesQuery.graphql.ts rename to test/integration/relay-graphql-swc-single-project/queries/__generated__/pagesQuery.graphql.ts diff --git a/test/integration/relay-graphql-swc-single-project/queries/pagesQuery.js b/test/integration/relay-graphql-swc-single-project/queries/pagesQuery.js new file mode 100644 index 000000000000000..e61601cfe5296bf --- /dev/null +++ b/test/integration/relay-graphql-swc-single-project/queries/pagesQuery.js @@ -0,0 +1,7 @@ +import { graphql } from 'relay-runtime' + +export default graphql` + query pagesQuery { + greeting + } +` diff --git a/test/integration/relay-graphql-swc-single-project/relay.config.js b/test/integration/relay-graphql-swc-single-project/relay.config.js index a79dff77603833f..cd1174db373f41f 100644 --- a/test/integration/relay-graphql-swc-single-project/relay.config.js +++ b/test/integration/relay-graphql-swc-single-project/relay.config.js @@ -1,6 +1,5 @@ module.exports = { src: './pages', schema: './schema.graphql', - artifactDirectory: './__generated__', language: 'typescript', } diff --git a/test/unit/eslint-plugin-next/inline-script-id.test.ts b/test/unit/eslint-plugin-next/inline-script-id.test.ts index eb59af7744304c6..d584af36402ad75 100644 --- a/test/unit/eslint-plugin-next/inline-script-id.test.ts +++ b/test/unit/eslint-plugin-next/inline-script-id.test.ts @@ -76,6 +76,28 @@ ruleTester.run('inline-script-id', rule, { ) }`, }, + { + code: `import Script from 'next/script'; + + export default function TestPage() { + return ( + + ) + }`, + }, + { + code: `import Script from 'next/script'; + + export default function TestPage() { + return ( + + ) + }`, + }, ], invalid: [ {