diff --git a/.eslintignore b/.eslintignore index 02f6d89cd328d8..22d834344e383e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -8,6 +8,7 @@ examples/with-typescript-eslint-jest/** examples/with-kea/** examples/with-custom-babel-config/** examples/with-flow/** +examples/with-jest/** examples/with-mobx-state-tree/** examples/with-mobx/** packages/next/bundles/webpack/packages/*.runtime.js diff --git a/.github/labeler.json b/.github/labeler.json index 1499d280fb2962..4da78e91522914 100644 --- a/.github/labeler.json +++ b/.github/labeler.json @@ -7,7 +7,10 @@ "packages/next/**", "packages/react-dev-overlay/**", "packages/react-refresh-utils/**", - "packages/next-codemod/**" + "packages/next-codemod/**", + "packages/eslint-plugin-next/**", + "packages/eslint-config-next/**", + "packages/next-env/**" ], "created-by: Chrome Aurora": [ { "type": "user", "pattern": "spanicker" }, diff --git a/.github/workflows/build_native.yml b/.github/workflows/build_native.yml index dcf21e7da8fddb..a69c679ca6a90d 100644 --- a/.github/workflows/build_native.yml +++ b/.github/workflows/build_native.yml @@ -11,12 +11,16 @@ jobs: include: - os: ubuntu-18.04 target: x86_64-unknown-linux-gnu + name: linux-x64-gnu - os: windows-latest target: x86_64-pc-windows-msvc + name: win32-x64-msvc - os: macos-latest target: x86_64-apple-darwin + name: darwin-x64 - os: macos-latest target: aarch64-apple-darwin + name: darwin-arm64 description: m1 name: next-swc - ${{ matrix.os }} - ${{ matrix.target }} - node@14 @@ -66,10 +70,10 @@ jobs: MACOSX_DEPLOYMENT_TARGET: '10.13' working-directory: packages/next - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v2.2.4 with: name: next-swc-binaries - path: packages/next/native/next-swc.*.node + path: packages/next/native/next-swc.${{ matrix.name }}.node - name: Clear the cargo caches run: | cargo install cargo-cache --no-default-features --features ci-autoclean @@ -80,7 +84,7 @@ jobs: steps: - uses: actions/checkout@v2 - - uses: actions/download-artifact@v2 + - uses: actions/download-artifact@v2.0.10 with: name: next-swc-binaries path: packages/next/native diff --git a/.github/workflows/build_test_deploy.yml b/.github/workflows/build_test_deploy.yml index 0cf4b6046ee003..40ed314be2eee2 100644 --- a/.github/workflows/build_test_deploy.yml +++ b/.github/workflows/build_test_deploy.yml @@ -86,8 +86,6 @@ jobs: ./packages/next/native/next-swc.linux-x64-gnu.node if: ${{needs.build.outputs.docsChange != 'docs only change'}} - run: ./scripts/check-pre-compiled.sh - env: - NODE_OPTIONS: '--max_old_space_size=4096' if: ${{needs.build.outputs.docsChange != 'docs only change'}} testUnit: @@ -106,7 +104,7 @@ jobs: path: ./* key: ${{ github.sha }} - - run: node run-tests.js --timings --type unit -g 1/1 + - run: node run-tests.js --type unit if: ${{needs.build.outputs.docsChange != 'docs only change'}} testIntegration: @@ -293,7 +291,7 @@ jobs: runs-on: ubuntu-latest needs: [build, build-native] env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN_ELEVATED }} steps: # https://github.com/actions/virtual-environments/issues/1187 - name: tune linux network @@ -410,7 +408,7 @@ jobs: MACOSX_DEPLOYMENT_TARGET: '10.13' working-directory: packages/next - name: Upload artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v2.2.4 if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} with: name: next-swc-binaries diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 37fd3bc6bd482f..dc023d97813be9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -111,7 +111,7 @@ stages: path: $(System.DefaultWorkingDirectory) displayName: Cache Build - script: | - node run-tests.js -g 1/1 --timings --azure --type unit + node run-tests.js --type unit displayName: 'Run tests' # TODO: investigate re-enabling when stability matches running in # tests in ubuntu environment diff --git a/data.sqlite b/data.sqlite deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/docs/advanced-features/i18n-routing.md b/docs/advanced-features/i18n-routing.md index 5932f80d77461d..219a9956e5aa19 100644 --- a/docs/advanced-features/i18n-routing.md +++ b/docs/advanced-features/i18n-routing.md @@ -234,6 +234,30 @@ Next.js doesn't know about variants of a page so it's up to you to add the `href > Note that Internationalized Routing does not integrate with [`next export`](/docs/advanced-features/static-html-export.md) as `next export` does not leverage the Next.js routing layer. Hybrid Next.js applications that do not use `next export` are fully supported. +### Dynamic Routes and `getStaticProps` Pages + +For pages using `getStaticProps` with [Dynamic Routes](/docs/routing/dynamic-routes.md), all locale variants of the page desired to be prerendered need to be returned from [`getStaticPaths`](/docs/basic-features/data-fetching.md#getstaticpaths-static-generation). Along with the `params` object returned for `paths`, you can also return a `locale` field specifying which locale you want to render. For example: + +```js +// pages/blog/[slug].js +export const getStaticPaths = ({ locales }) => { + return { + paths: [ + // if no `locale` is provided only the defaultLocale will be generated + { params: { slug: 'post-1' }, locale: 'en-US' }, + { params: { slug: 'post-1' }, locale: 'fr' }, + ], + fallback: true, + } +} +``` + +For [Automatically Statically Optimized](/docs/advanced-features/automatic-static-optimization.md) and non-dynamic `getStaticProps` pages, **a version of the page will be generated for each locale**. This is important to consider because it can increase build times depending on how many locales are configured inside `getStaticProps`. + +For example, if you have 50 locales configured with 10 non-dynamic pages using `getStaticProps`, this means `getStaticProps` will be called 500 times. 50 versions of the 10 pages will be generated during each build. + +To decrease the build time of dynamic pages with `getStaticProps`, use a [`fallback` mode](https://nextjs.org/docs/basic-features/data-fetching#fallback-true). This allows you to return only the most popular paths and locales from `getStaticPaths` for prerendering during the build. Then, Next.js will build the remaining pages at runtime as they are requested. + ### Automatically Statically Optimized Pages For pages that are [automatically statically optimized](/docs/advanced-features/automatic-static-optimization.md), a version of the page will be generated for each locale. @@ -265,24 +289,9 @@ export async function getStaticProps({ locale }) { } ``` -### Dynamic getStaticProps Pages - -For dynamic `getStaticProps` pages, any locale variants of the page that is desired to be prerendered needs to be returned from [`getStaticPaths`](/docs/basic-features/data-fetching.md#getstaticpaths-static-generation). Along with the `params` object that can be returned for the `paths`, you can also return a `locale` field specifying which locale you want to render. For example: - -```js -// pages/blog/[slug].js -export const getStaticPaths = ({ locales }) => { - return { - paths: [ - { params: { slug: 'post-1' }, locale: 'en-US' }, - { params: { slug: 'post-1' }, locale: 'fr' }, - ], - fallback: true, - } -} -``` - ## Limits for the i18n config - `locales`: 100 total locales - `domains`: 100 total locale domain items + +> **Note:** These limits have been added initially to prevent potential [performance issues at build time](#dynamic-routes-and-getStaticProps-pages). We are continuing to evaluate if these limits are sufficient. diff --git a/docs/api-reference/next.config.js/custom-page-extensions.md b/docs/api-reference/next.config.js/custom-page-extensions.md index 793228d67fc248..dc11fdc6fac1ca 100644 --- a/docs/api-reference/next.config.js/custom-page-extensions.md +++ b/docs/api-reference/next.config.js/custom-page-extensions.md @@ -14,8 +14,37 @@ module.exports = { } ``` +> **Note**: The default value of `pageExtensions` is [`['tsx', 'ts', 'jsx', 'js']`](https://github.com/vercel/next.js/blob/f1dbc9260d48c7995f6c52f8fbcc65f08e627992/packages/next/server/config-shared.ts#L161). + > **Note**: configuring `pageExtensions` also affects `_document.js`, `_app.js` as well as files under `pages/api/`. For example, setting `pageExtensions: ['page.tsx', 'page.ts']` means the following files: `_document.tsx`, `_app.tsx`, `pages/users.tsx` and `pages/api/users.ts` will have to be renamed to `_document.page.tsx`, `_app.page.tsx`, `pages/users.page.tsx` and `pages/api/users.page.ts` respectively. +## Including non-page files in the `pages` directory + +To colocate test files, generated files, or other files used by components in the `pages` directory, you can prefix the extensions with something like `page`. + +Open `next.config.js` and add the `pageExtensions` config: + +```js +module.exports = { + pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'], +} +``` + +Then rename your pages to have a file extension that includes `.page` (ex. rename `MyPage.tsx` to `MyPage.page.tsx`). + +> **Note**: Make sure you also rename `_document.js`, `_app.js` as well as files under `pages/api/`. + +Without this config, Next.js assumes every tsx/ts/jsx/js file in the `pages` directory is a page or API route, and may expose unintended routes vulnerable to denial of service attacks, or throw an error like the following when building the production bundle: + +``` +Build error occurred +Error: Build optimization failed: found pages without a React Component as default export in +pages/MyPage.generated +pages/MyPage.test + +See https://nextjs.org/docs/messages/page-without-valid-component for more info. +``` + ## Related
diff --git a/docs/api-reference/next.config.js/exportPathMap.md b/docs/api-reference/next.config.js/exportPathMap.md index 6a5efe93f305ce..a5e4420ffa112b 100644 --- a/docs/api-reference/next.config.js/exportPathMap.md +++ b/docs/api-reference/next.config.js/exportPathMap.md @@ -4,7 +4,7 @@ description: Customize the pages that will be exported as HTML files when using # exportPathMap -> This feature is exclusive of `next export`. Please refer to [Static HTML export](/docs/advanced-features/static-html-export.md) if you want to learn more about it. +> This feature is exclusive to `next export`. Please refer to [Static HTML export](/docs/advanced-features/static-html-export.md) if you want to learn more about it.
Examples @@ -40,7 +40,7 @@ module.exports = { } ``` -Note: the `query` field in `exportPathMap` can not be used with [automatically statically optimized pages](/docs/advanced-features/automatic-static-optimization) or [`getStaticProps` pages](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) as they are rendered to HTML files at build-time and additional query information can not be provided during `next export`. +Note: the `query` field in `exportPathMap` cannot be used with [automatically statically optimized pages](/docs/advanced-features/automatic-static-optimization) or [`getStaticProps` pages](https://nextjs.org/docs/basic-features/data-fetching#getstaticprops-static-generation) as they are rendered to HTML files at build-time and additional query information cannot be provided during `next export`. The pages will then be exported as HTML files, for example, `/about` will become `/about.html`. diff --git a/docs/api-reference/next.config.js/redirects.md b/docs/api-reference/next.config.js/redirects.md index 9d35b97c345061..a173840875af91 100644 --- a/docs/api-reference/next.config.js/redirects.md +++ b/docs/api-reference/next.config.js/redirects.md @@ -201,13 +201,14 @@ module.exports = { // if the host is `example.com`, // this redirect will be applied { - source: '/:path((?!another-page$).*)',, + source: '/:path((?!another-page$).*)', has: [ { type: 'host', value: 'example.com', }, ], + permanent: false, destination: '/another-page', }, ] diff --git a/docs/api-reference/next/head.md b/docs/api-reference/next/head.md index 63010ff4e0643c..96a6d14a5ea316 100644 --- a/docs/api-reference/next/head.md +++ b/docs/api-reference/next/head.md @@ -55,7 +55,7 @@ function IndexPage() { export default IndexPage ``` -In this case only the second `` is rendered. `meta` tags with duplicate `name` attributes are automatically handled. +In this case only the second `` is rendered. `meta` tags with duplicate `key` attributes are automatically handled. > The contents of `head` get cleared upon unmounting the component, so make sure each page completely defines what it needs in `head`, without making assumptions about what other pages added. diff --git a/docs/api-reference/next/image.md b/docs/api-reference/next/image.md index 05b53dedb83ae3..b7d6cbba79008f 100644 --- a/docs/api-reference/next/image.md +++ b/docs/api-reference/next/image.md @@ -90,29 +90,26 @@ The `` component optionally accepts the following properties. ### layout -The layout behavior of the image as the viewport changes size. Defaults to -`intrinsic`. +The layout behavior of the image as the viewport changes size. -When `fixed`, the image dimensions will not change as the viewport changes (no -responsiveness) similar to the native `img` element. - -When `intrinsic`, the image will scale the dimensions down for smaller viewports -but maintain the original dimensions for larger viewports. - -When `responsive`, the image will scale the dimensions down for smaller -viewports and scale up for larger viewports. -Note: the responsive layout may not work correctly if the parent element uses a display value other than `block` such as `display: flex` or `display: grid`. - -When `fill`, the image will stretch both width and height to the dimensions of -the parent element, provided the parent element is relative. This is usually paired with the [`objectFit`](#objectFit) property. -Ensure the parent element has `position: relative` in their stylesheet. - -Try it out: +| `layout` | Behavior | `srcSet` | `sizes` | +| --------------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | +| `intrinsic` (default) | Scale *down* to fit width of container, up to image size | `1x`, `2x` (based on [imageSizes](/docs/basic-features/image-optimization.md#image-sizes)) | N/A | +| `fixed` | Sized to `width` and `height` exactly | `1x`, `2x` (based on [imageSizes](/docs/basic-features/image-optimization.md#image-sizes)) | N/A | +| `responsive` | Scale to fit width of container | `640w`, `750w`, ... `2048w`, `3840w` (based on [imageSizes](/docs/basic-features/image-optimization.md#image-sizes) and [deviceSizes](/docs/basic-features/image-optimization.md#device-sizes)) | `100vw` | +| `fill` | Grow in X and Y axes to fill container | `640w`, `750w`, ... `2048w`, `3840w` (based on [imageSizes](/docs/basic-features/image-optimization.md#image-sizes) and [deviceSizes](/docs/basic-features/image-optimization.md#device-sizes)) | `100vw` | +- [Demo the `intrinsic` layout (default)](https://image-component.nextjs.gallery/layout-intrinsic) + - When `intrinsic`, the image will scale the dimensions down for smaller viewports, but maintain the original dimensions for larger viewports. - [Demo the `fixed` layout](https://image-component.nextjs.gallery/layout-fixed) -- [Demo the `intrinsic` layout](https://image-component.nextjs.gallery/layout-intrinsic) + - When `fixed`, the image dimensions will not change as the viewport changes (no responsiveness) similar to the native `img` element. - [Demo the `responsive` layout](https://image-component.nextjs.gallery/layout-responsive) + - When `responsive`, the image will scale the dimensions down for smaller viewports and scale up for larger viewports. + - Ensure the parent element uses `display: block` in their stylesheet. - [Demo the `fill` layout](https://image-component.nextjs.gallery/layout-fill) + - When `fill`, the image will stretch both width and height to the dimensions of the parent element, provided the parent element is relative. + - This is usually paired with the [`objectFit`](#objectFit) property. + - Ensure the parent element has `position: relative` in their stylesheet. - [Demo background image](https://image-component.nextjs.gallery/background) ### loader @@ -265,7 +262,7 @@ Other properties on the `` component will be passed to the underlying ## Styling -`next/image` wraps the `img` element with other `div` elements to maintain the aspect ratio of the image and prevent [Cumulative Layout Shift](https://vercel.com/blog/core-web-vitals#cumulative-layout-shift). +`next/image` wraps the `img` element with a single `div` element to maintain the aspect ratio of the image and prevent [Cumulative Layout Shift](https://vercel.com/blog/core-web-vitals#cumulative-layout-shift). To add styles to the underlying `img` element, pass the `className` prop to the `` component. Then, use Next.js' [built-in CSS support](/docs/basic-features/built-in-css-support.md) to add rules to that class. diff --git a/docs/api-reference/next/link.md b/docs/api-reference/next/link.md index a5272331968a4d..6a6c40770a766e 100644 --- a/docs/api-reference/next/link.md +++ b/docs/api-reference/next/link.md @@ -91,7 +91,7 @@ export default Posts ## If the child is a custom component that wraps an `` tag -If the child of `Link` is a custom component that wraps an `` tag, you must add `passHref` to `Link`. This is necessary if you’re using libraries like [styled-components](https://styled-components.com/). Without this, the `` tag will not have the `href` attribute, which might hurt your site’s SEO. +If the child of `Link` is a custom component that wraps an `` tag, you must add `passHref` to `Link`. This is necessary if you’re using libraries like [styled-components](https://styled-components.com/). Without this, the `` tag will not have the `href` attribute, which hurts your site's accessibility and might affect SEO. If you're using [ESLint](/docs/basic-features/eslint.md#eslint-plugin), there is a built-in rule `next/link-passhref` to ensure correct usage of `passHref`. ```jsx import Link from 'next/link' diff --git a/docs/api-routes/api-middlewares.md b/docs/api-routes/api-middlewares.md index 5710da1593df29..7f1b41d398d9b4 100644 --- a/docs/api-routes/api-middlewares.md +++ b/docs/api-routes/api-middlewares.md @@ -145,7 +145,7 @@ export const setCookie = ( options.maxAge /= 1000 } - res.setHeader('Set-Cookie', serialize(name, String(stringValue), options)) + res.setHeader('Set-Cookie', serialize(name, stringValue, options)) } // pages/api/cookies.ts diff --git a/docs/api-routes/introduction.md b/docs/api-routes/introduction.md index dab2047832ab34..4274f7d0f7b2b5 100644 --- a/docs/api-routes/introduction.md +++ b/docs/api-routes/introduction.md @@ -55,7 +55,7 @@ For new projects, you can build your entire API with API Routes. If you have an ## Caveats -- API Routes [do not specify CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), meaning they are **same-origin only** by default. You can customize such behavior by wrapping the request handler with the [cors middleware](/docs/api-routes/api-middlewares.md#connectexpress-middleware-support). +- API Routes [do not specify CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), meaning they are **same-origin only** by default. You can customize such behavior by wrapping the request handler with the [CORS middleware](/docs/api-routes/api-middlewares.md#connectexpress-middleware-support). - API Routes can't be used with [`next export`](/docs/advanced-features/static-html-export.md) ## Related diff --git a/docs/basic-features/data-fetching.md b/docs/basic-features/data-fetching.md index b63575f7f9eae4..2eb8dd943e82e8 100644 --- a/docs/basic-features/data-fetching.md +++ b/docs/basic-features/data-fetching.md @@ -672,7 +672,7 @@ The `context` parameter is an object containing the following keys: `getServerSideProps` should return an object with: -- `props` - An **optional** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization) +- `props` - An **optional** object with the props that will be received by the page component. It should be a [serializable object](https://en.wikipedia.org/wiki/Serialization) or a Promise that resolves to a serializable object. - `notFound` - An **optional** boolean value to allow the page to return a 404 status and page. Below is an example of how it works: ```js diff --git a/docs/basic-features/environment-variables.md b/docs/basic-features/environment-variables.md index 7e2ff8e70c3bf2..93f65cfdc3a39e 100644 --- a/docs/basic-features/environment-variables.md +++ b/docs/basic-features/environment-variables.md @@ -78,7 +78,7 @@ export async function getStaticProps() { ## Exposing Environment Variables to the Browser -By default all environment variables loaded through `.env.local` are only available in the Node.js environment, meaning they won't be exposed to the browser. +By default environment variables are only available in the Node.js environment, meaning they won't be exposed to the browser. In order to expose a variable to the browser you have to prefix the variable with `NEXT_PUBLIC_`. For example: diff --git a/docs/basic-features/eslint.md b/docs/basic-features/eslint.md index dc68f5faed35cf..2887e2f18b18ef 100644 --- a/docs/basic-features/eslint.md +++ b/docs/basic-features/eslint.md @@ -94,6 +94,7 @@ Next.js provides an ESLint plugin, [`eslint-plugin-next`](https://www.npmjs.com/ | ✔️ | [next/no-sync-scripts](https://nextjs.org/docs/messages/no-sync-scripts) | Forbid synchronous scripts | | ✔️ | [next/no-title-in-document-head](https://nextjs.org/docs/messages/no-title-in-document-head) | Disallow using <title> with Head from next/document | | ✔️ | [next/no-unwanted-polyfillio](https://nextjs.org/docs/messages/no-unwanted-polyfillio) | Prevent duplicate polyfills from Polyfill.io | +| ✔️ | [next/inline-script-id](https://nextjs.org/docs/messages/inline-script-id) | Enforce id attribute on next/script components with inline content | | ✔️ | next/no-typos | Ensure no typos were made declaring [Next.js's data fetching function](https://nextjs.org/docs/basic-features/data-fetching) | | ✔️ | [next/next-script-for-ga](https://nextjs.org/docs/messages/next-script-for-ga) | Use the Script component to defer loading of the script until necessary. | @@ -101,7 +102,26 @@ Next.js provides an ESLint plugin, [`eslint-plugin-next`](https://www.npmjs.com/ If you already have ESLint configured in your application, we recommend extending from this plugin directly instead of including `eslint-config-next` unless a few conditions are met. Refer to the [Recommended Plugin Ruleset](/docs/basic-features/eslint.md#recommended-plugin-ruleset) to learn more. -## Linting Custom Directories +### Custom Settings + +#### `rootDir` + +If you're using `eslint-plugin-next` in a project where Next.js isn't installed in your root directory (such as a monorepo), you can tell `eslint-plugin-next` where to find your Next.js application using the `settings` property in your `.eslintrc`: + +```json +{ + "extends": "next", + "settings": { + "next": { + "rootDir": "/packages/my-app/" + } + } +} +``` + +`rootDir` can be a path (relative or absolute), a glob (i.e. `"/packages/*/"`), or an array of paths and/or globs. + +## Linting Custom Directories and Files By default, Next.js will run ESLint for all files in the `pages/`, `components/`, and `lib/` directories. However, you can specify which directories using the `dirs` option in the `eslint` config in `next.config.js` for production builds: @@ -113,10 +133,18 @@ module.exports = { } ``` -Similarly, the `--dir` flag can be used for `next lint`: +Similarly, the `--dir` and `--file` flags can be used for `next lint` to lint specific directories and files: + +```bash +next lint --dir pages --dir utils --file bar.js +``` + +## Caching + +To improve performance, information of files processed by ESLint are cached by default. This is stored in `.next/cache` or in your defined [build directory](/docs/api-reference/next.config.js/setting-a-custom-build-directory). If you include any ESLint rules that depend on more than the contents of a single source file and need to disable the cache, use the `--no-cache` flag with `next lint`. ```bash -next lint --dir pages --dir utils +next lint --no-cache ``` ## Disabling Rules @@ -147,7 +175,9 @@ The `next/core-web-vitals` rule set is enabled when `next lint` is run for the f > The `next/core-web-vitals` entry point is automatically included for new applications built with [Create Next App](/docs/api-reference/create-next-app.md). -## Usage with Prettier +## Usage With Other Tools + +### 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. @@ -157,6 +187,19 @@ ESLint also contains code formatting rules, which can conflict with your existin } ``` +### lint-staged + +If you would like to use `next lint` with [lint-staged](https://github.com/okonet/lint-staged) to run the linter on staged git files, you'll have to add the following to the `.lintstagedrc.js` file in the root of your project in order to specify usage of the `--file` flag. + +```js +module.exports = { + '**/*.js?(x)': (filenames) => + `next lint --fix --file ${filenames + .map((file) => file.split(process.cwd())[1]) + .join(' --file ')}`, +} +``` + ## Migrating Existing Config ### Recommended Plugin Ruleset diff --git a/docs/basic-features/font-optimization.md b/docs/basic-features/font-optimization.md index 1c63fda0332cab..7f9d06a1557b26 100644 --- a/docs/basic-features/font-optimization.md +++ b/docs/basic-features/font-optimization.md @@ -35,7 +35,7 @@ export default function IndexPage() {
@@ -58,7 +58,7 @@ class MyDocument extends Document { @@ -76,6 +76,8 @@ export default MyDocument Automatic Webfont Optimization currently supports Google Fonts and Typekit with support for other font providers coming soon. We're also planning to add control over [loading strategies](https://github.com/vercel/next.js/issues/21555) and `font-display` values. +See [Google Font Display](https://nextjs.org/docs/messages/google-font-display) for more information. + ## Disabling Optimization If you do not want Next.js to optimize your fonts, you can opt-out. diff --git a/docs/basic-features/image-optimization.md b/docs/basic-features/image-optimization.md index ee8a6ad7e31712..39c09b84f93eca 100644 --- a/docs/basic-features/image-optimization.md +++ b/docs/basic-features/image-optimization.md @@ -52,9 +52,9 @@ export default Home ## Image Imports -You can `import` images that live in your project. (Note that `require` is not supported—only `import`.) +You can statically `import` images that live in your project. Dynamic `await import()` or `require()` are _not_ supported. -With direct `import`s, `width`, `height`, and `blurDataURL` will be automatically provided to the image component. Alt text is still needed separately. +With static `import`s, you only need to provide the `src` prop. The `width`, `height`, and `blurDataURL` props will automatically be populated. Alt text is still needed separately. ```js import Image from 'next/image' @@ -70,8 +70,7 @@ function Home() { // 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" + // placeholder="blur" // Optional blur-up while loading />

Welcome to my homepage!

@@ -79,7 +78,7 @@ function Home() { } ``` -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. +For remote images, you'll need to provide the [`width`](/docs/api-reference/next/image.md#width), [`height`](/docs/api-reference/next/image.md#height) and [`blurDataURL`](/docs/api-reference/next/image.md#blurdataurl) props manually. ## Properties @@ -128,7 +127,7 @@ If you need a different provider, you can use the [`loader`](/docs/api-reference > The `next/image` component's default loader is not supported when using [`next export`](/docs/advanced-features/static-html-export.md). However, other loader options will work. -> The `next/image` component's default loader uses the ['squoosh'](https://www.npmjs.com/package/@squoosh/lib) library for image resizing and optimization. This library is quick to install and suitable for a dev server environment. For a production environment, it is strongly recommended that you install the optional [`sharp`](https://www.npmjs.com/package/sharp) library by running `yarn add sharp` in your project directory. If sharp is already installed but can't be resolved you can manually pass the path to it via the `NEXT_SHARP_PATH` environment variable e.g. `NEXT_SHARP_PATH=/tmp/node_modules/sharp` +> The `next/image` component's default loader uses [`squoosh`](https://www.npmjs.com/package/@squoosh/lib) because it is quick to install and suitable for a development environment. When using `next start` in your production environment, it is strongly recommended that you install [`sharp`](https://www.npmjs.com/package/sharp) by running `yarn add sharp` in your project directory. This is not necessary for Vercel deployments, as `sharp` is installed automatically. ## Caching diff --git a/docs/basic-features/script.md b/docs/basic-features/script.md index 1d4a0b302e13ac..ef688170332e49 100644 --- a/docs/basic-features/script.md +++ b/docs/basic-features/script.md @@ -131,13 +131,14 @@ export default function Home() { ```js import Script from 'next/script' - // or + + + ) +} +``` + +## Useful links + +- [Docs for Next.js Script component](https://nextjs.org/docs/basic-features/script) diff --git a/errors/invalid-api-status-body.md b/errors/invalid-api-status-body.md new file mode 100644 index 00000000000000..b0d5fd60fd99d5 --- /dev/null +++ b/errors/invalid-api-status-body.md @@ -0,0 +1,32 @@ +Invalid API Route Status/Body Response + +#### Why This Error Occurred + +In one of your API routes a 204 or 304 status code was used as well as sending a response body. + +This is invalid as a 204 or 304 status code dictates no response body should be present. + +#### Possible Ways to Fix It + +Send an empty body when using a 204 or 304 status code or use a different status code while sending a response body. + +Before + +```js +export default function handler(req, res) { + res.status(204).send('invalid body') +} +``` + +After + +```js +export default function handler(req, res) { + res.status(204).send() +} +``` + +### Useful Links + +- [204 status code documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204) +- [304 status code documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304) diff --git a/errors/manifest.json b/errors/manifest.json index 5645b9cd13e89b..0141c1fa548124 100644 --- a/errors/manifest.json +++ b/errors/manifest.json @@ -4,6 +4,10 @@ "title": "Messages", "heading": true, "routes": [ + { + "title": "custom-document-image-import", + "path": "/errors/custom-document-image-import.md" + }, { "title": "404-get-initial-props", "path": "/errors/404-get-initial-props.md" @@ -145,6 +149,10 @@ "title": "incompatible-href-as", "path": "/errors/incompatible-href-as.md" }, + { + "title": "inline-script-id", + "path": "/errors/inline-script-id.md" + }, { "title": "install-sass", "path": "/errors/install-sass.md" }, { "title": "install-sharp", "path": "/errors/install-sharp.md" }, { @@ -265,6 +273,10 @@ "title": "next-image-unconfigured-host", "path": "/errors/next-image-unconfigured-host.md" }, + { + "title": "next-script-for-ga", + "path": "/errors/next-script-for-ga.md" + }, { "title": "next-start-serverless", "path": "/errors/next-start-serverless.md" @@ -450,6 +462,10 @@ { "title": "next-config-error", "path": "/errors/next-config-error.md" + }, + { + "title": "invalid-api-status-body", + "path": "/errors/invalid-api-status-body.md" } ] } diff --git a/errors/next-script-for-ga.md b/errors/next-script-for-ga.md index 15d400c098bd5d..2f367dff127c31 100644 --- a/errors/next-script-for-ga.md +++ b/errors/next-script-for-ga.md @@ -20,8 +20,8 @@ const Home = () => { - + />
) } diff --git a/errors/no-html-link-for-pages.md b/errors/no-html-link-for-pages.md index 76c8fd8e7bd5be..0fe1449d69a9a3 100644 --- a/errors/no-html-link-for-pages.md +++ b/errors/no-html-link-for-pages.md @@ -40,6 +40,24 @@ function Home() { export default Home ``` +### Options + +#### `pagesDir` + +This rule can normally locate your `pages` directory automatically. + +If you're working in a monorepo, we recommend configuring the [`rootDir`](/docs/basic-features/eslint.md#rootDir) setting in `eslint-plugin-next`, which `pagesDir` will use to locate your `pages` directory. + +In some cases, you may also need to configure this rule directly by providing a `pages` directory. This can be a path or an array of paths. + +```json +{ + "rules": { + "@next/next/no-html-link-for-pages": ["error", "/my-app/pages/"] + } +} +``` + ### Useful Links - [next/link API Reference](https://nextjs.org/docs/api-reference/next/link) diff --git a/errors/sharp-missing-in-production.md b/errors/sharp-missing-in-production.md index 01fc602b4b4e33..02face5fc054f1 100644 --- a/errors/sharp-missing-in-production.md +++ b/errors/sharp-missing-in-production.md @@ -2,11 +2,16 @@ #### Why This Error Occurred -The `next/image` component's default loader uses the ['squoosh'](https://www.npmjs.com/package/@squoosh/lib) library for image resizing and optimization. This library is quick to install and suitable for a dev server environment. For a production environment, it is strongly recommended that you install the optional [`sharp`](https://www.npmjs.com/package/sharp). This package was not detected when leveraging the Image Optimization in production mode (`next start`). +The `next/image` component's default loader uses [`squoosh`](https://www.npmjs.com/package/@squoosh/lib) because it is quick to install and suitable for a development environment. For a production environment using `next start`, it is strongly recommended you install [`sharp`](https://www.npmjs.com/package/sharp) by running `yarn add sharp` in your project directory. + +You are seeing this error because Image Optimization in production mode (`next start`) was detected. #### Possible Ways to Fix It -Install `sharp` by running `yarn add sharp` in your project directory. +- Install `sharp` by running `yarn add sharp` in your project directory and then reboot the server by running `next start` again +- If `sharp` is already installed but can't be resolved, set the `NEXT_SHARP_PATH` environment variable such as `NEXT_SHARP_PATH=/tmp/node_modules/sharp next start` + +> Note: This is not necessary for Vercel deployments, since `sharp` is installed automatically for you. ### Useful Links diff --git a/examples/active-class-name/package.json b/examples/active-class-name/package.json index 349de02f4d84be..6513b825ee0a6c 100644 --- a/examples/active-class-name/package.json +++ b/examples/active-class-name/package.json @@ -8,6 +8,7 @@ "dependencies": { "next": "latest", "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "prop-types": "^15.7.2" } } diff --git a/examples/cms-prepr/README.md b/examples/cms-prepr/README.md index 8607f98c15494e..8c5d571130c30a 100644 --- a/examples/cms-prepr/README.md +++ b/examples/cms-prepr/README.md @@ -61,9 +61,7 @@ After that Import the [`models/post.json`](models/post.json) file. -Click on the Author field and select `Author` at the option `Publication model` and click **Save**. - -### Step 3. Set up environment variables +### Step 3. Set up environment variables (for production) Copy the `.env.local.example` file in this directory to `.env.local` (which will be ignored by Git): @@ -73,15 +71,17 @@ cp .env.local.example .env.local Inside your environment, navigate to **Settings > Development > Access Tokens**. -Click **Add access token**, enter the name `Next.js Preview` and add the scope `graphql_preview` and click **Save**. +Click **Add access token**, enter the name `Next.js Production` and add the scope `graphql_published` and click **Save**. -Copy the generated access token and set the variable `PREPRIO_PREVIEW_TOKEN` in `.env.local`. +Copy the generated access token and set the variable `PREPRIO_PRODUCTION_TOKEN` in `.env.local`. + +### Step 3.1 Set up environment variables (for preview) Go back to the Access token overview and click **Add access token**. -Enter the name `Next.js Production` and add the scope `graphql_published` and click **Save**. +Click **Add access token**, enter the name `Next.js Preview` and add the scope `graphql_preview` and click **Save**. -Copy the generated access token and set the variable `PREPRIO_PRODUCTION_TOKEN` in `.env.local`. +Copy the generated access token and set the variable `PREPRIO_PREVIEW_TOKEN` in `.env.local`. The `PREPRIO_PREVIEW_KEY` can be any random string (but avoid spaces), like a UUID`, this is used for [Preview Mode](https://nextjs.org/docs/advanced-features/preview-mode). diff --git a/examples/cms-prepr/models/post.json b/examples/cms-prepr/models/post.json index f0b9c9e1dbefc8..285663dceb5222 100644 --- a/examples/cms-prepr/models/post.json +++ b/examples/cms-prepr/models/post.json @@ -16,7 +16,7 @@ "seo_score": false, "ab_testing": false, "versioning": false, - "slug": null, + "slug": "{title}", "for": null, "fields": [ { @@ -133,7 +133,16 @@ "description": null, "disable_editing": false, "appearance": null, - "accept_restrictions": null + "accept_restrictions": null, + "publication_models": { + "items": [ + { + "id": "7214e365-1b4c-4de3-8412-e311250fb4da", + "body": "Author" + } + ], + "total": 1 + } }, { "type": "Slug", diff --git a/examples/cms-sanity/lib/config.js b/examples/cms-sanity/lib/config.js index 018ad4f2aeeb31..b4b0101e5494c2 100644 --- a/examples/cms-sanity/lib/config.js +++ b/examples/cms-sanity/lib/config.js @@ -6,4 +6,6 @@ export const sanityConfig = { // useCdn == true gives fast, cheap responses using a globally distributed cache. // Set this to false if your application require the freshest possible // data always (potentially slightly slower and a bit more expensive). + apiVersion: '2021-03-25', + // see https://www.sanity.io/docs/api-versioning for how versioning works } diff --git a/examples/with-couchbase/.env.local.example b/examples/with-couchbase/.env.local.example new file mode 100644 index 00000000000000..3860cf6cc902ac --- /dev/null +++ b/examples/with-couchbase/.env.local.example @@ -0,0 +1,5 @@ +COUCHBASE_USER= +COUCHBASE_PASSWORD= +COUCHBASE_ENDPOINT= +COUCHBASE_BUCKET= +IS_CLOUD_INSTANCE= diff --git a/examples/with-couchbase/.gitignore b/examples/with-couchbase/.gitignore new file mode 100644 index 00000000000000..b9c882b7965724 --- /dev/null +++ b/examples/with-couchbase/.gitignore @@ -0,0 +1,33 @@ +# 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 + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE Files +.idea/ diff --git a/examples/with-couchbase/README.md b/examples/with-couchbase/README.md new file mode 100644 index 00000000000000..383a329d8e9109 --- /dev/null +++ b/examples/with-couchbase/README.md @@ -0,0 +1,95 @@ +## Example app using Couchbase + +[Couchbase](https://www.couchbase.com/) is a modern database for enterprise applications. This example will show you how to connect to and use Couchbase in your Next.js app. + +If you want to learn more about Couchbase, visit the following pages: + +- [Couchbase Docs](https://docs.couchbase.com/) +- [Couchbase Developer Portal](https://developer.couchbase.com/) +- [Couchbase Cloud](https://cloud.couchbase.com/sign-up) + +## Preview + +Preview the example live on [StackBlitz](http://stackblitz.com/): + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-couchbase) + +## Deploy your own + +Once you have access to the environment variables you'll need, deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-couchbase&project-name=with-couchbase&repository-name=with-couchbase&env=COUCHBASE_USER,COUCHBASE_PASSWORD,COUCHBASE_ENDPOINT,COUCHBASE_BUCKET,IS_CLOUD_INSTANCE&envDescription=Required%20to%20connect%20the%20app%20with%20Couchbase) + +## How to use + +Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: + +```bash +npx create-next-app --example with-couchbase with-couchbase-app +# or +yarn create next-app --example with-couchbase with-couchbase-app +``` + +Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). + +## Configuration + +### Set up a Couchbase database + +Set up a Couchbase database either locally or with [Couchbase Cloud](https://cloud.couchbase.com/sign-up). + +Local installation can be accomplished through a variety of methods, but [Docker](https://docs.couchbase.com/server/current/install/getting-started-docker.html) is the simplest. + +After Couchbase is installed, set up a cluster by following [this tutorial](https://docs.couchbase.com/server/current/manage/manage-nodes/create-cluster.html). + +- _NOTE:_ the **eventing** and **analytics** services can be unchecked if memory is a constraint (this is often the case with docker and other local installations). + +A variety of sample buckets can be installed to get up and running with a data model quickly. + +### Set up environment variables + +Copy the `env.local.example` file in this directory to `.env.local` (which will be ignored by Git): + +```bash +cp .env.local.example .env.local +``` + +Set each variable on `.env.local`: + +- `COUCHBASE_USERNAME` - The username of an authorized user on your Couchbase instance +- `COUCHBASE_PASSWORD` - The corresponding password for the username specified above +- `COUCHBASE_ENDPOINT` - The endpoint to connect to. Use `localhost` for a local instance of Couchbase, or the Wide Area Network address for a cloud instance. +- `COUCHBASE_BUCKET` - The bucket you'd like to connect to for testing. +- `IS_CLOUD_INSTANCE` - `true` if you are trying to connect to an instance of Couchbase Cloud, `false` otherwise. + +### Run Next.js in development mode + +```bash +npm install +npm run dev +# or +yarn install +yarn dev +``` + +Your app should be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/vercel/next.js/discussions). + +You will either see a message stating "You are connected to Couchbase" or "You are NOT connected to Couchbase". Ensure that you have provided the correct environment variables. + +When you are successfully connected, you can refer to the [Couchbase Node.js SDK docs](https://docs.couchbase.com/nodejs-sdk/current/hello-world/start-using-sdk.html) for further instructions on how to query your database. + +## Deploy on Vercel + +You can deploy this app to the cloud with [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). + +#### Deploy Your Local Project + +To deploy your local project to Vercel, push it to GitHub/GitLab/Bitbucket and [import to Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example). + +## Notes + +- When you import your project on Vercel, make sure to click on **Environment Variables** and set the keys to match your `.env.local` file. + +- For a cloud deployment on Vercel, the **Environment Variables** values will need to **correspond to a cloud instance of Couchbase** (localhost will **NOT** connect from a remote server such as Vercel). Find info on [getting started with Couchbase cloud](https://developer.couchbase.com/tutorial-cloud-getting-started/). + + - _Important:_ you will have to allowlist 0.0.0.0/0 as the IP address, since Vercel's serverless deployments use [dynamic IP addresses](https://vercel.com/docs/solutions/databases#allowing-&-blocking-ip-addresses) diff --git a/examples/with-couchbase/package.json b/examples/with-couchbase/package.json new file mode 100644 index 00000000000000..d5d061dc33aac9 --- /dev/null +++ b/examples/with-couchbase/package.json @@ -0,0 +1,14 @@ +{ + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "couchbase": "^3.1.3", + "next": "latest", + "react": "^17.0.2", + "react-dom": "^17.0.2" + } +} diff --git a/examples/with-couchbase/pages/_app.js b/examples/with-couchbase/pages/_app.js new file mode 100644 index 00000000000000..1e1cec92425c8b --- /dev/null +++ b/examples/with-couchbase/pages/_app.js @@ -0,0 +1,7 @@ +import '../styles/globals.css' + +function MyApp({ Component, pageProps }) { + return +} + +export default MyApp diff --git a/examples/with-couchbase/pages/index.js b/examples/with-couchbase/pages/index.js new file mode 100644 index 00000000000000..a50b899f7408e7 --- /dev/null +++ b/examples/with-couchbase/pages/index.js @@ -0,0 +1,78 @@ +import Head from 'next/head' +import styles from '../styles/Home.module.css' +import { connectToDatabase } from '../util/couchbase' + +export default function Home({ isConnected }) { + return ( +
+ + Create Next App + + + +
+

+ Welcome to Next.js with Couchbase! +

+ + {isConnected ? ( +

+ You are connected to Couchbase +

+ ) : ( + <> +

+ You are NOT connected to Couchbase. Try refreshing the page, and + if this error persists check the README.md for + instructions. +

+ + Note: if the database was recently started, you might have to + re-start the app (in dev mode) or re-deploy to your serverless + environment for changes to take effect. + + + )} + +

+ Get started by editing{' '} + pages/index.js +

+
+ + +
+ ) +} + +export async function getServerSideProps(context) { + let connection = await connectToDatabase() + + const { collection } = connection + + // Check connection with a KV GET operation for a key that doesnt exist + let isConnected = false + try { + await collection.get('testingConnectionKey') + } catch (err) { + // error message will return 'document not found' if and only if we are connected + // (but this document is not present, we're only trying to test the connection here) + if (err.message === 'document not found') { + isConnected = true + } + // if the error message is anything OTHER THAN 'document not found', the connection is broken + } + + return { + props: { isConnected }, + } +} diff --git a/examples/with-couchbase/public/favicon.ico b/examples/with-couchbase/public/favicon.ico new file mode 100644 index 00000000000000..4965832f2c9b06 Binary files /dev/null and b/examples/with-couchbase/public/favicon.ico differ diff --git a/examples/with-couchbase/public/vercel.svg b/examples/with-couchbase/public/vercel.svg new file mode 100644 index 00000000000000..fbf0e25a651c28 --- /dev/null +++ b/examples/with-couchbase/public/vercel.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/examples/with-couchbase/styles/Home.module.css b/examples/with-couchbase/styles/Home.module.css new file mode 100644 index 00000000000000..ef4de859109aa6 --- /dev/null +++ b/examples/with-couchbase/styles/Home.module.css @@ -0,0 +1,148 @@ +.small { + font-size: 10px; +} + +.center { + text-align: center; +} + +.red, +.error { + color: indianred; +} + +.green, +.success { + color: lightseagreen; +} + +.container { + min-height: 100vh; + padding: 0 0.5rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.main { + padding: 5rem 0; + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.footer { + width: 100%; + height: 100px; + border-top: 1px solid #eaeaea; + display: flex; + justify-content: center; + align-items: center; +} + +.footer img { + margin-left: 0.5rem; +} + +.footer a { + display: flex; + justify-content: center; + align-items: center; + text-decoration: none; + color: inherit; +} + +.title a { + color: #0070f3; + text-decoration: none; +} + +.title a:hover, +.title a:focus, +.title a:active { + text-decoration: underline; +} + +.title { + margin: 0; + line-height: 1.15; + font-size: 4rem; +} + +.title, +.description { + text-align: center; +} + +.subtitle { + font-size: 2rem; + text-align: center; +} + +.description { + line-height: 1.5; + font-size: 1.5rem; +} + +.code { + background: #fafafa; + border-radius: 5px; + padding: 0.75rem; + font-size: 1.1rem; + font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, + Bitstream Vera Sans Mono, Courier New, monospace; +} + +.grid { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + + max-width: 800px; + margin-top: 3rem; +} + +.card { + margin: 1rem; + flex-basis: 45%; + padding: 1.5rem; + text-align: left; + color: inherit; + text-decoration: none; + border: 1px solid #eaeaea; + border-radius: 10px; + transition: color 0.15s ease, border-color 0.15s ease; +} + +.card:hover, +.card:focus, +.card:active { + color: #0070f3; + border-color: #0070f3; +} + +.card h3 { + margin: 0 0 1rem 0; + font-size: 1.5rem; +} + +.card p { + margin: 0; + font-size: 1.25rem; + line-height: 1.5; +} + +.logo { + height: 1em; +} + +@media (max-width: 600px) { + .grid { + width: 100%; + flex-direction: column; + } +} diff --git a/examples/with-couchbase/styles/globals.css b/examples/with-couchbase/styles/globals.css new file mode 100644 index 00000000000000..8147d4355dbd06 --- /dev/null +++ b/examples/with-couchbase/styles/globals.css @@ -0,0 +1,11 @@ +html, +body { + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; +} + +* { + box-sizing: border-box; +} diff --git a/examples/with-couchbase/util/couchbase.js b/examples/with-couchbase/util/couchbase.js new file mode 100644 index 00000000000000..f1a683cd767071 --- /dev/null +++ b/examples/with-couchbase/util/couchbase.js @@ -0,0 +1,65 @@ +import * as couchbase from 'couchbase' + +const COUCHBASE_USER = process.env.COUCHBASE_USER +const COUCHBASE_PASSWORD = process.env.COUCHBASE_PASSWORD +const COUCHBASE_ENDPOINT = process.env.COUCHBASE_ENDPOINT || 'localhost' +const COUCHBASE_BUCKET = process.env.COUCHBASE_BUCKET || 'travel-sample' +let IS_CLOUD_INSTANCE = process.env.IS_CLOUD_INSTANCE || 'false' + +if (!COUCHBASE_USER) { + throw new Error( + 'Please define the COUCHBASE_USER environment variable inside .env.local' + ) +} + +if (!COUCHBASE_PASSWORD) { + throw new Error( + 'Please define the COUCHBASE_PASSWORD environment variable inside .env.local' + ) +} + +/** + * Global is used here to maintain a cached connection across hot reloads + * in development. This prevents connections growing exponentially + * during API Route usage. + */ +let cached = global.couchbase + +if (!cached) { + cached = global.couchbase = { conn: null } +} + +async function createCouchbaseCluster() { + if (cached.conn) { + return cached.conn + } + + cached.conn = await couchbase.connect( + 'couchbase://' + + COUCHBASE_ENDPOINT + + (IS_CLOUD_INSTANCE === 'true' + ? '?ssl=no_verify&console_log_level=5' + : ''), + { + username: COUCHBASE_USER, + password: COUCHBASE_PASSWORD, + } + ) + + return cached.conn +} + +export async function connectToDatabase() { + const cluster = await createCouchbaseCluster() + + const bucket = cluster.bucket(COUCHBASE_BUCKET) + const collection = bucket.defaultCollection() + + let dbConnection = { + cluster, + bucket, + collection, + } + + return dbConnection +} diff --git a/examples/with-docker/README.md b/examples/with-docker/README.md index cfb64979d62b2d..868cb6ce5091af 100644 --- a/examples/with-docker/README.md +++ b/examples/with-docker/README.md @@ -22,7 +22,7 @@ You can view your images created with `docker images`. ## Deploying to Google Cloud Run -The `start` script in `package.json` has been modified to accept a `PORT` environment variable (for compatability with Google Cloud Run). +The `start` script in `package.json` has been modified to accept a `PORT` environment variable (for compatibility with Google Cloud Run). 1. Install the [Google Cloud SDK](https://cloud.google.com/sdk/docs/install) so you can use `gcloud` on the command line. 1. Run `gcloud auth login` to log in to your account. diff --git a/examples/with-elasticsearch/.env.local.example b/examples/with-elasticsearch/.env.local.example new file mode 100644 index 00000000000000..07c5c889085c65 --- /dev/null +++ b/examples/with-elasticsearch/.env.local.example @@ -0,0 +1,3 @@ +ESS_CLOUD_ID= +ESS_CLOUD_USERNAME= +ESS_CLOUD_PASSWORD= \ No newline at end of file diff --git a/examples/with-elasticsearch/.gitignore b/examples/with-elasticsearch/.gitignore new file mode 100644 index 00000000000000..c9512eaab3c601 --- /dev/null +++ b/examples/with-elasticsearch/.gitignore @@ -0,0 +1,28 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local diff --git a/examples/with-elasticsearch/README.md b/examples/with-elasticsearch/README.md new file mode 100644 index 00000000000000..74159992351b03 --- /dev/null +++ b/examples/with-elasticsearch/README.md @@ -0,0 +1,78 @@ +## Example app using Elasticsearch + +[Elasticsearch](https://www.elastic.co/elasticsearch) is a distributed, RESTful search and analytics engine. As the heart of the Elastic Stack, it centrally stores your data for lightning fast search, fine‑tuned relevancy, and powerful analytics that scale with ease. This example will show you how to connect to and use Elasticsearch as your search backend for your Next.js app. + +If you want to learn more about Elasticsearch, visit the following pages: + +- [Elastic Stack](https://https://www.elastic.co/products) +- [Elastic Documentation](https://elastic.co/docs) + +## Deploy your own + +Once you have access to the environment variables you'll need, deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-elasticsearch&project-name=with-elasticsearch&repository-name=with-elasticsearch&env=ESS_CLOUD_ID,ESS_CLOUD_USERNAME,ESS_CLOUD_PASSWORD&envDescription=Required%20to%20connect%20the%20app%20with%Elasticsearch) + +## How to use + +Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: + +```bash +npx create-next-app --example with-elasticsearch with-elasticsearch-app +# or +yarn create next-app --example with-elasticsearch with-elasticsearch-app +``` + +## Configuration + +### Set up Elasticsearch + +Set up a Elasticsearch either locally or with [Elastic Cloud for free](https://elastic.co/cloud). + +### Set up environment variables + +Copy the `env.local.example` file in this directory to `.env.local` (which will be ignored by Git): + +```bash +cp .env.local.example .env.local +``` + +Set each variable on `.env.local`: + +- `ESS_CLOUD_ID` - URL for the Elasticsearch instance, if you are using [Elastic Cloud](https://elastic.co/cloud) you can find this in the Elastic Cloud console. +- `ESS_CLOUD_USERNAME` - The username for the Elasticsearch instance you have created, if you are using default user it would be `elastic`. +- `ESS_CLOUD_PASSWORD` - Password for the Elasticsearch instance + +### Run Next.js in development mode + +```bash +npm install +npm run dev + +# or + +yarn install +yarn dev +``` + +Your app should be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/vercel/next.js/discussions). + +Please ensure that you have configured the env variables in the `.env.local`, if not you will see the message "You are not connected to Elasticsearch!" in the main page. + +If you see that you are connected, you can refer to the [Elasticsearch NodeJS language client docs](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html) for further instructions on querying Elasticsearch. + +## Deploy on Vercel + +You can deploy this app to the cloud with [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). + +#### Deploy Your Local Project + +To deploy your local project to Vercel, push it to GitHub/GitLab/Bitbucket and [import to Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example). + +**Important**: When you import your project on Vercel, make sure to click on **Environment Variables** and set them to match your `.env.local` file. + +#### Deploy from Our Template + +Alternatively, you can deploy using our template by clicking on the Deploy button below. + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-elasticsearch&project-name=with-elasticsearch&repository-name=with-elasticsearch&env=ESS_CLOUD_ID,ESS_CLOUD_USERNAME,ESS_CLOUD_PASSWORD&envDescription=Required%20to%20connect%20the%20app%20with%20Elasticsearch) diff --git a/examples/with-elasticsearch/lib/elasticsearch.js b/examples/with-elasticsearch/lib/elasticsearch.js new file mode 100644 index 00000000000000..cd5e21661c2189 --- /dev/null +++ b/examples/with-elasticsearch/lib/elasticsearch.js @@ -0,0 +1,21 @@ +import { Client } from '@elastic/elasticsearch' + +export async function connectToElasticsearch() { + const ESS_CLOUD_ID = process.env.ESS_CLOUD_ID + const ESS_CLOUD_USERNAME = process.env.ESS_CLOUD_USERNAME + const ESS_CLOUD_PASSWORD = process.env.ESS_CLOUD_PASSWORD + + if (!ESS_CLOUD_ID || !ESS_CLOUD_USERNAME || !ESS_CLOUD_PASSWORD) { + return 'ERR_ENV_NOT_DEFINED' + } + + return new Client({ + cloud: { + id: ESS_CLOUD_ID, + }, + auth: { + username: ESS_CLOUD_USERNAME, + password: ESS_CLOUD_PASSWORD, + }, + }) +} diff --git a/examples/with-elasticsearch/package.json b/examples/with-elasticsearch/package.json new file mode 100644 index 00000000000000..dba769002bf1b8 --- /dev/null +++ b/examples/with-elasticsearch/package.json @@ -0,0 +1,15 @@ +{ + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@elastic/elasticsearch": "^7.14.0", + "next": "latest", + "react": "^17.0.2", + "react-dom": "^17.0.2" + } +} diff --git a/examples/with-elasticsearch/pages/_app.js b/examples/with-elasticsearch/pages/_app.js new file mode 100644 index 00000000000000..58ec64709d8610 --- /dev/null +++ b/examples/with-elasticsearch/pages/_app.js @@ -0,0 +1,7 @@ +import '../styles/globals.css' + +function MyElasticsearchApp({ Component, pageProps }) { + return +} + +export default MyElasticsearchApp diff --git a/examples/with-elasticsearch/pages/index.js b/examples/with-elasticsearch/pages/index.js new file mode 100644 index 00000000000000..2a4a49573b13be --- /dev/null +++ b/examples/with-elasticsearch/pages/index.js @@ -0,0 +1,90 @@ +import Head from 'next/head' +import Image from 'next/image' +import styles from '../styles/Home.module.css' +import { connectToElasticsearch } from '../lib/elasticsearch' + +export default function Home({ isConnected }) { + return ( +
+ + Create Next App + + + + +
+

+ Welcome to{' '} + Next.js with Elasticsearch! +

+ {isConnected ? ( +
You are connected to Elasticsearch
+ ) : ( +
+ You are NOT connected to Elasticsearch. Check the{' '} + README.md for instructions. +
+ )} + +

+ Get started by editing{' '} + pages/index.js +

+ + +
+ + +
+ ) +} + +export async function getServerSideProps(context) { + let isConnected = false + const client = await connectToElasticsearch() + if (client !== 'ERR_ENV_NOT_DEFINED') { + isConnected = true + } + return { + props: { isConnected }, + } +} diff --git a/examples/with-elasticsearch/public/favicon.ico b/examples/with-elasticsearch/public/favicon.ico new file mode 100644 index 00000000000000..4965832f2c9b06 Binary files /dev/null and b/examples/with-elasticsearch/public/favicon.ico differ diff --git a/examples/with-elasticsearch/public/vercel.svg b/examples/with-elasticsearch/public/vercel.svg new file mode 100644 index 00000000000000..fbf0e25a651c28 --- /dev/null +++ b/examples/with-elasticsearch/public/vercel.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/examples/with-elasticsearch/styles/Home.module.css b/examples/with-elasticsearch/styles/Home.module.css new file mode 100644 index 00000000000000..35454bb748190d --- /dev/null +++ b/examples/with-elasticsearch/styles/Home.module.css @@ -0,0 +1,121 @@ +.container { + min-height: 100vh; + padding: 0 0.5rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: 100vh; +} + +.main { + padding: 5rem 0; + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.footer { + width: 100%; + height: 100px; + border-top: 1px solid #eaeaea; + display: flex; + justify-content: center; + align-items: center; +} + +.footer a { + display: flex; + justify-content: center; + align-items: center; + flex-grow: 1; +} + +.title a { + color: #0070f3; + text-decoration: none; +} + +.title a:hover, +.title a:focus, +.title a:active { + text-decoration: underline; +} + +.title { + margin: 0; + line-height: 1.15; + font-size: 4rem; +} + +.title, +.description { + text-align: center; +} + +.description { + line-height: 1.5; + font-size: 1.5rem; +} + +.code { + background: #fafafa; + border-radius: 5px; + padding: 0.75rem; + font-size: 1.1rem; + font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, + Bitstream Vera Sans Mono, Courier New, monospace; +} + +.grid { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + max-width: 800px; + margin-top: 3rem; +} + +.card { + margin: 1rem; + padding: 1.5rem; + text-align: left; + color: inherit; + text-decoration: none; + border: 1px solid #eaeaea; + border-radius: 10px; + transition: color 0.15s ease, border-color 0.15s ease; + width: 45%; +} + +.card:hover, +.card:focus, +.card:active { + color: #0070f3; + border-color: #0070f3; +} + +.card h2 { + margin: 0 0 1rem 0; + font-size: 1.5rem; +} + +.card p { + margin: 0; + font-size: 1.25rem; + line-height: 1.5; +} + +.logo { + height: 1em; + margin-left: 0.5rem; +} + +@media (max-width: 600px) { + .grid { + width: 100%; + flex-direction: column; + } +} diff --git a/examples/with-elasticsearch/styles/globals.css b/examples/with-elasticsearch/styles/globals.css new file mode 100644 index 00000000000000..e5e2dcc23baf19 --- /dev/null +++ b/examples/with-elasticsearch/styles/globals.css @@ -0,0 +1,16 @@ +html, +body { + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, + Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; +} + +a { + color: inherit; + text-decoration: none; +} + +* { + box-sizing: border-box; +} diff --git a/examples/with-eslint/README.md b/examples/with-eslint/README.md index 5d950e77522720..e5be81bf47745b 100644 --- a/examples/with-eslint/README.md +++ b/examples/with-eslint/README.md @@ -21,9 +21,9 @@ Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_mediu Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: ```bash -npx create-next-app --example with-eslint with-eslint +npx create-next-app --example with-eslint with-eslint-app # or -yarn create next-app --example with-eslint with-eslint +yarn create next-app --example with-eslint with-eslint-app ``` Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). diff --git a/examples/with-jest/.eslintrc.json b/examples/with-jest/.eslintrc.json new file mode 100644 index 00000000000000..4f67f8cbc08db1 --- /dev/null +++ b/examples/with-jest/.eslintrc.json @@ -0,0 +1,15 @@ +{ + "root": true, + "extends": ["next/core-web-vitals"], + "plugins": ["testing-library"], + "overrides": [ + // Only uses Testing Library lint rules in test files + { + "files": [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[jt]s?(x)" + ], + "extends": ["plugin:testing-library/react"] + } + ] +} diff --git a/examples/with-jest/__tests__/index.test.jsx b/examples/with-jest/__tests__/index.test.jsx new file mode 100644 index 00000000000000..b2fc240afb8f69 --- /dev/null +++ b/examples/with-jest/__tests__/index.test.jsx @@ -0,0 +1,19 @@ +/** + * @jest-environment jsdom + */ + +import React from 'react' +import { render, screen } from '@testing-library/react' +import Home from '../pages/index' + +describe('Home', () => { + it('renders a heading', () => { + render() + + const heading = screen.getByRole('heading', { + name: /welcome to next\.js!/i, + }) + + expect(heading).toBeInTheDocument() + }) +}) diff --git a/examples/with-jest/__tests__/testing-library.js b/examples/with-jest/__tests__/testing-library.js deleted file mode 100644 index 333e1cb9fe622e..00000000000000 --- a/examples/with-jest/__tests__/testing-library.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react' -import { render } from '@testing-library/react' -import Index from '../pages/index' - -describe('App', () => { - it('renders a heading', () => { - const { getByRole } = render() - - const heading = getByRole('heading', { - name: /welcome to next\.js!/i, - }) - - expect(heading).toBeInTheDocument() - }) -}) diff --git a/examples/with-jest/package.json b/examples/with-jest/package.json index a208d0c205f4f2..eb77b739d3e5ea 100644 --- a/examples/with-jest/package.json +++ b/examples/with-jest/package.json @@ -2,6 +2,7 @@ "private": true, "scripts": { "dev": "next dev", + "lint": "next lint", "build": "next build", "start": "next start", "test": "jest --watch", @@ -13,11 +14,15 @@ "react-dom": "^17.0.2" }, "devDependencies": { - "@testing-library/jest-dom": "^5.1.0", - "@testing-library/react": "^9.4.0", - "babel-jest": "^25.1.0", - "identity-obj-proxy": "^3.0.0", - "jest": "^25.1.0", - "react-test-renderer": "^17.0.2" + "@testing-library/jest-dom": "5.14.1", + "@testing-library/react": "12.0.0", + "@testing-library/user-event": "13.2.1", + "babel-jest": "27.0.6", + "eslint": "7.32.0", + "eslint-config-next": "latest", + "eslint-plugin-testing-library": "4.11.0", + "identity-obj-proxy": "3.0.0", + "jest": "27.0.6", + "react-test-renderer": "17.0.2" } } diff --git a/examples/with-mongodb/.env.local.example b/examples/with-mongodb/.env.local.example index 0bc8a2ce22f984..9dead415dc211a 100644 --- a/examples/with-mongodb/.env.local.example +++ b/examples/with-mongodb/.env.local.example @@ -1,2 +1 @@ -MONGODB_URI= -MONGODB_DB= \ No newline at end of file +MONGODB_URI= \ No newline at end of file diff --git a/examples/with-mongodb/README.md b/examples/with-mongodb/README.md index 77add3af3cb0ea..12db73e8f41fd0 100644 --- a/examples/with-mongodb/README.md +++ b/examples/with-mongodb/README.md @@ -11,7 +11,7 @@ If you want to learn more about MongoDB, visit the following pages: Once you have access to the environment variables you'll need, deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-mongodb&project-name=with-mongodb&repository-name=with-mongodb&env=MONGODB_URI,MONGODB_DB&envDescription=Required%20to%20connect%20the%20app%20with%20MongoDB) +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-mongodb&project-name=with-mongodb&repository-name=with-mongodb&env=MONGODB_URI&envDescription=Required%20to%20connect%20the%20app%20with%20MongoDB) ## How to use @@ -40,7 +40,6 @@ cp .env.local.example .env.local Set each variable on `.env.local`: - `MONGODB_URI` - Your MongoDB connection string. If you are using [MongoDB Atlas](https://mongodb.com/atlas) you can find this by clicking the "Connect" button for your cluster. -- `MONGODB_DB` - The name of the MongoDB database you want to use. ### Run Next.js in development mode @@ -56,7 +55,7 @@ yarn dev Your app should be up and running on [http://localhost:3000](http://localhost:3000)! If it doesn't work, post on [GitHub discussions](https://github.com/vercel/next.js/discussions). -You will either see a message stating "You are connected to MongoDB" or "You are NOT connected to MongoDB". Ensure that you have provided the correct `MONGODB_URI` and `MONGODB_DB` environment variables. +You will either see a message stating "You are connected to MongoDB" or "You are NOT connected to MongoDB". Ensure that you have provided the correct `MONGODB_URI` environment variable. When you are successfully connected, you can refer to the [MongoDB Node.js Driver docs](https://mongodb.github.io/node-mongodb-native/3.4/tutorials/collections/) for further instructions on how to query your database. diff --git a/examples/with-mongodb/lib/mongodb.js b/examples/with-mongodb/lib/mongodb.js index 12db0928f904d1..2990cffd2cac46 100644 --- a/examples/with-mongodb/lib/mongodb.js +++ b/examples/with-mongodb/lib/mongodb.js @@ -1,49 +1,32 @@ import { MongoClient } from 'mongodb' -const MONGODB_URI = process.env.MONGODB_URI -const MONGODB_DB = process.env.MONGODB_DB - -if (!MONGODB_URI) { - throw new Error( - 'Please define the MONGODB_URI environment variable inside .env.local' - ) -} - -if (!MONGODB_DB) { - throw new Error( - 'Please define the MONGODB_DB environment variable inside .env.local' - ) +const uri = process.env.MONGODB_URI +const options = { + useUnifiedTopology: true, + useNewUrlParser: true, } -/** - * Global is used here to maintain a cached connection across hot reloads - * in development. This prevents connections growing exponentially - * during API Route usage. - */ -let cached = global.mongo +let client +let clientPromise -if (!cached) { - cached = global.mongo = { conn: null, promise: null } +if (!process.env.MONGODB_URI) { + throw new Error('Please add your Mongo URI to .env.local') } -export async function connectToDatabase() { - if (cached.conn) { - return cached.conn +if (process.env.NODE_ENV === 'development') { + // In development mode, use a global variable so that the value + // is preserved across module reloads caused by HMR (Hot Module Replacement). + if (!global._mongoClientPromise) { + client = new MongoClient(uri, options) + global._mongoClientPromise = client.connect() } - - if (!cached.promise) { - const opts = { - useNewUrlParser: true, - useUnifiedTopology: true, - } - - cached.promise = MongoClient.connect(MONGODB_URI, opts).then((client) => { - return { - client, - db: client.db(MONGODB_DB), - } - }) - } - cached.conn = await cached.promise - return cached.conn + clientPromise = global._mongoClientPromise +} else { + // In production mode, it's best to not use a global variable. + client = new MongoClient(uri, options) + clientPromise = client.connect() } + +// Export a module-scoped MongoClient promise. By doing this in a +// separate module, the client can be shared across functions. +export default clientPromise diff --git a/examples/with-mongodb/pages/index.js b/examples/with-mongodb/pages/index.js index 17e3b78f7d7352..9628afb6523c74 100644 --- a/examples/with-mongodb/pages/index.js +++ b/examples/with-mongodb/pages/index.js @@ -1,5 +1,5 @@ import Head from 'next/head' -import { connectToDatabase } from '../lib/mongodb' +import clientPromise from '../lib/mongodb' export default function Home({ isConnected }) { return ( @@ -223,7 +223,13 @@ export default function Home({ isConnected }) { } export async function getServerSideProps(context) { - const { client } = await connectToDatabase() + const client = await clientPromise + + // client.db() will be the default database passed in the MONGODB_URI + // You can change the database by calling the client.db() function and specifying a database like: + // const db = client.db("myDatabase"); + // Then you can execute queries against your database like so: + // db.find({}) or any of the MongoDB Node Driver commands const isConnected = await client.isConnected() diff --git a/examples/with-stitches/package.json b/examples/with-stitches/package.json index aad336c6652ca4..866c3d09219d3b 100644 --- a/examples/with-stitches/package.json +++ b/examples/with-stitches/package.json @@ -6,7 +6,7 @@ "start": "next start" }, "dependencies": { - "@stitches/react": "latest", + "@stitches/react": "^1.0.0", "next": "latest", "react": "^17.0.2", "react-dom": "^17.0.2" diff --git a/examples/with-stitches/pages/_document.jsx b/examples/with-stitches/pages/_document.jsx index 4e2be3e7bdb262..72b213555b6958 100644 --- a/examples/with-stitches/pages/_document.jsx +++ b/examples/with-stitches/pages/_document.jsx @@ -1,6 +1,6 @@ import React from 'react' import NextDocument, { Html, Head, Main, NextScript } from 'next/document' -import { getCssString } from '../stitches.config' +import { getCssText } from '../stitches.config' export default class Document extends NextDocument { render() { @@ -9,7 +9,7 @@ export default class Document extends NextDocument {