From f26a80177533a194336e9ecdbc0c60d554b2ca50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Chopin?= Date: Wed, 18 Oct 2023 03:59:43 -0700 Subject: [PATCH] docs: update to new website (#23743) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Daniel Roe --- .github/assets/banner.png | Bin 135841 -> 0 bytes .github/assets/banner.svg | 2 +- .markdownlint.yml | 3 + .markdownlintignore | 3 + .website/.gitignore | 12 - .website/README.md | 35 - .website/app.config.ts | 14 - .website/nuxt.config.ts | 20 - .website/package.json | 14 - .website/tsconfig.json | 3 - README.md | 2 +- docs/0.index.md | 216 -- docs/1.getting-started/1.introduction.md | 75 +- docs/1.getting-started/10.deployment.md | 223 +- docs/1.getting-started/11.testing.md | 137 +- docs/1.getting-started/12.upgrade.md | 51 +- docs/1.getting-started/2.installation.md | 54 +- docs/1.getting-started/3.configuration.md | 36 +- docs/1.getting-started/3.views.md | 32 +- docs/1.getting-started/4.assets.md | 30 +- docs/1.getting-started/4.styling.md | 35 +- docs/1.getting-started/5.routing.md | 42 +- docs/1.getting-started/5.seo-meta.md | 30 +- docs/1.getting-started/5.transitions.md | 19 +- docs/1.getting-started/6.data-fetching.md | 58 +- docs/1.getting-started/7.state-management.md | 39 +- docs/1.getting-started/8.error-handling.md | 230 +- docs/1.getting-started/8.server.md | 45 +- docs/1.getting-started/9.layers.md | 31 +- docs/1.getting-started/_dir.yml | 2 +- docs/2.guide/0.index.md | 19 + docs/2.guide/1.concepts/1.auto-imports.md | 59 +- .../2.guide/1.concepts/2.vuejs-development.md | 55 +- docs/2.guide/1.concepts/3.rendering.md | 69 +- docs/2.guide/1.concepts/4.server-engine.md | 25 +- docs/2.guide/1.concepts/5.modules.md | 25 +- docs/2.guide/1.concepts/7.esm.md | 7 +- docs/2.guide/1.concepts/8.typescript.md | 57 +- docs/2.guide/1.concepts/_dir.yml | 3 +- docs/2.guide/1.concepts/index.md | 4 - docs/2.guide/2.directory-structure/0.nuxt.md | 18 +- .../2.guide/2.directory-structure/0.output.md | 18 +- .../2.guide/2.directory-structure/1.assets.md | 8 +- .../2.directory-structure/1.components.md | 451 ++- .../2.directory-structure/1.composables.md | 35 +- .../2.directory-structure/1.content.md | 65 +- .../2.directory-structure/1.layouts.md | 163 +- .../2.directory-structure/1.middleware.md | 67 +- .../2.directory-structure/1.modules.md | 10 +- .../2.directory-structure/1.node_modules.md | 8 +- docs/2.guide/2.directory-structure/1.pages.md | 55 +- .../2.directory-structure/1.plugins.md | 151 +- .../2.guide/2.directory-structure/1.public.md | 23 +- .../2.guide/2.directory-structure/1.server.md | 266 +- docs/2.guide/2.directory-structure/1.utils.md | 47 +- docs/2.guide/2.directory-structure/2.env.md | 57 +- .../2.directory-structure/2.gitignore.md | 6 +- .../2.directory-structure/2.nuxtignore.md | 16 +- .../2.directory-structure/3.app-config.md | 39 +- docs/2.guide/2.directory-structure/3.app.md | 26 +- .../2.directory-structure/3.nuxt.config.md | 28 +- .../2.directory-structure/3.package.md | 29 +- .../2.directory-structure/3.tsconfig.md | 16 +- docs/2.guide/2.directory-structure/_dir.yml | 3 +- docs/2.guide/2.directory-structure/index.md | 4 - .../1.experimental-features.md | 222 +- docs/2.guide/3.going-further/1.internals.md | 13 +- .../3.going-further/10.runtime-config.md | 73 +- .../11.nightly-release-channel.md | 28 +- docs/2.guide/3.going-further/2.hooks.md | 34 +- docs/2.guide/3.going-further/3.modules.md | 58 +- docs/2.guide/3.going-further/4.kit.md | 11 +- docs/2.guide/3.going-further/6.nuxt-app.md | 40 +- docs/2.guide/3.going-further/7.layers.md | 52 +- .../3.going-further/8.custom-routing.md | 22 +- docs/2.guide/3.going-further/9.debugging.md | 2 +- docs/2.guide/3.going-further/_dir.yml | 5 +- docs/2.guide/_dir.yml | 3 +- docs/2.guide/index.md | 4 - .../1.client-only.md | 15 +- .../1.nuxt-client-fallback.md | 25 +- .../10.nuxt-picture.md | 9 +- .../11.teleports.md | 13 +- docs/3.api/1.components/2.nuxt-page.md | 93 + .../3.nuxt-layout.md | 64 +- docs/3.api/1.components/4.nuxt-link.md | 122 + .../1.components/5.nuxt-loading-indicator.md | 42 + .../1.components/6.nuxt-error-boundary.md | 42 + docs/3.api/1.components/7.nuxt-welcome.md | 25 + .../8.nuxt-island.md | 32 +- .../9.nuxt-img.md | 7 +- docs/3.api/1.components/_dir.yml | 3 + docs/3.api/1.composables/_dir.yml | 3 - docs/3.api/1.composables/use-app-config.md | 13 - docs/3.api/1.composables/use-error.md | 37 - docs/3.api/1.composables/use-head.md | 100 - docs/3.api/1.composables/use-hydration.md | 38 - .../1.composables/use-lazy-async-data.md | 43 - docs/3.api/1.composables/use-request-url.md | 25 - docs/3.api/1.composables/use-router.md | 66 - .../1.composables/use-server-seo-meta.md | 11 - docs/3.api/1.composables/use-state.md | 35 - docs/3.api/2.components/2.nuxt-page.md | 83 - docs/3.api/2.components/4.nuxt-link.md | 122 - .../2.components/5.nuxt-loading-indicator.md | 41 - .../2.components/6.nuxt-error-boundary.md | 38 - docs/3.api/2.components/7.nuxt-welcome.md | 14 - docs/3.api/2.components/_dir.yml | 3 - docs/3.api/2.components/index.md | 5 - docs/3.api/2.composables/_dir.yml | 3 + docs/3.api/2.composables/use-app-config.md | 21 + .../use-async-data.md | 149 +- .../use-cookie.md | 64 +- docs/3.api/2.composables/use-error.md | 32 + .../use-fetch.md | 215 +- .../use-head-safe.md | 12 +- docs/3.api/2.composables/use-head.md | 69 + docs/3.api/2.composables/use-hydration.md | 36 + .../2.composables/use-lazy-async-data.md | 47 + .../use-lazy-fetch.md | 24 +- .../use-nuxt-app.md | 143 +- .../use-nuxt-data.md | 59 +- .../use-request-event.md | 15 +- .../use-request-headers.md | 17 +- docs/3.api/2.composables/use-request-url.md | 35 + .../use-route.md | 32 +- docs/3.api/2.composables/use-router.md | 92 + .../use-runtime-config.md | 41 +- .../use-seo-meta.md | 19 +- .../2.composables/use-server-seo-meta.md | 27 + docs/3.api/2.composables/use-state.md | 47 + docs/3.api/3.utils/$fetch.md | 23 +- docs/3.api/3.utils/_dir.yml | 4 +- docs/3.api/3.utils/abort-navigation.md | 14 +- docs/3.api/3.utils/add-route-middleware.md | 37 +- docs/3.api/3.utils/clear-error.md | 8 +- docs/3.api/3.utils/clear-nuxt-data.md | 14 +- docs/3.api/3.utils/clear-nuxt-state.md | 16 +- docs/3.api/3.utils/create-error.md | 25 +- docs/3.api/3.utils/define-nuxt-component.md | 15 +- .../3.utils/define-nuxt-route-middleware.md | 12 +- docs/3.api/3.utils/define-page-meta.md | 15 +- docs/3.api/3.utils/define-route-rules.md | 52 + docs/3.api/3.utils/index.md | 5 - docs/3.api/3.utils/navigate-to.md | 148 +- docs/3.api/3.utils/on-before-route-leave.md | 12 +- docs/3.api/3.utils/on-before-route-update.md | 12 +- docs/3.api/3.utils/on-nuxt-ready.md | 18 +- docs/3.api/3.utils/prefetch-components.md | 23 +- docs/3.api/3.utils/preload-components.md | 20 +- .../3.api/3.utils/preload-route-components.md | 27 +- docs/3.api/3.utils/prerender-routes.md | 12 +- docs/3.api/3.utils/refresh-nuxt-data.md | 20 +- docs/3.api/3.utils/reload-nuxt-app.md | 17 +- docs/3.api/3.utils/set-page-layout.md | 15 +- docs/3.api/3.utils/set-response-status.md | 13 +- docs/3.api/3.utils/show-error.md | 24 +- docs/3.api/3.utils/update-app-config.md | 18 +- docs/3.api/4.commands/_dir.yml | 3 + docs/3.api/{6.commands => 4.commands}/add.md | 44 +- .../{6.commands => 4.commands}/analyze.md | 11 +- .../build-module.md | 16 +- .../3.api/{6.commands => 4.commands}/build.md | 11 +- .../{6.commands => 4.commands}/cleanup.md | 10 +- docs/3.api/{6.commands => 4.commands}/dev.md | 13 +- .../{6.commands => 4.commands}/devtools.md | 12 +- .../{6.commands => 4.commands}/generate.md | 13 +- docs/3.api/{6.commands => 4.commands}/info.md | 9 +- docs/3.api/{6.commands => 4.commands}/init.md | 9 +- docs/3.api/4.commands/prepare.md | 19 + .../{6.commands => 4.commands}/preview.md | 13 +- .../{6.commands => 4.commands}/typecheck.md | 19 +- .../{6.commands => 4.commands}/upgrade.md | 9 +- docs/3.api/4.kit/_dir.yml | 3 - docs/3.api/5.advanced/_dir.yml | 2 - docs/3.api/{4.kit => 5.kit}/1.modules.md | 8 +- docs/3.api/{4.kit => 5.kit}/10.templates.md | 9 +- docs/3.api/{4.kit => 5.kit}/11.nitro.md | 15 +- docs/3.api/{4.kit => 5.kit}/12.resolving.md | 9 +- docs/3.api/{4.kit => 5.kit}/13.logging.md | 9 +- docs/3.api/{4.kit => 5.kit}/14.builder.md | 21 +- docs/3.api/{4.kit => 5.kit}/15.examples.md | 2 - docs/3.api/{4.kit => 5.kit}/2.programmatic.md | 9 +- .../3.api/{4.kit => 5.kit}/3.compatibility.md | 9 +- docs/3.api/{4.kit => 5.kit}/4.autoimports.md | 9 +- docs/3.api/{4.kit => 5.kit}/5.components.md | 11 +- docs/3.api/{4.kit => 5.kit}/6.context.md | 11 +- docs/3.api/{4.kit => 5.kit}/7.pages.md | 13 +- docs/3.api/{4.kit => 5.kit}/8.layout.md | 11 +- docs/3.api/{4.kit => 5.kit}/9.plugins.md | 13 +- docs/3.api/5.kit/_dir.yml | 3 + .../{5.advanced => 6.advanced}/1.hooks.md | 14 +- docs/3.api/6.advanced/_dir.yml | 1 + docs/3.api/6.commands/_dir.yml | 2 - docs/3.api/6.commands/prepare.md | 14 - docs/3.api/6.nuxt-config.md | 12 + docs/3.api/7.configuration/_dir.yml | 2 - docs/3.api/7.configuration/nuxt-config.md | 14 - docs/3.api/_dir.yml | 3 +- docs/3.api/index.md | 29 +- docs/5.community/1.nuxt-community.md | 210 -- docs/5.community/2.getting-help.md | 8 +- docs/5.community/3.reporting-bugs.md | 30 +- docs/5.community/4.contribution.md | 34 +- docs/5.community/5.framework-contribution.md | 180 +- docs/5.community/6.roadmap.md | 48 +- docs/5.community/7.changelog.md | 76 +- docs/5.community/_contributors.yml | 4 - docs/5.community/_dir.yml | 4 +- docs/5.community/index.md | 5 - docs/6.bridge/1.overview.md | 17 +- docs/6.bridge/10.configuration.md | 7 +- docs/6.bridge/2.typescript.md | 13 +- docs/6.bridge/3.bridge-composition-api.md | 5 +- docs/6.bridge/4.plugins-and-middleware.md | 15 +- docs/6.bridge/5.nuxt3-compatible-api.md | 15 +- docs/6.bridge/6.meta.md | 9 +- docs/6.bridge/7.runtime-config.md | 7 +- docs/6.bridge/8.nitro.md | 11 +- docs/6.bridge/9.vite.md | 11 +- docs/6.bridge/_dir.yml | 5 +- docs/7.migration/1.overview.md | 19 +- docs/7.migration/10.bundling.md | 15 +- docs/7.migration/11.server.md | 15 +- docs/7.migration/2.configuration.md | 20 +- docs/7.migration/20.module-authors.md | 19 +- docs/7.migration/3.auto-imports.md | 11 +- docs/7.migration/4.meta.md | 27 +- docs/7.migration/5.plugins-and-middleware.md | 19 +- docs/7.migration/6.pages-and-layouts.md | 106 +- docs/7.migration/7.component-options.md | 44 +- docs/7.migration/8.runtime-config.md | 18 +- docs/7.migration/_dir.yml | 3 +- docs/README.md | 4 +- docs/_dir.yml | 1 + package.json | 1 - packages/kit/src/plugin.ts | 2 +- packages/nuxt/src/core/builder.ts | 2 +- .../nuxt/src/core/external-config-files.ts | 8 +- packages/schema/src/config/common.ts | 2 +- packages/schema/src/config/experimental.ts | 22 +- packages/schema/src/config/vite.ts | 2 +- packages/schema/src/types/config.ts | 8 +- pnpm-lock.yaml | 2494 +---------------- pnpm-workspace.yaml | 1 - test/fixtures/runtime-compiler/nuxt.config.ts | 2 +- 246 files changed, 4436 insertions(+), 6591 deletions(-) delete mode 100644 .github/assets/banner.png delete mode 100755 .website/.gitignore delete mode 100755 .website/README.md delete mode 100644 .website/app.config.ts delete mode 100755 .website/nuxt.config.ts delete mode 100755 .website/package.json delete mode 100755 .website/tsconfig.json delete mode 100644 docs/0.index.md create mode 100644 docs/2.guide/0.index.md delete mode 100644 docs/2.guide/1.concepts/index.md delete mode 100644 docs/2.guide/2.directory-structure/index.md delete mode 100644 docs/2.guide/index.md rename docs/3.api/{2.components => 1.components}/1.client-only.md (56%) rename docs/3.api/{2.components => 1.components}/1.nuxt-client-fallback.md (56%) rename docs/3.api/{2.components => 1.components}/10.nuxt-picture.md (56%) rename docs/3.api/{2.components => 1.components}/11.teleports.md (78%) create mode 100644 docs/3.api/1.components/2.nuxt-page.md rename docs/3.api/{2.components => 1.components}/3.nuxt-layout.md (55%) create mode 100644 docs/3.api/1.components/4.nuxt-link.md create mode 100644 docs/3.api/1.components/5.nuxt-loading-indicator.md create mode 100644 docs/3.api/1.components/6.nuxt-error-boundary.md create mode 100644 docs/3.api/1.components/7.nuxt-welcome.md rename docs/3.api/{2.components => 1.components}/8.nuxt-island.md (57%) rename docs/3.api/{2.components => 1.components}/9.nuxt-img.md (80%) create mode 100644 docs/3.api/1.components/_dir.yml delete mode 100644 docs/3.api/1.composables/_dir.yml delete mode 100644 docs/3.api/1.composables/use-app-config.md delete mode 100644 docs/3.api/1.composables/use-error.md delete mode 100644 docs/3.api/1.composables/use-head.md delete mode 100644 docs/3.api/1.composables/use-hydration.md delete mode 100644 docs/3.api/1.composables/use-lazy-async-data.md delete mode 100644 docs/3.api/1.composables/use-request-url.md delete mode 100644 docs/3.api/1.composables/use-router.md delete mode 100644 docs/3.api/1.composables/use-server-seo-meta.md delete mode 100644 docs/3.api/1.composables/use-state.md delete mode 100644 docs/3.api/2.components/2.nuxt-page.md delete mode 100644 docs/3.api/2.components/4.nuxt-link.md delete mode 100644 docs/3.api/2.components/5.nuxt-loading-indicator.md delete mode 100644 docs/3.api/2.components/6.nuxt-error-boundary.md delete mode 100644 docs/3.api/2.components/7.nuxt-welcome.md delete mode 100644 docs/3.api/2.components/_dir.yml delete mode 100644 docs/3.api/2.components/index.md create mode 100644 docs/3.api/2.composables/_dir.yml create mode 100644 docs/3.api/2.composables/use-app-config.md rename docs/3.api/{1.composables => 2.composables}/use-async-data.md (61%) rename docs/3.api/{1.composables => 2.composables}/use-cookie.md (79%) create mode 100644 docs/3.api/2.composables/use-error.md rename docs/3.api/{1.composables => 2.composables}/use-fetch.md (57%) rename docs/3.api/{1.composables => 2.composables}/use-head-safe.md (79%) create mode 100644 docs/3.api/2.composables/use-head.md create mode 100644 docs/3.api/2.composables/use-hydration.md create mode 100644 docs/3.api/2.composables/use-lazy-async-data.md rename docs/3.api/{1.composables => 2.composables}/use-lazy-fetch.md (52%) rename docs/3.api/{1.composables => 2.composables}/use-nuxt-app.md (63%) rename docs/3.api/{1.composables => 2.composables}/use-nuxt-data.md (66%) rename docs/3.api/{1.composables => 2.composables}/use-request-event.md (50%) rename docs/3.api/{1.composables => 2.composables}/use-request-headers.md (58%) create mode 100644 docs/3.api/2.composables/use-request-url.md rename docs/3.api/{1.composables => 2.composables}/use-route.md (50%) create mode 100644 docs/3.api/2.composables/use-router.md rename docs/3.api/{1.composables => 2.composables}/use-runtime-config.md (81%) rename docs/3.api/{1.composables => 2.composables}/use-seo-meta.md (79%) create mode 100644 docs/3.api/2.composables/use-server-seo-meta.md create mode 100644 docs/3.api/2.composables/use-state.md create mode 100644 docs/3.api/3.utils/define-route-rules.md delete mode 100644 docs/3.api/3.utils/index.md create mode 100644 docs/3.api/4.commands/_dir.yml rename docs/3.api/{6.commands => 4.commands}/add.md (80%) rename docs/3.api/{6.commands => 4.commands}/analyze.md (72%) rename docs/3.api/{6.commands => 4.commands}/build-module.md (56%) rename docs/3.api/{6.commands => 4.commands}/build.md (81%) rename docs/3.api/{6.commands => 4.commands}/cleanup.md (70%) rename docs/3.api/{6.commands => 4.commands}/dev.md (90%) rename docs/3.api/{6.commands => 4.commands}/devtools.md (69%) rename docs/3.api/{6.commands => 4.commands}/generate.md (71%) rename docs/3.api/{6.commands => 4.commands}/info.md (71%) rename docs/3.api/{6.commands => 4.commands}/init.md (87%) create mode 100644 docs/3.api/4.commands/prepare.md rename docs/3.api/{6.commands => 4.commands}/preview.md (68%) rename docs/3.api/{6.commands => 4.commands}/typecheck.md (56%) rename docs/3.api/{6.commands => 4.commands}/upgrade.md (71%) delete mode 100644 docs/3.api/4.kit/_dir.yml delete mode 100644 docs/3.api/5.advanced/_dir.yml rename docs/3.api/{4.kit => 5.kit}/1.modules.md (96%) rename docs/3.api/{4.kit => 5.kit}/10.templates.md (98%) rename docs/3.api/{4.kit => 5.kit}/11.nitro.md (97%) rename docs/3.api/{4.kit => 5.kit}/12.resolving.md (97%) rename docs/3.api/{4.kit => 5.kit}/13.logging.md (85%) rename docs/3.api/{4.kit => 5.kit}/14.builder.md (95%) rename docs/3.api/{4.kit => 5.kit}/15.examples.md (99%) rename docs/3.api/{4.kit => 5.kit}/2.programmatic.md (95%) rename docs/3.api/{4.kit => 5.kit}/3.compatibility.md (96%) rename docs/3.api/{4.kit => 5.kit}/4.autoimports.md (97%) rename docs/3.api/{4.kit => 5.kit}/5.components.md (96%) rename docs/3.api/{4.kit => 5.kit}/6.context.md (95%) rename docs/3.api/{4.kit => 5.kit}/7.pages.md (97%) rename docs/3.api/{4.kit => 5.kit}/8.layout.md (93%) rename docs/3.api/{4.kit => 5.kit}/9.plugins.md (96%) create mode 100644 docs/3.api/5.kit/_dir.yml rename docs/3.api/{5.advanced => 6.advanced}/1.hooks.md (96%) create mode 100644 docs/3.api/6.advanced/_dir.yml delete mode 100644 docs/3.api/6.commands/_dir.yml delete mode 100644 docs/3.api/6.commands/prepare.md create mode 100644 docs/3.api/6.nuxt-config.md delete mode 100644 docs/3.api/7.configuration/_dir.yml delete mode 100644 docs/3.api/7.configuration/nuxt-config.md delete mode 100644 docs/5.community/1.nuxt-community.md delete mode 100644 docs/5.community/_contributors.yml delete mode 100644 docs/5.community/index.md diff --git a/.github/assets/banner.png b/.github/assets/banner.png deleted file mode 100644 index a6d77b947e783e96b4bec84e8ae8c3556a2097d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 135841 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 Xg1|!AnFC4(00000NkvXXu0mjf1QQL= diff --git a/.github/assets/banner.svg b/.github/assets/banner.svg index 9a7abed71b..25c5a7e375 100644 --- a/.github/assets/banner.svg +++ b/.github/assets/banner.svg @@ -1 +1 @@ - + diff --git a/.markdownlint.yml b/.markdownlint.yml index c1fac0779d..3894667202 100644 --- a/.markdownlint.yml +++ b/.markdownlint.yml @@ -14,3 +14,6 @@ MD033: false MD032: false MD046: style: fenced +MD034: false +MD031: false +MD007: false diff --git a/.markdownlintignore b/.markdownlintignore index 76059468f3..4b7de8a82a 100644 --- a/.markdownlintignore +++ b/.markdownlintignore @@ -3,3 +3,6 @@ docs/0.index.md docs/1.getting-started/1.introduction.md docs/**/*.nuxt.config.md +docs/5.community/7.changelog.md +docs/1.getting-started/10.deployment.md +docs/2.guide/1.concepts/3.rendering.md diff --git a/.website/.gitignore b/.website/.gitignore deleted file mode 100755 index 69f6b69d07..0000000000 --- a/.website/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -node_modules -*.iml -.idea -*.log* -.nuxt -.vscode -.DS_Store -coverage -dist -sw.* -.env -.output diff --git a/.website/README.md b/.website/README.md deleted file mode 100755 index 197a0d921a..0000000000 --- a/.website/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# Nuxt Docs Website - -This is a temporary directory until we open source the repository for nuxt.com. - -The goal is to simplify the contribution in the meantime to the documentation by having the possibility to preview the changes locally. - -## Setup - -Install dependencies in the root of the `nuxt` folder: - -```bash -pnpm i -``` - -Then stub the dependencies: - -```bash -pnpm build:stub -``` - -## Development - -In the root of the `nuxt` folder, run: - -```bash -pnpm docs:dev -``` - -Then open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -Update the documentation within the `docs` folder. - ---- - -For a detailed explanation of how things work, check out [Docus](https://docus.dev). diff --git a/.website/app.config.ts b/.website/app.config.ts deleted file mode 100644 index 9692072acb..0000000000 --- a/.website/app.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -export default defineAppConfig({ - docus: { - title: 'Nuxt Docs [dev]', - description: 'The best place to start your documentation.', - socials: { - twitter: 'nuxt_js', - github: 'nuxt/nuxt' - }, - aside: { - level: 1, - collapsed: false, - }, - } -}) diff --git a/.website/nuxt.config.ts b/.website/nuxt.config.ts deleted file mode 100755 index 8de14298ae..0000000000 --- a/.website/nuxt.config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { createResolver } from 'nuxt/kit' - -const { resolve } = createResolver(import.meta.url) - -export default defineNuxtConfig({ - // https://github.com/nuxt-themes/docus - extends: '@nuxt-themes/docus', - content: { - sources: { - docs: { - driver: 'fs', - prefix: '/', - base: resolve('../docs') - } - } - }, - experimental: { - renderJsonPayloads: false - } -}) diff --git a/.website/package.json b/.website/package.json deleted file mode 100755 index 3cb01d7ff8..0000000000 --- a/.website/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "docus-starter", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "nuxt dev", - "build": "nuxt build", - "generate": "nuxt generate", - "preview": "nuxt preview" - }, - "devDependencies": { - "@nuxt-themes/docus": "1.15.0" - } -} diff --git a/.website/tsconfig.json b/.website/tsconfig.json deleted file mode 100755 index 4b34df1571..0000000000 --- a/.website/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "./.nuxt/tsconfig.json" -} diff --git a/README.md b/README.md index 488fc275cf..9b6f314534 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Here are a few ways you can get involved: ## Local Development -Follow the docs to [Set Up Your Local Development Environment](https://nuxt.com/docs/community/framework-contribution#set-up-your-local-development-environment) to contribute to the framework and documentation. +Follow the docs to [Set Up Your Local Development Environment](https://nuxt.com/docs/community/framework-contribution#setup) to contribute to the framework and documentation. ## Nuxt 2 diff --git a/docs/0.index.md b/docs/0.index.md deleted file mode 100644 index db35c15b03..0000000000 --- a/docs/0.index.md +++ /dev/null @@ -1,216 +0,0 @@ ---- -title: Documentation -navigation: false -description: Learn everything you need to know about Nuxt, from beginner to master. ---- - - - -::docs-hero -#title -Nuxt Docs -#description -Nuxt is a free and [open-source framework](https://github.com/nuxt/nuxt) with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with [Vue.js](https://vuejs.org). -:: - -::card-item{ .mt-4 } ---- -is: 'div' -gradientBorder: false -descriptionClass: 'w-full sm:w-2/3' -buttonsWrapperClass: 'pr-[100px] sm:pr-0' -backgroundImage: - path: '/assets/docs/getting-started/views/getting-started' - width: '100' - height: '100' - format: 'png' -buttons: - - label: 'Get started' - size: 'sm' - variant: 'primary-gradient' - to: '/docs/getting-started/introduction' - - label: 'Explore Examples' - size: 'sm' - variant: 'secondary' - to: '/docs/examples/hello-world' ---- -#title -Getting Started -#description -Start by learning Nuxt core features, from installation to deployment. -:: - - - -::docs-landing-section -#title -Guide -#description -From an idea to a masterpiece, guides take you on the path to becoming a Nuxter. -#extra - ::card-list - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/key-concepts' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/guide/concepts/auto-imports' - --- - #title - Key Concepts - #description - Get an overview of the concepts that drive the Nuxt experience. - ::: - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/directory-structure' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/guide/directory-structure/nuxt' - --- - #title - Directory Structure - #description - Navigate Nuxt directory structure with this handy guide. - ::: - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/going-further' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/guide/going-further/internals' - --- - #title - Going further - #description - Deep dive into Nuxt internals to master all the features. - ::: - :: -:: - -::docs-landing-section -#title -API -#description -Every Nuxt component, composable and utility, in detail. -#extra - ::card-list - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/composables' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/api/composables/use-app-config' - --- - #title - Composables - #description - From data fetching to error handling, get familiar with Nuxt built-in composables. - ::: - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/components' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/api/components/client-only' - --- - #title - Components - #description - Nuxt components, auto-imported and ready to use in your application. - ::: - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/utils' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/api/utils/dollarfetch' - --- - #title - Utils - #description - Use utility functions to get fine-grained control over your app behavior. - ::: - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/advanced' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/api/advanced/hooks' - --- - #title - Advanced - #description - Learn about lifecycle hooks and Kit utilities in the advanced section. - ::: - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/commands' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/api/commands/add' - --- - #title - Commands - #description - Meet Nuxi, Nuxt 3 command-line tool. The essential companion in your journey. - ::: - :::card-item - --- - gradientBorder: false - headerClass: 'justify-start px-4 pt-4 sm:px-6' - image: - path: '/assets/docs/getting-started/views/docs-landing/configuration' - width: '52' - height: '58' - format: 'svg' - contentClass: 'gap-y-2' - to: '/docs/api/configuration/nuxt-config' - --- - #title - Configuration - #description - Master the Nuxt config file to customize the framework behavior. - ::: - :: -:: diff --git a/docs/1.getting-started/1.introduction.md b/docs/1.getting-started/1.introduction.md index 4503a53691..1337e7187b 100644 --- a/docs/1.getting-started/1.introduction.md +++ b/docs/1.getting-started/1.introduction.md @@ -1,21 +1,19 @@ --- -navigation.icon: uil:info-circle +title: 'Introduction' description: Nuxt's goal is to make web development intuitive and performant with a great Developer Experience in mind. +navigation.icon: i-ph-info-duotone --- -# Introduction - Nuxt is a free and [open-source framework](https://github.com/nuxt/nuxt) with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with [Vue.js](https://vuejs.org). We made everything so you can start writing `.vue` files from the beginning while enjoying hot module replacement in development and a performant application in production with server-side rendering by default. -Nuxt has no vendor lock-in, allowing you to deploy your application [**anywhere, even to the edge**](/docs/getting-started/deployment). +Nuxt has no vendor lock-in, allowing you to deploy your application [**everywhere, even on the edge**](/blog/nuxt-on-the-edge). ## Automation and Conventions Nuxt uses conventions and an opinionated directory structure to automate repetitive tasks and allow developers to focus on pushing features. The configuration file can still customize and override its default behaviors. -::list{type=success} - **File-based routing:** define routes based on the structure of your [`pages/` directory](/docs/guide/directory-structure/pages). This can make it easier to organize your application and avoid the need for manual route configuration. - **Code splitting:** Nuxt automatically splits your code into smaller chunks, which can help reduce the initial load time of your application. - **Server-side rendering out of the box:** Nuxt comes with built-in SSR capabilities, so you don't have to set up a separate server yourself. @@ -23,7 +21,6 @@ Nuxt uses conventions and an opinionated directory structure to automate repetit - **Data-fetching utilities:** Nuxt provides composables to handle SSR-compatible data fetching as well as different strategies. - **Zero-config TypeScript support:** write type-safe code without having to learn TypeScript with our auto-generated types and `tsconfig.json` - **Configured build tools:** we use [Vite](https://vitejs.dev) by default to support hot module replacement (HMR) in development and bundling your code for production with best-practices baked-in. -:: Nuxt takes care of these and provides both frontend and backend functionality so you can focus on what matters: **creating your web application**. @@ -31,22 +28,18 @@ Nuxt takes care of these and provides both frontend and backend functionality so Nuxt comes with built-in server-side rendering (SSR) capabilities by default, without having to configure a server yourself, which has many benefits for web applications: -::list{type=success} - **Faster initial page load time:** Nuxt sends a fully rendered HTML page to the browser, which can be displayed immediately. This can provide a faster perceived page load time and a better user experience (UX), especially on slower networks or devices. - **Improved SEO:** search engines can better index SSR pages because the HTML content is available immediately, rather than requiring JavaScript to render the content on the client-side. - **Better performance on low-powered devices:** it reduces the amount of JavaScript that needs to be downloaded and executed on the client-side, which can be beneficial for low-powered devices that may struggle with processing heavy JavaScript applications. - **Better accessibility:** the content is immediately available on the initial page load, improving accessibility for users who rely on screen readers or other assistive technologies. - **Easier caching:** pages can be cached on the server-side, which can further improve performance by reducing the amount of time it takes to generate and send the content to the client. -:: Overall, server-side rendering can provide a faster and more efficient user experience, as well as improve search engine optimization and accessibility. As Nuxt is a versatile framework, it gives you the possibility to statically render your whole application to a static hosting with `nuxt generate`, disable SSR globally with the `ssr: false` option or leverage hybrid rendering by setting up the `routeRules` option. -::alert{type="info"} -Read more about the [Nuxt rendering modes](/docs/guide/concepts/rendering). -:: +:read-more{title="Nuxt rendering modes" to="/docs/guide/concepts/rendering"} ### Server engine @@ -56,84 +49,30 @@ In development, it uses Rollup and Node.js workers for your server code and cont In production, Nitro builds your app and server into one universal `.output` directory. This output is light: minified and removed from any Node.js modules (except polyfills). You can deploy this output on any system supporting JavaScript, from Node.js, Serverless, Workers, Edge-side rendering or purely static. -::alert{type="info"} -Read more about [Nuxt server engine](/docs/guide/concepts/server-engine). -:: +:read-more{title="Nuxt server engine" to="/docs/guide/concepts/server-engine"} ### Production-ready A Nuxt application can be deployed on a Node or Deno server, pre-rendered to be hosted in static environments, or deployed to serverless and edge providers. -::alert{type="info"} -Discover more in the [deployment section](/docs/getting-started/deployment). -:: +:read-more{title="Deployment section" to="/docs/getting-started/deployment"} ### Modular A module system allows to extend Nuxt with custom features and integrations with third-party services. -::alert{type="info"} -Discover more about [modules](/docs/guide/concepts/modules). -:: +:read-more{title="Nuxt Modules Concept" to="/docs/guide/concepts/modules"} ### Architecture Nuxt is composed of different [core packages](https://github.com/nuxt/nuxt/tree/main/packages): -::list{type=info} - Core Engine: [nuxt](https://github.com/nuxt/nuxt/tree/main/packages/nuxt) - Bundlers: [@nuxt/vite-builder](https://github.com/nuxt/nuxt/tree/main/packages/vite) and [@nuxt/webpack-builder](https://github.com/nuxt/nuxt/tree/main/packages/webpack) - Command line interface: [nuxi](https://github.com/nuxt/nuxt/tree/main/packages/nuxi) - Server engine: [nitro](https://github.com/unjs/nitro) - Development kit: [@nuxt/kit](https://github.com/nuxt/nuxt/tree/main/packages/kit) - Nuxt 2 Bridge: [@nuxt/bridge](https://github.com/nuxt/bridge) -:: We recommend reading each concept to have a full vision of Nuxt capabilities and the scope of each package. -::card-list ---- -cardListClass: 'grid grid-cols-1 gap-y-4' ---- - :::card-item - --- - gradientBorder: false - backgroundImage: - path: '/assets/docs/getting-started/views/are-you-nuxt' - width: '72px' - height: '92px' - format: 'png' - titleClass: 'text-5xl font-semibold u-text-gray-900 pb-2' - descriptionClass: 'md:mr-[64px] w-[90%]' - --- - #title - Are you Nuxt? - #description - Nuxt is the backbone of your Vue.js project, giving structure to build your project with confidence while keeping flexibility. -
-
- Extendable with a strong module ecosystem and hooks engine, it makes it easy to connect your REST or GraphQL endpoints, favorite CMS, CSS frameworks and more. PWA and AMP support is only a module away from your Nuxt project. -
-
- Ready to try? Head over to the [Installation section](/docs/getting-started/installation). - ::: - - :::card-item - --- - gradientBorder: false - backgroundImage: - path: '/assets/docs/getting-started/views/contribute' - width: '72' - height: '92' - format: 'png' - titleClass: 'text-2xl u-text-gray-900 font-semibold' - descriptionClass: 'md:mr-[64px]' - --- - #title - Contribute - #description - Do you want to get involved in the evolution of Nuxt? -
- Follow the [contribution guide](/docs/community/contribution). - ::: -:: diff --git a/docs/1.getting-started/10.deployment.md b/docs/1.getting-started/10.deployment.md index 672d1c5f65..a0bfbff5c9 100644 --- a/docs/1.getting-started/10.deployment.md +++ b/docs/1.getting-started/10.deployment.md @@ -1,50 +1,40 @@ --- -navigation.icon: uil:rocket -description: Deploy on a Node.js server, pre-render for static hosting and to serverless or edge environments. +title: 'Deployment' +description: Learn how to deploy your Nuxt application to any hosting provider. +navigation.icon: i-ph-cloud-duotone --- -# Deployment - A Nuxt application can be deployed on a Node.js server, pre-rendered for static hosting, or deployed to serverless or edge (CDN) environments. -::alert{type=info} -If you are looking for a list of cloud providers that support Nuxt 3, see the [list below](#supported-hosting-providers). +::callout +If you are looking for a list of cloud providers that support Nuxt 3, see the [Hosting providers](#hosting-providers) section. :: ## Node.js Server Discover the Node.js server preset with Nitro to deploy on any Node hosting. -::list{type="success"} - **Default output format** if none is specified or auto-detected
- Loads only the required chunks to render the request for optimal cold start timing
- Useful for deploying Nuxt apps to any Node.js hosting -:: ### Entry Point When running `nuxt build` with the Node server preset, the result will be an entry point that launches a ready-to-run Node server. -```bash +```bash [Terminal] node .output/server/index.mjs ``` -### Example +This will launch your production Nuxt server that listens on port 3000 by default. -```bash -$ node .output/server/index.mjs -Listening on http://localhost:3000 -``` - -### Configuring Defaults at Runtime - -This preset will respect the following runtime environment variables: +It respects the following runtime environment variables: - `NITRO_PORT` or `PORT` (defaults to `3000`) - `NITRO_HOST` or `HOST` (defaults to `'0.0.0.0'`) - `NITRO_SSL_CERT` and `NITRO_SSL_KEY` - if both are present, this will launch the server in HTTPS mode. In the vast majority of cases, this should not be used other than for testing, and the Nitro server should be run behind a reverse proxy like nginx or Cloudflare which terminates SSL. -#### Using PM2 +### PM2 To use `pm2`, use an `ecosystem.config.js`: @@ -62,7 +52,7 @@ module.exports = { } ``` -#### Using Cluster Mode +### Cluster Mode You can use `NITRO_PRESET=node_cluster` in order to leverage multi-process performance using Node.js [cluster](https://nodejs.org/dist/latest/docs/api/cluster.html) module. @@ -70,20 +60,20 @@ By default, the workload gets distributed to the workers with the round robin st ### Learn More -:ReadMore{link="https://nitro.unjs.io/deploy/node" title="the Nitro documentation for node-server preset"} +:read-more{to="https://nitro.unjs.io/deploy/node" title="the Nitro documentation for node-server preset"} ## Static Hosting There are two ways to deploy a Nuxt application to any static hosting services: - Static site generation (SSG) with `ssr: true` pre-renders routes of your application at build time. (This is the default behavior when running `nuxi generate`.) It will also generate `/200.html` and `/404.html` single-page app fallback pages, which can render dynamic routes or 404 errors on the client (though you may need to configure this on your static host). -- Alternatively, you can prerender your site with `ssr: false` (static single-page app). This will produce HTML pages with an empty `

` where your Vue app would normally be rendered. You will lose many of the benefits of prerendering your site, so it is suggested instead to use `` to wrap the portions of your site that cannot be server rendered (if any). +- Alternatively, you can prerender your site with `ssr: false` (static single-page app). This will produce HTML pages with an empty `
` where your Vue app would normally be rendered. You will lose many SEO benefits of prerendering your site, so it is suggested instead to use [``](/docs/api/components/client-only) to wrap the portions of your site that cannot be server rendered (if any). ### Crawl-based Pre-rendering Use the [`nuxi generate` command](/docs/api/commands/generate) to build and pre-render your application using the [Nitro](/docs/guide/concepts/server-engine) crawler. This command is similar to `nuxt build` with the `nitro.static` option set to `true`, or running `nuxt build --prerender`. -```bash +```bash [Terminal] npx nuxi generate ``` @@ -98,15 +88,15 @@ Working of the Nitro crawler: This is important to understand since pages that are not linked to a discoverable page can't be pre-rendered automatically. -::alert{type=info} -Read more about the [`nuxi generate` command](/docs/api/commands/generate#nuxi-generate). +::read-more{to="/docs/api/commands/generate#nuxi-generate"} +Read more about the `nuxi generate` command. :: ### Selective Pre-rendering You can manually specify routes that [Nitro](/docs/guide/concepts/server-engine) will fetch and pre-render during the build or ignore routes that you don't want to pre-render like `/dynamic` in the `nuxt.config` file: -```ts [nuxt.config.ts|js] +```ts [nuxt.config.ts] defineNuxtConfig({ nitro: { prerender: { @@ -119,7 +109,7 @@ defineNuxtConfig({ You can combine this with the `crawLinks` option to pre-render a set of routes that the crawler can't discover like your `/sitemap.xml` or `/robots.txt`: -```ts [nuxt.config.ts|js] +```ts [nuxt.config.ts] defineNuxtConfig({ nitro: { prerender: { @@ -132,27 +122,178 @@ defineNuxtConfig({ Setting `nitro.prerender` to `true` is similar to `nitro.prerender.crawlLinks` to `true`. -::alert{type=info} -Read more about [pre-rendering](https://nitro.unjs.io/config#prerender) in the Nitro documentation. +::read-more{to="https://nitro.unjs.io/config#prerender"} +Read more about pre-rendering in the Nitro documentation. :: ### Client-side Only Rendering If you don't want to pre-render your routes, another way of using static hosting is to set the `ssr` property to `false` in the `nuxt.config` file. The `nuxi generate` command will then output an `.output/public/index.html` entrypoint and JavaScript bundles like a classic client-side Vue.js application. -```ts [nuxt.config.ts|js] +```ts [nuxt.config.ts] defineNuxtConfig({ ssr: false }) ``` +## Hosting Providers + +Nuxt 3 can be deployed to several cloud providers with a minimal amount of configuration: + +::card-group + ::card + --- + title: AWS + icon: i-simple-icons-amazonaws + to: https://nitro.unjs.io/deploy/providers/aws + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Azure + icon: i-simple-icons-microsoftazure + to: https://nitro.unjs.io/deploy/providers/azure + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Cleavr + icon: i-ph-cloud-duotone + to: https://nitro.unjs.io/deploy/providers/cleavr + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Deno + icon: i-simple-icons-deno + to: https://nitro.unjs.io/deploy/providers/deno + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: CloudFlare + icon: i-simple-icons-cloudflare + to: https://nitro.unjs.io/deploy/providers/cloudflare + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: DigitalOcean + icon: i-simple-icons-digitalocean + to: https://nitro.unjs.io/deploy/providers/digitalocean + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Edgio + icon: i-ph-cloud-duotone + to: https://nitro.unjs.io/deploy/providers/edgio + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Firebase + icon: i-simple-icons-firebase + to: https://nitro.unjs.io/deploy/providers/firebase + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Flightcontrol + icon: i-ph-cloud-duotone + to: https://nitro.unjs.io/deploy/providers/flightcontrol + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: GitHub Pages + icon: i-simple-icons-github + to: https://nitro.unjs.io/deploy/providers/github-pages + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Heroku + icon: i-simple-icons-heroku + to: https://nitro.unjs.io/deploy/providers/heroku + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Lagon + icon: i-ph-cloud-duotone + to: https://nitro.unjs.io/deploy/providers/lagon + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Netlify + icon: i-simple-icons-netlify + to: https://nitro.unjs.io/deploy/providers/netlify + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Render + icon: i-simple-icons-render + to: https://nitro.unjs.io/deploy/providers/render + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Stormkit + icon: i-ph-cloud-duotone + to: https://nitro.unjs.io/deploy/providers/stormkit + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: + ::card + --- + title: Vercel + icon: i-simple-icons-vercel + to: https://nitro.unjs.io/deploy/providers/vercel + target: _blank + ui.icon.base: 'text-black dark:text-white' + --- + :: +:: + ## Presets In addition to Node.js servers and static hosting services, a Nuxt 3 project can be deployed with several well-tested presets and minimal amount of configuration. You can explicitly set the desired preset in the [`nuxt.config`](/docs/guide/directory-structure/nuxt.config) file: -```js [nuxt.config.js|ts] +```js [nuxt.config.ts] export default { nitro: { preset: 'node-server' @@ -162,30 +303,12 @@ export default { ... or use the `NITRO_PRESET` environment variable when running `nuxt build`: -```bash +```bash [Terminal] NITRO_PRESET=node-server nuxt build ``` 🔎 Check [the Nitro deployment](https://nitro.unjs.io/deploy) for all possible deployment presets and providers. -### Supported Hosting Providers - -Nuxt 3 can be deployed to several cloud providers with a minimal amount of configuration: - -- :icon{name="logos:aws" class="h-5 w-4 inline mb-2"} [AWS](https://nitro.unjs.io/deploy/providers/aws) -- :icon{name="logos:microsoft-azure" class="h-5 w-4 inline mb-2"} [Azure](https://nitro.unjs.io/deploy/providers/azure) -- :icon{name="ph:cloud-duotone" class="h-5 w-4 inline mb-2"} [Cleavr](https://nitro.unjs.io/deploy/providers/cleavr) -- :icon{name="logos:cloudflare" class="h-5 w-4 inline mb-2"} [Cloudflare](https://nitro.unjs.io/deploy/providers/cloudflare) -- :icon{name="logos:digital-ocean" class="h-5 w-4 inline mb-2"} [DigitalOcean](https://nitro.unjs.io/deploy/providers/digitalocean) -- :icon{name="ph:cloud-duotone" class="h-5 w-4 inline mb-2"} [Edgio](https://nitro.unjs.io/deploy/providers/edgio) -- :icon{name="logos:firebase" class="h-5 w-4 inline mb-2"} [Firebase](https://nitro.unjs.io/deploy/providers/firebase) -- :icon{name="logos:heroku-icon" class="h-5 w-4 inline mb-2"} [Heroku](https://nitro.unjs.io/deploy/providers/heroku) -- :icon{name="IconLagon" class="h-5 w-4 inline mb-2 text-black dark:text-white"} [Lagon](https://nitro.unjs.io/deploy/providers/lagon) -- :icon{name="logos:netlify" class="h-5 w-4 inline mb-2"} [Netlify](https://nitro.unjs.io/deploy/providers/netlify) -- :icon{name="simple-icons:render" class="h-5 w-4 inline mb-2"} [Render](https://nitro.unjs.io/deploy/providers/render) -- :icon{name="ph:cloud-duotone" class="h-5 w-4 inline mb-2"} [Stormkit](https://nitro.unjs.io/deploy/providers/stormkit) -- :icon{name="simple-icons:vercel" class="h-5 w-4 inline mb-2 text-black dark:text-white"} [Vercel](https://nitro.unjs.io/deploy/providers/vercel) - ## CDN Proxy In most cases, Nuxt can work with third-party content that is not generated or created by Nuxt itself. But sometimes such content can cause problems, especially Cloudflare's "Minification and Security Options". diff --git a/docs/1.getting-started/11.testing.md b/docs/1.getting-started/11.testing.md index 6ae12d8375..e01cddefdf 100644 --- a/docs/1.getting-started/11.testing.md +++ b/docs/1.getting-started/11.testing.md @@ -1,12 +1,10 @@ --- -navigation.icon: uil:check-circle +title: Testing +description: How to test your Nuxt application. +navigation.icon: i-ph-check-circle-duotone --- -# Testing - -How to test your Nuxt application. - -::alert{icon=👉} +::callout Test utils are still in development and the API and behavior may change. Currently, it is in preview stage but not yet ready for testing production apps. If you are a module author, you can find more specific information in the [Module Author's guide](/docs/guide/going-further/modules#testing) :: @@ -15,15 +13,26 @@ In Nuxt 3, we have a rewritten version of `@nuxt/test-utils`. We support [Vitest ## Installation -```bash +::code-group +```bash [yarn] yarn add --dev @nuxt/test-utils vitest ``` +```bash [npm] +npm i --save-dev @nuxt/test-utils vitest +``` +```bash [pnpm] +pnpm add --dev @nuxt/test-utils vitest +``` +```bash [bun] +bun add --dev @nuxt/test-utils vitest +``` +:: ## Setup In each `describe` block where you are taking advantage of the `@nuxt/test-utils` helper methods, you will need to set up the test context before beginning. -```ts +```ts [test/my-test.spec.ts] import { describe, test } from 'vitest' import { setup, $fetch } from '@nuxt/test-utils' @@ -40,89 +49,55 @@ describe('My test', async () => { Behind the scenes, `setup` performs a number of tasks in `beforeAll`, `beforeEach`, `afterEach` and `afterAll` to set up the Nuxt test environment correctly. -## Options +Please the options below for the `setup` method. -### Nuxt Configuration +### Nuxt Config -#### `rootDir` - -Path to a directory with a Nuxt app to be put under test. - -* Type: `string` -* Default: `'.'` - -#### `configFile` - -Name of the configuration file. - -* Type: `string` -* Default: `'nuxt.config'` +- `rootDir`: Path to a directory with a Nuxt app to be put under test. + - Type: `string` + - Default: `'.'` +- `configFile`: Name of the configuration file. + - Type: `string` + - Default: `'nuxt.config'` -Object with configuration overrides. +### Timings -* Type: `NuxtConfig` -* Default: `{}` --> +- `setupTimeout`: The amount of time (in milliseconds) to allow for `setupTest` to complete its work (which could include building or generating files for a Nuxt application, depending on the options that are passed). + - Type: `number` + - Default: `60000` -### Setup Timings +### Features -#### `setupTimeout` +- `server`: Whether to launch a server to respond to requests in the test suite. + - Type: `boolean` + - Default: `true` -The amount of time (in milliseconds) to allow for `setupTest` to complete its work (which could include building or generating files for a Nuxt application, depending on the options that are passed). +- `port`: If provided, set the launched test server port to the value. + - Type: `number | undefined` + - Default: `undefined` -* Type: `number` -* Default: `60000` - -### Features to Enable - -#### `server` - -Whether to launch a server to respond to requests in the test suite. - -* Type: `boolean` -* Default: `true` - -#### `port` - -If provided, set the launched test server port to the value. - -* Type: `number | undefined` -* Default: `undefined` - -#### `build` - -Whether to run a separate build step. - -* Type: `boolean` -* Default: `true` (`false` if `browser` or `server` is disabled) - -#### `browser` - -Under the hood, Nuxt test utils uses [`playwright`](https://playwright.dev/) to carry out browser testing. If this option is set, a browser will be launched and can be controlled in the subsequent test suite. (More info can be found [here](/docs/getting-started/testing).) - -* Type: `boolean` -* Default: `false` - -#### `browserOptions` - -* Type: `object` with the following properties - * **type**: The type of browser to launch - either `chromium`, `firefox` or `webkit` - * **launch**: `object` of options that will be passed to playwright when launching the browser. See [full API reference](https://playwright.dev/docs/api/class-browsertype#browser-type-launch). - -#### `runner` - -Specify the runner for the test suite. Currently, [Vitest](https://vitest.dev/) is recommended. - -* Type: `'vitest' | 'jest'` -* Default: `'vitest'` +- `build`: Whether to run a separate build step. + - Type: `boolean` + - Default: `true` (`false` if `browser` or `server` is disabled) +- `browser`: Under the hood, Nuxt test utils uses [`playwright`](https://playwright.dev/) to carry out browser testing. If this option is set, a browser will be launched and can be controlled in the subsequent test suite. + - Type: `boolean` + - Default: `false` +- `browserOptions` + - Type: `object` with the following properties + - `type`: The type of browser to launch - either `chromium`, `firefox` or `webkit` + - `launch`: `object` of options that will be passed to playwright when launching the browser. See [full API reference](https://playwright.dev/docs/api/class-browsertype#browser-type-launch). +- `runner`: Specify the runner for the test suite. Currently, [Vitest](https://vitest.dev/) is recommended. + - Type: `'vitest' | 'jest'` + - Default: `'vitest'` ## APIs -### APIs for Rendering Testing - -#### `$fetch(url)` +### `$fetch(url)` Get the HTML of a server-rendered page. @@ -132,7 +107,7 @@ import { $fetch } from '@nuxt/test-utils' const html = await $fetch('/') ``` -#### `fetch(url)` +### `fetch(url)` Get the response of a server-rendered page. @@ -143,7 +118,7 @@ const res = await fetch('/') const { body, headers } = res ``` -#### `url(path)` +### `url(path)` Get the full URL for a given page (including the port the test server is running on.) @@ -156,6 +131,6 @@ const pageUrl = url('/page') ## Testing in a Browser -::alert{icon=🚧} +::callout We are working on it, stay tuned! :: diff --git a/docs/1.getting-started/12.upgrade.md b/docs/1.getting-started/12.upgrade.md index 3b2b459d93..99ddd7195c 100644 --- a/docs/1.getting-started/12.upgrade.md +++ b/docs/1.getting-started/12.upgrade.md @@ -1,14 +1,25 @@ --- -navigation.icon: uil:arrow-up -description: Have a Nuxt 2 project to migrate? Use these guides to upgrade your applications to Nuxt 3. +title: Upgrade Guide +description: 'Learn how to upgrade to the lastest Nuxt version.' +navigation.icon: i-ph-arrow-circle-up-duotone --- -# Upgrade Guide -Have a Nuxt 2 project to migrate? Use these guides to upgrade your Nuxt applications to Nuxt 3 or take the first step in that direction with Nuxt Bridge. -If you are already using Nuxt 3 and want to upgrade to the latest release or test new features before their release, head over to the [Upgrading Nuxt 3](#upgrading-nuxt-3) section. +## Upgrading Nuxt 3 -## Feature Comparison +### Latest release + +To upgrade Nuxt 3 to the [latest release](https://github.com/nuxt/nuxt/releases), use the `nuxi upgrade` command. + +```bash [Terminal] +npx nuxi upgrade +``` + +### Nightly Release Channel + +To use the latest Nuxt 3 build and test features before their release, read about the [nightly release channel](/docs/guide/going-further/nightly-release-channel) guide. + +## Nuxt 2 vs Nuxt 3 In the table below, there is a quick comparison between 3 versions of Nuxt: @@ -34,34 +45,14 @@ Static sites | ✅ | ✅ | ✅ The migration guide provides a step-by-step comparison of Nuxt 2 features to Nuxt 3 features and guidance to adapt your current application. -::alert{type=info} -👉 Check out the [**guide to migrating from Nuxt 2 to Nuxt 3**](/docs/migration/overview). -:: - -::alert{type=info} -:rocket: Migrate with confidence with our [official Nuxt 2 to Nuxt 3 workshop](/support/workshop). +::read-more{to="/docs/migration/overview"} +Check out the **guide to migrating from Nuxt 2 to Nuxt 3**. :: ## Nuxt 2 to Nuxt Bridge If you prefer to progressively migrate your Nuxt 2 application to Nuxt 3, you can use Nuxt Bridge. Nuxt Bridge is a compatibility layer that allows you to use Nuxt 3 features in Nuxt 2 with an opt-in mechanism. -::alert{type=info icon=👉} -[**Migrate from Nuxt 2 to Nuxt Bridge**](/docs/bridge/overview) -:: - -## Upgrading Nuxt 3 - -### Latest Release - -To upgrade Nuxt 3 to the [latest release](/docs/community/changelog), use the `nuxi upgrade` command. - -```bash -npx nuxi upgrade -``` - -### Nightly Release Channel - -::alert{type=info icon=👉} -To use the latest Nuxt 3 build and test features before their release, read about the [nightly release channel](/docs/guide/going-further/nightly-release-channel) guide. +::read-more{to="/docs/bridge/overview"} +**Migrate from Nuxt 2 to Nuxt Bridge** :: diff --git a/docs/1.getting-started/2.installation.md b/docs/1.getting-started/2.installation.md index 7c6b4cb12d..c2786e0c53 100644 --- a/docs/1.getting-started/2.installation.md +++ b/docs/1.getting-started/2.installation.md @@ -1,22 +1,20 @@ --- -navigation.icon: uil:play-circle +title: 'Installation' +description: 'Get started with Nuxt quickly with our online starters or start locally with your terminal.' +navigation.icon: i-ph-play-duotone --- -# Installation - -Get started with Nuxt quickly with our online starters or start locally with your terminal. - ## Play Online You can start playing with Nuxt 3 in your browser using our online sandboxes: -:button-link[Play on StackBlitz]{href="https://nuxt.new/s/v3" blank .mr-2} -:button-link[Play on CodeSandbox]{href="https://nuxt.new/c/v3" blank} +::card-group + :card{title="Open on StackBlitz" icon="i-simple-icons-stackblitz" to="https://nuxt.new/s/v3" target="_blank"} + :card{title="Open on CodeSandbox" icon="i-simple-icons-codesandbox" to="https://nuxt.new/c/v3" target="_blank"} +:: Start with one of our starters and themes directly by opening [nuxt.new](https://nuxt.new). -:button-link[Discover nuxt.new]{href="https://nuxt.new" blank} - ## New Project @@ -27,24 +25,23 @@ Start with one of our starters and themes directly by opening [nuxt.new](https:/ - **Text editor** - We recommend [Visual Studio Code](https://code.visualstudio.com/) with the [Volar Extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar) - **Terminal** - In order to run Nuxt commands -::alert -::details -:summary[Additional notes for an optimal setup:] -- **Node.js**: Make sure to use an even numbered version (18, 20, etc) -- **Nuxtr**: Install the community-developed [Nuxtr extension](https://marketplace.visualstudio.com/items?itemName=Nuxtr.nuxtr-vscode) -- **Volar**: Either enable [**Take Over Mode**](https://vuejs.org/guide/typescript/overview.html#volar-takeover-mode) (recommended) or add the [TypeScript Vue Plugin](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) +::callout + ::details + :summary[Additional notes for an optimal setup:] + - **Node.js**: Make sure to use an even numbered version (18, 20, etc) + - **Nuxtr**: Install the community-developed [Nuxtr extension](https://marketplace.visualstudio.com/items?itemName=Nuxtr.nuxtr-vscode) + - **Volar**: Either enable [**Take Over Mode**](https://vuejs.org/guide/typescript/overview.html#volar-takeover-mode) (recommended) or add the [TypeScript Vue Plugin](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) -If you have enabled **Take Over Mode** or installed the **TypeScript Vue Plugin (Volar)**, you can disable generating the shim for `*.vue` files in your [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt.config) file: + If you have enabled **Take Over Mode** or installed the **TypeScript Vue Plugin (Volar)**, you can disable generating the shim for `*.vue` files in your [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt.config) file: -```ts [nuxt.config.ts] -export default defineNuxtConfig({ - typescript: { - shim: false - } -}) -``` - -:: + ```ts [nuxt.config.ts] + export default defineNuxtConfig({ + typescript: { + shim: false + } + }) + ``` + :: :: Open a terminal (if you're using [Visual Studio Code](https://code.visualstudio.com/), you can open an [integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal)) and use the following command to create a new starter project: @@ -67,7 +64,7 @@ bunx nuxi@latest init Open your project folder in Visual Studio Code: -```bash +```bash [Terminal] code ``` @@ -115,10 +112,9 @@ pnpm dev -o ```bash [bun] bun run dev -o ``` - :: -::alert{type=success icon=✨ .font-bold} +::callout{icon="i-ph-check-circle-duotone"} Well done! A browser window should automatically open for . :: @@ -126,4 +122,4 @@ Well done! A browser window should automatically open for @@ -86,7 +86,7 @@ const runtimeConfig = useRuntimeConfig() ``` -:ReadMore{link="/docs/guide/going-further/runtime-config"} +:read-more{to="/docs/guide/going-further/runtime-config"} ## App Configuration @@ -114,7 +114,7 @@ const appConfig = useAppConfig() ``` -:ReadMore{link="/docs/guide/directory-structure/app-config"} +:read-more{to="/docs/guide/directory-structure/app-config"} ## `runtimeConfig` vs `app.config` @@ -139,10 +139,10 @@ Nuxt uses [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt.config) file a Name | Config File | How To Configure |---------------------------------------------|---------------------------|------------------------- -| [Nitro](https://nitro.unjs.io/) | ~~`nitro.config.ts`~~ | Use [`nitro`](/docs/api/configuration/nuxt-config#nitro) key in `nuxt.config` -| [PostCSS](https://postcss.org) | ~~`postcss.config.js`~~ | Use [`postcss`](/docs/api/configuration/nuxt-config#postcss) key in `nuxt.config` -| [Vite](https://vitejs.dev) | ~~`vite.config.ts`~~ | Use [`vite`](/docs/api/configuration/nuxt-config#vite) key in `nuxt.config` -| [webpack](https://webpack.js.org/) | ~~`webpack.config.ts`~~ | Use [`webpack`](/docs/api/configuration/nuxt-config#webpack-1) key in `nuxt.config` +| [Nitro](https://nitro.unjs.io/) | ~~`nitro.config.ts`~~ | Use [`nitro`](/docs/api/nuxt-config#nitro) key in `nuxt.config` +| [PostCSS](https://postcss.org) | ~~`postcss.config.js`~~ | Use [`postcss`](/docs/api/nuxt-config#postcss) key in `nuxt.config` +| [Vite](https://vitejs.dev) | ~~`vite.config.ts`~~ | Use [`vite`](/docs/api/nuxt-config#vite) key in `nuxt.config` +| [webpack](https://webpack.js.org/) | ~~`webpack.config.ts`~~ | Use [`webpack`](/docs/api/nuxt-config#webpack-1) key in `nuxt.config` Here is a list of other common config files: @@ -177,7 +177,7 @@ export default defineNuxtConfig({ }) ``` -:ReadMore{link="/docs/guide/directory-structure/nuxt.config#vue"} +:read-more{to="/docs/api/configuration/nuxt-config#vue"} ### With webpack @@ -195,7 +195,7 @@ export default defineNuxtConfig({ }) ``` -:ReadMore{link="/docs/guide/directory-structure/nuxt.config#loaders"} +:read-more{to="/docs/api/configuration/nuxt-config#loaders"} ### Enabling Experimental Vue Features @@ -210,4 +210,4 @@ export default defineNuxtConfig({ }) ``` -:ReadMore{link="/docs/guide/directory-structure/nuxt.config#vue-1"} +:read-more{to="/docs/api/configuration/nuxt-config#vue-1"} diff --git a/docs/1.getting-started/3.views.md b/docs/1.getting-started/3.views.md index f694015447..4a78fd7465 100644 --- a/docs/1.getting-started/3.views.md +++ b/docs/1.getting-started/3.views.md @@ -1,14 +1,12 @@ --- -navigation.icon: uil:window-section +title: 'Views' +description: 'Nuxt provides several component layers to implement the user interface of your application.' +navigation.icon: i-ph-layout-duotone --- -# Views - -Nuxt provides several component layers to implement the user interface of your application. - ## `app.vue` -![The `app.vue` file is the entry point of your application](/assets/docs/getting-started/views/app.svg) +![The app.vue file is the entry point of your application](/assets/docs/getting-started/views/app.svg) By default, Nuxt will treat this file as the **entrypoint** and render its content for every route of the application. @@ -20,7 +18,7 @@ By default, Nuxt will treat this file as the **entrypoint** and render its conte ``` -::alert +::callout If you are familiar with Vue, you might wonder where `main.js` is (the file that normally creates a Vue app). Nuxt does this behind the scene. :: @@ -28,7 +26,7 @@ If you are familiar with Vue, you might wonder where `main.js` is (the file that ![Components are reusable pieces of UI](/assets/docs/getting-started/views/components.svg) -Most components are reusable pieces of the user interface, like buttons and menus. In Nuxt, you can create these components in the [`components/` directory](/docs/guide/directory-structure/components), and they will be automatically available across your application without having to explicitly import them. +Most components are reusable pieces of the user interface, like buttons and menus. In Nuxt, you can create these components in the [`components/`](/docs/guide/directory-structure/components) directory, and they will be automatically available across your application without having to explicitly import them. ::code-group @@ -57,9 +55,9 @@ Most components are reusable pieces of the user interface, like buttons and menu ![Pages are views tied to a specific route](/assets/docs/getting-started/views/pages.svg) -Pages represent views for each specific route pattern. Every file in the [`pages/` directory](/docs/guide/directory-structure/pages) represents a different route displaying its content. +Pages represent views for each specific route pattern. Every file in the [`pages/`](/docs/guide/directory-structure/pages) directory represents a different route displaying its content. -To use pages, create `pages/index.vue` file and add `` component to the `app.vue` (or remove `app.vue` for default entry). You can now create more pages and their corresponding routes by adding new files in the [`pages/` directory](/docs/guide/directory-structure/pages). +To use pages, create `pages/index.vue` file and add `` component to the [`app.vue`](/docs/guide/directory-structure/app) (or remove `app.vue` for default entry). You can now create more pages and their corresponding routes by adding new files in the [`pages/`](/docs/guide/directory-structure/pages) directory. ::code-group @@ -84,9 +82,7 @@ To use pages, create `pages/index.vue` file and add `` component to :: -::alert -You will learn more about pages in the [Routing section](/docs/getting-started/routing) -:: +:read-more{title="Routing Section" to="/docs/getting-started/routing"} ## Layouts @@ -94,8 +90,8 @@ You will learn more about pages in the [Routing section](/docs/getting-started/r Layouts are wrappers around pages that contain a common User Interface for several pages, such as a header and footer display. Layouts are Vue files using `` components to display the **page** content. The `layouts/default.vue` file will be used by default. Custom layouts can be set as part of your page metadata. -::alert -If you only have a single layout in your application, we recommend using app.vue with the [`` component](/docs/api/components/nuxt-page) instead. +::callout +If you only have a single layout in your application, we recommend using [`app.vue`](/docs/guide/directory-structure/app) with [``](/docs/api/components/nuxt-page) instead. :: ::code-group @@ -135,8 +131,8 @@ If you want to create more layouts and learn how to use them in your pages, find ## Advanced: Extending the HTML template -::alert{type=info} -If you only need to modify the head, you can refer to the [SEO and meta section](/docs/getting-started/seo-meta). +::callout +If you only need to modify the ``, you can refer to the [SEO and meta section](/docs/getting-started/seo-meta). :: You can have full control over the HTML template by adding a Nitro plugin that registers a hook. @@ -154,4 +150,4 @@ export default defineNitroPlugin((nitroApp) => { }) ``` -:ReadMore{link="/docs/guide/going-further/hooks"} +:read-more{to="/docs/guide/going-further/hooks"} diff --git a/docs/1.getting-started/4.assets.md b/docs/1.getting-started/4.assets.md index efaab282f1..937035f982 100644 --- a/docs/1.getting-started/4.assets.md +++ b/docs/1.getting-started/4.assets.md @@ -1,19 +1,19 @@ --- -navigation.icon: uil:image +title: 'Assets' +description: 'Nuxt offers two options for your assets.' +navigation.icon: i-ph-image-duotone --- -# Assets - Nuxt uses two directories to handle assets like stylesheets, fonts or images. -- The [`public/` directory](/docs/guide/directory-structure/public) content is served at the server root as-is. -- The [`assets/` directory](/docs/guide/directory-structure/assets) contains by convention every asset that you want the build tool (Vite or webpack) to process. +- The [`public/`](/docs/guide/directory-structure/public) directory content is served at the server root as-is. +- The [`assets/`](/docs/guide/directory-structure/assets) directory contains by convention every asset that you want the build tool (Vite or webpack) to process. -## `public/` Directory +## Public Directory -The [`public/` directory](/docs/guide/directory-structure/public) is used as a public server for static assets publicly available at a defined URL of your application. +The [`public/`](/docs/guide/directory-structure/public) directory is used as a public server for static assets publicly available at a defined URL of your application. -You can get a file in the [`public/` directory](/docs/guide/directory-structure/public) from your application's code or from a browser by the root URL `/`. +You can get a file in the [`public/`](/docs/guide/directory-structure/public) directory from your application's code or from a browser by the root URL `/`. ### Example @@ -25,13 +25,13 @@ For example, referencing an image file in the `public/img/` directory, available ``` -## `assets/` Directory +## Assets Directory -Nuxt uses [Vite](https://vitejs.dev/guide/assets.html) or [webpack](https://webpack.js.org/guides/asset-management/) to build and bundle your application. The main function of these build tools is to process JavaScript files, but they can be extended through [plugins](https://vitejs.dev/plugins/) (for Vite) or [loaders](https://webpack.js.org/loaders/) (for webpack) to process other kind of assets, like stylesheets, fonts or SVG. This step transforms the original file mainly for performance or caching purposes (such as stylesheets minification or browser cache invalidation). +Nuxt uses [Vite](https://vitejs.dev/guide/assets.html) (default) or [webpack](https://webpack.js.org/guides/asset-management/) to build and bundle your application. The main function of these build tools is to process JavaScript files, but they can be extended through [plugins](https://vitejs.dev/plugins/) (for Vite) or [loaders](https://webpack.js.org/loaders/) (for webpack) to process other kind of assets, like stylesheets, fonts or SVG. This step transforms the original file mainly for performance or caching purposes (such as stylesheets minification or browser cache invalidation). -By convention, Nuxt uses the [`assets/` directory](/docs/guide/directory-structure/assets) to store these files but there is no auto-scan functionality for this directory, and you can use any other name for it. +By convention, Nuxt uses the [`assets/`](/docs/guide/directory-structure/assets) directory to store these files but there is no auto-scan functionality for this directory, and you can use any other name for it. -In your application's code, you can reference a file located in the [`assets/` directory](/docs/guide/directory-structure/assets) by using the `~/assets/` path. +In your application's code, you can reference a file located in the [`assets/`](/docs/guide/directory-structure/assets) directory by using the `~/assets/` path. ### Example @@ -43,13 +43,13 @@ For example, referencing an image file that will be processed if a build tool is ``` -::alert{type=info icon=💡} -Nuxt won't serve files in the [`assets/` directory](/docs/guide/directory-structure/assets) at a static URL like `/assets/my-file.png`. If you need a static URL, use the [`public/` directory](#public-directory). +::callout +Nuxt won't serve files in the [`assets/`](/docs/guide/directory-structure/assets) directory at a static URL like `/assets/my-file.png`. If you need a static URL, use the [`public/`](#public-directory) directory. :: ### Global Styles Imports -To globally insert statements in your Nuxt components styles, you can use the [`Vite`](/docs/api/configuration/nuxt-config#vite) option at your [`nuxt.config`](/docs/api/configuration/nuxt-config) file. +To globally insert statements in your Nuxt components styles, you can use the [`Vite`](/docs/api/nuxt-config#vite) option at your [`nuxt.config`](/docs/api/nuxt-config) file. #### Example diff --git a/docs/1.getting-started/4.styling.md b/docs/1.getting-started/4.styling.md index f9a68c154a..d1fd090ebf 100644 --- a/docs/1.getting-started/4.styling.md +++ b/docs/1.getting-started/4.styling.md @@ -1,9 +1,9 @@ --- -navigation.icon: uil:palette +title: 'Styling' +description: 'Learn how to style your Nuxt application.' +navigation.icon: i-ph-palette-duotone --- -# Styling - Nuxt is highly flexible when it comes to styling. Write your own styles, or reference local and external stylesheets. You can use CSS preprocessors, CSS frameworks, UI libraries and Nuxt modules to style your application. @@ -30,7 +30,7 @@ import('~/assets/css/first.css') ``` -::alert{type=info} +::callout The stylesheets will be inlined in the HTML rendered by Nuxt. :: @@ -45,7 +45,7 @@ export default defineNuxtConfig({ }) ``` -::alert{type=info} +::callout The stylesheets will be inlined in the HTML rendered by Nuxt, injected globally and present in all pages. :: @@ -77,7 +77,7 @@ h1 { You can also reference stylesheets that are distributed through npm. Let's use the popular `animate.css` library as an example. -```bash +```bash [Terminal] npm install animate.css ``` @@ -105,7 +105,7 @@ export default defineNuxtConfig({ You can include external stylesheets in your application by adding a link element in the head section of your nuxt.config file. You can achieve this result using different methods. Note that local stylesheets can also be included like this. -You can manipulate the head with the [`app.head`](/docs/api/configuration/nuxt-config#head) property of your Nuxt configuration: +You can manipulate the head with the [`app.head`](/docs/api/nuxt-config#head) property of your Nuxt configuration: ```ts [nuxt.config.ts] export default defineNuxtConfig({ @@ -120,8 +120,7 @@ export default defineNuxtConfig({ You can use the useHead composable to dynamically set a value in your head in your code. -::ReadMore{link="/docs/api/composables/use-head"} -:: +:read-more{to="/docs/api/composables/use-head"} ```ts useHead({ @@ -184,7 +183,7 @@ export default defineNuxtConfig({ }) ``` -::alert{type=info} +::callout In both cases, the compiled stylesheets will be inlined in the HTML rendered by Nuxt. :: @@ -453,24 +452,23 @@ Use different styles for different layouts. ``` -::ReadMore{link="/docs/guide/directory-structure/layouts"} -:: +:read-more{to="/docs/guide/directory-structure/layouts"} ## Third Party Libraries And Modules Nuxt isn't opinionated when it comes to styling and provides you with a wide variety of options. You can use any styling tool that you want, such as popular libraries like [UnoCSS](https://unocss.dev/) or [Tailwind CSS](https://tailwindcss.com/). The community and the Nuxt team have developed plenty of Nuxt modules to makes the integration easier. -You can discover them on the [modules section](https://nuxt.com/modules) of the website. +You can discover them on the [modules section](/modules) of the website. Here are a few modules to help you get started: -- [UnoCSS](https://nuxt.com/modules/unocss): Instant on-demand atomic CSS engine -- [Tailwind CSS](https://nuxt.com/modules/tailwindcss): Utility-first CSS framework +- [UnoCSS](/modules/unocss): Instant on-demand atomic CSS engine +- [Tailwind CSS](/modules/tailwindcss): Utility-first CSS framework - [Fontaine](https://github.com/nuxt-modules/fontaine): Font metric fallback - [Pinceau](https://pinceau.dev/): Adaptable styling framework - [Nuxt UI](https://ui.nuxt.com): A UI Library for Modern Web Apps -Nuxt modules provide you with a good developer experience out of the box, but remember that if your favorite tool doesn't have a module, it doesn't mean that you can't use it with Nuxt! You can configure it yourself for your own project. Depending on the tool, you might need to use a [Nuxt plugin](/docs/guide/directory-structure/plugins) and/or [make your own module](/docs/guide/going-further/modules). Share them with the [community](https://nuxt.com/modules) if you do! +Nuxt modules provide you with a good developer experience out of the box, but remember that if your favorite tool doesn't have a module, it doesn't mean that you can't use it with Nuxt! You can configure it yourself for your own project. Depending on the tool, you might need to use a [Nuxt plugin](/docs/guide/directory-structure/plugins) and/or [make your own module](/docs/guide/going-further/modules). Share them with the [community](/modules) if you do! ### Easily Load Webfonts @@ -484,14 +482,13 @@ If you are using [UnoCSS](https://unocss.dev/integrations/nuxt), note that it co Nuxt comes with the same `` element that Vue has, and also has support for the experimental [View Transitions API](/docs/getting-started/transitions#view-transitions-api-experimental). -::ReadMore{link="/docs/features/transitions"} -:: +:read-more{to="/docs/getting-started/transitions"} ### Font Advanced Optimization We would recommend using [Fontaine](https://github.com/nuxt-modules/fontaine) to reduce your [CLS](https://web.dev/cls/). If you need something more advanced, consider creating a Nuxt module to extend the build process or the Nuxt runtime. -::alert{type="info"} +::callout Always remember to take advantage of the various tools and techniques available in the Web ecosystem at large to make styling your application easier and more efficient. Whether you're using native CSS, a preprocessor, postcss, a UI library or a module, Nuxt has got you covered. Happy styling! :: diff --git a/docs/1.getting-started/5.routing.md b/docs/1.getting-started/5.routing.md index 3f5ce8de01..4476a47366 100644 --- a/docs/1.getting-started/5.routing.md +++ b/docs/1.getting-started/5.routing.md @@ -1,10 +1,10 @@ --- -navigation.icon: uil:sign-alt +title: 'Routing' description: Nuxt file-system routing creates a route for every file in the pages/ directory. +navigation.icon: i-ph-signpost-duotone --- -# Routing -One core feature of Nuxt is the file system router. Every Vue file inside the [`pages/` directory](/docs/guide/directory-structure/pages) creates a corresponding URL (or route) that displays the contents of the file. By using dynamic imports for each page, Nuxt leverages code-splitting to ship the minimum amount of JavaScript for the requested route. +One core feature of Nuxt is the file system router. Every Vue file inside the [`pages/`](/docs/guide/directory-structure/pages) directory creates a corresponding URL (or route) that displays the contents of the file. By using dynamic imports for each page, Nuxt leverages code-splitting to ship the minimum amount of JavaScript for the requested route. ## Pages @@ -14,15 +14,15 @@ This file system routing uses naming conventions to create dynamic and nested ro ::code-group -```text [pages/ directory] -pages/ ---| about.vue ---| index.vue ---| posts/ -----| [id].vue +```bash [Directory Structure] +| pages/ +---| about.vue +---| index.vue +---| posts/ +-----| [id].vue ``` -```js [Generated Router file] +```json [Generated Router File] { "routes": [ { @@ -43,13 +43,13 @@ pages/ :: -:ReadMore{link="/docs/guide/directory-structure/pages"} +:read-more{to="/docs/guide/directory-structure/pages"} ## Navigation -The `` component links pages between them. It renders an `
` tag with the `href` attribute set to the route of the page. Once the application is hydrated, page transitions are performed in JavaScript by updating the browser URL. This prevents full-page refreshes and allows for animated transitions. +The [``](/docs/api/components/nuxt-link) component links pages between them. It renders an `` tag with the `href` attribute set to the route of the page. Once the application is hydrated, page transitions are performed in JavaScript by updating the browser URL. This prevents full-page refreshes and allows for animated transitions. -When a `` enters the viewport on the client side, Nuxt will automatically prefetch components and payload (generated pages) of the linked pages ahead of time, resulting in faster navigation. +When a [``](/docs/api/components/nuxt-link) enters the viewport on the client side, Nuxt will automatically prefetch components and payload (generated pages) of the linked pages ahead of time, resulting in faster navigation. ```vue [pages/app.vue] ``` -:ReadMore{link="/docs/api/components/nuxt-link"} +:read-more{to="/docs/api/components/nuxt-link"} ## Route Parameters -The `useRoute()` composable can be used in a ` ``` -:ReadMore{link="/docs/api/composables/use-route"} +:read-more{to="/docs/api/composables/use-route"} ## Route Middleware Nuxt provides a customizable route middleware framework you can use throughout your application, ideal for extracting code that you want to run before navigating to a particular route. -::alert{type=info} +::callout Route middleware runs within the Vue part of your Nuxt app. Despite the similar name, they are completely different from server middleware, which are run in the Nitro server part of your app. :: There are three kinds of route middleware: 1. Anonymous (or inline) route middleware, which are defined directly in the pages where they are used. -2. Named route middleware, which are placed in the [`middleware/` directory](/docs/guide/directory-structure/middleware) and will be automatically loaded via asynchronous import when used on a page. (**Note**: The route middleware name is normalized to kebab-case, so `someMiddleware` becomes `some-middleware`.) +2. Named route middleware, which are placed in the [`middleware/`](/docs/guide/directory-structure/middleware) directory and will be automatically loaded via asynchronous import when used on a page. (**Note**: The route middleware name is normalized to kebab-case, so `someMiddleware` becomes `some-middleware`.) 3. Global route middleware, which are placed in the [`middleware/` directory](/docs/guide/directory-structure/middleware) (with a `.global` suffix) and will be automatically run on every route change. Example of an `auth` middleware protecting the `/dashboard` page: @@ -123,11 +123,11 @@ definePageMeta({ :: -:ReadMore{link="/docs/guide/directory-structure/middleware"} +:read-more{to="/docs/guide/directory-structure/middleware"} ## Route Validation -Nuxt offers route validation via the `validate` property in [`definePageMeta`](/docs/api/utils/define-page-meta) in each page you wish to validate. +Nuxt offers route validation via the `validate` property in [`definePageMeta()`](/docs/api/utils/define-page-meta) in each page you wish to validate. The `validate` property accepts the `route` as an argument. You can return a boolean value to determine whether or not this is a valid route to be rendered with this page. If you return `false`, and another match can't be found, this will cause a 404 error. You can also directly return an object with `statusCode`/`statusMessage` to respond immediately with an error (other matches will not be checked). @@ -143,3 +143,5 @@ definePageMeta({ }) ``` + +:read-more{to="/docs/api/utils/define-page-meta"} diff --git a/docs/1.getting-started/5.seo-meta.md b/docs/1.getting-started/5.seo-meta.md index 74cc43861f..d20b50de96 100644 --- a/docs/1.getting-started/5.seo-meta.md +++ b/docs/1.getting-started/5.seo-meta.md @@ -1,19 +1,13 @@ --- -navigation.icon: uil:file-search-alt +title: SEO and Meta description: Improve your Nuxt app's SEO with powerful head config, composables and components. +navigation.icon: i-ph-file-search-duotone --- -# SEO and Meta - -Improve your Nuxt app's SEO with powerful head config, composables and components. - ## Defaults Out-of-the-box, Nuxt provides sane defaults, which you can override if needed. -- `charset`: `utf-8` -- `viewport`: `width=device-width, initial-scale=1` - ```ts [nuxt.config.ts] export default defineNuxtConfig({ app: { @@ -25,9 +19,9 @@ export default defineNuxtConfig({ }) ``` -Providing an [`app.head`](/docs/api/configuration/nuxt-config#head) property in your [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt.config) allows you to customize the head for your entire app. +Providing an [`app.head`](/docs/api/nuxt-config#head) property in your [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt.config) allows you to customize the head for your entire app. -::alert{type=info} +::callout This method does not allow you to provide reactive data. We recommend to use `useHead()` in `app.vue`. :: @@ -57,9 +51,9 @@ useHead({ We recommend to take a look at the [`useHead`](/docs/api/composables/use-head) and [`useHeadSafe`](/docs/api/composables/use-head-safe) composables. -## `useSeoMeta` and `useServerSeoMeta` +## `useSeoMeta` -The `useSeoMeta` and [`useServerSeoMeta`](/docs/api/composables/use-server-seo-meta) composables let you define your site's SEO meta tags as a flat object with full TypeScript support. +The [`useSeoMeta`](/docs/api/composables/use-seo-meta) composable lets you define your site's SEO meta tags as a flat object with full TypeScript support. This helps you avoid typos and common mistakes, such as using `name` instead of `property`. @@ -76,7 +70,7 @@ useSeoMeta({ ``` -Read more on the [`useSeoMeta`](/docs/api/composables/use-seo-meta) and [`useServerSeoMeta`](/docs/api/composables/use-server-seo-meta) composables. +:read-more{to="/docs/api/composables/use-seo-meta"} ## Components @@ -108,7 +102,7 @@ const title = ref('Hello World') ## Types -Below are the non-reactive types used for [`useHead`](/docs/api/composables/use-head), [`app.head`](/docs/api/configuration/nuxt-config#head) and components. +Below are the non-reactive types used for [`useHead`](/docs/api/composables/use-head), [`app.head`](/docs/api/nuxt-config#head) and components. ```ts interface MetaObject { @@ -226,7 +220,7 @@ Within your [`pages/` directory](/docs/guide/directory-structure/pages), you can For example, you can first set the current page title (this is extracted at build time via a macro, so it can't be set dynamically): -```vue{}[pages/some-page.vue] +```vue [pages/some-page.vue] ``` -:LinkExample{link="/docs/examples/features/meta-tags"} +:link-example{to="/docs/examples/features/meta-tags"} -:ReadMore{link="/docs/guide/directory-structure/pages/#page-metadata"} +:read-more{to="/docs/guide/directory-structure/pages/#page-metadata"} ### Dynamic Title diff --git a/docs/1.getting-started/5.transitions.md b/docs/1.getting-started/5.transitions.md index 29e2cdddc4..d93cf5960c 100644 --- a/docs/1.getting-started/5.transitions.md +++ b/docs/1.getting-started/5.transitions.md @@ -1,11 +1,12 @@ --- -navigation.icon: uil:moon-eclipse -description: Nuxt leverages Vue's Transition component to apply transitions between pages and layouts. +title: 'Transitions' +description: Apply transitions between pages and layouts with Vue or native browser View Transitions. +navigation.icon: i-ph-exclude-square-duotone --- -# Transitions - +::callout Nuxt leverages Vue's [``](https://vuejs.org/guide/built-ins/transition.html#the-transition-component) component to apply transitions between pages and layouts. +:: ## Page transitions @@ -19,7 +20,7 @@ export default defineNuxtConfig({ }) ``` -::alert{type=warning} +::callout If you are changing layouts as well as page, the page transition you set here will not run. Instead, you should set a [layout transition](/docs/getting-started/transitions#layout-transitions). :: @@ -245,7 +246,7 @@ export default defineNuxtConfig({ }) ``` -::alert{type="info"} +::callout If you change the `name` property, you also have to rename the CSS classes accordingly. :: @@ -290,7 +291,7 @@ defineNuxtConfig({ For advanced use-cases, you can use JavaScript hooks to create highly dynamic and custom transitions for your Nuxt pages. -This way presents perfect use-cases for JavaScript animation libraries such as [GSAP](https://greensock.com/gsap/) or [Tween.js](https://createjs.com/tweenjs). +This way presents perfect use-cases for JavaScript animation libraries such as [GSAP](https://gsap.com/). ```vue [pages/some-page.vue] ``` -::alert{type="info"} +::callout Learn more about additional [JavaScript hooks](https://vuejs.org/guide/built-ins/transition.html#javascript-hooks) available in the `Transition` component. :: @@ -405,7 +406,7 @@ When `` is used in `app.vue`, transition-props can be passed directl ``` -::alert{type="warning"} +::callout Remember, this page transition cannot be overridden with `definePageMeta` on individual pages. :: diff --git a/docs/1.getting-started/6.data-fetching.md b/docs/1.getting-started/6.data-fetching.md index 4b8554da38..93419a6651 100644 --- a/docs/1.getting-started/6.data-fetching.md +++ b/docs/1.getting-started/6.data-fetching.md @@ -1,11 +1,12 @@ --- -navigation.icon: uil:channel +title: 'Data fetching' description: Nuxt provides composables to handle data fetching within your application. +navigation.icon: i-ph-plugs-connected-duotone --- -# Data fetching +Nuxt comes with two composables and a built-in library to perform data-fetching in browser or server environments: `useFetch`, [`useAsyncData`](/docs/api/composables/use-async-data) and `$fetch`. -Nuxt comes with two composables and a built-in library to perform data-fetching in browser or server environments: `useFetch`, [`useAsyncData`](/docs/api/composables/use-async-data) and `$fetch` . In a nutshell: +In a nutshell: - [`useFetch`](/docs/api/composables/use-fetch) is the most straightforward way to handle data fetching in a component setup function. - [`$fetch`](/docs/api/utils/dollarfetch) is great to make network requests based on user interaction. @@ -17,7 +18,7 @@ Before that, it's imperative to know why these composables exist in the first pl ## Why using specific composables? -When using a framework like Nuxt that can perform calls and render pages on both client and server environments, some challenges must be addressed. This is why Nuxt provides composables to wrap your queries, instead of letting the developer rely on `$fetch` calls alone. +When using a framework like Nuxt that can perform calls and render pages on both client and server environments, some challenges must be addressed. This is why Nuxt provides composables to wrap your queries, instead of letting the developer rely on [`$fetch`](/docs/api/utils/dollarfetch) calls alone. ### Network calls duplication @@ -25,18 +26,14 @@ The [`useFetch`](/docs/api/composables/use-fetch) and [`useAsyncData`](/docs/api The payload is a JavaScript object accessible through [`useNuxtApp().payload`](/docs/api/composables/use-nuxt-app#payload). It is used on the client to avoid refetching the same data when the code is executed in the browser. -::alert{icon=⚙️} -Use the [Nuxt DevTools](https://devtools.nuxt.com) to inspect this data in the payload tab. +::callout +Use the [Nuxt DevTools](https://devtools.nuxt.com) to inspect this data in the **Payload tab**. :: ### Suspense Nuxt uses Vue’s [``](https://vuejs.org/guide/built-ins/suspense) component under the hood to prevent navigation before every async data is available to the view. The data fetching composables can help you leverage this feature and use what suits best on a per-calls basis. -::alert{icon=👉} -These composables are auto-imported and can be used in `setup` functions or lifecycle hooks -:: - ## `useFetch` The [`useFetch`](/docs/api/composables/use-fetch) composable is the most straightforward way to perform data fetching. @@ -53,11 +50,9 @@ const { data: count } = await useFetch('/api/count') This composable is a wrapper around the [`useAsyncData`](/docs/api/composables/use-async-data) composable and `$fetch` utility. -::ReadMore{link="/docs/api/composables/use-fetch"} -:: +:read-more{to="/docs/api/composables/use-fetch"} -::LinkExample{link="/docs/examples/features/data-fetching"} -:: +:link-example{to="/docs/examples/features/data-fetching"} ## `$fetch` @@ -67,7 +62,7 @@ Nuxt includes the `ofetch` library, and is auto-imported as the `$fetch` alias g const users = await $fetch('/api/users').catch((error) => error.data) ``` -::alert{type="warning"} +::callout Beware that using only `$fetch` will not provide [network calls de-duplication and navigation prevention](#why-using-specific-composables). It is recommended to use `$fetch` when posting data to an event handler, when doing client-side only logic, or combined with `useAsyncData`. :: @@ -79,11 +74,12 @@ The `ofetch` library is built on top of [the `fetch` API](https://developer.mozi - Auto-retry - Interceptors -::alert{icon=📘} -[Read the full documentation of ofetch](https://github.com/unjs/ofetch) +::read-more{title="ofetch" to="https://github.com/unjs/ofetch" target="_blank"} +Read the full documentation of `ofetch` :: -::ReadMore{link="/docs/api/utils/dollarfetch"} +::read-more{to="/docs/api/utils/dollarfetch"} +Read more about `$fetch` :: ## `useAsyncData` @@ -123,7 +119,8 @@ const { data: discounts, pending } = await useAsyncData('cart-discount', async ( }) ``` -::ReadMore{link="/docs/api/composables/use-async-data"} +::read-more{to="/docs/api/composables/use-async-data"} +Read more about `useAsyncData` :: ## Options @@ -160,10 +157,12 @@ You can alternatively use [`useLazyFetch`](/docs/api/composables/use-lazy-fetch) const { pending, data: posts } = useLazyFetch('/api/posts') ``` -::ReadMore{link="/docs/api/composables/use-lazy-fetch"} +::read-more{to="/docs/api/composables/use-lazy-fetch"} +Read more about `useLazyFetch` :: -::ReadMore{link="/docs/api/composables/use-lazy-async-data"} +::read-more{to="/docs/api/composables/use-lazy-async-data"} +Read more about `useLazyAsyncData` :: ### Client-only fetching @@ -211,7 +210,7 @@ const { data: mountains } = await useFetch('/api/mountains', { }) ``` -::alert{type="warning"} +::callout Both `pick` and `transform` don't prevent the unwanted data from being fetched initially. But they will prevent unwanted data from being added to the payload transferred from server to client. :: @@ -224,7 +223,7 @@ Both `pick` and `transform` don't prevent the unwanted data from being fetched i - [`useFetch`](/docs/api/composables/use-fetch) uses the provided URL as a key. Alternatively, a `key` value can be provided in the `options` object passed as a last argument. - [`useAsyncData`](/docs/api/composables/use-async-data) uses its first argument as a key if it is a string. If the first argument is the handler function that performs the query, then a key that is unique to the file name and line number of the instance of `useAsyncData` will be generated for you. -::alert{icon=📘} +::callout To get the cached data by key, you can use [`useNuxtData`](/docs/api/composables/use-nuxt-data) :: @@ -247,7 +246,7 @@ const { data, error, execute, refresh } = await useFetch('/api/users') The `execute` function is an alias for `refresh` that works in exactly the same way but is more semantic for cases when the fetch is [not immediate](#not-immediate). -::alert{icon=📘} +::callout To globally refetch or invalidate cached data, see [`clearNuxtData`](/docs/api/utils/clear-nuxt-data) and [`refreshNuxtData`](/docs/api/utils/refresh-nuxt-data). :: @@ -376,7 +375,7 @@ const { data } = await useFetch('/api/me', { headers }) ``` -::alert{type="warning"} +::callout Be very careful before proxying headers to an external API and just include headers that you need. Not all headers are safe to be bypassed and might introduce unwanted behavior. Here is a list of common headers that are NOT to be proxied: - `host`, `accept` @@ -435,19 +434,18 @@ export default defineNuxtComponent({ ``` -::Alert +::callout Using ` ``` -## Error Helper Methods +::callout +Although it is called an 'error page' it's not a route and shouldn't be placed in your `~/pages` directory. For the same reason, you shouldn't use `definePageMeta` within this page. +:: + +The error page has a single prop - `error` which contains an error for you to handle. + +The `error` object provides the fields: +```ts +{ + url: string + statusCode: number + statusMessage: string + message: string + description: string + data: any +} +``` + +If you have an error with custom fields they will be lost; you should assign them to `data` instead: + +```ts +throw createError({ + statusCode: 404, + statusMessage: 'Page Not Found', + data: { + myCustomField: true + } +}) +``` + +For custom errors we highly recommend to use `onErrorCaptured` composable that can be called in a page/component setup function or `vue:error` runtime nuxt hook that can be configured in a nuxt plugin. + +```ts [plugins/error-handler.ts] +export default defineNuxtPlugin(nuxtApp => { + nuxtApp.hook('vue:error', (err) => { + // + }) +}) +``` + +When you are ready to remove the error page, you can call the [`clearError`](/docs/api/utils/clear-error) helper function, which takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page). + +::callout +Make sure to check before using anything dependent on Nuxt plugins, such as `$route` or `useRouter`, as if a plugin threw an error, then it won't be re-run until you clear the error. +:: + +::callout +If you are running on Node 16 and you set any cookies when rendering your error page, they will [overwrite cookies previously set](https://github.com/nuxt/nuxt/pull/20585). We recommend using a newer version of Node as Node 16 reached end-of-life in September 2023. +:: + +## Error Utils ### `useError` -* `function useError (): Ref` +```ts [TS Signature] +function useError (): Ref +``` This function will return the global Nuxt error that is being handled. -::ReadMore{link="/docs/api/composables/use-error"} +::read-more{to="/docs/api/composables/use-error"} +Read more about `useError` composable. :: ### `createError` -* `function createError (err: { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error` +```ts [TS Signature] +function createError (err: { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error +``` -You can use this function to create an error object with additional metadata. It is usable in both the Vue and Nitro portions of your app, and is meant to be thrown. +Create an error object with additional metadata. It is usable in both the Vue and Server portions of your app, and is meant to be thrown. If you throw an error created with `createError`: - -* on server-side, it will trigger a full-screen error page which you can clear with `clearError`. -* on client-side, it will throw a non-fatal error for you to handle. If you need to trigger a full-screen error page, then you can do this by setting `fatal: true`. - -### Example +- on server-side, it will trigger a full-screen error page which you can clear with [`clearError`](#clearerror). +- on client-side, it will throw a non-fatal error for you to handle. If you need to trigger a full-screen error page, then you can do this by setting `fatal: true`. ```vue [pages/movies/[slug\\].vue] ``` +::read-more{to="/docs/api/utils/create-error"} +Read more about `createError` util. +:: + ### `showError` -* `function showError (err: string | Error | { statusCode, statusMessage }): Error` +```ts [TS Signature] +function showError (err: string | Error | { statusCode, statusMessage }): Error +``` -You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page which you can clear with `clearError`. +You can call this function at any point on client-side, or (on server side) directly within middleware, plugins or `setup()` functions. It will trigger a full-screen error page which you can clear with [`clearError`](#clearerror). It is recommended instead to use `throw createError()`. -::ReadMore{link="/docs/api/utils/show-error"} +::read-more{to="/docs/api/utils/show-error"} +Read more about `showError` util. :: ### `clearError` -* `function clearError (options?: { redirect?: string }): Promise` +```ts [TS Signature] +function clearError (options?: { redirect?: string }): Promise +``` This function will clear the currently handled Nuxt error. It also takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page). -::ReadMore{link="/docs/api/utils/clear-error"} +::read-more{to="/docs/api/utils/clear-error"} +Read more about `clearError` util. :: -## Rendering Errors Within Your App +## Render Error in Component -Nuxt also provides a `` component that allows you to handle client-side errors within your app, without replacing your entire site with an error page. +Nuxt also provides a [``](/docs/api/components/nuxt-error-boundary) component that allows you to handle client-side errors within your app, without replacing your entire site with an error page. This component is responsible for handling errors that occur within its default slot. On client-side, it will prevent the error from bubbling up to the top level, and will render the `#error` slot instead. The `#error` slot will receive `error` as a prop. (If you set `error = null` it will trigger re-rendering the default slot; you'll need to ensure that the error is fully resolved first or the error slot will just be rendered a second time.) -::alert{type="info"} +::callout If you navigate to another route, the error will be cleared automatically. :: -### Example - ```vue [pages/index.vue] ``` -::LinkExample{link="/docs/examples/advanced/error-handling"} -:: +:link-example{to="/docs/examples/advanced/error-handling"} diff --git a/docs/1.getting-started/8.server.md b/docs/1.getting-started/8.server.md index a0a3163e86..0a7d38569a 100644 --- a/docs/1.getting-started/8.server.md +++ b/docs/1.getting-started/8.server.md @@ -1,14 +1,12 @@ --- -navigation.icon: uil:laptop-connection +title: 'Server' description: Build full-stack applications, fetch data from your database, create APIs, or even generate static server-side content like a sitemap or a RSS feed, from a single codebase. +navigation.icon: i-ph-computer-tower-duotone --- -# Server - Nuxt's server framework allows you to build **full-stack applications**. For example, you can fetch data from a database or another server, create an API or even generate static server-side content like a sitemap or an RSS feed - all from a single codebase. -::ReadMore{link="/docs/guide/directory-structure/server"} -:: +:read-more{to="/docs/guide/directory-structure/server"} ## Powered by Nitro @@ -27,7 +25,7 @@ With Nitro, you can easily manage the server part of your Nuxt app, from API end Both endpoints and middleware can be defined like this: ```ts [server/api/test.ts] -export default defineEventHandler({ +export default defineEventHandler(async (event) => { // ... Do whatever you want here }) ``` @@ -36,27 +34,30 @@ And you can directly return `text`, `json`, `html` or even a `stream`. Out-of-the-box, Nitro supports **hot module replacement** and **auto-import** like the other parts of your Nuxt application. -::ReadMore{link="/docs/guide/directory-structure/server"} -:: +:read-more{to="/docs/guide/directory-structure/server"} ## Universal Deployment Nitro offers the ability to deploy your Nuxt app anywhere, from a bare metal server to the edge network, with a start time of just a few milliseconds. That's fast! +:read-more{to="/blog/nuxt-on-the-edge"} + Today, Nitro offers more than 15 presets to build your Nuxt app for different cloud providers and servers, including: - [Cloudflare Workers](https://workers.cloudflare.com/) - [Netlify Functions](https://www.netlify.com/products/functions/) - [Vercel Edge Network](https://vercel.com/docs/edge-network/introduction) +- [Lagon](https://lagon.app/) Or for other runtimes: -- [Deno](https://deno.land/) -- [Bun](https://bun.sh/) - -::ReadMore{link="/docs/getting-started/deployment"} +::card-group + :card{icon="i-logos-deno" title="Deno" to="https://deno.land" target="_blank"} + :card{icon="i-logos-bun" title="Bun" to="https://bun.sh" target="_blank"} :: +:read-more{to="/docs/getting-started/deployment"} + ## Hybrid Rendering Do you need both static and dynamic pages in your Nuxt app? Nitro has your back! @@ -66,21 +67,27 @@ Nitro has a powerful feature called `routeRules` which allows you to define a se ```ts [nuxt.config.ts] export default defineNuxtConfig({ routeRules: { - '/': { prerender: true }, // Generated at build time for SEO purpose - '/api/*': { cache: { maxAge: 60 * 60 } }, // Cached for 1 hour - '/old-page': { redirect: { to: '/new-page', statusCode: 302 } } // Redirection to avoid 404 + // Generated at build time for SEO purpose + '/': { prerender: true }, + // Cached for 1 hour + '/api/*': { cache: { maxAge: 60 * 60 } }, + // Redirection to avoid 404 + '/old-page': { + redirect: { to: { '/new-page', statusCode: 302 } + } // ... } }) ``` -[More rules are available](https://nuxt.com/docs/guide/concepts/rendering#hybrid-rendering) to customize the rendering mode of your routes. +::read-more{to="/docs/guide/concepts/rendering#hybrid-rendering"} +Learn about all available route rules are available to customize the rendering mode of your routes. +:: -In addition, there are some route rules (for example, `ssr` and `experimentalNoScripts`) that are not Nitro rules but affect Nuxt's behavior when rendering your pages to HTML. +In addition, there are some route rules (for example, `ssr` and `experimentalNoScripts`) that are not Nuxt specific to change the behavior when rendering your pages to HTML. Some route rules (`redirect` and `prerender`) also affect client-side behavior. Nitro is used to build the app for server side rendering, as well as pre-rendering. -::ReadMore{link="/docs/guide/concepts/rendering"} -:: +:read-more{to="/docs/guide/concepts/rendering"} diff --git a/docs/1.getting-started/9.layers.md b/docs/1.getting-started/9.layers.md index 72417888f2..92801a0a18 100644 --- a/docs/1.getting-started/9.layers.md +++ b/docs/1.getting-started/9.layers.md @@ -1,24 +1,23 @@ --- -navigation.icon: uil:layer-group +title: 'Layers' description: Nuxt provides a powerful system that allows you to extend the default files, configs, and much more. +navigation.icon: i-ph-stack-duotone --- -# Layers - One of the core features of Nuxt 3 is the layers and extending support. You can extend a default Nuxt application to reuse components, utils, and configuration. The layers structure is almost identical to a standard Nuxt application which makes them easy to author and maintain. -Some use cases: +## Use Cases -::list{type="success"} - Share reusable configuration presets across projects using `nuxt.config` and `app.config` -- Create a component library using [`components/` directory](/docs/guide/directory-structure/components) -- Create utility and composable library using [`composables/` directory](/docs/guide/directory-structure/composables) and [`utils/` directory](/docs/guide/directory-structure/utils) -- Create [Nuxt themes](https://github.com/nuxt-themes) +- Create a component library using [`components/`](/docs/guide/directory-structure/components) directory +- Create utility and composable library using [`composables/`](/docs/guide/directory-structure/composables) and [`utils/`](/docs/guide/directory-structure/utils) directories - Create Nuxt module presets - Share standard setup across projects -:: +- Create [Nuxt themes](https://github.com/nuxt-themes) -You can extend a layer by adding the [extends](/docs/api/configuration/nuxt-config#extends) property to the [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt.config) file. +## Usage + +You can extend a layer by adding the [extends](/docs/api/nuxt-config#extends) property to the [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt.config) file. ```ts [nuxt.config.ts] export default defineNuxtConfig({ @@ -30,13 +29,13 @@ export default defineNuxtConfig({ }) ``` -A quick video made by [Learn Vue](https://go.learnvue.co) to showcase the power of `extends`: +::read-more{to="/docs/guide/going-further/layers"} +Read more about layers in the **Layer Author Guide**. +:: -:video-player{src="https://www.youtube.com/watch?v=lnFCM7c9f7I"} - -## Authoring Nuxt Layers - -See [Layer Author Guide](/docs/guide/going-further/layers) to learn more. +::callout{color="blue" icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=lnFCM7c9f7I" target="_blank"} +Watch Learn Vue video about Nuxt Layers. +:: ## Examples diff --git a/docs/1.getting-started/_dir.yml b/docs/1.getting-started/_dir.yml index 538f390e40..2a4a0c0f12 100644 --- a/docs/1.getting-started/_dir.yml +++ b/docs/1.getting-started/_dir.yml @@ -1,3 +1,3 @@ title: Get Started titleTemplate: '%s · Get Started with Nuxt' -image: '/socials/get-started.jpg' +icon: i-ph-rocket-launch-duotone diff --git a/docs/2.guide/0.index.md b/docs/2.guide/0.index.md new file mode 100644 index 0000000000..af767967eb --- /dev/null +++ b/docs/2.guide/0.index.md @@ -0,0 +1,19 @@ +--- +title: 'Nuxt Guide' +titleTemplate: '%s' +description: 'Lean how Nuxt works with in-depth guides.' +navigation: false +surround: false +--- + +::card-group{class="sm:grid-cols-1"} + ::card{icon="i-ph-medal-duotone" title="Key Concepts" to="/docs/guide/concepts"} + Discover the main concepts behind Nuxt, from auto-import, hybrid rendering to its TypeScript support. + :: + ::card{icon="i-ph-folders-duotone" title="Directory Structure" to="/docs/guide/directory-structure"} + Learn about Nuxt directory structure and what benefits each directory or file offers. + :: + ::card{icon="i-ph-star-duotone" title="Going Further" to="/docs/guide/going-further"} + Master Nuxt with advanced concepts like experimental features, hooks, modules, and more. + :: +:: diff --git a/docs/2.guide/1.concepts/1.auto-imports.md b/docs/2.guide/1.concepts/1.auto-imports.md index 572ea66fc0..8f9c2e9643 100644 --- a/docs/2.guide/1.concepts/1.auto-imports.md +++ b/docs/2.guide/1.concepts/1.auto-imports.md @@ -1,43 +1,43 @@ --- -description: "Nuxt auto-imports helper functions, composables and Vue APIs." +title: Auto-imports +description: "Nuxt auto-imports components, composables, helper functions and Vue APIs." --- -# Auto-imports +Nuxt auto-imports components, composables and [Vue.js APIs](https://vuejs.org/api/) to use across your application without explicitly importing them. -## Composables and Helper Functions +```vue [app.vue] + +``` -Nuxt auto-imports helper functions, composables and Vue APIs to use across your application without explicitly importing them. Based on the directory structure, every Nuxt application can also use auto-imports for its own components, composables and plugins. Components, composables or plugins can use these functions. +Thanks to its opiniated directory structure, Nuxt can auto-import your [`components/`](/docs/guide/directory-structure/components), [`composables/`](/docs/guide/directory-structure/components) and [`utils/`](/docs/guide/directory-structure/components). -Contrary to a classic global declaration, Nuxt preserves typings and IDEs completions and hints, and only includes what is actually used in your production code. +Contrary to a classic global declaration, Nuxt preserves typings, IDEs completions and hints, and **only includes what is used in your production code**. -::alert{type=info icon=💡} -In the documentation, every function that is not explicitly imported is auto-imported by Nuxt and can be used as-is in your code. -You can find a reference for auto-imported [composables](/docs/api/composables/use-async-data) and [utilities](/docs/api/utils/dollarfetch) in the API section. +::callout{color="blue" icon="i-ph-lightbulb-duotone"} +In the docs, every function that is not explicitly imported is auto-imported by Nuxt and can be used as-is in your code. You can find a reference for auto-imported components, composables and utilities in the [API section](/docs/api). :: -::alert{type=info} -In the [server directory](/docs/guide/directory-structure/server), we auto import exported functions and variables from `server/utils/`. +::callout +In the [`server`](/docs/guide/directory-structure/server) directory, Nuxt auto-imports exported functions and variables from `server/utils/`. :: -::alert -You can also auto-import functions exported from custom folders or third-party packages by configuring the [`imports` section](/docs/api/configuration/nuxt-config#imports) of your `nuxt.config` file. +::callout +You can also auto-import functions exported from custom folders or third-party packages by configuring the [`imports`](/docs/api/nuxt-config#imports) section of your `nuxt.config` file. :: -### Built-in Auto-imports - -#### Nuxt Auto-imports +## Built-in Auto-imports Nuxt auto-imports functions and composables to perform [data fetching](/docs/getting-started/data-fetching), get access to the [app context](/docs/api/composables/use-nuxt-app) and [runtime config](/docs/guide/going-further/runtime-config), manage [state](/docs/getting-started/state-management) or define components and plugins. ```vue ``` -#### Vue Auto-imports - Vue 3 exposes Reactivity APIs like `ref` or `computed`, as well as lifecycle hooks and helpers that are auto-imported by Nuxt. ```vue @@ -48,7 +48,7 @@ const double = computed(() => count.value * 2) ``` -#### Using Vue and Nuxt composables +### Vue and Nuxt composables @@ -60,14 +60,15 @@ That means that (with very few exceptions) you cannot use them outside a Nuxt pl If you get an error message like `Nuxt instance is unavailable` then it probably means you are calling a Nuxt composable in the wrong place in the Vue or Nuxt lifecycle. -See the full explanation in this [comment](https://github.com/nuxt/nuxt/issues/14269#issuecomment-1397352832). - -::NeedContribution +::read-more{to="/docs/guide/going-further/experimental-features#asynccontext" icon="i-ph-star-duotone"} +Checkout the `asyncContext` experimental feature to use Nuxt composables in async functions. :: -##### Example +::read-more{to="https://github.com/nuxt/nuxt/issues/14269#issuecomment-1397352832" target="_blank"} +See the full explanation in this GitHub comment. +:: -**Example:** Breaking code: +**Example of breaking code:** ```ts [composables/example.ts] // trying to access runtime config outside a composable @@ -78,7 +79,7 @@ export const useMyComposable = () => { } ``` -**Example:** Fixing the error: +**Example of working code:** ```ts [composables/example.ts] export const useMyComposable = () => { @@ -90,7 +91,7 @@ export const useMyComposable = () => { } ``` -### Directory-based Auto-imports +## Directory-based Auto-imports Nuxt directly auto-imports files created in defined directories: @@ -98,6 +99,8 @@ Nuxt directly auto-imports files created in defined directories: - `composables/` for [Vue composables](/docs/guide/directory-structure/composables). - `utils/` for helper functions and other utilities. +:link-example{to="/docs/examples/features/auto-imports"} + ### Explicit Imports Nuxt exposes every auto-import with the `#imports` alias that can be used to make the import explicit if needed: @@ -129,7 +132,7 @@ This will disable auto-imports completely but it's still possible to use [explic Nuxt also automatically imports components from your `~/components` directory, although this is configured separately from auto-importing composables and utility functions. -:ReadMore{link="/docs/guide/directory-structure/components"} +:read-more{to="/docs/guide/directory-structure/components"} To disable auto-importing components from your own `~/components` directory, you can set `components.dirs` to an empty array (though note that this will not affect components added by modules). @@ -145,7 +148,7 @@ export default defineNuxtConfig({ Nuxt also allows auto-importing from third-party packages. -::alert +::callout If you are using the Nuxt module for that package, it is likely that the module has already configured auto-imports for that package. :: diff --git a/docs/2.guide/1.concepts/2.vuejs-development.md b/docs/2.guide/1.concepts/2.vuejs-development.md index 8209ee832f..8d3b1c40ee 100644 --- a/docs/2.guide/1.concepts/2.vuejs-development.md +++ b/docs/2.guide/1.concepts/2.vuejs-development.md @@ -1,15 +1,17 @@ --- -description: "Nuxt uses Vue and adds features such as component auto-imports and file-based routing." +title: 'Vue.js Development' +description: "Nuxt uses Vue.js and adds features such as component auto-imports, file-based routing and composables for a SSR-friendly usage." --- -# Vue.js Development +Nuxt integrates Vue 3, the new major release of Vue that enables new patterns for Nuxt users. -Nuxt uses Vue as a frontend framework and adds features such as component auto-imports and file-based routing. Nuxt 3 integrates Vue 3, the new major release of Vue that enables new patterns for Nuxt users. +::callout +While an in-depth knowledge of Vue is not required to use Nuxt, we recommend that you read the documentation and go through some of the examples on [vuejs.org](https://vuejs.org/). +:: -> While an in-depth knowledge of Vue is not required to use Nuxt, we recommend that you read the documentation and go through some of the examples on [vuejs.org](https://vuejs.org/). -> +Nuxt has always used Vue as a frontend framework. -Nuxt has always used Vue as a frontend framework. We chose to build Nuxt on top of Vue for these reasons: +We chose to build Nuxt on top of Vue for these reasons: - The reactivity model of Vue, where a change in data automatically triggers a change in the interface. - The component-based templating, while keeping HTML as the common language of the web, enables intuitive patterns to keep your interface consistent, yet powerful. @@ -19,34 +21,21 @@ Nuxt has always used Vue as a frontend framework. We chose to build Nuxt on top ### Single File Components -[Vue’s single-file components](https://v3.vuejs.org/guide/single-file-component.html) (SFC, or `*.vue` files) encapsulate the markup (` ``` -Note that [h3 utilities](https://github.com/unjs/h3#utilities) are auto-imported. - -:ReadMore{link="https://nitro.unjs.io/guide/routing" title="Nitro Route Handling Docs"} - ## Server Routes Files inside the `~/server/api` are automatically prefixed with `/api` in their route. @@ -56,8 +55,8 @@ export default defineEventHandler(() => 'Hello World!') Given the example above, the `/hello` route will be accessible at . -::alert{type=info icon=💡} -Note that currently server routes do not support the full functionality of dynamic routes as [pages](https://nuxt.com/docs/guide/directory-structure/pages#dynamic-routes) do. +::callout +Note that currently server routes do not support the full functionality of dynamic routes as [pages](/docs/guide/directory-structure/pages#dynamic-routes) do. :: ## Server Middleware @@ -66,7 +65,7 @@ Nuxt will automatically read in any file in the `~/server/middleware` to create Middleware handlers will run on every request before any other server route to add or check headers, log requests, or extend the event's request object. -::alert{type=warning} +::callout Middleware handlers should not return anything (nor close or respond to the request) and only inspect or extend the request context or throw an error. :: @@ -96,13 +95,13 @@ export default defineNitroPlugin((nitroApp) => { }) ``` -:ReadMore{link="https://nitro.unjs.io/guide/plugins" title="Nitro Plugins"} +:read-more{to="https://nitro.unjs.io/guide/plugins" title="Nitro Plugins" target="_blank"} ## Server Utilities Server routes are powered by [unjs/h3](https://github.com/unjs/h3) which comes with a handy set of helpers. -:ReadMore{link="https://www.jsdocs.io/package/h3#package-index-functions" title="Available H3 Request Helpers"} +:read-more{to="https://www.jsdocs.io/package/h3#package-index-functions" title="Available H3 Request Helpers" target="_blank"} You can add more helpers yourself inside the `~/server/utils` directory. @@ -131,7 +130,7 @@ export const defineWrappedResponseHandler = ( ## Server Types -::alert{type="info"} +::callout This feature is available from Nuxt >= 3.5 :: @@ -143,24 +142,23 @@ To improve clarity within your IDE between the auto-imports from 'nitro' and 'vu } ``` -Although right now these values won't be respected when type checking (`nuxi typecheck`), you should get better type hints in your IDE. +Although right now these values won't be respected when type checking ([`nuxi typecheck`](/docs/api/commands/typecheck)), you should get better type hints in your IDE. -## Usage Examples +## Recipes -### Matching Route Parameters +### Route Parameters Server routes can use dynamic parameters within brackets in the file name like `/api/hello/[name].ts` and be accessed via `event.context.params`. -**Example:** - ```ts [server/api/hello/[name\\].ts] export default defineEventHandler((event) => { const name = getRouterParam(event, 'name') + return `Hello, ${name}!` }) ``` -You can now universally call this API using `await $fetch('/api/hello/nuxt')` and get `Hello, nuxt!`. +You can now universally call this API on `/api/hello/nuxt` and get `Hello, nuxt!`. ### Matching HTTP Method @@ -180,87 +178,99 @@ Given the example above, fetching `/test` with: - **POST** method: Returns `Test post handler` - Any other method: Returns 405 error -You can also use `index.[method].ts` inside a directory for structuring your code differently. - -**Example:** - -```ts [server/api/foo/index.ts] -export default defineEventHandler((event) => { - // handle the `api/foo` endpoint -}) -``` - -This is useful to create API namespaces. - -**Examples:** +You can also use `index.[method].ts` inside a directory for structuring your code differently, this is useful to create API namespaces. +::code-group ```ts [server/api/foo/index.get.ts] export default defineEventHandler((event) => { // handle GET requests for the `api/foo` endpoint }) ``` - ```ts [server/api/foo/index.post.ts] export default defineEventHandler((event) => { // handle POST requests for the `api/foo` endpoint }) ``` - ```ts [server/api/foo/bar.get.ts] export default defineEventHandler((event) => { // handle GET requests for the `api/foo/bar` endpoint }) ``` +:: ### Catch-all Route -Catch-all routes are helpful for fallback route handling. For example, creating a file named `~/server/api/foo/[...].ts` will register a catch-all route for all requests that do not match any route handler, such as `/api/foo/bar/baz`. +Catch-all routes are helpful for fallback route handling. -**Examples:** +For example, creating a file named `~/server/api/foo/[...].ts` will register a catch-all route for all requests that do not match any route handler, such as `/api/foo/bar/baz`. ```ts [server/api/foo/[...\\].ts] -export default defineEventHandler(() => `Default foo handler`) -``` - -```ts [server/api/[...\\].ts] -export default defineEventHandler(() => `Default api handler`) -``` - -### Handling Requests with Body - -```ts [server/api/submit.post.ts] -export default defineEventHandler(async (event) => { - const body = await readBody(event) - return { body } +export default defineEventHandler((event) => { + // event.context.path to get the route path: '/api/foo/bar/baz' + // event.context.params._ to get the route segment: 'bar/baz' + return `Default foo handler` }) ``` -You can now universally call this API using `$fetch('/api/submit', { method: 'post', body: { test: 123 } })`. +You can set a name for the catch-all route by using `~/server/api/foo/[...slug].ts` and access it via `event.context.params.slug`. -::alert{type=warning title=Attention} +```ts [server/api/foo/[...slug\\].ts] +export default defineEventHandler((event) => { + // event.context.params.slug to get the route segment: 'bar/baz' + return `Default foo handler` +}) +``` + +### Body Handling + +```ts [server/api/submit.post.ts] +export default defineEventHandler(async (event) => { + const body = await readBody(event) + return { body } +}) +``` + +You can now universally call this API using: + +```vue [app.vue] + +``` + +::callout We are using `submit.post.ts` in the filename only to match requests with `POST` method that can accept the request body. When using `readBody` within a GET request, `readBody` will throw a `405 Method Not Allowed` HTTP error. :: -### Handling Requests With Query Parameters +### Query Parameters -Sample query `/api/query?param1=a¶m2=b` +Sample query `/api/query?foo=bar&baz=qux` ```ts [server/api/query.get.ts] export default defineEventHandler((event) => { const query = getQuery(event) - return { a: query.param1, b: query.param2 } + + return { a: query.foo, b: query.baz } }) ``` -### Error handling +### Error Handling -If no errors are thrown, a status code of `200 OK` will be returned. Any uncaught errors will return a `500 Internal Server Error` HTTP Error. +If no errors are thrown, a status code of `200 OK` will be returned. -To return other error codes, throw an exception with `createError` +Any uncaught errors will return a `500 Internal Server Error` HTTP Error. + +To return other error codes, throw an exception with [`createError`](/docs/api/utils/create-error): ```ts [server/api/validation/[id\\].ts] export default defineEventHandler((event) => { const id = parseInt(event.context.params.id) as number + if (!Number.isInteger(id)) { throw createError({ statusCode: 400, @@ -271,9 +281,9 @@ export default defineEventHandler((event) => { }) ``` -### Returning other status codes +### Status Codes -To return other status codes, you can use the `setResponseStatus` utility. +To return other status codes, use the [`setResponseStatus`](/docs/api/utils/set-response-status) utility. For example, to return `202 Accepted` @@ -283,32 +293,55 @@ export default defineEventHandler((event) => { }) ``` -### Accessing Runtime Config +### Runtime Config +::code-group ```ts [server/api/foo.ts] +export default defineEventHandler(async (event) => { + const config = useRuntimeConfig(event) -export default defineEventHandler((event) => { - const config = useRuntimeConfig() - return { key: config.KEY } + const repo = await $fetch('https://api.github.com/repos/nuxt/nuxt', { + headers: { + Authorization: `token ${config.githubToken}` + } + }) + + return repo }) ``` +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + runtimeConfig: { + githubToken: '' + } +}) +``` +```bash [.env] +NUXT_GITHUB_TOKEN='' +``` +:: -### Accessing Request Cookies +::callout +Giving the `event` as argument to `useRuntimeConfig` is optional, but it is recommended to pass it to get the runtime config overwritten by [environment variables](/docs/guide/going-further/runtime-config#environment-variables) at runtime for server routes. +:: -```ts +### Request Cookies + +```ts [server/api/cookies.ts] export default defineEventHandler((event) => { const cookies = parseCookies(event) + return { cookies } }) ``` -## Advanced Usage Examples +## Advanced Usage -### Nitro Configuration +### Nitro Config You can use `nitro` key in `nuxt.config` to directly set [Nitro configuration](https://nitro.unjs.io/config). -::alert{type=warning} +::callout{color="amber" icon="i-ph-warning-duotone"} This is an advanced option. Custom config can affect production deployments, as the configuration interface might change over time when Nitro is upgraded in semver-minor versions of Nuxt. :: @@ -319,7 +352,9 @@ export default defineNuxtConfig({ }) ``` -### Using a Nested Router +:read-more{to="/docs/guide/concepts/server-engine"} + +### Nested Router ```ts [server/api/hello/[...slug\\].ts] import { createRouter, defineEventHandler, useBase } from 'h3' @@ -331,9 +366,11 @@ router.get('/test', defineEventHandler(() => 'Hello World')) export default useBase('/api/hello', router.handler) ``` -### Sending Streams (Experimental) +### Sending Streams -**Note:** This is an experimental feature and is only available within Node.js environments. +::callout +This is an experimental feature and is only available in all environments. +:: ```ts [server/api/foo.get.ts] import fs from 'node:fs' @@ -352,7 +389,7 @@ export default defineEventHandler(async (event) => { }) ``` -### Return a Legacy Handler or Middleware +### Legacy Handler or Middleware ```ts [server/api/legacy.ts] export default fromNodeMiddleware((req, res) => { @@ -360,7 +397,7 @@ export default fromNodeMiddleware((req, res) => { }) ``` -::alert{type=warning} +::callout{color="amber" icon="i-ph-warning-duotone"} Legacy support is possible using [unjs/h3](https://github.com/unjs/h3), but it is advised to avoid legacy handlers as much as you can. :: @@ -371,15 +408,15 @@ export default fromNodeMiddleware((req, res, next) => { }) ``` -::alert{type=warning} -Never combine `next()` callback with a legacy middleware that is `async` or returns a `Promise`! +::callout{color="amber" icon="i-ph-warning-duotone"} +Never combine `next()` callback with a legacy middleware that is `async` or returns a `Promise`. :: ### Server Storage Nitro provides a cross-platform [storage layer](https://nitro.unjs.io/guide/storage). In order to configure additional storage mount points, you can use `nitro.storage`, or [server plugins](#server-plugins). -#### Example: Using Redis +**Example of adding a Redis storage:** Using `nitro.storage`: @@ -387,7 +424,7 @@ Using `nitro.storage`: export default defineNuxtConfig({ nitro: { storage: { - 'redis': { + redis: { driver: 'redis', /* redis connector options */ port: 6379, // Redis port @@ -402,10 +439,30 @@ export default defineNuxtConfig({ }) ``` -Alternatively, using server plugins: +Then in your API handler: + +```ts [server/api/storage/test.ts] +export default defineEventHandler(async (event) => { + // List all keys with + const keys = await useStorage('redis').getKeys() + + // Set a key with + await useStorage('redis').setItem('foo', 'bar') + + // Remove a key with + await useStorage('redis').removeItem('foo') + + return {} +}) +``` + +::read-more{to="https://nitro.unjs.io/guide/storage" target="_blank"} +Read more about Nitro Storage Layer. +:: + +Alternatively, you can create a storage mount point using a server plugin and runtime config: ::code-group - ```ts [server/plugins/storage.ts] import redisDriver from 'unstorage/drivers/redis' @@ -436,45 +493,4 @@ export default defineNuxtConfig({ } }) ``` - :: - -Create a new file in `server/api/test.post.ts`: - -```ts [server/api/test.post.ts] -export default defineEventHandler(async (event) => { - const body = await readBody(event) - await useStorage().setItem('redis:test', body) - return 'Data is set' -}) -``` - -Create a new file in `server/api/test.get.ts`: - -```ts [server/api/test.get.ts] -export default defineEventHandler(async (event) => { - const data = await useStorage().getItem('redis:test') - return data -}) -``` - -Create a new file in `app.vue`: - -```vue [app.vue] - - - -``` - -::ReadMore{link="/docs/guide/directory-structure/server"} diff --git a/docs/2.guide/2.directory-structure/1.utils.md b/docs/2.guide/2.directory-structure/1.utils.md index 97d257f3cc..9201dc37fb 100644 --- a/docs/2.guide/2.directory-structure/1.utils.md +++ b/docs/2.guide/2.directory-structure/1.utils.md @@ -1,20 +1,49 @@ --- -navigation.icon: IconDirectory title: 'utils' head.title: 'utils/' description: Use the utils/ directory to auto-import your utility functions throughout your application. +navigation.icon: i-ph-folder-duotone --- -# Utils Directory - -Nuxt 3 uses the [`utils/` directory](/docs/guide/directory-structure/utils) to automatically import helper functions and other utilities throughout your application using [auto-imports](/docs/guide/concepts/auto-imports)! - -::alert{type=info} The main purpose of the [`utils/` directory](/docs/guide/directory-structure/utils) is to allow a semantic distinction between your Vue composables and other auto-imported utility functions. -The way `utils/` auto-imports work and are scanned is identical to [the composables/ directory](/docs/guide/directory-structure/composables). You can see examples and more information about how they work in that section of the docs. +## Usage + +**Method 1:** Using named export + +```js [utils/index.ts] +export const { format: formatNumber } = Intl.NumberFormat('en-GB', { + notation: 'compact', + maximumFractionDigits: 1 +}) +``` + +**Method 2:** Using default export + +```js [utils/random-entry.ts or utils/randomEntry.ts] +// It will be available as randomEntry() (camelCase of file name without extension) +export default function (arr: Array) { + return arr[Math.floor(Math.random() * arr.length)] +} +``` + +You can now use auto imported utility functions in `.js`, `.ts` and `.vue` files + +```vue [app.vue] + +``` + +:read-more{to="/docs/guide/concepts/auto-imports"} + +:link-example{to="/docs/examples/features/auto-imports"} + +::callout +The way `utils/` auto-imports work and are scanned is identical to the [`composables/`](/docs/guide/directory-structure/composables) directory. :: -::alert{type=info} -These utils are only available within the Vue part of your app. Within the [server directory](/docs/guide/directory-structure/server#server-utilities), we auto import exported functions and variables from `~/server/utils` instead. +::callout{color="amber" icon="i-ph-warning-duotone"} +These utils are only available within the Vue part of your app. :br +Only `server/utils` are auto-imported in the [`server/`](/docs/guide/directory-structure/server#server-utilities) directory. :: diff --git a/docs/2.guide/2.directory-structure/2.env.md b/docs/2.guide/2.directory-structure/2.env.md index 1d353907b6..3932c4e2ad 100644 --- a/docs/2.guide/2.directory-structure/2.env.md +++ b/docs/2.guide/2.directory-structure/2.env.md @@ -1,50 +1,57 @@ --- -navigation.icon: IconFile title: ".env" description: "A .env file specifies your build/dev-time environment variables." head.title: ".env" +navigation.icon: i-ph-file-duotone --- -# .env File - -## At Build, Dev, and Generate Time - -Nuxt CLI has built-in [dotenv](https://github.com/motdotla/dotenv) support in development mode and when running `nuxi build` and `nuxi generate`. - -In addition to any process environment variables, if you have a `.env` file in your project root directory, it will be automatically loaded **at build, dev, and generate time**, and any environment variables set there will be accessible within your `nuxt.config` file and modules. - -::alert -If you want to use a different file - for example, to use `.env.local` or `.env.production` - you can do so by passing the `--dotenv` flag when using `nuxi`. For example: - -```bash -npx nuxi dev --dotenv .env.local -``` - -Just as above, this will only apply in development mode and when running `nuxi build` and `nuxi generate`. +::callout{icon="i-ph-warning-duotone" color="amber"} +This file should be added to your [`.gitignore`](/docs/guide/directory-structure/gitignore) file to avoid pushing secrets to your repository. :: -When updating `.env` in development mode, the Nuxt instance is automatically restarted to apply new values to the `process.env`. +## Dev, Build and Generate Time -::alert{type=warning} +Nuxt CLI has built-in [dotenv](https://github.com/motdotla/dotenv) support in development mode and when running [`nuxi build`](/docs/api/commands/build) and [`nuxi generate`](/docs/api/commands/generate). + +In addition to any process environment variables, if you have a `.env` file in your project root directory, it will be automatically loaded **at dev, build and generate time**. Any environment variables set there will be accessible within your `nuxt.config` file and modules. + +```bash [.env] +MY_ENV_VARIABLE=hello +``` + +::callout Note that removing a variable from `.env` or removing the `.env` file entirely will not unset values that have already been set. :: +## Custom File + +If you want to use a different file - for example, to use `.env.local` or `.env.production` - you can do so by passing the `--dotenv` flag when using `nuxi`. + +```bash [Terminal] +npx nuxi dev --dotenv .env.local +``` + +When updating `.env` in development mode, the Nuxt instance is automatically restarted to apply new values to the `process.env`. + ## Production Preview -**After your server is built**, you are responsible for setting environment variables when you run the server. Your `.env` file will not be read at this point. How you do this is different for every environment. +**After your server is built**, you are responsible for setting environment variables when you run the server. -For local production preview purpose, we recommend using [`nuxi preview`](https://nuxt.com/docs/api/commands/preview) since using this command, the `.env` file will be loaded into `process.env` for convenience. Note that this command requires dependencies to be installed in the package directory. +Your `.env` file will not be read at this point. How you do this is different for every environment. + +For local production preview purpose, we recommend using [`nuxi preview`](/docs/api/commands/preview) since using this command, the `.env` file will be loaded into `process.env` for convenience. Note that this command requires dependencies to be installed in the package directory. Or you could pass the environment variables as arguments using the terminal. For example, on Linux or macOS: -```bash +```bash [Terminal] DATABASE_HOST=mydatabaseconnectionstring node .output/server/index.mjs ``` Note that for a purely static site, it is not possible to set runtime configuration config after your project is prerendered. -:ReadMore{link="/docs/guide/going-further/runtime-config"} +:read-more{to="/docs/guide/going-further/runtime-config"} +::callout If you want to use environment variables set at build time but do not care about updating these down the line (or only need to update them reactively _within_ your app) then `appConfig` may be a better choice. You can define `appConfig` both within your `nuxt.config` (using environment variables) and also within an `~/app.config.ts` file in your project. - -:ReadMore{link="/docs/guide/directory-structure/app-config"} +:read-more{to="/docs/guide/directory-structure/app-config"} +:: diff --git a/docs/2.guide/2.directory-structure/2.gitignore.md b/docs/2.guide/2.directory-structure/2.gitignore.md index d2020a77fb..515959e0c0 100644 --- a/docs/2.guide/2.directory-structure/2.gitignore.md +++ b/docs/2.guide/2.directory-structure/2.gitignore.md @@ -1,13 +1,13 @@ --- -navigation.icon: IconFile title: ".gitignore" description: "A .gitignore file specifies intentionally untracked files that git should ignore." head.title: ".gitignore" +navigation.icon: i-ph-file-duotone --- -# Git Ignore File +A `.gitignore` file specifies intentionally untracked files that git should ignore. -A `.gitignore` file specifies intentionally untracked files that git should ignore. Learn more about it in [the git documentation](https://git-scm.com/docs/gitignore). +:read-more{icon="i-simple-icons-git" color="gray" title="the git documentation" to="https://git-scm.com/docs/gitignore" target="_blank"} We recommend having a `.gitignore` file that has **at least** the following entries present: diff --git a/docs/2.guide/2.directory-structure/2.nuxtignore.md b/docs/2.guide/2.directory-structure/2.nuxtignore.md index 4fbdb38b47..b222f4dab9 100644 --- a/docs/2.guide/2.directory-structure/2.nuxtignore.md +++ b/docs/2.guide/2.directory-structure/2.nuxtignore.md @@ -1,17 +1,19 @@ --- -navigation.icon: IconFile title: .nuxtignore head.title: '.nuxtignore' description: The .nuxtignore file lets Nuxt ignore files in your project’s root directory during the build phase. +navigation.icon: i-ph-file-duotone --- -# Nuxt Ignore File +The `.nuxtignore` file tells Nuxt to ignore files in your project’s root directory ([`rootDir`](/docs/api/nuxt-config#rootdir)) during the build phase. -The `.nuxtignore` file lets Nuxt ignore `layouts`, `pages`, `components`, `composables` and `middleware` files in your project’s root directory (`rootDir`) during the build phase. The `.nuxtignore` file is subject to the same specification as `.gitignore` and `.eslintignore` files, in which each line is a glob pattern indicating which files should be ignored. +It is subject to the same specification as [`.gitignore`](/docs/guide/directory-structure/gitignore) and `.eslintignore` files, in which each line is a glob pattern indicating which files should be ignored. -**Note**: You can also configure [`ignoreOptions`](/docs/api/configuration/nuxt-config#ignoreoptions), [`ignorePrefix`](/docs/api/configuration/nuxt-config#ignoreprefix) and [`ignore`](/docs/api/configuration/nuxt-config#ignore) in your `nuxt.config` file. +::callout +You can also configure [`ignoreOptions`](/docs/api/nuxt-config#ignoreoptions), [`ignorePrefix`](/docs/api/nuxt-config#ignoreprefix) and [`ignore`](/docs/api/nuxt-config#ignore) in your `nuxt.config` file. +:: -## Example +## Usage ```bash [.nuxtignore] # ignore layout foo.vue @@ -29,4 +31,6 @@ middleware/foo/*.js !middleware/foo/bar.js ``` -> More details about the spec are in the [gitignore doc](https://git-scm.com/docs/gitignore). +::read-more{icon="i-simple-icons-git" color="gray" title="the git documentation" to="https://git-scm.com/docs/gitignore" target="_blank"} +More details about the spec are in the **gitignore documentation**. +:: diff --git a/docs/2.guide/2.directory-structure/3.app-config.md b/docs/2.guide/2.directory-structure/3.app-config.md index 5aa08da7b0..b2e9dba7f3 100644 --- a/docs/2.guide/2.directory-structure/3.app-config.md +++ b/docs/2.guide/2.directory-structure/3.app-config.md @@ -1,12 +1,10 @@ --- -navigation.icon: IconFile title: app.config.ts head.title: 'app.config.ts' -description: Nuxt 3 provides the app.config file to expose reactive configuration within your application. +description: Expose reactive configuration within your application with the App Config file. +navigation.icon: i-ph-file-duotone --- -# App Config File - Nuxt 3 provides an `app.config` config file to expose reactive configuration within your application with the ability to update it at runtime within lifecycle or using a nuxt plugin and editing it with HMR (hot-module-replacement). You can easily provide runtime app configuration using `app.config.ts` file. It can have either of `.ts`, `.js`, or `.mjs` extensions. @@ -17,16 +15,14 @@ export default defineAppConfig({ }) ``` -::alert{type=warning} +::callout{color="amber" icon="i-ph-warning-duotone"} Do not put any secret values inside `app.config` file. It is exposed to the user client bundle. :: -## Defining App Config +## Usage To expose config and environment variables to the rest of your app, you will need to define configuration in `app.config` file. -**Example:** - ```ts [app.config.ts] export default defineAppConfig({ theme: { @@ -35,21 +31,23 @@ export default defineAppConfig({ }) ``` -When adding `theme` to the `app.config`, Nuxt uses Vite or webpack to bundle the code. We can universally access `theme` both when server-rendering the page and in the browser using [useAppConfig](/docs/api/composables/use-app-config) composable. +When adding `theme` to the `app.config`, Nuxt uses Vite or webpack to bundle the code. We can universally access `theme` both when server-rendering the page and in the browser using [`useAppConfig`](/docs/api/composables/use-app-config) composable. -```js +```vue [pages/index.vue] + ``` -### Manually Typing App Config +## Typing App Config -Nuxt tries to automatically generate a TypeScript interface from provided app config. +Nuxt tries to automatically generate a TypeScript interface from provided app config so you won't have to type it yourself. -It is also possible to type app config manually. There are two possible things you might want to type. +However, there are some cases where you might want to type it yourself. There are two possible things you might want to type. -#### Typing App Config Input +### App Config Input `AppConfigInput` might be used by module authors who are declaring what valid _input_ options are when setting app config. This will not affect the type of `useAppConfig()`. @@ -68,11 +66,11 @@ declare module 'nuxt/schema' { export {} ``` -#### Typing App Config Output +### App Config Output -If you want to type the result of calling `useAppConfig()`, then you will want to extend `AppConfig`. +If you want to type the result of calling [`useAppConfig()`](/docs/api/composables/use-app-config), then you will want to extend `AppConfig`. -::alert{type=warning} +::callout{color="amber" icon="i-ph-warning-duotone"} Be careful when typing `AppConfig` as you will overwrite the types Nuxt infers from your actually defined app config. :: @@ -92,12 +90,13 @@ declare module 'nuxt/schema' { export {} ``` -### App Config Merging Strategy in Layers +## Merging Strategy + +Nuxt uses a custom merging strategy for the `AppConfig` within [the layers](/docs/getting-started/layers) of your application. -Nuxt uses a custom merging strategy for the `AppConfig` within the layers of your application. This strategy is implemented using a [Function Merger](https://github.com/unjs/defu#function-merger), which allows defining a custom merging strategy for every key in `app.config` that has an array as value. -::alert{type=warning} +::callout The Function Merger should only be used in the base `app.config` of your application. :: diff --git a/docs/2.guide/2.directory-structure/3.app.md b/docs/2.guide/2.directory-structure/3.app.md index da3facadba..e56bea7691 100644 --- a/docs/2.guide/2.directory-structure/3.app.md +++ b/docs/2.guide/2.directory-structure/3.app.md @@ -1,15 +1,11 @@ --- -navigation.icon: IconFile title: "app.vue" -description: "The app.vue file is the main component in your Nuxt 3 applications." +description: "The app.vue file is the main component of your Nuxt application." head.title: "app.vue" +navigation.icon: i-ph-file-duotone --- -# App file - -The `app.vue` file is the main component in your Nuxt 3 applications. - -## Minimal usage +## Minimal Usage With Nuxt 3, the [`pages/`](/docs/guide/directory-structure/pages) directory is optional. If not present, Nuxt won't include [vue-router](https://router.vuejs.org/) dependency. This is useful when working on a landing page or an application that does not need routing. @@ -19,9 +15,11 @@ With Nuxt 3, the [`pages/`](/docs/guide/directory-structure/pages) directory is ``` -## Usage With Pages +:link-example{to="/docs/examples/hello-world"} -If you have a [`pages/`](/docs/guide/directory-structure/pages) directory, to display the current page, use the `` component: +## Usage with Pages + +If you have a [`pages/`](/docs/guide/directory-structure/pages) directory, to display the current page, use the [``](/docs/api/components/nuxt-page) component: ```vue [app.vue] ``` -::alert{type=danger} -Since `` internally uses the [``](https://vuejs.org/guide/built-ins/suspense.html#suspense) component, `` cannot be set as a root element. +::callout{color="amber" icon="i-ph-warning-duotone"} +Since [``](/docs/api/components/nuxt-page) internally uses Vue's [``](https://vuejs.org/guide/built-ins/suspense.html#suspense) component, it cannot be set as a root element. :: -::alert{type=warning} +::callout{color="blue" icon="i-ph-info-duotone"} Remember that `app.vue` acts as the main component of your Nuxt application. Anything you add to it (JS and CSS) will be global and included in every page. :: -If you want to have the possibility to customize the structure around the page between pages, check out the [`layouts/`](/docs/guide/directory-structure/layouts) directory. +::read-more{to="/docs/guide/directory-structure/layouts"} +If you want to have the possibility to customize the structure around the page between pages, check out the `layouts/` directory. +:: diff --git a/docs/2.guide/2.directory-structure/3.nuxt.config.md b/docs/2.guide/2.directory-structure/3.nuxt.config.md index fda0cee7b8..e7a81c8240 100644 --- a/docs/2.guide/2.directory-structure/3.nuxt.config.md +++ b/docs/2.guide/2.directory-structure/3.nuxt.config.md @@ -1,28 +1,26 @@ --- -navigation.icon: IconFile title: "nuxt.config.ts" description: "Nuxt can be easily configured with a single nuxt.config file." head.title: "nuxt.config.ts" +navigation.icon: i-ph-file-duotone --- -# Nuxt Config File +The `nuxt.config` file extension can either be `.js`, `.ts` or `.mjs`. -Nuxt can be easily configured with a single `nuxt.config` file, which can have either a `.js`, `.ts` or `.mjs` extension. - -```ts +```ts [nuxt.config.ts] export default defineNuxtConfig({ // My Nuxt config }) ``` -::alert +::callout `defineNuxtConfig` helper is globally available without import. :: You can explicitly import `defineNuxtConfig` from `nuxt/config` if you prefer: -```js +```ts [nuxt.config.ts] import { defineNuxtConfig } from 'nuxt/config' export default defineNuxtConfig({ @@ -30,7 +28,17 @@ export default defineNuxtConfig({ }) ``` -To ensure your configuration is up to date, Nuxt will make a full restart when detecting changes in the main configuration file, the `.env`, `.nuxtignore` and `.nuxtrc` dotfiles. - -::ReadMore{link="/docs/api/configuration/nuxt-config"} +::read-more{to="/docs/api/configuration/nuxt-config"} +Discover all the available options in the **Nuxt configuration** documentation. :: + +To ensure your configuration is up to date, Nuxt will make a full restart when detecting changes in the main configuration file, the [`.env`](/docs/guide/directory-structure/env), [`.nuxtignore`](/docs/guide/directory-structure/nuxtignore) and `.nuxtrc` dotfiles. + + +The `.nuxtrc` file is a file that can be used to configure Nuxt with a fla syntax, it is based on [`unjs/rc9`](https://github.com/unjs/rc9). + +``` [.nuxtrc] +ssr=false +``` + +If prevent the properties in `.nuxtrc` file will overwrite the properties in the `nuxt.config` file. diff --git a/docs/2.guide/2.directory-structure/3.package.md b/docs/2.guide/2.directory-structure/3.package.md index bb9d7c98e0..ad5757fbf0 100644 --- a/docs/2.guide/2.directory-structure/3.package.md +++ b/docs/2.guide/2.directory-structure/3.package.md @@ -1,10 +1,33 @@ --- -navigation.icon: IconFile title: package.json head.title: package.json description: The package.json file contains all the dependencies and scripts for your application. +navigation.icon: i-ph-file-duotone --- -# Package.json File +The minimal `package.json` of your Nuxt application should looks like: -The `package.json` file contains all the dependencies and scripts for your application ([learn more](https://docs.npmjs.com/cli/configuring-npm/package-json)). +```json [package.json] +{ + "name": "nuxt-app", + "private": true, + "type": "module", + "scripts": { + "build": "nuxt build", + "dev": "nuxt dev", + "generate": "nuxt generate", + "preview": "nuxt preview", + "postinstall": "nuxt prepare" + }, + "devDependencies": { + "@nuxt/devtools": "latest", + "nuxt": "latest", + "vue": "latest", + "vue-router": "latest" + } +} +``` + +::read-more{icon="i-simple-icons-npm" color="gray" to="https://docs.npmjs.com/cli/configuring-npm/package-json" target="_blank"} +Read more about the `package.json` file. +:: diff --git a/docs/2.guide/2.directory-structure/3.tsconfig.md b/docs/2.guide/2.directory-structure/3.tsconfig.md index 8210ce9d4c..edcc1a7cbc 100644 --- a/docs/2.guide/2.directory-structure/3.tsconfig.md +++ b/docs/2.guide/2.directory-structure/3.tsconfig.md @@ -1,18 +1,24 @@ --- -navigation.icon: IconFile title: "tsconfig.json" description: "Nuxt generates a .nuxt/tsconfig.json file with sensible defaults and your aliases." head.title: "tsconfig.json" +navigation.icon: i-ph-file-duotone --- -# TypeScript Configuration File +Nuxt [automatically generates](/docs/guide/concepts/typescript) a `.nuxt/tsconfig.json` file with the resolved aliases you are using in your Nuxt project, as well as with other sensible defaults. -Nuxt [automatically generates](/docs/guide/concepts/typescript) a `.nuxt/tsconfig.json` file with the resolved aliases you are using in your Nuxt project, as well as with other sensible defaults. You can benefit from this by creating a `tsconfig.json` in the root of your project with the following content: +You can benefit from this by creating a `tsconfig.json` in the root of your project with the following content: -```json +```json [tsconfig.json] { "extends": "./.nuxt/tsconfig.json" } ``` -As you need to, you can customize the contents of this file. However, it is recommended that you don't overwrite `target`, `module` and `moduleResolution`. Moreover, note that if you need to customize your `paths`, this will override the auto-generated path aliases. Instead, we recommend that you add any path aliases you need to the `alias` property within your `nuxt.config`, where they will get picked up and added to the auto-generated `tsconfig`. +::callout +As you need to, you can customize the contents of this file. However, it is recommended that you don't overwrite `target`, `module` and `moduleResolution`. +:: + +::callout +If you need to customize your `paths`, this will override the auto-generated path aliases. Instead, we recommend that you add any path aliases you need to the [`alias`](/docs/api/nuxt-config#alias) property within your `nuxt.config`, where they will get picked up and added to the auto-generated `tsconfig`. +:: diff --git a/docs/2.guide/2.directory-structure/_dir.yml b/docs/2.guide/2.directory-structure/_dir.yml index af618270a4..4d663658ad 100644 --- a/docs/2.guide/2.directory-structure/_dir.yml +++ b/docs/2.guide/2.directory-structure/_dir.yml @@ -1,4 +1,3 @@ title: Directory Structure titleTemplate: '%s · Nuxt Directory Structure' -navigation.icon: uil:folder-open -image: '/socials/directory-structure.jpg' +icon: i-ph-folders-duotone diff --git a/docs/2.guide/2.directory-structure/index.md b/docs/2.guide/2.directory-structure/index.md deleted file mode 100644 index 1f32316657..0000000000 --- a/docs/2.guide/2.directory-structure/index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -navigation: false -redirect: /guide/directory-structure/nuxt ---- diff --git a/docs/2.guide/3.going-further/1.experimental-features.md b/docs/2.guide/3.going-further/1.experimental-features.md index 6f77a2b8d2..e80d1218f7 100644 --- a/docs/2.guide/3.going-further/1.experimental-features.md +++ b/docs/2.guide/3.going-further/1.experimental-features.md @@ -1,31 +1,42 @@ --- title: "Experimental Features" -description: "Nuxt experimental features needs to be enabled manually." +description: "Enable Nuxt experimental features to unlock new possibilities." --- -# Experimental Features - The Nuxt experimental features can be enabled in the Nuxt configuration file. -Internally, Nuxt uses `@nuxt/schema` to define these experimental features. You can refer to the [API documentation](https://nuxt.com/docs/api/configuration/nuxt-config#experimental) or the [source code](https://github.com/nuxt/nuxt/blob/main/packages/schema/src/config/experimental.ts) for more information. -::alert{type=info icon=💡} +Internally, Nuxt uses `@nuxt/schema` to define these experimental features. You can refer to the [API documentation](/docs/api/configuration/nuxt-config#experimental) or the [source code](https://github.com/nuxt/nuxt/blob/main/packages/schema/src/config/experimental.ts) for more information. + +::callout Note that these features are experimental and could be removed or modified in the future. :: ## asyncContext -Enable native async context to be accessible for nested composables in Nuxt and in Nitro. See [full explanation in #20918](https://github.com/nuxt/nuxt/pull/20918). +Enable native async context to be accessible for nested composables in Nuxt and in Nitro. This opens the possibility to use composables inside async composables and reduce the chance to get the `Nuxt instance is unavailable` error. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { asyncContext: true } }) +export defineNuxtConfig({ + experimental: { + asyncContext: true + } +}) ``` +::read-more{icon="i-simple-icons-github" color="gray" to="https://github.com/nuxt/nuxt/pull/20918" target="_blank"} +See full explanation on the GitHub pull-request. +:: + ## asyncEntry Enables generation of an async entry point for the Vue bundle, aiding module federation support. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { asyncEntry: true } }) +export defineNuxtConfig({ + experimental: { + asyncEntry: true + } +}) ``` ## reactivityTransform @@ -33,65 +44,111 @@ export defineNuxtConfig({ experimental: { asyncEntry: true } }) Enables Vue's reactivity transform. Note that this feature has been marked as deprecated in Vue 3.3 and is planned to be removed from core in Vue 3.4. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { reactivityTransform: true } }) +export defineNuxtConfig({ + experimental: { + reactivityTransform: true + } +}) ``` -::ReadMore{link="/docs/getting-started/configuration#enabling-experimental-vue-features"} -:: +:read-more{to="/docs/getting-started/configuration#enabling-experimental-vue-features"} ## externalVue Externalizes `vue`, `@vue/*` and `vue-router` when building. + *Enabled by default.* ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { externalVue: true } }) +export defineNuxtConfig({ + experimental: { + externalVue: true + } +}) ``` -::alert{type=warning icon=⚠️} -This feature will likely be removed in Nuxt 3.6. +::callout{color="amber" icon="i-ph-warning-duotone"} +This feature will likely be removed in a near future. :: ## treeshakeClientOnly Tree shakes contents of client-only components from server bundle. + *Enabled by default.* ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { treeshakeClientOnly: true } }) +export defineNuxtConfig({ + experimental: { + treeshakeClientOnly: true + } +}) ``` ## emitRouteChunkError Emits `app:chunkError` hook when there is an error loading vite/webpack chunks. Default behavior is to perform a hard reload of the new route when a chunk fails to load. + You can disable automatic handling by setting this to `false`, or handle chunk errors manually by setting it to `manual`. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { emitRouteChunkError: 'automatic' } }) // or 'manual' or false +export defineNuxtConfig({ + experimental: { + emitRouteChunkError: 'automatic' // or 'manual' or false + } +}) ``` ## restoreState -Allows Nuxt app state to be restored from `sessionStorage` when reloading the page after a chunk error or manual `reloadNuxtApp()` call. - To avoid hydration errors, it will be applied only after the Vue app has been mounted, - meaning there may be a flicker on initial load. +Allows Nuxt app state to be restored from `sessionStorage` when reloading the page after a chunk error or manual [`reloadNuxtApp()`](/docs/api/utils/reload-nuxt-app) call. -::alert{type=warning icon=⚠️} +To avoid hydration errors, it will be applied only after the Vue app has been mounted, meaning there may be a flicker on initial load. + +::callout{color="amber" icon="i-ph-warning-duotone"} Consider carefully before enabling this as it can cause unexpected behavior, and consider providing explicit keys to [`useState`](/docs/api/composables/use-state) as auto-generated keys may not match across builds. :: ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { restoreState: true } }) +export defineNuxtConfig({ + experimental: { + restoreState: true + } +}) ``` +## inlineRouteRules + +Define route rules at the page level using [`defineRouteRules`](/docs/api/utils/define-route-rules). + +```ts [nuxt.config.ts] +export defineNuxtConfig({ + experimental: { + inlineRouteRules: true + } +}) +``` + +Matching route rules will be created, based on the page's `path`. + +::read-more{to="/docs/api/utils/define-route-rules" icon="i-ph-function-duotone"} +Read more in `defineRouteRules` utility. +:: + +:read-more{to="/docs/guide/concepts/rendering#hybrid-rendering" icon="i-ph-medal-duotone"} + ## inlineSSRStyles Inlines styles when rendering HTML. This is currently available only when using Vite. You can also pass a function that receives the path of a Vue component and returns a boolean indicating whether to inline the styles for that component. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { inlineSSRStyles: true } }) // or a function to determine inlining +export defineNuxtConfig({ + experimental: { + inlineSSRStyles: true // or a function to determine inlining + } +}) ``` ## noScripts @@ -99,16 +156,25 @@ export defineNuxtConfig({ experimental: { inlineSSRStyles: true } }) // or a fun Disables rendering of Nuxt scripts and JS resource hints. Can also be configured granularly within `routeRules`. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { noScripts: true } }) +export defineNuxtConfig({ + experimental: { + noScripts: true + } +}) ``` ## renderJsonPayloads Allows rendering of JSON payloads with support for revivifying complex types. + *Enabled by default.* ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { renderJsonPayloads: true } }) +export defineNuxtConfig({ + experimental: { + renderJsonPayloads: true + } +}) ``` ## noVueServer @@ -116,7 +182,11 @@ export defineNuxtConfig({ experimental: { renderJsonPayloads: true } }) Disables Vue server renderer endpoint within Nitro. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { noVueServer: true } }) +export defineNuxtConfig({ + experimental: { + noVueServer: true + } +}) ``` ## payloadExtraction @@ -124,15 +194,23 @@ export defineNuxtConfig({ experimental: { noVueServer: true } }) Enables extraction of payloads of pages generated with `nuxt generate`. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { payloadExtraction: true } }) +export defineNuxtConfig({ + experimental: { + payloadExtraction: true + } +}) ``` ## clientFallback -Enables the experimental `` component for rendering content on the client if there's an error in SSR. +Enables the experimental [``](/docs/api/components/nuxt-client-fallback) component for rendering content on the client if there's an error in SSR. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { clientFallback: true } }) +export defineNuxtConfig({ + experimental: { + clientFallback: true + } +}) ``` ## crossOriginPrefetch @@ -140,18 +218,33 @@ export defineNuxtConfig({ experimental: { clientFallback: true } }) Enables cross-origin prefetch using the Speculation Rules API. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { crossOriginPrefetch: true } }) +export defineNuxtConfig({ + experimental: { + crossOriginPrefetch: true + } +}) ``` +::read-more{icon="i-simple-icons-w3c" color="gray" to="https://wicg.github.io/nav-speculation/prefetch.html" target="_blank"} +Read more about the **Speculation Rules API**. +:: + ## viewTransition Enables View Transition API integration with client-side router. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { viewTransition: true } }) +export defineNuxtConfig({ + experimental: { + viewTransition: true + } +}) ``` -::ReadMore{link="/docs/getting-started/transitions#view-transitions-api-experimental"} +:link-example{to="https://stackblitz.com/edit/nuxt-view-transitions?file=app.vue" target="_blank"} + +::read-more{icon="i-simple-icons-mdnwebdocs" color="gray" to="https://developer.mozilla.org/en-US/docs/Web/API/View_Transitions_API" target="_blank"} +Read more about the **View Transition API**. :: ## writeEarlyHints @@ -159,29 +252,43 @@ export defineNuxtConfig({ experimental: { viewTransition: true } }) Enables writing of early hints when using node server. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { writeEarlyHints: true } }) +export defineNuxtConfig({ + experimental: { + writeEarlyHints: true + } +}) ``` ## componentIslands -Enables experimental component islands support with `` and `.island.vue` files. +Enables experimental component islands support with [``](/docs/api/components/nuxt-island) and `.island.vue` files. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { componentIslands: true } }) +export defineNuxtConfig({ + experimental: { + componentIslands: true // false or 'local+remote' + } +}) ``` -::ReadMore{link="/docs/guide/directory-structure/components#server-components"} -:: +:read-more{to="/docs/guide/directory-structure/components#server-components"} -You can follow the server components roadmap on [GitHub](https://github.com/nuxt/nuxt/issues/19772). +::read-more{icon="i-simple-icons-github" color="gray" to="https://github.com/nuxt/nuxt/issues/19772" target="_blank"} +You can follow the server components roadmap on GitHub. +:: ## configSchema Enables config schema support. + *Enabled by default.* ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { configSchema: true } }) +export defineNuxtConfig({ + experimental: { + configSchema: true + } +}) ``` ## polyfillVueUseHead @@ -189,7 +296,11 @@ export defineNuxtConfig({ experimental: { configSchema: true } }) Adds a compatibility layer for modules, plugins, or user code relying on the old `@vueuse/head` API. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { polyfillVueUseHead: false } }) +export defineNuxtConfig({ + experimental: { + polyfillVueUseHead: false + } +}) ``` ## respectNoSSRHeader @@ -197,42 +308,59 @@ export defineNuxtConfig({ experimental: { polyfillVueUseHead: false } }) Allow disabling Nuxt SSR responses by setting the `x-nuxt-no-ssr` header. ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { respectNoSSRHeader: false } }) +export defineNuxtConfig({ + experimental: { + respectNoSSRHeader: false + } +}) ``` ## localLayerAliases Resolve `~`, `~~`, `@` and `@@` aliases located within layers with respect to their layer source and root directories. + *Enabled by default.* ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { localLayerAliases: true } }) +export defineNuxtConfig({ + experimental: { + localLayerAliases: true + } +}) ``` ## typedPages -Enable the new experimental typed router using [unplugin-vue-router](https://github.com/posva/unplugin-vue-router). +Enable the new experimental typed router using [`unplugin-vue-router`](https://github.com/posva/unplugin-vue-router). ```ts [nuxt.config.ts] -export defineNuxtConfig({ experimental: { typedPages: false } }) +export defineNuxtConfig({ + experimental: { + typedPages: false + } +}) ``` -Out of the box, this will enable typed usage of `navigateTo`, ``, `router.push()` and more. +Out of the box, this will enable typed usage of [`navigateTo`](/docs/api/utils/navigate-to), [``](/docs/api/components/nuxt-link), [`router.push()`](/docs/api/composables/use-router) and more. + You can even get typed params within a page by using `const route = useRoute('route-name')`. ## watcher Set an alternative watcher that will be used as the watching service for Nuxt. + Nuxt uses `chokidar-granular` by default, which will ignore top-level directories (like `node_modules` and `.git`) that are excluded from watching. + You can set this instead to `parcel` to use `@parcel/watcher`, which may improve performance in large projects or on Windows platforms. + You can also set this to `chokidar` to watch all files in your source directory. ```ts [nuxt.config.ts] export defineNuxtConfig({ - experimental: { - watcher: 'chokidar-granular' // 'chokidar' or 'parcel' are also options - } + experimental: { + watcher: 'chokidar-granular' // 'chokidar' or 'parcel' are also options + } }) ``` diff --git a/docs/2.guide/3.going-further/1.internals.md b/docs/2.guide/3.going-further/1.internals.md index ea1134b960..e0e60f733d 100644 --- a/docs/2.guide/3.going-further/1.internals.md +++ b/docs/2.guide/3.going-further/1.internals.md @@ -3,18 +3,16 @@ title: "How Nuxt Works?" description: "Nuxt is a minimal but highly customizable framework to build web applications." --- -# How Nuxt Works? - -Nuxt is a minimal but highly customizable framework to build web applications. This guide helps you better understand Nuxt internals to develop new solutions and module integrations on top of Nuxt. +This guide helps you better understand Nuxt internals to develop new solutions and module integrations on top of Nuxt. ## The Nuxt Interface -When you start Nuxt in development mode with `nuxi dev` or building a production application with `nuxi build`, +When you start Nuxt in development mode with [`nuxi dev`](/docs/api/commands/dev) or building a production application with [`nuxi build`](/docs/api/commands/build), a common context will be created, referred to as `nuxt` internally. It holds normalized options merged with `nuxt.config` file, some internal state, and a powerful [hooking system](/docs/api/advanced/hooks) powered by [unjs/hookable](https://github.com/unjs/hookable) allowing different components to communicate with each other. You can think of it as **Builder Core**. -This context is globally available to be used with [nuxt/kit](/docs/api/advanced/kit) composables. +This context is globally available to be used with [Nuxt Kit](/docs/guide/going-further/kit) composables. Therefore only one instance of Nuxt is allowed to run per process. To extend the Nuxt interface and hook into different stages of the build process, we can use [Nuxt Modules](/docs/guide/going-further/modules). @@ -27,7 +25,7 @@ When rendering a page in the browser or on the server, a shared context will be This context keeps vue instance, runtime hooks, and internal states like ssrContext and payload for hydration. You can think of it as **Runtime Core**. -This context can be accessed using `useNuxtApp()` composable within Nuxt plugins and ` +``` + +:link-example{to="/docs/examples/routing/pages"} + +## Page's Ref + +To get the `ref` of a page component, access it through `ref.value.pageRef` + +````vue [app.vue] + + + +```` + +## Custom Props + +In addition, `` also accepts custom props that you may need to pass further down the hierarchy. + +These custom props are accessible via `attrs` in the Nuxt app. + +```html + +``` + +For example, in the above example, the value of `foobar` will be available using `$attrs.foobar` in the template or `useAttrs().foobar` in ` ``` -## Layout and Transition +## Transitions `` renders incoming content via ``, which is then wrapped around Vue’s `` component to activate layout transition. For this to work as expected, it is recommended that `` is **not** the root element of the page component. @@ -81,13 +93,16 @@ In the above example, the value of `title` will be available using `$attrs.title ``` -## Accessing a layout's component ref +:read-more{to="/docs/getting-started/transitions"} + +## Layout's Ref To get the ref of a layout component, access it through `ref.value.layoutRef` -````html +````vue [app.vue] - - -``` - -::alert{type=warning} -`useLazyAsyncData` is a reserved function name transformed by the compiler, so you should not name your own function `useLazyAsyncData`. -:: - -:ReadMore{link="/docs/getting-started/data-fetching#uselazyasyncdata"} diff --git a/docs/3.api/1.composables/use-request-url.md b/docs/3.api/1.composables/use-request-url.md deleted file mode 100644 index ff2b497523..0000000000 --- a/docs/3.api/1.composables/use-request-url.md +++ /dev/null @@ -1,25 +0,0 @@ -# useRequestURL - -`useRequestURL` is a helper function that returns an [URL object](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) working on both server-side and client-side. - -::code-group - -```vue [pages/about.vue] - - - -``` - -```html [Result in development] -

URL is: http://localhost:3000/about

-

Path is: /about

-``` - -:: - -You can find the list of the [URL instance properties](https://developer.mozilla.org/en-US/docs/Web/API/URL#instance_properties) on the MDN documentation. diff --git a/docs/3.api/1.composables/use-router.md b/docs/3.api/1.composables/use-router.md deleted file mode 100644 index 396ed0c2a1..0000000000 --- a/docs/3.api/1.composables/use-router.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "useRouter" -description: "The useRouter composable returns the router instance." ---- - -# `useRouter` - -The [`useRouter`](/docs/api/composables/use-router) composable returns the router instance and must be called in a setup function, plugin, or route middleware. - -Within the template of a Vue component, you can access the router using `$router` instead. - -If you have a `pages/` folder, [`useRouter`](/docs/api/composables/use-router) is identical in behavior to the one provided by `vue-router`. Feel free to read the router documentation for more information on what each method does. - -::ReadMore{link="https://router.vuejs.org/api/interfaces/Router.html#Properties-currentRoute"} -:: - -## Basic Manipulation - -- **addRoute:** Add a new route to the router instance. `parentName` can be provided to add new route as the child of an existing route. -- **removeRoute:** Remove an existing route by its name. -- **getRoutes:** Get a full list of all the route records. -- **hasRoute:** Checks if a route with a given name exists. - -## Based on History API - -- **back:** Go back in history if possible, same as `router.go(-1)`. -- **forward:** Go forward in history if possible, same as `router.go(1)`. -- **go:** Move forward or backward through the history without the hierarchical restrictions enforced in `router.back()` and `router.forward()`. -- **push:** Programmatically navigate to a new URL by pushing an entry in the history stack. **It is recommended to use [`navigateTo`](/docs/api/utils/navigate-to) instead.** -- **replace:** Programmatically navigate to a new URL by replacing the current entry in the routes history stack. **It is recommended to use [`navigateTo`](/docs/api/utils/navigate-to) instead.** - -> TIP: `router.addRoute()` adds route details into an array of routes and it is useful while building Nuxt plugins while `router.push()` on the other hand, triggers a new navigation immediately and it is useful in Nuxt Page components, Vue components and composable. - -```js [js] -const router = useRouter(); -router.back(); -router.forward(); -router.go(); -router.push({ path: "/home" }); -router.replace({ hash: "#bio" }); -```` - -::ReadMore{link="https://developer.mozilla.org/en-US/docs/Web/API/History"} -:: - -## Navigation Guards - -`useRouter` composable provides `afterEach`, `beforeEach` and `beforeResolve` helper methods that acts as navigation guards. - -However, Nuxt has a concept of **route middleware** that simplifies the implementation of navigation guards and provides a better developer experience. - -::ReadMore{link="/docs/guide/directory-structure/middleware"} -:: - -## Promise and Error Handling - -- **isReady:** Returns a Promise that resolves when the router has completed the initial navigation. -- **onError:** Adds an error handler that is called every time a non caught error happens during navigation. -- **resolve:** Returns the normalized version of a route location. Also includes an `href` property that includes any existing base. - -::ReadMore{link="https://router.vuejs.org/api/interfaces/Router.html#Methods"} -:: - -## Universal Router Instance - -If you do not have a `pages/` folder, then [`useRouter`](/docs/api/composables/use-router) will return a universal router instance with similar helper methods, but be aware that not all features may be supported or behave in exactly the same way as with `vue-router`. diff --git a/docs/3.api/1.composables/use-server-seo-meta.md b/docs/3.api/1.composables/use-server-seo-meta.md deleted file mode 100644 index 60b8f94060..0000000000 --- a/docs/3.api/1.composables/use-server-seo-meta.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -description: The useServerSeoMeta composable lets you define your site's SEO meta tags as a flat object with full TypeScript support. ---- - -# `useServerSeoMeta` - -Just like [`useSeoMeta`](/docs/api/composables/use-seo-meta), [`useServerSeoMeta`](/docs/api/composables/use-server-seo-meta) composable lets you define your site's SEO meta tags as a flat object with full TypeScript support. -:ReadMore{link="/docs/api/composables/use-seo-meta"} - -In most instances, the meta doesn't need to be reactive as robots will only scan the initial load. So we recommend using [`useServerSeoMeta`](/docs/api/composables/use-server-seo-meta) as a performance-focused utility that will not do anything (or return a `head` object) on the client. -Parameters are exactly the same as with [`useSeoMeta`](/docs/api/composables/use-seo-meta) diff --git a/docs/3.api/1.composables/use-state.md b/docs/3.api/1.composables/use-state.md deleted file mode 100644 index 9c82f7af60..0000000000 --- a/docs/3.api/1.composables/use-state.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "useState" -description: The useState composable creates a reactive and SSR-friendly shared state. ---- - -# `useState` - -```ts -useState(init?: () => T | Ref): Ref -useState(key: string, init?: () => T | Ref): Ref -``` - -* **key**: A unique key ensuring that data fetching is properly de-duplicated across requests. If you do not provide a key, then a key that is unique to the file and line number of the instance of [`useState`](/docs/api/composables/use-state) will be generated for you. -* **init**: A function that provides initial value for the state when not initiated. This function can also return a `Ref`. -* **T**: (typescript only) Specify the type of state - -::alert{type=warning} -Because the data inside [`useState`](/docs/api/composables/use-state) will be serialized to JSON, it is important that it does not contain anything that cannot be serialized, such as classes, functions or symbols. -:: - -::alert{type=warning} -[`useState`](/docs/api/composables/use-state) is a reserved function name transformed by the compiler, so you should not name your own function `useState`. -:: - -::ReadMore{link="/docs/getting-started/state-management"} -:: - -## Using `shallowRef` - -If you don't need your state to be deeply reactive, you can combine `useState` with [`shallowRef`](https://vuejs.org/api/reactivity-advanced.html#shallowref). This can improve performance when your state contains large objects and arrays. - -```ts -const state = useState('my-shallow-state', () => shallowRef({ deep: 'not reactive' })) -// isShallow(state) === true -``` diff --git a/docs/3.api/2.components/2.nuxt-page.md b/docs/3.api/2.components/2.nuxt-page.md deleted file mode 100644 index 9d050c5c86..0000000000 --- a/docs/3.api/2.components/2.nuxt-page.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: "" -description: The NuxtPage component is required to display pages located in the pages/ directory. ---- - -# `` - -`` is a built-in component that comes with Nuxt. `NuxtPage` is required to display top-level or nested pages located in the [`pages/` directory](/docs/guide/directory-structure/pages). - -`NuxtPage` is a wrapper around [``](https://router.vuejs.org/api/interfaces/RouterViewProps.html#interface-routerviewprops) component from Vue Router. `NuxtPage` component accepts same `name` and `route` props. - -- **name:** type: `string` - -`name` helps `RouterView` render the component with the corresponding name in the matched route record's components option. - -- **route:** type: `RouteLocationNormalized` - -`route` is a route location that has all of its components resolved. - -> **Nuxt automatically resolves the `name` and `route` by scanning and rendering all Vue component files found in the `/pages` directory.** - -Apart from the `name` and `route`, `NuxtPage` component also accepts `pageKey` props. - -- **pageKey:** type: `string` or `function` - -`pageKey` helps control when the `NuxtPage` component is re-rendered. - -## Example - -For example, passing `static` key, `NuxtPage` component is rendered only once when it is mounted. - -```html - - -``` - -You can also use a dynamic key based on the current route. (Don't use `$route` object here as it can cause problems with how `` renders pages with ``.) - -```html - -``` - -Alternatively, `pageKey` can be passed as a `key` value via `definePageMeta` from the ` -``` - -:button-link[Open on StackBlitz]{href="https://stackblitz.com/github/nuxt/examples/tree/main/routing/pages?file=app.vue" blank} - -## Accessing a page's component ref - -To get the ref of a page component, access it through `ref.value.pageRef` - -````html - - - -```` - -## Custom Props - -In addition, `NuxtPage` also accepts custom props that you may need to pass further down the hierarchy. These custom props are accessible via `attrs` in the Nuxt app. - -```html - -``` - -For example, in the above example, the value of `foobar` will be available using `$attrs.foobar` in the template or `useAttrs().foobar` in ` +``` + +### Watch Params + +The built-in `watch` option allows automatically rerunning the fetcher function when any changes are detected. + +```vue [pages/index.vue] + +``` + +::callout{color="amber" icon="i-ph-warning-duotone"} +[`useAsyncData`](/docs/api/composables/use-async-data) is a reserved function name transformed by the compiler, so you should not name your own function [`useAsyncData`](/docs/api/composables/use-async-data) . +:: + +:read-more{to="/docs/getting-started/data-fetching#useasyncdata"} + +## Params + +- `key`: a unique key to ensure that data fetching can be properly de-duplicated across requests. If you do not provide a key, then a key that is unique to the file name and line number of the instance of `useAsyncData` will be generated for you. +- `handler`: an asynchronous function that must return a truthy value (for example, it should not be `undefined` or `null`) or the request may be duplicated on the client side +- `options`: + - `server`: whether to fetch the data on the server (defaults to `true`) + - `lazy`: whether to resolve the async function after loading the route, instead of blocking client-side navigation (defaults to `false`) + - `immediate`: when set to `false`, will prevent the request from firing immediately. (defaults to `true`) + - `default`: a factory function to set the default value of the `data`, before the async function resolves - useful with the `lazy: true` or `immediate: false` option + - `transform`: a function that can be used to alter `handler` function result after resolving + - `pick`: only pick specified keys in this array from the `handler` function result + - `watch`: watch reactive sources to auto-refresh + - `deep`: return data in a deep ref object (it is `true` by default). It can be set to `false` to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive. + +::callout +Under the hood, `lazy: false` uses `` to block the loading of the route before the data has been fetched. Consider using `lazy: true` and implementing a loading state instead for a snappier user experience. +:: + +::read-more{to="/docs/api/composables/use-lazy-async-data"} +You can use `useLazyAsyncData` to have the same behavior as `lazy: true` with `useAsyncData`. +:: + +## Return Values + +- `data`: the result of the asynchronous function that is passed in. +- `pending`: a boolean indicating whether the data is still being fetched. +- `refresh`/`execute`: a function that can be used to refresh the data returned by the `handler` function. +- `error`: an error object if the data fetching failed. +- `status`: a string indicating the status of the data request (`"idle"`, `"pending"`, `"success"`, `"error"`). + +By default, Nuxt waits until a `refresh` is finished before it can be executed again. + +::callout +If you have not fetched data on the server (for example, with `server: false`), then the data _will not_ be fetched until hydration completes. This means even if you await [`useAsyncData`](/docs/api/composables/use-async-data) on the client side, `data` will remain `null` within ` @@ -38,7 +39,7 @@ counter.value = counter.value || Math.round(Math.random() * 1000) ``` -:button-link[Open on StackBlitz]{href="https://stackblitz.com/github/nuxt/examples/tree/main/advanced/use-cookie?terminal=dev&file=app.vue" blank} +:link-example{to="/docs/examples/advanced/use-cookie"} ## Options @@ -48,20 +49,22 @@ Most of the options will be directly passed to the [cookie](https://github.com/j ### `maxAge` / `expires` -**`maxAge`** Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2). +Use these options to set the expiration of the cookie. + +`maxAge`: Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2). The given number will be converted to an integer by rounding down. By default, no maximum age is set. -**`expires`**: Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1). +`expires`: Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1). By default, no expiration is set. Most clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting a web browser application. -::alert{icon=💡} -**Note:** The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and +::callout +The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and `maxAge` is set, then `maxAge` takes precedence, but not all clients may obey this, so if both are set, they should point to the same date and time! :: -::alert +::callout If neither of `expires` and `maxAge` is set, the cookie will be session-only and removed when the user closes their browser. :: @@ -70,8 +73,8 @@ If neither of `expires` and `maxAge` is set, the cookie will be session-only and Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6). When truthy, the `HttpOnly` attribute is set; otherwise it is not. By default, the `HttpOnly` attribute is not set. -::alert{icon=💡} -**Note:** Be careful when setting this to `true`, as compliant clients will not allow client-side +::callout +Be careful when setting this to `true`, as compliant clients will not allow client-side JavaScript to see the cookie in `document.cookie`. :: @@ -80,20 +83,18 @@ JavaScript to see the cookie in `document.cookie`. Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5). When truthy, the `Secure` attribute is set; otherwise it is not. By default, the `Secure` attribute is not set. -::alert{icon=💡} -**Note:** Be careful when setting this to `true`, as compliant clients will not send the cookie back to +::callout +Be careful when setting this to `true`, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection. This can lead to hydration errors. :: ### `domain` -Specifies the value for the [`Domain` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.3). By default, no -domain is set, and most clients will consider applying the cookie only to the current domain. +Specifies the value for the [`Domain` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.3). By default, no domain is set, and most clients will consider applying the cookie only to the current domain. ### `path` -Specifies the value for the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4). By default, the path -is considered the ["default path"](https://tools.ietf.org/html/rfc6265#section-5.1.4). +Specifies the value for the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4). By default, the path is considered the ["default path"](https://tools.ietf.org/html/rfc6265#section-5.1.4). ### `sameSite` @@ -123,8 +124,8 @@ a previously encoded cookie value into a JavaScript string or other object. The default decoder is `decodeURIComponent` + [destr](https://github.com/unjs/destr). -::alert{icon=💡} -**Note:** If an error is thrown from this function, the original, non-decoded cookie value will +::callout +If an error is thrown from this function, the original, non-decoded cookie value will be returned as the cookie's value. :: @@ -136,9 +137,9 @@ Specifies a function that returns the cookie's default value. The function can a Specifies the `boolean` or `string` value for [watch](https://vuejs.org/api/reactivity-core.html#watch) cookie ref data. -- `true` - Will watch cookie ref data changes and its nested properties. (default) +- `true` - Will watch cookie ref data changes and its nested properties (default). - `shallow` - Will watch cookie ref data changes for only top level properties -- `false` Will not watch cookie ref data changes. +- `false` - Will not watch cookie ref data changes. **Example 1:** @@ -197,13 +198,11 @@ function save() { ``` -## Handling Cookies in API Routes +## Cookies in API Routes You can use `getCookie` and `setCookie` from [`h3`](https://github.com/unjs/h3) package to set cookies in server API routes. -**Example:** - -```js +```ts [server/api/counter.ts] export default defineEventHandler(event => { // Read counter cookie let counter = getCookie(event, 'counter') || 0 @@ -216,5 +215,4 @@ export default defineEventHandler(event => { }) ``` -::LinkExample{link="/docs/examples/advanced/use-cookie"} -:: +:link-example{to="/docs/examples/advanced/use-cookie"} diff --git a/docs/3.api/2.composables/use-error.md b/docs/3.api/2.composables/use-error.md new file mode 100644 index 0000000000..1368128d14 --- /dev/null +++ b/docs/3.api/2.composables/use-error.md @@ -0,0 +1,32 @@ +--- +title: "useError" +description: useError composable returns the global Nuxt error that is being handled. +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/error.ts + size: xs +--- + +The composable returns the global Nuxt error that is being handled and it is available on both client and server. + +```ts +const error = useError() +``` + +`useError` sets an error in the state and creates a reactive as well as SSR-friendly global Nuxt error across components. + +Nuxt errors have the following properties: + +```ts +interface { + // HTTP response status code + statusCode: number + // HTTP response status message + statusMessage: string + // Error message + message: string +} +``` + +:read-more{to="/docs/getting-started/error-handling"} diff --git a/docs/3.api/1.composables/use-fetch.md b/docs/3.api/2.composables/use-fetch.md similarity index 57% rename from docs/3.api/1.composables/use-fetch.md rename to docs/3.api/2.composables/use-fetch.md index 7abfc8d972..e26231098c 100644 --- a/docs/3.api/1.composables/use-fetch.md +++ b/docs/3.api/2.composables/use-fetch.md @@ -1,10 +1,117 @@ -# `useFetch` +--- +title: 'useFetch' +description: 'Fetch data from an API endpoint with a SSR-friendly composable.' +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/fetch.ts + size: xs +--- This composable provides a convenient wrapper around [`useAsyncData`](/docs/api/composables/use-async-data) and [`$fetch`](/docs/api/utils/dollarfetch). It automatically generates a key based on URL and fetch options, provides type hints for request url based on server routes, and infers API response type. -::alert{type=warning} -[`useFetch`](/docs/api/composables/use-fetch) is a composable meant to be called directly in a setup function, plugin, or route middleware. It returns reactive composables and handles adding responses to the Nuxt payload so they can be passed from server to client without re-fetching the data on client side when the page hydrates. +::callout +`useFetch` is a composable meant to be called directly in a setup function, plugin, or route middleware. It returns reactive composables and handles adding responses to the Nuxt payload so they can be passed from server to client without re-fetching the data on client side when the page hydrates. +:: + +## Usage + +```vue [pages/index.vue] + +``` + +Using the `query` option, you can add search parameters to your query. This option is extended from [unjs/ofetch](https://github.com/unjs/ofetch) and is using [unjs/ufo](https://github.com/unjs/ufo) to create the URL. Objects are automatically stringified. + +```ts +const param1 = ref('value1') +const { data, pending, error, refresh } = await useFetch('https://api.nuxtjs.dev/mountains', { + query: { param1, param2: 'value2' } +}) +``` + +Results in `https://api.nuxtjs.dev/mountains?param1=value1¶m2=value2` + +You can also use [interceptors](https://github.com/unjs/ofetch#%EF%B8%8F-interceptors): + +```ts +const { data, pending, error, refresh } = await useFetch('/api/auth/login', { + onRequest({ request, options }) { + // Set the request headers + options.headers = options.headers || {} + options.headers.authorization = '...' + }, + onRequestError({ request, options, error }) { + // Handle the request errors + }, + onResponse({ request, response, options }) { + // Process the response data + localStorage.setItem('token', response._data.token) + }, + onResponseError({ request, response, options }) { + // Handle the response errors + } +}) +``` + +::callout{color="amber" icon="i-ph-warning-duotone"} +`useFetch` is a reserved function name transformed by the compiler, so you should not name your own function `useFetch`. +:: + +:link-example{to="/docs/examples/advanced/use-custom-fetch-composable"} + +:read-more{to="/docs/getting-started/data-fetching"} + +:link-example{to="/docs/examples/features/data-fetching"} + +## Params + +- `URL`: The URL to fetch. +- `Options` (extends [unjs/ofetch](https://github.com/unjs/ofetch) options & [AsyncDataOptions](/docs/api/composables/use-async-data#params)): + - `method`: Request method. + - `query`: Adds query search params to URL using [ufo](https://github.com/unjs/ufo) + - `params`: Alias for `query` + - `body`: Request body - automatically stringified (if an object is passed). + - `headers`: Request headers. + - `baseURL`: Base URL for the request. + +::callout +All fetch options can be given a `computed` or `ref` value. These will be watched and new requests made automatically with any new values if they are updated. +:: + +- `Options` (from [`useAsyncData`](/docs/api/composables/use-async-data)): + - `key`: a unique key to ensure that data fetching can be properly de-duplicated across requests, if not provided, it will be generated based on the static code location where `useAsyncData` is used. + - `server`: whether to fetch the data on the server (defaults to `true`) + - `lazy`: whether to resolve the async function after loading the route, instead of blocking client-side navigation (defaults to `false`) + - `immediate`: when set to `false`, will prevent the request from firing immediately. (defaults to `true`) + - `default`: a factory function to set the default value of the `data`, before the async function resolves - useful with the `lazy: true` or `immediate: false` option + - `transform`: a function that can be used to alter `handler` function result after resolving + - `pick`: only pick specified keys in this array from the `handler` function result + - `watch`: watch an array of reactive sources and auto-refresh the fetch result when they change. Fetch options and URL are watched by default. You can completely ignore reactive sources by using `watch: false`. Together with `immediate: false`, this allows for a fully-manual `useFetch`. + - `deep`: return data in a deep ref object (it is `true` by default). It can be set to `false` to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive. + +::callout +If you provide a function or ref as the `url` parameter, or if you provide functions as arguments to the `options` parameter, then the `useFetch` call will not match other `useFetch` calls elsewhere in your codebase, even if the options seem to be identical. If you wish to force a match, you may provide your own key in `options`. +:: + +## Return Values + +- `data`: the result of the asynchronous function that is passed in. +- `pending`: a boolean indicating whether the data is still being fetched. +- `refresh`/`execute`: a function that can be used to refresh the data returned by the `handler` function. +- `error`: an error object if the data fetching failed. +- `status`: a string indicating the status of the data request (`"idle"`, `"pending"`, `"success"`, `"error"`). + +By default, Nuxt waits until a `refresh` is finished before it can be executed again. + +::callout +If you have not fetched data on the server (for example, with `server: false`), then the data _will not_ be fetched until hydration completes. This means even if you await `useFetch` on client-side, `data` will remain null within ` + + +``` + +::callout{color="amber" icon="i-ph-warning-duotone"} +`useLazyAsyncData` is a reserved function name transformed by the compiler, so you should not name your own function `useLazyAsyncData`. +:: + +:read-more{to="/docs/getting-started/data-fetching#uselazyasyncdata"} diff --git a/docs/3.api/1.composables/use-lazy-fetch.md b/docs/3.api/2.composables/use-lazy-fetch.md similarity index 52% rename from docs/3.api/1.composables/use-lazy-fetch.md rename to docs/3.api/2.composables/use-lazy-fetch.md index c79f9be1b5..3e5bd0a6e1 100644 --- a/docs/3.api/1.composables/use-lazy-fetch.md +++ b/docs/3.api/2.composables/use-lazy-fetch.md @@ -1,22 +1,26 @@ --- +title: 'useLazyFetch' description: This wrapper around useFetch triggers navigation immediately. +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/fetch.ts + size: xs --- -# `useLazyFetch` - -`useLazyFetch` provides a wrapper around [`useFetch`](/docs/api/composables/use-fetch) that triggers navigation before the handler is resolved by setting the `lazy` option to `true`. - ## Description -By default, [useFetch](/docs/api/composables/use-fetch) blocks navigation until its async handler is resolved. +By default, [`useFetch`](/docs/api/composables/use-fetch) blocks navigation until its async handler is resolved. `useLazyFetch` provides a wrapper around [`useFetch`](/docs/api/composables/use-fetch) that triggers navigation before the handler is resolved by setting the `lazy` option to `true`. -> [`useLazyFetch`](/docs/api/composables/use-lazy-fetch) has the same signature as `useFetch`. +::callout +`useLazyFetch` has the same signature as [`useFetch`](/docs/api/composables/use-fetch). +:: -:ReadMore{link="/docs/api/composables/use-fetch"} +:read-more{to="/docs/api/composables/use-fetch"} ## Example -```vue +```vue [pages/index.vue] -``` + ::code-group + ```vue [app.vue] + + ``` + ```ts [server/api/count.ts] + export default defineEventHandler(event => { + return { count: 1 } + }) + ``` + :: -After fetching the value of `count` using [`useAsyncData`](/docs/api/composables/use-async-data) in the example above, if you access `payload.data`, you will see `{ count: 1 }` recorded there. The value of `count` is updated whenever the page count increases. + After fetching the value of `count` using [`useAsyncData`](/docs/api/composables/use-async-data) in the example above, if you access `payload.data`, you will see `{ count: 1 }` recorded there. -When accessing the same `payload.data` from [ssrcontext](#ssrcontext), you can access the same value on the server side as well. + When accessing the same `payload.data` from [`ssrcontext`](#ssrcontext), you can access the same value on the server side as well. -- **state** (object) - When you use [`useState`](/docs/api/composables/use-state) composable in Nuxt to set shared state, this state data is accessed through `payload.state.[name-of-your-state]`. +- `state` (object) - When you use [`useState`](/docs/api/composables/use-state) composable in Nuxt to set shared state, this state data is accessed through `payload.state.[name-of-your-state]`. -```js [plugins/my-plugin.ts] -export const useColor = () => useState('color', () => 'pink') + ```ts [plugins/my-plugin.ts] + export const useColor = () => useState('color', () => 'pink') -export default defineNuxtPlugin((nuxtApp) => { - if (process.server) { - const color = useColor() - } -}) -``` + export default defineNuxtPlugin((nuxtApp) => { + if (process.server) { + const color = useColor() + } + }) + ``` -It is also possible to use more advanced types, such as `ref`, `reactive`, `shallowRef`, `shallowReactive` and `NuxtError`. + It is also possible to use more advanced types, such as `ref`, `reactive`, `shallowRef`, `shallowReactive` and `NuxtError`. -You can also add your own types, with a special plugin helper: + You can also add your own types, with a special plugin helper: -```ts [plugins/custom-payload.ts] - /** - * This kind of plugin runs very early in the Nuxt lifecycle, before we revive the payload. - * You will not have access to the router or other Nuxt-injected properties. - */ -export default definePayloadPlugin((nuxtApp) => { - definePayloadReducer('BlinkingText', data => data === '' && '_') - definePayloadReviver('BlinkingText', () => '') -}) -``` + ```ts [plugins/custom-payload.ts] + /** + * This kind of plugin runs very early in the Nuxt lifecycle, before we revive the payload. + * You will not have access to the router or other Nuxt-injected properties. + */ + export default definePayloadPlugin((nuxtApp) => { + definePayloadReducer('BlinkingText', data => data === '' && '_') + definePayloadReviver('BlinkingText', () => '') + }) + ``` ### `isHydrating` Use `nuxtApp.isHydrating` (boolean) to check if the Nuxt app is hydrating on the client side. -**Example:** - ```ts [components/nuxt-error-boundary.ts] export default defineComponent({ setup (_props, { slots, emit }) { @@ -147,23 +158,13 @@ export default defineComponent({ ### `runWithContext` -::alert - -

- -You are likely here because you got a "Nuxt instance unavailable" message. Please use this method sparingly, and report -examples that are causing issues, so that it can ultimately be solved at the framework level. - -

- +::callout +You are likely here because you got a "Nuxt instance unavailable" message. Please use this method sparingly, and report examples that are causing issues, so that it can ultimately be solved at the framework level. :: -The `runWithContext` method is meant to be used to call a function and give it an explicit Nuxt context. Typically, the -Nuxt context is passed around implicitly and you do not need to worry about this. However, when working with complex -`async`/`await` scenarios in middleware/plugins, you can run into instances where the current instance has been unset -after an async call. +The `runWithContext` method is meant to be used to call a function and give it an explicit Nuxt context. Typically, the Nuxt context is passed around implicitly and you do not need to worry about this. However, when working with complex `async`/`await` scenarios in middleware/plugins, you can run into instances where the current instance has been unset after an async call. -```js +```ts [middleware/auth.ts] export default defineNuxtRouteMiddleware(async (to, from) => { const nuxtApp = useNuxtApp() let user @@ -186,18 +187,12 @@ export default defineNuxtRouteMiddleware(async (to, from) => { const result = nuxtApp.runWithContext(() => functionWithContext()) ``` -##### `functionWithContext` - -Any function that requires the context of the current Nuxt application. This context will be correctly applied automatically. - -##### Return value +- `functionWithContext`: Any function that requires the context of the current Nuxt application. This context will be correctly applied automatically. `runWithContext` will return whatever is returned by `functionWithContext`. #### A Deeper Explanation of Context -##### Background - Vue.js Composition API (and Nuxt composables similarly) work by depending on an implicit context. During the lifecycle, Vue sets the temporary instance of the current component (and Nuxt temporary instance of nuxtApp) to a global variable and unsets it in same tick. When rendering on the server side, there are multiple requests from different users and nuxtApp running in a same global context. Because of this, Nuxt and Vue immediately unset this global instance to avoid leaking a shared reference between two users or components. What it does mean? The Composition API and Nuxt Composables are only available during lifecycle and in same tick before any async operation: @@ -230,7 +225,7 @@ getCurrentInstance() // Still works! For a better description of what Vue actually does, see [unjs/unctx#2 (comment)](https://github.com/unjs/unctx/issues/2#issuecomment-942193723). -##### Solution +#### Solution This is where `runWithContext` can be used to restore context, similarly to how ` ``` -```ts [single.vue] -// Access to the cached value of useFetch in archive.vue +```ts [pages/posts/[id\\].vue] +// Access to the cached value of useFetch in posts.vue (parent route) +const { id } = useRoute().params const { data: posts } = useNuxtData('posts') - -const { data } = await useFetch(`/api/posts/${postId}`, { - key: `post-${postId}`, - default: () => { +const { data } = useLazyFetch(`/api/posts/${id}`, { + key: `post-${id}`, + default() { // Find the individual post from the cache and set it as the default value. - return posts.value.find(post => post.id === postId) + return posts.value.find(post => post.id === id) } }) ``` -### Optimistic Updates +## Optimistic Updates We can leverage the cache to update the UI after a mutation, while the data is being invalidated in the background. -```ts [todos.vue] +```vue [pages/todos.vue] + ``` -```ts [add-todo.vue] +```vue [components/NewTodo.vue] + +``` + +## Type + +```ts +useNuxtData (key: string): { data: Ref } ``` diff --git a/docs/3.api/1.composables/use-request-event.md b/docs/3.api/2.composables/use-request-event.md similarity index 50% rename from docs/3.api/1.composables/use-request-event.md rename to docs/3.api/2.composables/use-request-event.md index 68ddeeec85..5cb1b318bb 100644 --- a/docs/3.api/1.composables/use-request-event.md +++ b/docs/3.api/2.composables/use-request-event.md @@ -1,13 +1,16 @@ --- -title: "useRequestEvent" -description: "You can use useRequestEvent to access the incoming request." +title: 'useRequestEvent' +description: 'Access the incoming request event with the useRequestEvent composable.' +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/ssr.ts + size: xs --- -# `useRequestEvent` - Within your pages, components, and plugins you can use `useRequestEvent` to access the incoming request. -```js +```ts // Get underlying request event const event = useRequestEvent() @@ -15,6 +18,6 @@ const event = useRequestEvent() const url = event.path ``` -::alert{icon=👉} +::callout In the browser, `useRequestEvent` will return `undefined`. :: diff --git a/docs/3.api/1.composables/use-request-headers.md b/docs/3.api/2.composables/use-request-headers.md similarity index 58% rename from docs/3.api/1.composables/use-request-headers.md rename to docs/3.api/2.composables/use-request-headers.md index 7a89b69f07..76434bddb0 100644 --- a/docs/3.api/1.composables/use-request-headers.md +++ b/docs/3.api/2.composables/use-request-headers.md @@ -1,10 +1,13 @@ --- title: "useRequestHeaders" description: "Use useRequestHeaders to access the incoming request headers." +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/ssr.ts + size: xs --- -# `useRequestHeaders` - You can use built-in [`useRequestHeaders`](/docs/api/composables/use-request-headers) composable to access the incoming request headers within your pages, components, and plugins. ```js @@ -15,13 +18,13 @@ const headers = useRequestHeaders() const headers = useRequestHeaders(['cookie']) ``` -::alert{icon=👉} -In the browser, [`useRequestHeaders`](/docs/api/composables/use-request-headers) will return an empty object. +::callout +In the browser, `useRequestHeaders` will return an empty object. :: ## Example -We can use [`useRequestHeaders`](/docs/api/composables/use-request-headers) to access and proxy the initial request's `authorization` header to any future internal requests during SSR. +We can use `useRequestHeaders` to access and proxy the initial request's `authorization` header to any future internal requests during SSR. The example below adds the `authorization` request header to an isomorphic `$fetch` call. @@ -32,7 +35,3 @@ const { data } = await useFetch('/api/confidential', { }) ``` - -::alert{icon=👉} -[Another example](/docs/getting-started/data-fetching#example-pass-client-headers-to-the-api) shows how we can pass cookies from the initial request to another API route. -:: diff --git a/docs/3.api/2.composables/use-request-url.md b/docs/3.api/2.composables/use-request-url.md new file mode 100644 index 0000000000..29a0486bd1 --- /dev/null +++ b/docs/3.api/2.composables/use-request-url.md @@ -0,0 +1,35 @@ +--- +title: 'useRequestURL' +description: 'Access the incoming request URL with the useRequestURL composable.' +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/url.ts + size: xs +--- + +`useRequestURL` is a helper function that returns an [URL object](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) working on both server-side and client-side. + +::code-group + +```vue [pages/about.vue] + + + +``` + +```html [Result in development] +

URL is: http://localhost:3000/about

+

Path is: /about

+``` + +:: + +::callout{icon="i-simple-icons-mdnwebdocs" color="gray" to="https://developer.mozilla.org/en-US/docs/Web/API/URL#instance_properties" target="_blank"} +Read about the URL instance properties on the MDN documentation. +:: diff --git a/docs/3.api/1.composables/use-route.md b/docs/3.api/2.composables/use-route.md similarity index 50% rename from docs/3.api/1.composables/use-route.md rename to docs/3.api/2.composables/use-route.md index c2875bf51d..2b315a4c70 100644 --- a/docs/3.api/1.composables/use-route.md +++ b/docs/3.api/2.composables/use-route.md @@ -1,13 +1,16 @@ --- title: "useRoute" description: The useRoute composable returns the current route. +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/router.ts + size: xs --- -# `useRoute` - -The [`useRoute`](/docs/api/composables/use-route) composable returns the current route and must be called in a `setup` function, plugin, or route middleware. - +::callout Within the template of a Vue component, you can access the route using `$route`. +:: ## Example @@ -16,7 +19,7 @@ In the following example, we call an API via [`useFetch`](/docs/api/composables/ ```html [~/pages/[slug\\].vue] ``` -### Refresh Specific Data +## Refresh Specific Data This example below refreshes only data where the key matches to `count`. @@ -67,5 +70,4 @@ const refresh = () => refreshNuxtData('count') ``` -::ReadMore{link="/docs/getting-started/data-fetching"} -:: +:read-more{to="/docs/getting-started/data-fetching"} diff --git a/docs/3.api/3.utils/reload-nuxt-app.md b/docs/3.api/3.utils/reload-nuxt-app.md index 79502aa56a..0868e1319c 100644 --- a/docs/3.api/3.utils/reload-nuxt-app.md +++ b/docs/3.api/3.utils/reload-nuxt-app.md @@ -1,13 +1,22 @@ --- -title: "reloadNuxtApp" +title: 'reloadNuxtApp' description: reloadNuxtApp will perform a hard reload of the page. +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/chunk.ts + size: xs --- -# `reloadNuxtApp` - +::callout `reloadNuxtApp` will perform a hard reload of your app, re-requesting a page and its dependencies from the server. +:: -By default, it will also save the current `state` of your app (that is, any state you could access with `useState`). You can enable experimental restoration of this state by enabling the `experimental.restoreState` option in your `nuxt.config` file. +By default, it will also save the current `state` of your app (that is, any state you could access with `useState`). + +::read-more{to="/docs/guide/going-further/experimental-features#restorestate" icon="i-ph-star-duotone"} +You can enable experimental restoration of this state by enabling the `experimental.restoreState` option in your `nuxt.config` file. +:: ## Type diff --git a/docs/3.api/3.utils/set-page-layout.md b/docs/3.api/3.utils/set-page-layout.md index 41ca0f02d9..1a0a6f1968 100644 --- a/docs/3.api/3.utils/set-page-layout.md +++ b/docs/3.api/3.utils/set-page-layout.md @@ -1,17 +1,24 @@ --- +title: 'setPageLayout' description: setPageLayout allows you to dynamically change the layout of a page. +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/router.ts + size: xs --- -# `setPageLayout` -`setPageLayout` allows you to dynamically change the layout of a page. It relies on access to the Nuxt context and can only be called within components' setup functions, plugins, and route middleware. +::callout +`setPageLayout` relies on access to the Nuxt context and can only be called within components' setup functions, plugins, and route middleware. +:: -```ts +```ts [middleware/custom-layout.ts] export default defineNuxtRouteMiddleware((to) => { // Set the layout on the route you are navigating _to_ setPageLayout('other') }) ``` -::alert{icon=👉} +::callout If you choose to set the layout dynamically on the server side, you _must_ do so before the layout is rendered by Vue (that is, within a plugin or route middleware) to avoid a hydration mismatch. :: diff --git a/docs/3.api/3.utils/set-response-status.md b/docs/3.api/3.utils/set-response-status.md index 946a715815..200d644f91 100644 --- a/docs/3.api/3.utils/set-response-status.md +++ b/docs/3.api/3.utils/set-response-status.md @@ -1,14 +1,17 @@ --- +title: 'setResponseStatus' description: setResponseStatus sets the statusCode (and optionally the statusMessage) of the response. +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/ssr.ts + size: xs --- -# `setResponseStatus` Nuxt provides composables and utilities for first-class server-side-rendering support. `setResponseStatus` sets the statusCode (and optionally the statusMessage) of the response. -`setResponseStatus` can only be called within component setup functions, plugins, and route middleware. - ```js const event = useRequestEvent() @@ -19,6 +22,8 @@ setResponseStatus(event, 404) setResponseStatus(event, 404, 'Page Not Found') ``` -::alert{icon=👉} +::callout In the browser, `setResponseStatus` will have no effect. :: + +:read-more{to="/docs/getting-started/error-handling"} diff --git a/docs/3.api/3.utils/show-error.md b/docs/3.api/3.utils/show-error.md index 51eae9ad77..c0a32fdd87 100644 --- a/docs/3.api/3.utils/show-error.md +++ b/docs/3.api/3.utils/show-error.md @@ -1,6 +1,12 @@ -# `showError` - -Nuxt provides a quick and simple way to show a full screen error page if needed. +--- +title: 'showError' +description: Nuxt provides a quick and simple way to show a full screen error page if needed. +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/error.ts + size: xs +--- Within your pages, components and plugins you can use `showError` to show an error. @@ -8,14 +14,18 @@ Within your pages, components and plugins you can use `showError` to show an err - `error`: `string | Error | Partial<{ cause, data, message, name, stack, statusCode, statusMessage }>` -```js +```ts showError("😱 Oh no, an error has been thrown.") -showError({ statusCode: 404, statusMessage: "Page Not Found" }) +showError({ + statusCode: 404, + statusMessage: "Page Not Found" +}) ``` The error is set in the state using [`useError()`](/docs/api/composables/use-error) to create a reactive and SSR-friendly shared error state across components. +::callout `showError` calls the `app:error` hook. - -::ReadMore{link="/docs/getting-started/error-handling"} :: + +:read-more{to="/docs/getting-started/error-handling"} diff --git a/docs/3.api/3.utils/update-app-config.md b/docs/3.api/3.utils/update-app-config.md index a51dfcacdf..15f32044be 100644 --- a/docs/3.api/3.utils/update-app-config.md +++ b/docs/3.api/3.utils/update-app-config.md @@ -1,8 +1,18 @@ -# `updateAppConfig` +--- +title: 'updateAppConfig' +description: 'Update the App Config at runtime.' +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/config.ts + size: xs +--- -Updates [app config](/docs/guide/directory-structure/app-config) using deep assignment. Existing (nested) properties will be preserved. +::callout +Updates the [`app.config`](/docs/guide/directory-structure/app-config) using deep assignment. Existing (nested) properties will be preserved. +:: -**Usage:** +## Usage ```js const appConfig = useAppConfig() // { foo: 'bar' } @@ -14,4 +24,4 @@ updateAppConfig(newAppConfig) console.log(appConfig) // { foo: 'baz' } ``` -::ReadMore{link="/docs/guide/directory-structure/app-config"} +:read-more{to="/docs/guide/directory-structure/app-config"} diff --git a/docs/3.api/4.commands/_dir.yml b/docs/3.api/4.commands/_dir.yml new file mode 100644 index 0000000000..b1123168e0 --- /dev/null +++ b/docs/3.api/4.commands/_dir.yml @@ -0,0 +1,3 @@ +title: 'Commands' +icon: i-ph-terminal-window-duotone +titleTemplate: '%s · Nuxt Commands' diff --git a/docs/3.api/6.commands/add.md b/docs/3.api/4.commands/add.md similarity index 80% rename from docs/3.api/6.commands/add.md rename to docs/3.api/4.commands/add.md index b94e56d545..6b88b119fd 100644 --- a/docs/3.api/6.commands/add.md +++ b/docs/3.api/4.commands/add.md @@ -1,11 +1,14 @@ --- title: "nuxi add" description: "Scaffold an entity into your Nuxt application." +links: + - label: Source + icon: i-simple-icons-github + to: https://github.com/nuxt/cli/blob/main/src/commands/add.ts + size: xs --- -# `nuxi add` - -```{bash} +```bash [Terminal] npx nuxi add [--cwd] [--force]