Merge remote-tracking branch 'origin/main' into remove-pending

This commit is contained in:
Daniel Roe 2024-10-08 16:56:55 +02:00
commit c376a1f240
No known key found for this signature in database
GPG Key ID: CBC814C393D93268
782 changed files with 31695 additions and 16264 deletions

View File

@ -1,4 +1,4 @@
FROM node:lts
FROM node:lts@sha256:fffa89e023a3351904c04284029105d9e2ac7020886d683775a298569591e5bb
RUN apt-get update && \
apt-get install -fy libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdbus-1-3 libdrm2 libxkbcommon0 libatspi2.0-0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 && \

View File

@ -2,7 +2,7 @@
// https://containers.dev/implementors/json_reference/
{
"name": "nuxt-devcontainer",
"dockerFile": "Dockerfile",
"build": { "dockerfile": "Dockerfile" },
"features": {},
"customizations": {
"vscode": {

168
.eslintrc
View File

@ -1,168 +0,0 @@
{
"$schema": "https://json.schemastore.org/eslintrc",
"ignorePatterns": [
"dist",
"public",
"node_modules",
"packages/schema/schema"
],
"globals": {
"NodeJS": true,
"$fetch": true
},
"plugins": ["jsdoc", "import", "unicorn", "no-only-tests"],
"extends": [
"plugin:jsdoc/recommended",
"@nuxt/eslint-config",
"plugin:import/typescript"
],
"rules": {
"sort-imports": [
"error",
{
"ignoreDeclarationSort": true
}
],
"no-only-tests/no-only-tests": "error",
"unicorn/prefer-node-protocol": "error",
"no-console": "warn",
"vue/one-component-per-file": "off",
"vue/require-default-prop": "off",
// Vue stylistic rules from `@antfu/eslint-config`
"vue/array-bracket-spacing": ["error", "never"],
"vue/arrow-spacing": ["error", { "after": true, "before": true }],
"vue/block-spacing": ["error", "always"],
"vue/block-tag-newline": [
"error",
{
"multiline": "always",
"singleline": "always"
}
],
"vue/brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
"vue/comma-dangle": ["error", "always-multiline"],
"vue/comma-spacing": ["error", { "after": true, "before": false }],
"vue/comma-style": ["error", "last"],
"vue/html-comment-content-spacing": [
"error",
"always",
{
"exceptions": ["-"]
}
],
"vue/key-spacing": ["error", { "afterColon": true, "beforeColon": false }],
"vue/keyword-spacing": ["error", { "after": true, "before": true }],
"vue/object-curly-newline": "off",
"vue/object-curly-spacing": ["error", "always"],
"vue/object-property-newline": [
"error",
{ "allowMultiplePropertiesPerLine": true }
],
"vue/operator-linebreak": ["error", "before"],
"vue/padding-line-between-blocks": ["error", "always"],
"vue/quote-props": ["error", "consistent-as-needed"],
"vue/space-in-parens": ["error", "never"],
"vue/template-curly-spacing": "error",
"jsdoc/require-jsdoc": "off",
"jsdoc/require-param": "off",
"jsdoc/require-returns": "off",
"jsdoc/require-param-type": "off",
"import/order": [
"error",
{
"pathGroups": [
{
"pattern": "#vue-router",
"group": "external"
}
]
}
],
"import/no-restricted-paths": [
"error",
{
"zones": [
{
"from": "packages/nuxt/src/!(core)/**/*",
"target": "packages/nuxt/src/core",
"message": "core should not directly import from modules."
},
{
"from": "packages/nuxt/src/!(app)/**/*",
"target": "packages/nuxt/src/app",
"message": "app should not directly import from modules."
},
{
"from": "packages/nuxt/src/app/**/index.ts",
"target": "packages/nuxt/src",
"message": "should not import from barrel/index files"
},
{
"from": "packages/nitro",
"target": "packages/!(nitro)/**/*",
"message": "nitro should not directly import other packages."
}
]
}
],
"@typescript-eslint/consistent-type-imports": [
"error",
{
"disallowTypeAnnotations": false
}
],
"@typescript-eslint/ban-ts-comment": [
"error",
{
"ts-expect-error": "allow-with-description",
"ts-ignore": true
}
],
"@typescript-eslint/prefer-ts-expect-error": "error",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"ignoreRestSiblings": true
}
],
"jsdoc/check-tag-names": [
"error",
{
"definedTags": ["__NO_SIDE_EFFECTS__"]
}
]
},
"overrides": [
{
"files": ["packages/schema/**"],
"rules": {
"jsdoc/valid-types": "off",
"jsdoc/check-tag-names": [
"error",
{
"definedTags": ["experimental"]
}
]
}
},
{
"files": ["packages/nuxt/src/app/**", "test/**", "**/runtime/**"],
"rules": {
"no-console": "off"
}
}
],
"settings": {
"jsdoc": {
"ignoreInternal": true,
"tagNamePreference": {
"warning": "warning",
"note": "note"
}
}
}
}

View File

@ -1,6 +1,6 @@
name: "\U0001F41E Bug report"
description: Create a report to help us improve Nuxt
labels: ["pending triage", "3.x"]
labels: ["pending triage"]
body:
- type: markdown
attributes:
@ -36,7 +36,7 @@ body:
validations:
required: true
- type: textarea
id: additonal
id: additional
attributes:
label: Additional context
description: If applicable, add any other context about the problem here

View File

@ -1,11 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: 📚 Nuxt 3 Documentation
url: https://nuxt.com/docs/
about: Check the documentation for usage of Nuxt 3
- name: 📚 Nuxt 2 Documentation
url: https://v2.nuxt.com/
about: Check the documentation for usage of Nuxt 2
- name: 📚 Nuxt Documentation
url: https://nuxt.com/docs
about: Check the documentation for usage of Nuxt
- name: 💬 Discussions
url: https://github.com/nuxt/nuxt/discussions
about: Use discussions if you have another issue, an idea for improvement or for asking questions.

View File

@ -1,6 +1,6 @@
name: "🚀 Feature request"
description: Suggest a feature that will improve Nuxt
labels: ["pending triage", "3.x"]
labels: ["pending triage"]
body:
- type: markdown
attributes:

View File

@ -1,49 +0,0 @@
name: "\U0001F41E Bug report (Nuxt 2)"
description: Create a report to help us improve Nuxt
labels: ["pending triage", "2.x"]
body:
- type: markdown
attributes:
value: |
Please carefully read the contribution docs before creating a bug report
👉 https://nuxt.com/docs/community/reporting-bugs
Please use a template below to create a minimal reproduction
👉 https://stackblitz.com/github/nuxt/starter/tree/v2
👉 https://codesandbox.io/s/github/nuxt/starter/v2
- type: textarea
id: bug-env
attributes:
label: Environment
description: You can use `npx envinfo --system --npmPackages '{nuxt,@nuxt/*}' --binaries --browsers` to fill this section
placeholder: Environment
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction
description: Please provide a link to a repo that can reproduce the problem you ran into. A [**minimal reproduction**](https://nuxt.com/docs/community/reporting-bugs#create-a-minimal-reproduction) is required unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need reproduction" label. If no reproduction is provided we might close it.
placeholder: Reproduction
validations:
required: true
- type: textarea
id: bug-description
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!
placeholder: Bug description
validations:
required: true
- type: textarea
id: additonal
attributes:
label: Additional context
description: If applicable, add any other context about the problem here
- type: textarea
id: logs
attributes:
label: Logs
description: |
Optional if provided reproduction. Please try not to insert an image but copy paste the log text.
render: shell-script

View File

@ -1,37 +1,19 @@
<!---
☝️ PR title should follow conventional commits (https://conventionalcommits.org)
Please carefully read the contribution docs before creating a pull request
👉 https://nuxt.com/docs/community/contribution
-->
### 🔗 Linked issue
<!-- Please ensure there is an open issue and mention its number as #123 -->
### ❓ Type of change
<!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply. -->
- [ ] 📖 Documentation (updates to the documentation, readme or JSdoc annotations)
- [ ] 🐞 Bug fix (a non-breaking change that fixes an issue)
- [ ] 👌 Enhancement (improving an existing functionality like performance)
- [ ] ✨ New feature (a non-breaking change that adds functionality)
- [ ] 🧹 Chore (updates to the build process or auxiliary tools and libraries)
- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change)
<!-- Please ensure there is an open issue and mention its number. For example, "resolves #123" -->
### 📚 Description
<!-- Describe your changes in detail -->
<!-- Why is this change required? What problem does it solve? -->
<!-- If it resolves an open issue, please link to the issue here. For example "Resolves #1337" -->
<!-- Describe your changes in detail. Why is this change required? What problem does it solve? -->
### 📝 Checklist
<!----------------------------------------------------------------------
Before creating the pull request, please make sure you do the following:
<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- Check that there isn't already a PR that solves the problem the same way. If you find a duplicate, please help us reviewing it.
- Read the contribution docs at https://nuxt.com/docs/community/contribution
- Ensure that PR title follows conventional commits (https://www.conventionalcommits.org)
- Update the corresponding documentation if needed.
- Include relevant tests that fail without this PR but pass with it.
- [ ] I have linked an issue or discussion.
- [ ] I have added tests (if possible).
- [ ] I have updated the documentation accordingly.
Thank you for contributing to Nuxt!
----------------------------------------------------------------------->

10
.github/codeql/codeql-config.yml vendored Normal file
View File

@ -0,0 +1,10 @@
paths:
- 'packages/*/dist/**'
- 'packages/nuxt/bin/**'
- 'packages/schema/schema/**'
paths-ignore:
- 'test/**'
- '**/*.test.js'
- '**/*.test.ts'
- '**/*.test.tsx'
- '**/__tests__/**'

View File

@ -17,9 +17,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -27,7 +27,10 @@ jobs:
- name: Install dependencies
run: pnpm install
- name: Build (stub)
run: pnpm dev:prepare
- name: Lint (docs)
run: pnpm lint:docs:fix
- uses: autofix-ci/action@ea32e3a12414e6d3183163c3424a7d7a8631ad84
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c

View File

@ -13,9 +13,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -26,9 +26,6 @@ jobs:
- name: Build (stub)
run: pnpm dev:prepare
- name: Lint (code)
run: pnpm lint:fix
- name: Test (unit)
run: pnpm test:unit -u
@ -52,4 +49,7 @@ jobs:
if: ${{ !contains(github.head_ref, 'renovate') }}
run: pnpm vitest run bundle -u
- uses: autofix-ci/action@ea32e3a12414e6d3183163c3424a7d7a8631ad84
- name: Lint (code)
run: pnpm lint:fix
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c

View File

@ -15,8 +15,6 @@ env:
# 7 GiB by default on GitHub, setting to 6 GiB
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
NODE_OPTIONS: --max-old-space-size=6144
# install playwright binary manually (because pnpm only runs install script once)
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
# Remove default permissions of GITHUB_TOKEN for security
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
@ -31,9 +29,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -48,7 +46,7 @@ jobs:
run: pnpm build
- name: Run benchmarks
uses: CodSpeedHQ/action@fce3a2f16d0b352af341dcacb25caadfd9159055 # v2.1.1
uses: CodSpeedHQ/action@ab07afd34cbbb7a1306e8d14b7cc44e029eee37a # v3.0.0
with:
run: pnpm vitest bench
token: ${{ secrets.CODSPEED_TOKEN }}

38
.github/workflows/cache-cleanup.yml vendored Normal file
View File

@ -0,0 +1,38 @@
# From https://github.com/actions/cache/blob/main/tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy
name: cache
on:
pull_request:
types:
- closed
permissions: {}
jobs:
cleanup:
runs-on: ubuntu-latest
permissions:
# `actions:write` permission is required to delete caches
# See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id
actions: write
contents: read
steps:
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
echo "Fetching list of cache keys"
cacheKeysForPR=$(gh actions-cache list -R "$REPO" -B "$BRANCH" -L 100 | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete "$cacheKey" -R "$REPO" -B "$BRANCH" --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge

View File

@ -1,30 +1,32 @@
name: Release
name: changelog
on:
push:
branches:
- main
- 2.x
- 3.x
permissions:
pull-requests: write
contents: write
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
cancel-in-progress: ${{ github.event_name != 'push' }}
jobs:
update-changelog:
if: github.repository_owner == 'nuxt' && !contains(github.event.head_commit.message, 'v3.')
update:
if: github.repository_owner == 'nuxt' && !contains(github.event.head_commit.message, 'v3.') && !contains(github.event.head_commit.message, 'v4.')
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: write
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
fetch-depth: 0
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"

View File

@ -7,12 +7,14 @@ on:
- "*.md"
branches:
- main
- 3.x
pull_request:
paths-ignore:
- "docs/**"
- "*.md"
branches:
- main
- 3.x
- "!v[0-9]*"
# https://github.com/vitejs/vite/blob/main/.github/workflows/ci.yml
@ -20,8 +22,6 @@ env:
# 7 GiB by default on GitHub, setting to 6 GiB
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
NODE_OPTIONS: --max-old-space-size=6144
# install playwright binary manually (because pnpm only runs install script once)
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
# Remove default permissions of GITHUB_TOKEN for security
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
@ -37,9 +37,9 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -57,7 +57,7 @@ jobs:
run: pnpm build
- name: Cache dist
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1
with:
retention-days: 3
name: dist
@ -70,36 +70,30 @@ jobs:
actions: read
contents: read
security-events: write
needs:
- build
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- name: Initialize CodeQL
uses: github/codeql-action/init@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
with:
languages: javascript
config: |
paths:
- 'packages/*/src/**'
- 'packages/nuxt/bin/**'
- 'packages/schema/schema/**'
paths-ignore:
- 'test/**'
- '**/*.spec.ts'
- '**/*.test.ts'
- '**/__snapshots__/**'
languages: javascript-typescript
queries: +security-and-quality
- name: Restore dist cache
uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2
with:
name: dist
path: packages
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
with:
category: "/language:javascript"
category: "/language:javascript-typescript"
typecheck:
runs-on: ${{ matrix.os }}
@ -113,9 +107,9 @@ jobs:
module: ["bundler", "node"]
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -124,7 +118,7 @@ jobs:
run: pnpm install
- name: Restore dist cache
uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: dist
path: packages
@ -144,9 +138,9 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -168,9 +162,9 @@ jobs:
needs:
- build
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -200,8 +194,17 @@ jobs:
builder: ["vite", "webpack"]
context: ["async", "default"]
manifest: ["manifest-on", "manifest-off"]
payload: ["json", "js"]
node: [18]
exclude:
- builder: "webpack"
payload: "js"
- manifest: "manifest-off"
payload: "js"
- context: "default"
payload: "js"
- os: windows-latest
payload: "js"
- env: "dev"
builder: "webpack"
- manifest: "manifest-off"
@ -210,9 +213,9 @@ jobs:
timeout-minutes: 15
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: ${{ matrix.node }}
cache: "pnpm"
@ -220,34 +223,11 @@ jobs:
- name: Install dependencies
run: pnpm install
# Install playwright's binary under custom directory to cache
- name: (non-windows) Set Playwright path and Get playwright version
if: runner.os != 'Windows'
run: |
echo "PLAYWRIGHT_BROWSERS_PATH=$HOME/.cache/playwright-bin" >> $GITHUB_ENV
PLAYWRIGHT_VERSION="$(pnpm ls --depth 0 --json -w playwright-core | jq --raw-output '.[0].devDependencies["playwright-core"].version')"
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
- name: (windows) Set Playwright path and Get playwright version
if: runner.os == 'Windows'
run: |
echo "PLAYWRIGHT_BROWSERS_PATH=$HOME\.cache\playwright-bin" >> $env:GITHUB_ENV
$env:PLAYWRIGHT_VERSION="$(pnpm ls --depth 0 --json -w playwright-core | jq --raw-output '.[0].devDependencies["playwright-core"].version')"
echo "PLAYWRIGHT_VERSION=$env:PLAYWRIGHT_VERSION" >> $env:GITHUB_ENV
- name: Cache Playwright's binary
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
with:
key: ${{ runner.os }}-playwright-bin-v1-${{ env.PLAYWRIGHT_VERSION }}
path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }}
restore-keys: |
${{ runner.os }}-playwright-bin-v1-
- name: Install Playwright
run: pnpm playwright-core install chromium
- name: Restore dist cache
uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: dist
path: packages
@ -259,21 +239,23 @@ jobs:
TEST_BUILDER: ${{ matrix.builder }}
TEST_MANIFEST: ${{ matrix.manifest }}
TEST_CONTEXT: ${{ matrix.context }}
SKIP_BUNDLE_SIZE: ${{ github.event_name != 'push' || matrix.env == 'dev' || matrix.builder == 'webpack' || matrix.context == 'default' || runner.os == 'Windows' }}
TEST_PAYLOAD: ${{ matrix.payload }}
SKIP_BUNDLE_SIZE: ${{ github.event_name != 'push' || matrix.env == 'dev' || matrix.builder == 'webpack' || matrix.context == 'default' || matrix.payload == 'js' || runner.os == 'Windows' }}
- uses: codecov/codecov-action@e0b68c6749509c5f83f984dd99a76a1c1a231044 # v4.0.1
- uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
if: github.event_name != 'push' && matrix.env == 'built' && matrix.builder == 'vite' && matrix.context == 'default' && matrix.os == 'ubuntu-latest' && matrix.manifest == 'manifest-on'
with:
token: ${{ secrets.CODECOV_TOKEN }}
build-release:
concurrency:
group: release
permissions:
id-token: write
if: |
github.event_name == 'push' &&
github.repository == 'nuxt/nuxt' &&
!contains(github.event.head_commit.message, '[skip-release]') &&
!startsWith(github.event.head_commit.message, 'chore') &&
!startsWith(github.event.head_commit.message, 'docs')
needs:
- lint
@ -283,11 +265,11 @@ jobs:
timeout-minutes: 20
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
fetch-depth: 0
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -296,18 +278,20 @@ jobs:
run: pnpm install
- name: Restore dist cache
uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: dist
path: packages
- name: Release Edge
run: ./scripts/release-edge.sh
run: ./scripts/release-edge.sh ${{ github.ref == 'refs/heads/main' && 'latest' || '3x' }}
env:
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
NPM_CONFIG_PROVENANCE: true
release-pr:
concurrency:
group: release
permissions:
id-token: write
pull-requests: write
@ -322,11 +306,11 @@ jobs:
timeout-minutes: 20
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
fetch-depth: 0
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -335,7 +319,7 @@ jobs:
run: pnpm install
- name: Restore dist cache
uses: actions/download-artifact@eaceaf801fd36c7dee90939fad912460b18a1ffe # v4.1.2
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: dist
path: packages

View File

@ -17,6 +17,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- name: 'Dependency Review'
uses: actions/dependency-review-action@fd07d42ce87ab09f10c61a2d1a5e59e6c655620a # v4.1.1
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4

View File

@ -1,4 +1,4 @@
name: Check links with Lychee
name: docs
on:
pull_request:
@ -7,6 +7,7 @@ on:
- "*.md"
branches:
- main
- 3.x
# Remove default permissions of GITHUB_TOKEN for security
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
@ -18,17 +19,17 @@ jobs:
steps:
# Cache lychee results (e.g. to avoid hitting rate limits)
- name: Restore lychee cache
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
uses: actions/cache@2cdf405574d6ef1f33a1d12acccd3ae82f47b3f2 # v4.1.0
with:
path: .lycheecache
key: cache-lychee-${{ github.sha }}
restore-keys: cache-lychee-
# check links with Lychee
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- name: Lychee link checker
uses: lycheeverse/lychee-action@c053181aa0c3d17606addfe97a9075a32723548a # for v1.8.0
uses: lycheeverse/lychee-action@f87f0a62993c2647717456af92593666acb3a500 # for v1.8.0
with:
# arguments with file types to check
args: >-

View File

@ -1,11 +1,11 @@
name: Deploy docs
name: docs
on:
push:
paths:
- "docs/**"
branches:
- main
- 3.x
# Remove default permissions of GITHUB_TOKEN for security
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs

View File

@ -1,4 +1,4 @@
name: Docs
name: docs
on:
push:
@ -9,6 +9,7 @@ on:
# autofix workflow will be triggered instead for PRs
branches:
- main
- 3.x
- "!v[0-9]*"
# Remove default permissions of GITHUB_TOKEN for security
@ -20,9 +21,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
@ -30,6 +31,9 @@ jobs:
- name: Install dependencies
run: pnpm install
- name: Build (stub)
run: pnpm dev:prepare
- name: Lint (docs)
run: pnpm lint:docs

28
.github/workflows/label-issue.yml vendored Normal file
View File

@ -0,0 +1,28 @@
name: chore
on:
issues:
types:
- opened
permissions:
issues: write
jobs:
add-issue-labels:
name: Add labels
runs-on: ubuntu-latest
if: github.repository == 'nuxt/nuxt'
steps:
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
// add 'pending triage' label if issue is created with no labels
if (context.payload.issue.labels.length === 0) {
github.rest.issues.addLabels({
issue_number: context.payload.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['pending triage']
})
}

View File

@ -1,4 +1,4 @@
name: Label PR
name: chore
on:
pull_request_target:
@ -6,6 +6,9 @@ on:
- opened
branches:
- main
- 3.x
permissions: {}
jobs:
add-pr-labels:

36
.github/workflows/lint-sherif.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: CI
on:
push:
paths:
- "**/package.json"
branches:
- main
- 3.x
pull_request:
paths:
- "**/package.json"
branches:
- main
- 3.x
- "!v[0-9]*"
permissions:
contents: read
jobs:
lint-monorepo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- run: corepack enable
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Lint monorepo
run: pnpm sherif -r multiple-dependency-versions

View File

@ -6,11 +6,13 @@ on:
- ".github/workflows/**"
branches:
- main
- 3.x
pull_request:
paths:
- ".github/workflows/**"
branches:
- main
- 3.x
- "!v[0-9]*"
permissions:
@ -21,9 +23,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
# From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions
- name: Check workflow files
run: |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/590d3bd9dde0c91f7a66071d40eb84716526e5a6/scripts/download-actionlint.bash) 1.6.25
./actionlint -color -shellcheck=""
uses: docker://rhysd/actionlint:1.7.3@sha256:7617f05bd698cd2f1c3aedc05bc733ccec92cca0738f3e8722c32c5b42c70ae6
with:
args: -color

View File

@ -4,6 +4,9 @@ on:
types: [closed]
paths:
- "packages/nuxt/src/app/composables/**"
permissions: {}
jobs:
notify:
if: github.event.pull_request.merged == true

View File

@ -1,61 +0,0 @@
name: nuxt2-nightly
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
# https://github.com/vitejs/vite/blob/main/.github/workflows/ci.yml
env:
# 7 GiB by default on GitHub, setting to 6 GiB
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
NODE_OPTIONS: --max-old-space-size=6144
permissions:
contents: read
jobs:
nightly:
if: github.repository_owner == 'nuxt'
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: '2.x'
fetch-depth: 0 # All history
- name: fetch tags
run: git fetch --depth=1 origin "+refs/tags/*:refs/tags/*"
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
node-version: 18
registry-url: 'https://registry.npmjs.org'
- name: install
run: yarn --check-files --frozen-lockfile --non-interactive
- name: lint
run: yarn test:lint
- name: audit
run: yarn run audit
- name: build
run: yarn test:fixtures -i
- name: lint app
run: yarn lint:app
- name: test types
run: yarn test:types
- name: test dev
run: yarn test:dev
- name: test unit
run: yarn test:unit
- name: test e2e
run: yarn test:e2e
- name: bump version
run: yarn lerna version --yes --no-changelog --no-git-tag-version --no-push --force-publish "*" --loglevel verbose
- name: build
run: PACKAGE_SUFFIX=edge yarn build
- name: publish
run: ./scripts/workspace-run npm publish -q
env:
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
NPM_CONFIG_PROVENANCE: true

View File

@ -1,4 +1,4 @@
name: release
name: release-pr
on:
issue_comment:
@ -14,6 +14,8 @@ permissions:
jobs:
release-pr:
if: github.repository == 'nuxt/nuxt' && github.event.issue.pull_request && github.event.comment.body == '/trigger release'
concurrency:
group: release
permissions:
id-token: write
pull-requests: write
@ -22,20 +24,37 @@ jobs:
steps:
- name: Ensure action is by maintainer
uses: octokit/request-action@89697eb6635e52c6e1e5559f15b5c91ba5100cb0 # v2.1.9
uses: octokit/request-action@dad4362715b7fb2ddedf9772c8670824af564f0d # v2.4.0
id: check_role
with:
route: GET /repos/nuxt/nuxt/collaborators/${{ github.event.comment.user.login }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Get PR Info
id: pr
env:
PR_NUMBER: ${{ github.event.issue.number }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
COMMENT_AT: ${{ github.event.comment.created_at }}
run: |
pr="$(gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/"${GH_REPO}"/pulls/"${PR_NUMBER}")"
head_sha="$(echo "$pr" | jq -r .head.sha)"
updated_at="$(echo "$pr" | jq -r .updated_at)"
if [[ $(date -d "$updated_at" +%s) -gt $(date -d "$COMMENT_AT" +%s) ]]; then
exit 1
fi
echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
ref: refs/pull/${{ github.event.issue.number }}/merge
fetch-depth: 0
ref: ${{ steps.pr.outputs.head_sha }}
fetch-depth: 1
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
cache: "pnpm"

42
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,42 @@
name: release
on:
push:
tags:
- "v*"
# Remove default permissions of GITHUB_TOKEN for security
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
permissions: {}
jobs:
release:
if: github.repository == 'nuxt/nuxt' && (startsWith(github.event.head_commit.message, 'v3.') || startsWith(github.event.head_commit.message, 'v4.'))
concurrency:
group: release
permissions:
id-token: write
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
fetch-depth: 0
- run: corepack enable
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version: 20
registry-url: "https://registry.npmjs.org/"
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Build (stub)
run: pnpm dev:prepare
- name: Release
run: ./scripts/release.sh
env:
NODE_AUTH_TOKEN: ${{secrets.RELEASE_NODE_AUTH_TOKEN}}
NPM_CONFIG_PROVENANCE: true

View File

@ -1,4 +1,4 @@
name: Reproduire
name: chore
on:
issues:
types: [labeled]
@ -10,7 +10,7 @@ jobs:
reproduire:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp
with:
label: needs reproduction

View File

@ -2,7 +2,7 @@
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
name: Scorecard supply-chain security
name: ossf
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
@ -28,15 +28,16 @@ jobs:
id-token: write
contents: read
actions: read
if: github.event_name == 'push' || github.repository == 'nuxt/nuxt'
steps:
- name: "Checkout code"
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
with:
results_file: results.sarif
results_format: sarif
@ -58,7 +59,8 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1
if: github.repository == 'nuxt/nuxt' && success()
with:
name: SARIF file
path: results.sarif
@ -66,6 +68,7 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@379614612a29c9e28f31f39a59013eb8012a51f0 # v3.24.3
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
if: github.repository == 'nuxt/nuxt' && success()
with:
sarif_file: results.sarif

View File

@ -1,4 +1,4 @@
name: Semantic pull request
name: chore
on:
pull_request_target:
@ -7,12 +7,12 @@ on:
- edited
- synchronize
permissions:
contents: read
permissions: {}
jobs:
main:
semantic-pr:
permissions:
contents: read
pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
if: github.repository == 'nuxt/nuxt' && !startsWith(github.head_ref, 'v')
@ -20,14 +20,16 @@ jobs:
name: Semantic pull request
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@e9fabac35e210fea40ca5b14c0da95a099eff26f # v5.4.0
uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3
with:
scopes: |
kit
nuxi
nuxt
rspack
schema
test-utils
ui-templates
vite
webpack
deps

17
.github/workflows/stackblitz-link.yml vendored Normal file
View File

@ -0,0 +1,17 @@
name: chore
on:
issues:
types:
opened
permissions:
issues: write
jobs:
stackblitz:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- uses: huang-julien/reproduire-sur-stackblitz@9ceccbfbb0f2f9a9a8db2d1f0dd909cf5cfe67aa # v1.0.2
with:
reproduction-heading: '### Reproduction'

View File

@ -1,4 +1,4 @@
name: Close incomplete issues
name: chore
on:
workflow_dispatch:
schedule:
@ -10,6 +10,7 @@ permissions:
jobs:
stale:
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch' || github.repository == 'nuxt/nuxt'
steps:
- uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0
with:

2
.gitignore vendored
View File

@ -73,3 +73,5 @@ Temporary Items
fixtures-temp
.pnpm-store
eslint-typegen.d.ts
.eslintcache

5
.npmrc
View File

@ -1,3 +1,4 @@
shamefully-hoist=true
strict-peer-dependencies=false
# TODO: consider resolving webpack loaders to absolute path
public-hoist-pattern[]=*-loader
public-hoist-pattern[]=webpack-*
shell-emulator=true

1
CODEOWNERS Normal file
View File

@ -0,0 +1 @@
* @danielroe

View File

@ -5,7 +5,7 @@
<p>
<a href="https://www.npmjs.com/package/nuxt"><img src="https://img.shields.io/npm/v/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="Version"></a>
<a href="https://www.npmjs.com/package/nuxt"><img src="https://img.shields.io/npm/dm/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="Downloads"></a>
<a href="./LICENSE"><img src="https://img.shields.io/github/license/nuxt/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="License"></a>
<a href="https://github.com/nuxt/nuxt/tree/main/LICENSE"><img src="https://img.shields.io/github/license/nuxt/nuxt.svg?style=flat&colorA=18181B&colorB=28CF8D" alt="License"></a>
<a href="https://nuxt.com"><img src="https://img.shields.io/badge/Nuxt%20Docs-18181B?logo=nuxt.js" alt="Website"></a>
<a href="https://chat.nuxt.dev"><img src="https://img.shields.io/badge/Nuxt%20Discord-18181B?logo=discord" alt="Discord"></a>
</p>
@ -13,16 +13,33 @@
Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.
It provides a number of features that make it easy to build fast, SEO-friendly, and scalable web applications, including:
- Server-side rendering, Static Site Generation or Hybrid Rendering
- Automatic routing with code-splitting
- State management
- SEO Optimization
- Auto imports
- Extensible with [180+ modules](https://nuxt.com/modules)
- Server-side rendering, Static Site Generation, Hybrid Rendering and Edge-Side Rendering
- Automatic routing with code-splitting and pre-fetching
- Data fetching and state management
- SEO Optimization and Meta tags definition
- Auto imports of components, composables and utils
- TypeScript with zero configuration
- Go fullstack with our server/ directory
- Extensible with [200+ modules](https://nuxt.com/modules)
- Deployment to a variety of [hosting platforms](https://nuxt.com/deploy)
- ...[and much more](https://nuxt.com) 🚀
## Getting Started
### Table of Contents
- 🚀 [Getting Started](#getting-started)
- 💻 [ Vue Development](#vue-development)
- 📖 [Documentation](#documentation)
- 🧩 [Modules](#modules)
- ❤️ [Contribute](#contribute)
- 🏠 [Local Development](#local-development)
- ⛰️ [Nuxt 2](#nuxt-2)
- 🛟 [Professional Support](#professional-support)
- 🔗 [Follow Us](#follow-us)
- ⚖️ [License](#license)
---
## <a name="getting-started">🚀 Getting Started</a>
Use the following command to create a new starter project. This will create a starter project with all the necessary files and dependencies:
@ -30,9 +47,10 @@ Use the following command to create a new starter project. This will create a st
npx nuxi@latest init <my-project>
```
Discover also [nuxt.new](https://nuxt.new): Open a Nuxt starter on CodeSandbox, StackBlitz or locally to get up and running in a few seconds.
> [!TIP]
> Discover also [nuxt.new](https://nuxt.new): Open a Nuxt starter on CodeSandbox, StackBlitz or locally to get up and running in a few seconds.
## Vue Development
## <a name="vue-development">💻 Vue Development</a>
Simple, intuitive and powerful, Nuxt lets you write Vue components in a way that makes sense. Every repetitive task is automated, so you can focus on writing your full-stack Vue application with confidence.
@ -54,7 +72,7 @@ useSeoMeta({
</div>
</template>
<style>
<style scoped>
#app {
background-color: #020420;
color: #00DC82;
@ -62,38 +80,38 @@ useSeoMeta({
</style>
```
## Documentation
## <a name="documentation">📖 Documentation</a>
We highly recommend you take a look at the [Nuxt documentation](https://nuxt.com/docs) to level up. Its a great resource for learning more about the framework. It covers everything from getting started to advanced topics.
## Modules
## <a name="modules">🧩 Modules</a>
Discover our [list of modules](https://nuxt.com/modules) to supercharge your Nuxt project, created by the Nuxt team and community.
## Contribute
## <a name="contribute">❤️ Contribute</a>
We invite you to contribute and help improve Nuxt 💚
Here are a few ways you can get involved:
- **Reporting Bugs:** If you come across any bugs or issues, please check out the [reporting bugs guide](https://nuxt.com/docs/community/reporting-bugs) to learn how to submit a bug report.
- **Suggestions:** Have ideas to enhance Nuxt? We'd love to hear them! Check out the [contribution guide](https://nuxt.com/docs/community/contribution#creating-an-issue) to share your suggestions.
- **Suggestions:** Have ideas to enhance Nuxt? We'd love to hear them! Check out the [contribution guide](https://nuxt.com/docs/community/contribution) to share your suggestions.
- **Questions:** If you have questions or need assistance, the [getting help guide](https://nuxt.com/docs/community/getting-help) provides resources to help you out.
## Local Development
## <a name="local-development">🏠 Local Development</a>
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
## <a name="professional-support">🛟 Professional Support</a>
You can find the code for Nuxt 2 on the [`2.x` branch](https://github.com/nuxt/nuxt/tree/2.x) and the documentation at [v2.nuxt.com](https://v2.nuxt.com).
- Technical audit & consulting: [Nuxt Experts](https://nuxt.com/enterprise/support)
- Custom development & more: [Nuxt Agencies Partners](https://nuxt.com/enterprise/agencies)
## Follow us
## <a name="follow-us">🔗 Follow Us</a>
<p valign="center">
<a href="https://chat.nuxt.dev"><img width="20px" src="./.github/assets/discord.svg" alt="Discord"></a>&nbsp;&nbsp;<a href="https://twitter.nuxt.dev"><img width="20px" src="./.github/assets/twitter.svg" alt="Twitter"></a>&nbsp;&nbsp;<a href="https://github.nuxt.dev"><img width="20px" src="./.github/assets/github.svg" alt="GitHub"></a>
<a href="https://go.nuxt.com/discord"><img width="20px" src="./.github/assets/discord.svg" alt="Discord"></a>&nbsp;&nbsp;<a href="https://go.nuxt.com/x"><img width="20px" src="./.github/assets/twitter.svg" alt="Twitter"></a>&nbsp;&nbsp;<a href="https://go.nuxt.com/github"><img width="20px" src="./.github/assets/github.svg" alt="GitHub"></a>
</p>
## License
[MIT](./LICENSE)
## <a name="license">⚖️ License</a>
[MIT](https://github.com/nuxt/nuxt/tree/main/LICENSE)

View File

@ -1,7 +1,8 @@
---
title: 'Introduction'
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
navigation:
icon: i-ph-info
---
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).
@ -10,6 +11,10 @@ We made everything so you can start writing `.vue` files from the beginning whil
Nuxt has no vendor lock-in, allowing you to deploy your application [**everywhere, even on the edge**](/blog/nuxt-on-the-edge).
::tip
If you want to play around with Nuxt in your browser, you can [try it out in one of our online sandboxes](/docs/getting-started/installation#play-online).
::
## 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.
@ -72,7 +77,5 @@ Nuxt is composed of different [core packages](https://github.com/nuxt/nuxt/tree/
- 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.

View File

@ -1,12 +1,12 @@
---
title: 'Deployment'
description: Learn how to deploy your Nuxt application to any hosting provider.
navigation.icon: i-ph-cloud-duotone
navigation.icon: i-ph-cloud
---
A Nuxt application can be deployed on a Node.js server, pre-rendered for static hosting, or deployed to serverless or edge (CDN) environments.
::callout
::tip
If you are looking for a list of cloud providers that support Nuxt 3, see the [Hosting providers](/deploy) section.
::
@ -64,6 +64,10 @@ By default, the workload gets distributed to the workers with the round robin st
:read-more{to="https://nitro.unjs.io/deploy/node" title="the Nitro documentation for node-server preset"}
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=0x1H6K5yOfs" target="\_blank"}
Watch Daniel Roe's short video on the topic.
::
## Static Hosting
There are two ways to deploy a Nuxt application to any static hosting services:
@ -71,62 +75,7 @@ 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 `<div id="__nuxt"></div>` 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 [`<ClientOnly>`](/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 [Terminal]
npx nuxi generate
```
That's it! You can now deploy the `.output/public` directory to any static hosting service or preview it locally with `npx serve .output/public`.
Working of the Nitro crawler:
1. Load the HTML of your application's root route (`/`), any non-dynamic pages in your `~/pages` directory, and any other routes in the `nitro.prerender.routes` array.
2. Save the HTML and `payload.json` to the `~/.output/public/` directory to be served statically.
3. Find all anchor tags (`<a href="...">`) in the HTML to navigate to other routes.
4. Repeat steps 1-3 for each anchor tag found until there are no more anchor tags to crawl.
This is important to understand since pages that are not linked to a discoverable page can't be pre-rendered automatically.
::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 twoslash [nuxt.config.ts]
export default defineNuxtConfig({
nitro: {
prerender: {
routes: ['/user/1', '/user/2'],
ignore: ['/dynamic']
}
}
})
```
You can combine this with the `crawlLinks` option to pre-render a set of routes that the crawler can't discover like your `/sitemap.xml` or `/robots.txt`:
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
nitro: {
prerender: {
crawlLinks: true,
routes: ['/sitemap.xml', '/robots.txt']
}
}
})
```
Setting `nitro.prerender` to `true` is similar to `nitro.prerender.crawlLinks` to `true`.
::read-more{to="https://nitro.unjs.io/config#prerender"}
Read more about pre-rendering in the Nitro documentation.
::
:read-more{title="Nuxt prerendering" to="/docs/getting-started/prerendering"}
### Client-side Only Rendering
@ -140,13 +89,13 @@ export default defineNuxtConfig({
## Hosting Providers
Nuxt 3 can be deployed to several cloud providers with a minimal amount of configuration:
Nuxt can be deployed to several cloud providers with a minimal amount of configuration:
:read-more{to="/deploy"}
## 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.
In addition to Node.js servers and static hosting services, a Nuxt 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.ts`](/docs/guide/directory-structure/nuxt-config) file:
@ -172,10 +121,13 @@ In most cases, Nuxt can work with third-party content that is not generated or c
Accordingly, you should make sure that the following options are unchecked / disabled in Cloudflare. Otherwise, unnecessary re-rendering or hydration errors could impact your production application.
1. Speed > Optimization > Auto Minify: Uncheck JavaScript, CSS and HTML
2. Speed > Optimization > Disable "Rocket Loader™"
3. Speed > Optimization > Disable "Mirage"
1. Speed > Optimization > Content Optimization > Auto Minify: Uncheck JavaScript, CSS and HTML
2. Speed > Optimization > Content Optimization > Disable "Rocket Loader™"
3. Speed > Optimization > Image Optimization > Disable "Mirage"
4. Scrape Shield > Disable "Email Address Obfuscation"
5. Scrape Shield > Disable "Server-side Excludes"
With these settings, you can be sure that Cloudflare won't inject scripts into your Nuxt application that may cause unwanted side effects.
::tip
Their location on the Cloudflare dashboard sometimes changes so don't hesitate to look around.
::

View File

@ -1,30 +1,34 @@
---
title: Testing
description: How to test your Nuxt application.
navigation.icon: i-ph-check-circle-duotone
navigation.icon: i-ph-check-circle
---
::callout
::tip
If you are a module author, you can find more specific information in the [Module Author's guide](/docs/guide/going-further/modules#testing).
::
Nuxt offers first-class support for end-to-end and unit testing of your Nuxt application via `@nuxt/test-utils`, a library of test utilities and configuration that currently powers the [tests we use on Nuxt itself](https://github.com/nuxt/nuxt/tree/main/test) and tests throughout the module ecosystem.
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=yGzwk9xi9gU" target="_blank"}
Watch a video from Alexander Lichter about getting started with the `@nuxt/test-utils`.
::
## Installation
In order to allow you to manage your other testing dependencies, `@nuxt/test-utils` ships with various optional peer dependencies. For example:
- you can choose between `happy-dom` and `jsdom` for a runtime Nuxt environment
- you can choose between `vitest` and `jest` for end-to-end test runners
- `playwright-core` is only required if you wish to use the built-in browser testing utilities
- you can choose between `vitest`, `cucumber`, `jest` and `playwright` for end-to-end test runners
- `playwright-core` is only required if you wish to use the built-in browser testing utilities (and are not using `@playwright/test` as your test runner)
::code-group
```bash [yarn]
yarn add --dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
```
::package-managers
```bash [npm]
npm i --save-dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
```
```bash [yarn]
yarn add --dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
```
```bash [pnpm]
pnpm add -D @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
```
@ -59,6 +63,11 @@ We currently ship an environment for unit testing code that needs a [Nuxt](https
})
```
::tip
When importing `@nuxt/test-utils` in your vitest config, It is necessary to have `"type": "module"` specified in your `package.json` or rename your vitest config file appropriately.
> ie. `vitest.config.m{ts,js}`.
::
### Using a Nuxt Runtime Environment
By default, `@nuxt/test-utils` will not change your default Vitest environment, so you can do fine-grained opt-in and run Nuxt tests together with other unit tests.
@ -88,6 +97,7 @@ export default defineVitestConfig({
// environmentOptions: {
// nuxt: {
// rootDir: fileURLToPath(new URL('./playground', import.meta.url)),
// domEnvironment: 'happy-dom', // 'happy-dom' (default) or 'jsdom'
// overrides: {
// // other Nuxt config you want to pass
// }
@ -108,12 +118,10 @@ test('my test', () => {
})
```
::callout{icon="i-ph-warning-duotone" color="amber"}
::warning
When you run your tests within the Nuxt environment, they will be running in a [`happy-dom`](https://github.com/capricorn86/happy-dom) or [`jsdom`](https://github.com/jsdom/jsdom) environment. Before your tests run, a global Nuxt app will be initialized (including, for example, running any plugins or code you've defined in your `app.vue`).
This means you should take particular care not to mutate the global state in your tests (or, if you need to, to reset it afterwards).
::
### 🎭 Built-In Mocks
@ -153,24 +161,41 @@ export default defineVitestConfig({
#### `mountSuspended`
`mountSuspended` allows you to mount any Vue component within the Nuxt environment, allowing async setup and access to injections from your Nuxt plugins. For example:
`mountSuspended` allows you to mount any Vue component within the Nuxt environment, allowing async setup and access to injections from your Nuxt plugins.
::alert{type=info}
Under the hood, `mountSuspended` wraps `mount` from `@vue/test-utils`, so you can check out [the Vue Test Utils documentation](https://test-utils.vuejs.org/guide/) for more on the options you can pass, and how to use this utility.
::
For example:
```ts twoslash
import type { Component } from 'vue'
import { it, expect } from 'vitest'
declare const SomeComponent: Component
declare const App: Component
import type { Component } from 'vue'
declare module '#components' {
export const SomeComponent: Component
}
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { SomeComponent } from '#components'
it('can mount some component', async () => {
const component = await mountSuspended(SomeComponent)
expect(component.text()).toMatchInlineSnapshot(
'This is an auto-imported component'
'"This is an auto-imported component"'
)
})
```
```ts twoslash
import { it, expect } from 'vitest'
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { mountSuspended } from '@nuxt/test-utils/runtime'
import App from '~/app.vue'
// tests/App.nuxt.spec.ts
it('can also mount an app', async () => {
const component = await mountSuspended(App, { route: '/test' })
@ -188,6 +213,7 @@ it('can also mount an app', async () => {
`renderSuspended` allows you to render any Vue component within the Nuxt environment using `@testing-library/vue`, allowing async setup and access to injections from your Nuxt plugins.
This should be used together with utilities from Testing Library, e.g. `screen` and `fireEvent`. Install [@testing-library/vue](https://testing-library.com/docs/vue-testing-library/intro) in your project to use these.
Additionally, Testing Library also relies on testing globals for cleanup. You should turn these on in your [Vitest config](https://vitest.dev/config/#globals).
The passed in component will be rendered inside a `<div id="test-wrapper"></div>`.
@ -195,13 +221,15 @@ The passed in component will be rendered inside a `<div id="test-wrapper"></div>
Examples:
```ts twoslash
import type { Component } from 'vue'
import { it, expect } from 'vitest'
declare const SomeComponent: Component
declare const App: Component
import type { Component } from 'vue'
declare module '#components' {
export const SomeComponent: Component
}
// ---cut---
// tests/components/SomeComponents.nuxt.spec.ts
import { renderSuspended } from '@nuxt/test-utils/runtime'
import { SomeComponent } from '#components'
import { screen } from '@testing-library/vue'
it('can render some component', async () => {
@ -211,13 +239,11 @@ it('can render some component', async () => {
```
```ts twoslash
import type { Component } from 'vue'
import { it, expect } from 'vitest'
declare const SomeComponent: Component
declare const App: Component
// ---cut---
// tests/App.nuxt.spec.ts
import { renderSuspended } from '@nuxt/test-utils/runtime'
import App from '~/app.vue'
it('can also render an app', async () => {
const html = await renderSuspended(App, { route: '/test' })
@ -247,7 +273,9 @@ mockNuxtImport('useStorage', () => {
// your tests here
```
> **Note**: `mockNuxtImport` can only be used once per mocked import per test file. It is actually a macro that gets transformed to `vi.mock` and `vi.mock` is hoisted, as described [here](https://vitest.dev/api/vi.html#vi-mock).
::alert{type=info}
`mockNuxtImport` can only be used once per mocked import per test file. It is actually a macro that gets transformed to `vi.mock` and `vi.mock` is hoisted, as described [here](https://vitest.dev/api/vi.html#vi-mock).
::
If you need to mock a Nuxt import and provide different implementations between tests, you can do it by creating and exposing your mocks using [`vi.hoisted`](https://vitest.dev/api/vi.html#vi-hoisted), and then use those mocks in `mockNuxtImport`. You then have access to the mocked imports, and can change the implementation between tests. Be careful to [restore mocks](https://vitest.dev/api/mock.html#mockrestore) before or after each test to undo mock state changes between runs.
@ -338,8 +366,8 @@ For example, to mock `/test/` endpoint, you can do:
```ts twoslash
import { registerEndpoint } from '@nuxt/test-utils/runtime'
registerEndpoint("/test/", () => ({
test: "test-field"
registerEndpoint('/test/', () => ({
test: 'test-field'
}))
```
@ -348,13 +376,13 @@ By default, your request will be made using the `GET` method. You may use anothe
```ts twoslash
import { registerEndpoint } from '@nuxt/test-utils/runtime'
registerEndpoint("/test/", {
method: "POST",
handler: () => ({ test: "test-field" })
registerEndpoint('/test/', {
method: 'POST',
handler: () => ({ test: 'test-field' })
})
```
> **Note**: If your requests in a component go to external API, you can use `baseURL` and then make it empty using Nuxt Environment Config (`$test`) so all your requests will go to Nitro server.
> **Note**: If your requests in a component go to an external API, you can use `baseURL` and then make it empty using [Nuxt Environment Override Config](/docs/getting-started/configuration#environment-overrides) (`$test`) so all your requests will go to Nitro server.
#### Conflict with End-To-End Testing
@ -365,7 +393,7 @@ If you would like to use both the end-to-end and unit testing functionality of `
`app.nuxt.spec.ts`
```ts twoslash
import { mockNuxtImport } from "@nuxt/test-utils/runtime"
import { mockNuxtImport } from '@nuxt/test-utils/runtime'
mockNuxtImport('useStorage', () => {
return () => {
@ -387,9 +415,98 @@ await setup({
// ...
```
### Using `@vue/test-utils`
If you prefer to use `@vue/test-utils` on its own for unit testing in Nuxt, and you are only testing components which do not rely on Nuxt composables, auto-imports or context, you can follow these steps to set it up.
1. Install the needed dependencies
::package-managers
```bash [npm]
npm i --save-dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
```
```bash [yarn]
yarn add --dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
```
```bash [pnpm]
pnpm add -D vitest @vue/test-utils happy-dom @vitejs/plugin-vue
```
```bash [bun]
bun add --dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
```
::
2. Create a `vitest.config.ts` with the following content:
```ts twoslash
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
environment: 'happy-dom',
},
});
```
3. Add a new command for test in your `package.json`
```json
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
...
"test": "vitest"
},
```
4. Create a simple `<HelloWorld>` component `components/HelloWorld.vue` with the following content:
```vue
<template>
<p>Hello world</p>
</template>
```
5. Create a simple unit test for this newly created component `~/components/HelloWorld.spec.ts`
```ts twoslash
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import HelloWorld from './HelloWorld.vue'
describe('HelloWorld', () => {
it('component renders Hello world properly', () => {
const wrapper = mount(HelloWorld)
expect(wrapper.text()).toContain('Hello world')
})
})
```
6. Run vitest command
::package-managers
```bash [npm]
npm run test
```
```bash [yarn]
yarn test
```
```bash [pnpm]
pnpm run test
```
```bash [bun]
bun run test
```
::
Congratulations, you're all set to start unit testing with `@vue/test-utils` in Nuxt! Happy testing!
## End-To-End Testing
For end-to-end testing, we support [Vitest](https://github.com/vitest-dev/vitest) and [Jest](https://jestjs.io) as test runners.
For end-to-end testing, we support [Vitest](https://github.com/vitest-dev/vitest), [Jest](https://jestjs.io), [Cucumber](https://cucumber.io/) and [Playwright](https://playwright.dev/) as test runners.
### Setup
@ -436,17 +553,22 @@ Please use the options below for the `setup` method.
#### Features
- `build`: Whether to run a separate build step.
- Type: `boolean`
- Default: `true` (`false` if `browser` or `server` is disabled, or if a `host` is provided)
- `server`: Whether to launch a server to respond to requests in the test suite.
- Type: `boolean`
- Default: `true`
- Default: `true` (`false` if a `host` is provided)
- `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)
- `host`: If provided, a URL to use as the test target instead of building and running a new server. Useful for running "real" end-to-end tests against a deployed version of your application, or against an already running local server (which may provide a significant reduction in test execution timings). See the [target host end-to-end example below](#target-host-end-to-end-example).
- Type: `string`
- Default: `undefined`
- `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`
@ -455,9 +577,34 @@ Please use the options below for the `setup` method.
- `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'`
- Type: `'vitest' | 'jest' | 'cucumber'`
- Default: `'vitest'`
##### Target `host` end-to-end example
A common use-case for end-to-end testing is running the tests against a deployed application running in the same environment typically used for Production.
For local development or automated deploy pipelines, testing against a separate local server can be more efficient and is typically faster than allowing the test framework to rebuild between tests.
To utilize a separate target host for end-to-end tests, simply provide the `host` property of the `setup` function with the desired URL.
```ts
import { setup, createPage } from '@nuxt/test-utils/e2e'
import { describe, it, expect } from 'vitest'
describe('login page', async () => {
await setup({
host: 'http://localhost:8787',
})
it('displays the email and password fields', async () => {
const page = await createPage('/login')
expect(await page.getByTestId('email').isVisible()).toBe(true)
expect(await page.getByTestId('password').isVisible()).toBe(true)
})
})
```
### APIs
#### `$fetch(url)`
@ -494,11 +641,11 @@ const pageUrl = url('/page')
### Testing in a Browser
We provide built-in support using Playwright within `@nuxt/test-utils`, but you can also use other test runners for end-to-end browser testing.
We provide built-in support using Playwright within `@nuxt/test-utils`, either programmatically or via the Playwright test runner.
#### `createPage(url)`
You can create a configured Playwright browser instance, and (optionally) point it at a path from the running server. You can find out more about the API methods available from [in the Playwright documentation](https://playwright.dev/docs/api/class-page).
Within `vitest`, `jest` or `cucumber`, you can create a configured Playwright browser instance with `createPage`, and (optionally) point it at a path from the running server. You can find out more about the API methods available from [in the Playwright documentation](https://playwright.dev/docs/api/class-page).
```ts twoslash
import { createPage } from '@nuxt/test-utils/e2e'
@ -506,3 +653,70 @@ import { createPage } from '@nuxt/test-utils/e2e'
const page = await createPage('/page')
// you can access all the Playwright APIs from the `page` variable
```
#### Testing with Playwright Test Runner
We also provide first-class support for testing Nuxt within [the Playwright test runner](https://playwright.dev/docs/intro).
::package-managers
```bash [npm]
npm i --save-dev @playwright/test @nuxt/test-utils
```
```bash [yarn]
yarn add --dev @playwright/test @nuxt/test-utils
```
```bash [pnpm]
pnpm add -D @playwright/test @nuxt/test-utils
```
```bash [bun]
bun add --dev @playwright/test @nuxt/test-utils
```
::
You can provide global Nuxt configuration, with the same configuration details as the `setup()` function mentioned earlier in this section.
```ts [playwright.config.ts]
import { fileURLToPath } from 'node:url'
import { defineConfig, devices } from '@playwright/test'
import type { ConfigOptions } from '@nuxt/test-utils/playwright'
export default defineConfig<ConfigOptions>({
use: {
nuxt: {
rootDir: fileURLToPath(new URL('.', import.meta.url))
}
},
// ...
})
```
::read-more{title="See full example config" to="https://github.com/nuxt/test-utils/blob/main/examples/app-playwright/playwright.config.ts" target="_blank"}
::
Your test file should then use `expect` and `test` directly from `@nuxt/test-utils/playwright`:
```ts [tests/example.test.ts]
import { expect, test } from '@nuxt/test-utils/playwright'
test('test', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!')
})
```
You can alternatively configure your Nuxt server directly within your test file:
```ts [tests/example.test.ts]
import { expect, test } from '@nuxt/test-utils/playwright'
test.use({
nuxt: {
rootDir: fileURLToPath(new URL('..', import.meta.url))
}
})
test('test', async ({ page, goto }) => {
await goto('/', { waitUntil: 'hydration' })
await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!')
})
```

View File

@ -1,32 +1,606 @@
---
title: Upgrade Guide
description: 'Learn how to upgrade to the latest Nuxt version.'
navigation.icon: i-ph-arrow-circle-up-duotone
navigation.icon: i-ph-arrow-circle-up
---
## Upgrading Nuxt 3
## Upgrading Nuxt
### Latest release
To upgrade Nuxt 3 to the [latest release](https://github.com/nuxt/nuxt/releases), use the `nuxi upgrade` command.
To upgrade Nuxt to the [latest release](https://github.com/nuxt/nuxt/releases), use the `nuxi upgrade` command.
```bash [Terminal]
::package-managers
```bash [npm]
npx nuxi upgrade
```
```bash [yarn]
yarn dlx nuxi upgrade
```
```bash [pnpm]
pnpm dlx nuxi upgrade
```
```bash [bun]
bun x 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.
To use the latest Nuxt 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
::alert{type="warning"}
The nightly release channel `latest` tag is currently tracking the Nuxt v4 branch, meaning that it is particularly likely to have breaking changes right now - be careful!
You can opt in to the 3.x branch nightly releases with `"nuxt": "npm:nuxt-nightly@3x"`.
::
## Testing Nuxt 4
The release date of Nuxt 4 is **to be announced**. It is dependent on having enough time after Nitro's major release to be properly tested in the community. You can follow progress towards Nitro's release in [this PR](https://github.com/unjs/nitro/pull/2521).
Until the release, it is possible to test many of Nuxt 4's breaking changes from Nuxt version 3.12+.
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=r4wFKlcJK6c" target="_blank"}
Watch a video from Alexander Lichter showing how to opt in to Nuxt 4's breaking changes already.
::
### Opting in to Nuxt 4
First, upgrade Nuxt to the [latest release](https://github.com/nuxt/nuxt/releases).
Then you can set your `compatibilityVersion` to match Nuxt 4 behavior:
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
future: {
compatibilityVersion: 4,
},
// To re-enable _all_ Nuxt v3 behavior, set the following options:
// srcDir: '.',
// dir: {
// app: 'app'
// },
// experimental: {
// sharedPrerenderData: false,
// compileTemplate: true,
// resetAsyncDataToUndefined: true,
// templateUtils: true,
// relativeWatchPaths: true,
// normalizeComponentNames: false
// defaults: {
// useAsyncData: {
// deep: true
// }
// }
// },
// unhead: {
// renderSSRHeadOptions: {
// omitLineBreaks: false
// }
// }
})
```
When you set your `compatibilityVersion` to `4`, defaults throughout your Nuxt configuration will change to opt in to Nuxt v4 behavior, but you can granularly re-enable Nuxt v3 behavior when testing, following the commented out lines above. Please file issues if so, so that we can address them in Nuxt or in the ecosystem.
### Migrating to Nuxt 4
Breaking or significant changes will be noted here along with migration steps for backward/forward compatibility.
::alert
This section is subject to change until the final release, so please check back here regularly if you are testing Nuxt 4 using `compatibilityVersion: 4`.
::
#### Migrating Using Codemods
To facilitate the upgrade process, we have collaborated with the [Codemod](https://github.com/codemod-com/codemod) team to automate many migration steps with some open-source codemods.
::note
If you encounter any issues, please report them to the Codemod team with `npx codemod feedback` 🙏
::
For a complete list of Nuxt 4 codemods, detailed information on each, their source, and various ways to run them, visit the [Codemod Registry](https://go.codemod.com/codemod-registry).
You can run all the codemods mentioned in this guide using the following `codemod` recipe:
```bash
npx codemod@latest nuxt/4/migration-recipe
```
This command will execute all codemods in sequence, with the option to deselect any that you do not wish to run. Each codemod is also listed below alongside its respective change and can be executed independently.
#### New Directory Structure
🚦 **Impact Level**: Significant
Nuxt now defaults to a new directory structure, with backwards compatibility (so if Nuxt detects you are using the old structure, such as with a top-level `pages/` directory, this new structure will not apply).
👉 [See full RFC](https://github.com/nuxt/nuxt/issues/26444)
##### What Changed
* the new Nuxt default `srcDir` is `app/` by default, and most things are resolved from there.
* `serverDir` now defaults to `<rootDir>/server` rather than `<srcDir>/server`
* `layers/`, `modules/` and `public/` are resolved relative to `<rootDir>` by default
* if using [Nuxt Content v2.13+](https://github.com/nuxt/content/pull/2649), `content/` is resolved relative to `<rootDir>`
* a new `dir.app` is added, which is the directory we look for `router.options.ts` and `spa-loading-template.html` - this defaults to `<srcDir>/`
<details>
<summary>An example v4 folder structure.</summary>
```sh
.output/
.nuxt/
app/
assets/
components/
composables/
layouts/
middleware/
pages/
plugins/
utils/
app.config.ts
app.vue
router.options.ts
content/
layers/
modules/
node_modules/
public/
server/
api/
middleware/
plugins/
routes/
utils/
nuxt.config.ts
```
</details>
👉 For more details, see the [PR implementing this change](https://github.com/nuxt/nuxt/pull/27029).
##### Reasons for Change
1. **Performance** - placing all your code in the root of your repo causes issues with `.git/` and `node_modules/` folders being scanned/included by FS watchers which can significantly delay startup on non-Mac OSes.
1. **IDE type-safety** - `server/` and the rest of your app are running in two entirely different contexts with different global imports available, and making sure `server/` isn't _inside_ the same folder as the rest of your app is a big first step to ensuring you get good auto-completes in your IDE.
##### Migration Steps
1. Create a new directory called `app/`.
1. Move your `assets/`, `components/`, `composables/`, `layouts/`, `middleware/`, `pages/`, `plugins/` and `utils/` folders under it, as well as `app.vue`, `error.vue`, `app.config.ts`. If you have an `app/router-options.ts` or `app/spa-loading-template.html`, these paths remain the same.
1. Make sure your `nuxt.config.ts`, `content/`, `layers/`, `modules/`, `public/` and `server/` folders remain outside the `app/` folder, in the root of your project.
1. Remember to update any third-party configuration files to work with the new directory structure, such as your `tailwindcss` or `eslint` configuration (if required - `@nuxtjs/tailwindcss` should automatically configure `tailwindcss` correctly).
::tip
You can automate this migration by running `npx codemod@latest nuxt/4/file-structure`
::
However, migration is _not required_. If you wish to keep your current folder structure, Nuxt should auto-detect it. (If it does not, please raise an issue.) The one exception is that if you _already_ have a custom `srcDir`. In this case, you should be aware that your `modules/`, `public/` and `server/` folders will be resolved from your `rootDir` rather than from your custom `srcDir`. You can override this by configuring `dir.modules`, `dir.public` and `serverDir` if you need to.
You can also force a v3 folder structure with the following configuration:
```ts [nuxt.config.ts]
export default defineNuxtConfig({
// This reverts the new srcDir default from `app` back to your root directory
srcDir: '.',
// This specifies the directory prefix for `app/router.options.ts` and `app/spa-loading-template.html`
dir: {
app: 'app'
}
})
```
#### Normalized Component Names
🚦 **Impact Level**: Moderate
Vue will now generate component names that match the Nuxt pattern for component naming.
##### What Changed
By default, if you haven't set it manually, Vue will assign a component name that matches
the filename of the component.
```bash [Directory structure]
├─ components/
├─── SomeFolder/
├───── MyComponent.vue
```
In this case, the component name would be `MyComponent`, as far as Vue is concerned. If you wanted to use `<KeepAlive>` with it, or identify it in the Vue DevTools, you would need to use this name.
But in order to auto-import it, you would need to use `SomeFolderMyComponent`.
With this change, these two values will match, and Vue will generate a component name that matches the Nuxt pattern for component naming.
##### Migration Steps
Ensure that you use the updated name in any tests which use `findComponent` from `@vue/test-utils` and in any `<KeepAlive>` which depends on the name of your component.
Alternatively, for now, you can disable this behaviour with:
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
normalizeComponentNames: false
}
})
```
#### Shared Prerender Data
🚦 **Impact Level**: Medium
##### What Changed
We enabled a previously experimental feature to share data from `useAsyncData` and `useFetch` calls, across different pages. See [original PR](https://github.com/nuxt/nuxt/pull/24894).
##### Reasons for Change
This feature automatically shares payload _data_ between pages that are prerendered. This can result in a significant performance improvement when prerendering sites that use `useAsyncData` or `useFetch` and fetch the same data in different pages.
For example, if your site requires a `useFetch` call for every page (for example, to get navigation data for a menu, or site settings from a CMS), this data would only be fetched once when prerendering the first page that uses it, and then cached for use when prerendering other pages.
##### Migration Steps
Make sure that any unique key of your data is always resolvable to the same data. For example, if you are using `useAsyncData` to fetch data related to a particular page, you should provide a key that uniquely matches that data. (`useFetch` should do this automatically for you.)
```ts [app/pages/test/[slug\\].vue]
// This would be unsafe in a dynamic page (e.g. `[slug].vue`) because the route slug makes a difference
// to the data fetched, but Nuxt can't know that because it's not reflected in the key.
const route = useRoute()
const { data } = await useAsyncData(async () => {
return await $fetch(`/api/my-page/${route.params.slug}`)
})
// Instead, you should use a key that uniquely identifies the data fetched.
const { data } = await useAsyncData(route.params.slug, async () => {
return await $fetch(`/api/my-page/${route.params.slug}`)
})
```
Alternatively, you can disable this feature with:
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
sharedPrerenderData: false
}
})
```
#### Default `data` and `error` values in `useAsyncData` and `useFetch`
🚦 **Impact Level**: Minimal
##### What Changed
`data` and `error` objects returned from `useAsyncData` will now default to `undefined`.
##### Reasons for Change
Previously `data` was initialized to `null` but reset in `clearNuxtData` to `undefined`. `error` was initialized to `null`. This change is to bring greater consistency.
##### Migration Steps
If you were checking if `data.value` or `error.value` were `null`, you can update these checks to check for `undefined` instead.
::tip
You can automate this step by running `npx codemod@latest nuxt/4/default-data-error-value`
::
If you encounter any issues you can revert back to the previous behavior with:
```ts twoslash [nuxt.config.ts]
// @errors: 2353
export default defineNuxtConfig({
experimental: {
defaults: {
useAsyncData: {
value: 'null',
errorValue: 'null'
}
}
}
})
```
Please report an issue if you are doing this, as we do not plan to keep this as configurable.
#### Removal of deprecated `boolean` values for `dedupe` option when calling `refresh` in `useAsyncData` and `useFetch`
🚦 **Impact Level**: Minimal
##### What Changed
Previously it was possible to pass `dedupe: boolean` to `refresh`. These were aliases of `cancel` (`true`) and `defer` (`false`).
```ts twoslash [app.vue]
// @errors: 2322
const { refresh } = await useAsyncData(async () => ({ message: 'Hello, Nuxt 3!' }))
async function refreshData () {
await refresh({ dedupe: true })
}
```
##### Reasons for Change
These aliases were removed, for greater clarity.
The issue came up when adding `dedupe` as an option to `useAsyncData`, and we removed the boolean values as they ended up being _opposites_.
`refresh({ dedupe: false })` meant 'do not _cancel_ existing requests in favour of this new one'. But passing `dedupe: true` within the options of `useAsyncData` means 'do not make any new requests if there is an existing pending request.' (See [PR](https://github.com/nuxt/nuxt/pull/24564#pullrequestreview-1764584361).)
##### Migration Steps
The migration should be straightforward:
```diff
const { refresh } = await useAsyncData(async () => ({ message: 'Hello, Nuxt 3!' }))
async function refreshData () {
- await refresh({ dedupe: true })
+ await refresh({ dedupe: 'cancel' })
- await refresh({ dedupe: false })
+ await refresh({ dedupe: 'defer' })
}
```
::tip
You can automate this step by running `npx codemod@latest nuxt/4/deprecated-dedupe-value`
::
#### Respect defaults when clearing `data` in `useAsyncData` and `useFetch`
🚦 **Impact Level**: Minimal
##### What Changed
If you provide a custom `default` value for `useAsyncData`, this will now be used when calling `clear` or `clearNuxtData` and it will be reset to its default value rather than simply unset.
##### Reasons for Change
Often users set an appropriately empty value, such as an empty array, to avoid the need to check for `null`/`undefined` when iterating over it. This should be respected when resetting/clearing the data.
##### Migration Steps
If you encounter any issues you can revert back to the previous behavior, for now, with:
```ts twoslash [nuxt.config.ts]
// @errors: 2353
export default defineNuxtConfig({
experimental: {
resetAsyncDataToUndefined: true,
}
})
```
Please report an issue if you are doing so, as we do not plan to keep this as configurable.
#### Shallow Data Reactivity in `useAsyncData` and `useFetch`
🚦 **Impact Level**: Minimal
The `data` object returned from `useAsyncData`, `useFetch`, `useLazyAsyncData` and `useLazyFetch` is now a `shallowRef` rather than a `ref`.
##### What Changed
When new data is fetched, anything depending on `data` will still be reactive because the entire object is replaced. But if your code changes a property _within_ that data structure, this will not trigger any reactivity in your app.
##### Reasons for Change
This brings a **significant** performance improvement for deeply nested objects and arrays because Vue does not need to watch every single property/array for modification. In most cases, `data` should also be immutable.
##### Migration Steps
In most cases, no migration steps are required, but if you rely on the reactivity of the data object then you have two options:
1. You can granularly opt in to deep reactivity on a per-composable basis:
```diff
- const { data } = useFetch('/api/test')
+ const { data } = useFetch('/api/test', { deep: true })
```
1. You can change the default behavior on a project-wide basis (not recommended):
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
defaults: {
useAsyncData: {
deep: true
}
}
}
})
```
::tip
If you need to, you can automate this step by running `npx codemod@latest nuxt/4/shallow-function-reactivity`
::
#### Absolute Watch Paths in `builder:watch`
🚦 **Impact Level**: Minimal
##### What Changed
The Nuxt `builder:watch` hook now emits a path which is absolute rather than relative to your project `srcDir`.
##### Reasons for Change
This allows us to support watching paths which are outside your `srcDir`, and offers better support for layers and other more complex patterns.
##### Migration Steps
We have already proactively migrated the public Nuxt modules which we are aware use this hook. See [issue #25339](https://github.com/nuxt/nuxt/issues/25339).
However, if you are a module author using the `builder:watch` hook and wishing to remain backwards/forwards compatible, you can use the following code to ensure that your code works the same in both Nuxt v3 and Nuxt v4:
```diff
+ import { relative, resolve } from 'node:fs'
// ...
nuxt.hook('builder:watch', async (event, path) => {
+ path = relative(nuxt.options.srcDir, resolve(nuxt.options.srcDir, path))
// ...
})
```
::tip
You can automate this step by running `npx codemod@latest nuxt/4/absolute-watch-path`
::
#### Removal of `window.__NUXT__` object
##### What Changed
We are removing the global `window.__NUXT__` object after the app finishes hydration.
##### Reasons for Change
This opens the way to multi-app patterns ([#21635](https://github.com/nuxt/nuxt/issues/21635)) and enables us to focus on a single way to access Nuxt app data - `useNuxtApp()`.
##### Migration Steps
The data is still available, but can be accessed with `useNuxtApp().payload`:
```diff
- console.log(window.__NUXT__)
+ console.log(useNuxtApp().payload)
```
#### Directory index scanning
🚦 **Impact Level**: Medium
##### What Changed
Child folders in your `middleware/` folder are also scanned for `index` files and these are now also registered as middleware in your project.
##### Reasons for Change
Nuxt scans a number of folders automatically, including `middleware/` and `plugins/`.
Child folders in your `plugins/` folder are scanned for `index` files and we wanted to make this behavior consistent between scanned directories.
##### Migration Steps
Probably no migration is necessary but if you wish to revert to previous behavior you can add a hook to filter out these middleware:
```ts
export default defineNuxtConfig({
hooks: {
'app:resolve'(app) {
app.middleware = app.middleware.filter(mw => !/\/index\.[^/]+$/.test(mw.path))
}
}
})
```
#### Template Compilation Changes
🚦 **Impact Level**: Minimal
##### What Changed
Previously, Nuxt used `lodash/template` to compile templates located on the file system using the `.ejs` file format/syntax.
In addition, we provided some template utilities (`serialize`, `importName`, `importSources`) which could be used for code-generation within these templates, which are now being removed.
##### Reasons for Change
In Nuxt v3 we moved to a 'virtual' syntax with a `getContents()` function which is much more flexible and performant.
In addition, `lodash/template` has had a succession of security issues. These do not really apply to Nuxt projects because it is being used at build-time, not runtime, and by trusted code. However, they still appear in security audits. Moreover, `lodash` is a hefty dependency and is unused by most projects.
Finally, providing code serialization functions directly within Nuxt is not ideal. Instead, we maintain projects like [unjs/knitwork](http://github.com/unjs/knitwork) which can be dependencies of your project, and where security issues can be reported/resolved directly without requiring an upgrade of Nuxt itself.
##### Migration Steps
We have raised PRs to update modules using EJS syntax, but if you need to do this yourself, you have three backwards/forwards-compatible alternatives:
* Moving your string interpolation logic directly into `getContents()`.
* Using a custom function to handle the replacement, such as in https://github.com/nuxt-modules/color-mode/pull/240.
* Continuing to use `lodash`, as a dependency of _your_ project rather than Nuxt:
```diff
+ import { readFileSync } from 'node:fs'
+ import { template } from 'lodash-es'
// ...
addTemplate({
fileName: 'appinsights-vue.js'
options: { /* some options */ },
- src: resolver.resolve('./runtime/plugin.ejs'),
+ getContents({ options }) {
+ const contents = readFileSync(resolver.resolve('./runtime/plugin.ejs'), 'utf-8')
+ return template(contents)({ options })
+ },
})
```
Finally, if you are using the template utilities (`serialize`, `importName`, `importSources`), you can replace them as follows with utilities from `knitwork`:
```ts
import { genDynamicImport, genImport, genSafeVariableName } from 'knitwork'
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"(?=,?$)/gm, r => JSON.parse(r).replace(/^{(.*)}$/, '$1'))
const importSources = (sources: string | string[], { lazy = false } = {}) => {
return toArray(sources).map((src) => {
if (lazy) {
return `const ${genSafeVariableName(src)} = ${genDynamicImport(src, { comment: `webpackChunkName: ${JSON.stringify(src)}` })}`
}
return genImport(src, genSafeVariableName(src))
}).join('\n')
}
const importName = genSafeVariableName
```
::tip
You can automate this step by running `npx codemod@latest nuxt/4/template-compilation-changes`
::
#### Removal of Experimental Features
🚦 **Impact Level**: Minimal
##### What Changed
Four experimental features are no longer configurable in Nuxt 4:
* `experimental.treeshakeClientOnly` will be `true` (default since v3.0)
* `experimental.configSchema` will be `true` (default since v3.3)
* `experimental.polyfillVueUseHead` will be `false` (default since v3.4)
* `experimental.respectNoSSRHeader` will be `false` (default since v3.4)
* `vite.devBundler` is no longer configurable - it will use `vite-node` by default
##### Reasons for Change
These options have been set to their current values for some time and we do not have a reason to believe that they need to remain configurable.
##### Migration Steps
* `polyfillVueUseHead` is implementable in user-land with [this plugin](https://github.com/nuxt/nuxt/blob/f209158352b09d1986aa320e29ff36353b91c358/packages/nuxt/src/head/runtime/plugins/vueuse-head-polyfill.ts#L10-L11)
* `respectNoSSRHeader`is implementable in user-land with [server middleware](https://github.com/nuxt/nuxt/blob/c660b39447f0d5b8790c0826092638d321cd6821/packages/nuxt/src/core/runtime/nitro/no-ssr.ts#L8-L9)
## Nuxt 2 vs Nuxt 3+
In the table below, there is a quick comparison between 3 versions of Nuxt:
Feature / Version | Nuxt 2 | Nuxt Bridge | Nuxt 3
Feature / Version | Nuxt 2 | Nuxt Bridge | Nuxt 3+
-------------------------|-----------------|------------------|---------
Vue | 2 | 2 | 3
Stability | 😊 Stable | 😌 Semi-stable | 😊 Stable
Stability | 😊 Stable | 😊 Stable | 😊 Stable
Performance | 🏎 Fast | ✈️ Faster | 🚀 Fastest
Nitro Engine | ❌ | ✅ | ✅
ESM support | 🌙 Partial | 👍 Better | ✅
@ -41,9 +615,9 @@ Vite | ⚠️ Partial | 🚧 Partial | ✅
Nuxi CLI | ❌ Old | ✅ nuxi | ✅ nuxi
Static sites | ✅ | ✅ | ✅
## Nuxt 2 to Nuxt 3
## Nuxt 2 to Nuxt 3+
The migration guide provides a step-by-step comparison of Nuxt 2 features to Nuxt 3 features and guidance to adapt your current application.
The migration guide provides a step-by-step comparison of Nuxt 2 features to Nuxt 3+ features and guidance to adapt your current application.
::read-more{to="/docs/migration/overview"}
Check out the **guide to migrating from Nuxt 2 to Nuxt 3**.
@ -51,7 +625,7 @@ 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.
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.
::read-more{to="/docs/bridge/overview"}
**Migrate from Nuxt 2 to Nuxt Bridge**

View File

@ -1,19 +1,19 @@
---
title: 'Installation'
description: 'Get started with Nuxt quickly with our online starters or start locally with your terminal.'
navigation.icon: i-ph-play-duotone
navigation.icon: i-ph-play
---
## Play Online
You can start playing with Nuxt 3 in your browser using our online sandboxes:
If you just want to play around with Nuxt in your browser without setting up a project, you can use one of our online sandboxes:
::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).
Or follow the steps below to set up a new Nuxt project on your computer.
## New Project
@ -22,46 +22,43 @@ Start with one of our starters and themes directly by opening [nuxt.new](https:/
#### Prerequisites
- **Node.js** - [`v18.0.0`](https://nodejs.org/en) or newer
- **Text editor** - We recommend [Visual Studio Code](https://code.visualstudio.com/) with the [Volar Extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
- **Text editor** - We recommend [Visual Studio Code](https://code.visualstudio.com/) with the [official Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously known as Volar)
- **Terminal** - In order to run Nuxt commands
::callout
::note
::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:
```ts twoslash [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:
::code-group
::package-managers
```bash [npx]
```bash [npm]
npx nuxi@latest init <project-name>
```
```bash [yarn]
yarn dlx nuxi@latest init <project-name>
```
```bash [pnpm]
pnpm dlx nuxi@latest init <project-name>
```
```bash [bun]
bunx nuxi@latest init <project-name>
bun x nuxi@latest init <project-name>
```
::
::tip
Alternatively, you can find other starters or themes by opening [nuxt.new](https://nuxt.new) and following the instructions there.
::
Open your project folder in Visual Studio Code:
```bash [Terminal]
@ -74,47 +71,20 @@ Or change directory into your new project from your terminal:
cd <project-name>
```
Install the dependencies:
::code-group
```bash [yarn]
yarn install
```
```bash [npm]
npm install
```
```bash [pnpm]
pnpm install
```
```bash [bun]
bun install
```
::
::callout
If you are using Yarn 2+ (Berry), add `nodeLinker: node-modules` to your `.yarnrc.yml` file.
[You can follow this issue status here](https://github.com/nuxt/nuxt/issues/22861)
::
## Development Server
Now you'll be able to start your Nuxt app in development mode:
::code-group
```bash [yarn]
yarn dev --open
```
::package-managers
```bash [npm]
npm run dev -- -o
```
```bash [yarn]
yarn dev --open
```
```bash [pnpm]
pnpm dev -o
```
@ -124,12 +94,12 @@ bun run dev -o
```
::
::callout{icon="i-ph-check-circle-duotone"}
::tip{icon="i-ph-check-circle"}
Well done! A browser window should automatically open for <http://localhost:3000>.
::
## Next Steps
Now that you've created your Nuxt 3 project, you are ready to start building your application.
Now that you've created your Nuxt project, you are ready to start building your application.
:read-more{title="Nuxt Concepts" to="/docs/guide/concepts"}

View File

@ -1,10 +1,9 @@
---
title: Configuration
description: Nuxt is configured with sensible defaults to make you productive.
navigation.icon: i-ph-gear-duotone
navigation.icon: i-ph-gear
---
By default, Nuxt is configured to cover most use cases. The [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file can override or extend this default configuration.
## Nuxt Configuration
@ -25,11 +24,11 @@ This file will often be mentioned in the documentation, for example to add custo
Every option is described in the **Configuration Reference**.
::
::callout
::note
You don't have to use TypeScript to build an application with Nuxt. However, it is strongly recommended to use the `.ts` extension for the `nuxt.config` file. This way you can benefit from hints in your IDE to avoid typos and mistakes while editing your configuration.
::
### Environment overrides
### Environment Overrides
You can configure fully typed, per-environment overrides in your nuxt.config
@ -46,7 +45,11 @@ export default defineNuxtConfig({
})
```
::callout
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=DFZI2iVCrNc" target="_blank"}
Watch a video from Alexander Lichter about the env-aware `nuxt.config.ts`.
::
::note
If you're authoring layers, you can also use the `$meta` key to provide metadata that you or the consumers of your layer might use.
::
@ -135,7 +138,7 @@ Non primitive JS types | ❌ No | ✅ Yes
## External Configuration Files
Nuxt uses [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file as the single source of trust for configurations and skips reading external configuration files. During the course of building your project, you may have a need to configure those. The following table highlights common configurations and, where applicable, how they can be configured with Nuxt.
Nuxt uses [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file as the single source of truth for configurations and skips reading external configuration files. During the course of building your project, you may have a need to configure those. The following table highlights common configurations and, where applicable, how they can be configured with Nuxt.
Name | Config File | How To Configure
---------------------------------------------|---------------------------|-------------------------
@ -149,7 +152,7 @@ Here is a list of other common config files:
Name | Config File | How To Configure
---------------------------------------------|-------------------------|--------------------------
[TypeScript](https://www.typescriptlang.org) | `tsconfig.json` | [More Info](/docs/guide/concepts/typescript#nuxttsconfigjson)
[ESLint](https://eslint.org) | `.eslintrc.js` | [More Info](https://eslint.org/docs/latest/use/configure/configuration-files)
[ESLint](https://eslint.org) | `eslint.config.js` | [More Info](https://eslint.org/docs/latest/use/configure/configuration-files)
[Prettier](https://prettier.io) | `.prettierrc.json` | [More Info](https://prettier.io/docs/en/configuration.html)
[Stylelint](https://stylelint.io) | `.stylelintrc.json` | [More Info](https://stylelint.io/user-guide/configure)
[TailwindCSS](https://tailwindcss.com) | `tailwind.config.js` | [More Info](https://tailwindcss.nuxtjs.org/tailwind/config)

View File

@ -1,7 +1,7 @@
---
title: 'Views'
description: 'Nuxt provides several component layers to implement the user interface of your application.'
navigation.icon: i-ph-layout-duotone
navigation.icon: i-ph-layout
---
## `app.vue`
@ -18,7 +18,7 @@ By default, Nuxt will treat this file as the **entrypoint** and render its conte
</template>
```
::callout
::tip
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.
::
@ -90,12 +90,22 @@ To use pages, create `pages/index.vue` file and add `<NuxtPage />` component to
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 `<slot />` 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.
::callout
::note
If you only have a single layout in your application, we recommend using [`app.vue`](/docs/guide/directory-structure/app) with [`<NuxtPage />`](/docs/api/components/nuxt-page) instead.
::
::code-group
```vue [app.vue]
<template>
<div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
```
```vue [layouts/default.vue]
<template>
<div>
@ -131,7 +141,7 @@ If you want to create more layouts and learn how to use them in your pages, find
## Advanced: Extending the HTML template
::callout
::note
If you only need to modify the `<head>`, you can refer to the [SEO and meta section](/docs/getting-started/seo-meta).
::

View File

@ -1,7 +1,7 @@
---
title: 'Assets'
description: 'Nuxt offers two options for your assets.'
navigation.icon: i-ph-image-duotone
navigation.icon: i-ph-image
---
Nuxt uses two directories to handle assets like stylesheets, fonts or images.
@ -43,7 +43,7 @@ For example, referencing an image file that will be processed if a build tool is
</template>
```
::callout
::note
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.
::

View File

@ -1,7 +1,7 @@
---
title: 'Styling'
description: 'Learn how to style your Nuxt application.'
navigation.icon: i-ph-palette-duotone
navigation.icon: i-ph-palette
---
Nuxt is highly flexible when it comes to styling. Write your own styles, or reference local and external stylesheets.
@ -30,7 +30,7 @@ import('~/assets/css/first.css')
</style>
```
::callout
::tip
The stylesheets will be inlined in the HTML rendered by Nuxt.
::
@ -45,7 +45,7 @@ export default defineNuxtConfig({
})
```
::callout
::tip
The stylesheets will be inlined in the HTML rendered by Nuxt, injected globally and present in all pages.
::
@ -77,10 +77,26 @@ h1 {
You can also reference stylesheets that are distributed through npm. Let's use the popular `animate.css` library as an example.
```bash [Terminal]
::package-managers
```bash [npm]
npm install animate.css
```
```bash [yarn]
yarn add animate.css
```
```bash [pnpm]
pnpm install animate.css
```
```bash [bun]
bun install animate.css
```
::
Then you can reference it directly in your pages, layouts and components:
```vue [app.vue]
@ -113,7 +129,8 @@ export default defineNuxtConfig({
head: {
link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
}
}})
}
})
```
### Dynamically Adding Stylesheets
@ -153,15 +170,15 @@ To use a preprocessor like SCSS, Sass, Less or Stylus, install it first.
::code-group
```bash [Sass & SCSS]
npm install sass
npm install -D sass
```
```bash [Less]
npm install less
npm install -D less
```
```bash [Stylus]
npm install stylus
npm install -D stylus
```
::
@ -183,7 +200,7 @@ export default defineNuxtConfig({
})
```
::callout
::tip
In both cases, the compiled stylesheets will be inlined in the HTML rendered by Nuxt.
::
@ -243,7 +260,7 @@ Nuxt uses Vite by default. If you wish to use webpack instead, refer to each pre
## Single File Components (SFC) Styling
One of the best things about Vue and SFC is how great it is at naturally dealing with styling. You can directly write CSS or preprocessor code in the style block of your components file, therefore you will have fantastic developer experience without having to use something like CSS-in-JS. However if you wish to use CSS-in-JS, you can find 3rd party libraries and modules that support it, such as [pinceau](https://pinceau.dev).
One of the best things about Vue and SFC is how great it is at naturally dealing with styling. You can directly write CSS or preprocessor code in the style block of your components file, therefore you will have fantastic developer experience without having to use something like CSS-in-JS. However if you wish to use CSS-in-JS, you can find 3rd party libraries and modules that support it, such as [pinceau](https://github.com/Tahul/pinceau).
You can refer to the [Vue docs](https://vuejs.org/api/sfc-css-features.html) for a comprehensive reference about styling components in SFC.
@ -410,8 +427,8 @@ Nuxt comes with postcss built-in. You can configure it in your `nuxt.config` fil
export default defineNuxtConfig({
postcss: {
plugins: {
'postcss-nested': {}
"postcss-custom-media": {}
'postcss-nested': {},
'postcss-custom-media': {}
}
}
})
@ -421,7 +438,7 @@ For proper syntax highlighting in SFC, you can use the postcss lang attribute.
```vue
<style lang="postcss">
/* Write stylus here */
/* Write postcss here */
</style>
```
@ -430,7 +447,7 @@ By default, Nuxt comes with the following plugins already pre-configured:
- [postcss-import](https://github.com/postcss/postcss-import): Improves the `@import` rule
- [postcss-url](https://github.com/postcss/postcss-url): Transforms `url()` statements
- [autoprefixer](https://github.com/postcss/autoprefixer): Automatically adds vendor prefixes
- [cssnano](https://cssnano.co): Minification and purge
- [cssnano](https://cssnano.github.io/cssnano): Minification and purge
## Leveraging Layouts For Multiple Styles
@ -458,14 +475,14 @@ Use different styles for different layouts.
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.
The community and the Nuxt team have developed plenty of Nuxt modules to make the integration easier.
You can discover them on the [modules section](/modules) of the website.
Here are a few modules to help you get started:
- [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
- [Pinceau](https://github.com/Tahul/pinceau): Adaptable styling framework
- [Nuxt UI](https://ui.nuxt.com): A UI Library for Modern Web Apps
- [Panda CSS](https://panda-css.com/docs/installation/nuxt): CSS-in-JS engine that generates atomic CSS at build time
@ -489,7 +506,7 @@ Nuxt comes with the same `<Transition>` element that Vue has, and also has suppo
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.
::callout
::tip
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!
::
@ -513,7 +530,7 @@ export default defineNuxtConfig({
hooks: {
'build:manifest': (manifest) => {
// find the app entry, css list
const css = manifest['node_modules/nuxt/dist/app/entry.js']?.css
const css = Object.values(manifest).find(options => options.isEntry)?.css
if (css) {
// start from the end of the array and go to the beginning
for (let i = css.length - 1; i >= 0; i--) {

View File

@ -1,7 +1,7 @@
---
title: 'Routing'
description: Nuxt file-system routing creates a route for every file in the pages/ directory.
navigation.icon: i-ph-signpost-duotone
navigation.icon: i-ph-signpost
---
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.
@ -15,7 +15,7 @@ This file system routing uses naming conventions to create dynamic and nested ro
::code-group
```bash [Directory Structure]
| pages/
-| pages/
---| about.vue
---| index.vue
---| posts/
@ -86,7 +86,7 @@ console.log(route.params.id)
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.
::callout
::note
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.
::
@ -140,7 +140,7 @@ If you have a more complex use case, then you can use anonymous route middleware
definePageMeta({
validate: async (route) => {
// Check if the id is made up of digits
return /^\d+$/.test(route.params.id)
return typeof route.params.id === 'string' && /^\d+$/.test(route.params.id)
}
})
</script>

View File

@ -1,12 +1,12 @@
---
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
navigation.icon: i-ph-file-search
---
## Defaults
Out-of-the-box, Nuxt provides sane defaults, which you can override if needed.
Out-of-the-box, Nuxt provides sensible defaults, which you can override if needed.
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
@ -21,7 +21,7 @@ export default defineNuxtConfig({
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.
::callout
::important
This method does not allow you to provide reactive data. We recommend to use `useHead()` in `app.vue`.
::
@ -128,8 +128,6 @@ See [@unhead/schema](https://github.com/unjs/unhead/blob/main/packages/schema/sr
Reactivity is supported on all properties, by providing a computed value, a getter, or a reactive object.
It's recommended to use getters (`() => value`) over computed (`computed(() => value)`).
::code-group
```vue twoslash [useHead]
@ -174,7 +172,7 @@ You can use the `titleTemplate` option to provide a dynamic template for customi
The `titleTemplate` can either be a string, where `%s` is replaced with the title, or a function.
If you want to use a function (for full control), then this cannot be set in your `nuxt.config`, and it is recommended instead to set it within your `app.vue` file, where it will apply to all pages on your site:
If you want to use a function (for full control), then this cannot be set in your `nuxt.config`. It is recommended instead to set it within your `app.vue` file where it will apply to all pages on your site:
::code-group

View File

@ -1,10 +1,10 @@
---
title: 'Transitions'
description: Apply transitions between pages and layouts with Vue or native browser View Transitions.
navigation.icon: i-ph-exclude-square-duotone
navigation.icon: i-ph-exclude-square
---
::callout
::note
Nuxt leverages Vue's [`<Transition>`](https://vuejs.org/guide/built-ins/transition.html#the-transition-component) component to apply transitions between pages and layouts.
::
@ -20,7 +20,7 @@ export default defineNuxtConfig({
})
```
::callout
::note
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).
::
@ -246,7 +246,7 @@ export default defineNuxtConfig({
})
```
::callout
::warning
If you change the `name` property, you also have to rename the CSS classes accordingly.
::
@ -309,7 +309,7 @@ definePageMeta({
</script>
```
::callout
::tip
Learn more about additional [JavaScript hooks](https://vuejs.org/guide/built-ins/transition.html#javascript-hooks) available in the `Transition` component.
::
@ -328,7 +328,7 @@ definePageMeta({
},
middleware (to, from) {
if (to.meta.pageTransition && typeof to.meta.pageTransition !== 'boolean')
to.meta.pageTransition.name = +to.params.id > +from.params.id ? 'slide-left' : 'slide-right'
to.meta.pageTransition.name = +to.params.id! > +from.params.id! ? 'slide-left' : 'slide-right'
}
})
</script>
@ -392,7 +392,7 @@ The page now applies the `slide-left` transition when going to the next id and `
## Transition with NuxtPage
When `<NuxtPage />` is used in `app.vue`, transition-props can be passed directly as a component props to activate global transition.
When `<NuxtPage />` is used in `app.vue`, transitions can be configured with the `transition` prop to activate transitions globally.
```vue [app.vue]
<template>
@ -407,7 +407,7 @@ When `<NuxtPage />` is used in `app.vue`, transition-props can be passed directl
</template>
```
::callout
::note
Remember, this page transition cannot be overridden with `definePageMeta` on individual pages.
::
@ -470,6 +470,4 @@ export default defineNuxtRouteMiddleware(to => {
### Known issues
- View transitions may not work as expected with nested pages/layouts/async components owing to this upstream Vue bug: <https://github.com/vuejs/core/issues/5513>. If you make use of this pattern, you may need to delay adopting this experimental feature or implement it yourself. Feedback is very welcome.
- If you perform data fetching within your page setup functions, that you may wish to reconsider using this feature for the moment. (By design, View Transitions completely freeze DOM updates whilst they are taking place.) We're looking at restrict the View Transition to the final moments before `<Suspense>` resolves, but in the interim you may want to consider carefully whether to adopt this feature if this describes you.

View File

@ -1,7 +1,7 @@
---
title: 'Data fetching'
description: Nuxt provides composables to handle data fetching within your application.
navigation.icon: i-ph-plugs-connected-duotone
navigation.icon: i-ph-plugs-connected
---
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`.
@ -16,9 +16,9 @@ Both `useFetch` and `useAsyncData` share a common set of options and patterns th
Before that, it's imperative to know why these composables exist in the first place.
## Why using specific composables?
## Why use specific composables for data fetching?
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.
Nuxt is a framework which can run isomorphic (or universal) code in both server and client environments. If the [`$fetch` function](/docs/api/utils/dollarfetch) is used to perform data fetching in the setup function of a Vue component, this may cause data to be fetched twice, once on the server (to render the HTML) and once again on the client (when the HTML is hydrated). This is why Nuxt offers specific data fetching composables so data is fetched only once.
### Network calls duplication
@ -26,7 +26,7 @@ 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 [during hydration](/docs/guide/concepts/rendering#universal-rendering).
::callout{color="blue" icon="i-ph-info-duotone"}
::tip
Use the [Nuxt DevTools](https://devtools.nuxt.com) to inspect this data in the **Payload tab**.
::
@ -34,7 +34,7 @@ Use the [Nuxt DevTools](https://devtools.nuxt.com) to inspect this data in the *
Nuxt uses Vues [`<Suspense>`](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.
::callout{color="blue" icon="i-ph-info-duotone"}
::note
You can add the [`<NuxtLoadingIndicator>`](/docs/api/components/nuxt-loading-indicator) to add a progress bar between page navigations.
::
@ -54,13 +54,17 @@ 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.
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=njsGVmcWviY" target="_blank"}
Watch the video from Alexander Lichter to avoid using `useFetch` the wrong way!
::
:read-more{to="/docs/api/composables/use-fetch"}
:link-example{to="/docs/examples/features/data-fetching"}
## `$fetch`
Nuxt includes the `ofetch` library, and is auto-imported as the `$fetch` alias globally across your application. It's what `useFetch` uses behind the scenes.
Nuxt includes the [ofetch](https://github.com/unjs/ofetch) library, and is auto-imported as the `$fetch` alias globally across your application. It's what `useFetch` uses behind the scenes.
```vue twoslash [pages/todos.vue]
<script setup lang="ts">
@ -75,8 +79,8 @@ async function addTodo() {
</script>
```
::callout{color="amber" icon="i-ph-warning-duotone"}
Beware that using only `$fetch` will not provide [network calls de-duplication and navigation prevention](#why-using-specific-composables). :br
::warning
Beware that using only `$fetch` will not provide [network calls de-duplication and navigation prevention](#why-use-specific-composables-for-data-fetching). :br
It is recommended to use `$fetch` for client-side interactions (event based) or combined with [`useAsyncData`](#useasyncdata) when fetching the initial component data.
::
@ -88,11 +92,15 @@ Read more about `$fetch`.
The `useAsyncData` composable is responsible for wrapping async logic and returning the result once it is resolved.
::callout
::tip
`useFetch(url)` is nearly equivalent to `useAsyncData(url, () => $fetch(url))`. :br
It's developer experience sugar for the most common use case.
::
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=0X-aOpSGabA" target="_blank"}
Watch a video from Alexander Lichter to dig deeper into the difference between `useFetch` and `useAsyncData`.
::
There are some cases when using the [`useFetch`](/docs/api/composables/use-fetch) composable is not appropriate, for example when a CMS or a third-party provide their own query layer. In this case, you can use [`useAsyncData`](/docs/api/composables/use-async-data) to wrap your calls and still keep the benefits provided by the composable.
```vue [pages/users.vue]
@ -104,7 +112,7 @@ const { data, error } = await useAsyncData(() => myGetFunction('users'))
</script>
```
::callout{color="blue" icon="i-ph-info-duotone"}
::note
The first argument of [`useAsyncData`](/docs/api/composables/use-async-data) is a unique key used to cache the response of the second argument, the querying function. This key can be ignored by directly passing the querying function, the key will be auto-generated.
:br :br
Since the autogenerated key only takes into account the file and line where `useAsyncData` is invoked, it is recommended to always create your own key to avoid unwanted behavior, like when you are creating your own custom composable wrapping `useAsyncData`.
@ -122,11 +130,11 @@ const { data, error } = await useAsyncData(`user:${id}`, () => {
</script>
```
The `useAsyncData` composable is a great way to wrap and wait for multiple `useFetch` to be done, and then retrieve the results of each.
The `useAsyncData` composable is a great way to wrap and wait for multiple `$fetch` requests to be completed, and then process the results.
```vue
<script setup lang="ts">
const { data: discounts, pending } = await useAsyncData('cart-discount', async () => {
const { data: discounts, status } = await useAsyncData('cart-discount', async () => {
const [coupons, offers] = await Promise.all([
$fetch('/cart/coupons'),
$fetch('/cart/offers')
@ -148,18 +156,18 @@ Read more about `useAsyncData`.
`useFetch` and `useAsyncData` have the same return values listed below.
- `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.
- `clear`: a function that can be used to set `data` to `undefined`, set `error` to `null`, set `status` to `idle`, and mark any currently pending requests as cancelled.
- `error`: an error object if the data fetching failed.
- `status`: a string indicating the status of the data request (`"idle"`, `"pending"`, `"success"`, `"error"`).
::callout
`data`, `pending`, `error` and `status` are Vue refs accessible with `.value` in `<script setup>`
::note
`data`, `error` and `status` are Vue refs accessible with `.value` in `<script setup>`
::
By default, Nuxt waits until a `refresh` is finished before it can be executed again.
::callout
::note
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 `<script setup>`.
::
@ -169,18 +177,18 @@ If you have not fetched data on the server (for example, with `server: false`),
### Lazy
By default, data fetching composables will wait for the resolution of their asynchronous function before navigating to a new page by using Vues Suspense. This feature can be ignored on client-side navigation with the `lazy` option. In that case, you will have to manually handle loading state using the `pending` value.
By default, data fetching composables will wait for the resolution of their asynchronous function before navigating to a new page by using Vues Suspense. This feature can be ignored on client-side navigation with the `lazy` option. In that case, you will have to manually handle loading state using the `status` value.
```vue twoslash [app.vue]
<script setup lang="ts">
const { pending, data: posts } = useFetch('/api/posts', {
const { status, data: posts } = useFetch('/api/posts', {
lazy: true
})
</script>
<template>
<!-- you will need to handle a loading state -->
<div v-if="pending">
<div v-if="status === 'pending'">
Loading ...
</div>
<div v-else>
@ -195,7 +203,7 @@ You can alternatively use [`useLazyFetch`](/docs/api/composables/use-lazy-fetch)
```vue twoslash
<script setup lang="ts">
const { pending, data: posts } = useLazyFetch('/api/posts')
const { status, data: posts } = useLazyFetch('/api/posts')
</script>
```
@ -218,7 +226,7 @@ Combined with the `lazy` option, this can be useful for data that is not needed
const articles = await useFetch('/api/article')
/* This call will only be performed on the client */
const { pending, data: posts } = useFetch('/api/comments', {
const { status, data: comments } = useFetch('/api/comments', {
lazy: true,
server: false
})
@ -254,7 +262,7 @@ const { data: mountains } = await useFetch('/api/mountains', {
})
```
::callout
::note
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.
::
@ -267,7 +275,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.
::callout
::tip
To get the cached data by key, you can use [`useNuxtData`](/docs/api/composables/use-nuxt-data)
::
@ -283,17 +291,32 @@ const { data, error, execute, refresh } = await useFetch('/api/users')
<template>
<div>
<p>{{ data }}</p>
<button @click="refresh">Refresh data</button>
<button @click="() => refresh()">Refresh data</button>
</div>
</template>
```
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).
::callout{color="blue" icon="i-ph-info-duotone"}
::tip
To globally refetch or invalidate cached data, see [`clearNuxtData`](/docs/api/utils/clear-nuxt-data) and [`refreshNuxtData`](/docs/api/utils/refresh-nuxt-data).
::
#### Clear
If you want to clear the data provided, for whatever reason, without needing to know the specific key to pass to `clearNuxtData`, you can use the `clear` function provided by the composables.
```vue twoslash
<script setup lang="ts">
const { data, clear } = await useFetch('/api/users')
const route = useRoute()
watch(() => route.path, (path) => {
if (path === '/') clear()
})
</script>
```
#### Watch
To re-run your fetching function each time other reactive values in your application change, use the `watch` option. You can use it for one or multiple _watchable_ elements.
@ -331,7 +354,7 @@ Sometimes you may need to compute an URL from reactive values, and refresh the d
<script setup lang="ts">
const id = ref(null)
const { data, pending } = useLazyFetch('/api/user', {
const { data, status } = useLazyFetch('/api/user', {
query: {
user_id: id
}
@ -347,9 +370,11 @@ Every time a dependency changes, the data will be fetched using the newly constr
<script setup lang="ts">
const id = ref(null)
const { data, pending, status } = useLazyFetch(() => `/api/users/${id.value}`, {
const { data, status } = useLazyFetch(() => `/api/users/${id.value}`, {
immediate: false
})
const pending = computed(() => status.value === 'pending');
</script>
<template>
@ -382,7 +407,7 @@ With that, you will need both the `status` to handle the fetch lifecycle, and `e
```vue
<script setup lang="ts">
const { data, error, execute, pending, status } = await useLazyFetch('/api/comments', {
const { data, error, execute, status } = await useLazyFetch('/api/comments', {
immediate: false
})
</script>
@ -392,7 +417,7 @@ const { data, error, execute, pending, status } = await useLazyFetch('/api/comme
<button @click="execute">Get data</button>
</div>
<div v-else-if="pending">
<div v-else-if="status === 'pending'">
Loading comments...
</div>
@ -427,7 +452,7 @@ const { data } = await useFetch('/api/me', { headers })
</script>
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::caution
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`
@ -441,13 +466,14 @@ Be very careful before proxying headers to an external API and just include head
If you want to pass on/proxy cookies in the other direction, from an internal request back to the client, you will need to handle this yourself.
```ts [composables/fetch.ts]
import { appendResponseHeader, H3Event } from 'h3'
import { appendResponseHeader } from 'h3'
import type { H3Event } from 'h3'
export const fetchWithCookie = async (event: H3Event, url: string) => {
/* Get the response from the server endpoint */
const res = await $fetch.raw(url)
/* Get the cookies from the response */
const cookies = (res.headers.get('set-cookie') || '').split(',')
const cookies = res.headers.getSetCookie()
/* Attach each cookie to our incoming Request */
for (const cookie of cookies) {
appendResponseHeader(event, 'set-cookie', cookie)
@ -470,7 +496,7 @@ onMounted(() => console.log(document.cookie))
## Options API support
Nuxt 3 provides a way to perform `asyncData` fetching within the Options API. You must wrap your component definition within `defineNuxtComponent` for this to work.
Nuxt provides a way to perform `asyncData` fetching within the Options API. You must wrap your component definition within `defineNuxtComponent` for this to work.
```vue
<script>
@ -486,7 +512,7 @@ export default defineNuxtComponent({
</script>
```
::callout{color="blue" icon="i-ph-info-duotone"}
::note
Using `<script setup>` or `<script setup lang="ts">` are the recommended way of declaring Vue components in Nuxt 3.
::
@ -498,7 +524,7 @@ When using `useAsyncData` and `useLazyAsyncData` to transfer data fetched on ser
It is also possible to define your own serializer/deserializer for types that are not supported by Nuxt. You can read more in the [`useNuxtApp`](/docs/api/composables/use-nuxt-app#payload) docs.
::callout
::note
Note that this _does not apply_ to data passed from your server routes when fetched with `$fetch` or `useFetch` - see the next section for more information.
::
@ -599,3 +625,37 @@ const { data } = await useFetch('/api/superjson', {
})
</script>
```
## Recipes
### Consuming SSE (Server Sent Events) via POST request
::tip
If you're consuming SSE via GET request, you can use [`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) or VueUse composable [`useEventSource`](https://vueuse.org/core/useEventSource/).
::
When consuming SSE via POST request, you need to handle the connection manually. Here's how you can do it:
```ts
// Make a POST request to the SSE endpoint
const response = await $fetch<ReadableStream>('/chats/ask-ai', {
method: 'POST',
body: {
query: "Hello AI, how are you?",
},
responseType: 'stream',
})
// Create a new ReadableStream from the response with TextDecoderStream to get the data as text
const reader = response.pipeThrough(new TextDecoderStream()).getReader()
// Read the chunk of data as we get it
while (true) {
const { value, done } = await reader.read()
if (done)
break
console.log('Received:', value)
}
```

View File

@ -1,14 +1,18 @@
---
title: 'State Management'
description: Nuxt provides powerful state management libraries and the useState composable to create a reactive and SSR-friendly shared state.
navigation.icon: i-ph-database-duotone
navigation.icon: i-ph-database
---
Nuxt provides the [`useState`](/docs/api/composables/use-state) composable to create a reactive and SSR-friendly shared state across components.
[`useState`](/docs/api/composables/use-state) is an SSR-friendly [`ref`](https://vuejs.org/api/reactivity-core.html#ref) replacement. Its value will be preserved after server-side rendering (during client-side hydration) and shared across all components using a unique key.
::callout
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=mv0WcBABcIk" target="_blank"}
Watch a video from Alexander Lichter about why and when to use `useState()`.
::
::important
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.
::
@ -18,12 +22,12 @@ Read more about `useState` composable.
## Best Practices
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
Never define `const state = ref()` outside of `<script setup>` or `setup()` function.<br>
Such state will be shared across all users visiting your website and can lead to memory leaks!
For example, doing `export myState = ref({})` would result in state shared across requests on the server and can lead to memory leaks.
::
::callout{color="green" icon="i-ph-check-circle-duotone"}
::tip{icon="i-ph-check-circle"}
Instead use `const useX = () => useState('x')`
::
@ -53,7 +57,7 @@ const counter = useState('counter', () => Math.round(Math.random() * 1000))
:link-example{to="/docs/examples/features/state-management"}
::callout
::note
To globally invalidate cached state, see [`clearNuxtState`](/docs/api/utils/clear-nuxt-state) util.
::
@ -71,7 +75,7 @@ await callOnce(async () => {
</script>
```
::callout
::tip
This is similar to the [`nuxtServerInit` action](https://v2.nuxt.com/docs/directory-structure/store/#the-nuxtserverinit-action) in Nuxt 2, which allows filling the initial state of your store server-side before rendering the page.
::
@ -81,7 +85,7 @@ This is similar to the [`nuxtServerInit` action](https://v2.nuxt.com/docs/direct
In this example, we leverage the [Pinia module](/modules/pinia) to create a global store and use it across the app.
::callout
::important
Make sure to install the Pinia module with `npx nuxi@latest module add pinia` or follow the [module's installation steps](https://pinia.vuejs.org/ssr/nuxt.html#Installation).
::
@ -130,12 +134,12 @@ export const useLocale = () => {
export const useDefaultLocale = (fallback = 'en-US') => {
const locale = ref(fallback)
if (process.server) {
if (import.meta.server) {
const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
if (reqLocale) {
locale.value = reqLocale
}
} else if (process.client) {
} else if (import.meta.client) {
const navLang = navigator.language
if (navLang) {
locale.value = navLang
@ -192,7 +196,6 @@ const date = useLocaleDate(new Date('2016-10-26'))
By using [auto-imported composables](/docs/guide/directory-structure/composables) we can define global type-safe states and import them across the app.
```ts twoslash [composables/states.ts]
export const useCounter = () => useState<number>('counter', () => 0)
export const useColor = () => useState<string>('color', () => 'pink')
```
@ -209,6 +212,10 @@ const color = useColor() // Same as useState('color')
</template>
```
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=dZSNW07sO-A" target="_blank"}
Watch a video from Daniel Roe on how to deal with global state and SSR in Nuxt.
::
## Using third-party libraries
Nuxt **used to rely** on the Vuex library to provide global state management. If you are migrating from Nuxt 2, please head to [the migration guide](/docs/migration/configuration#vuex).

View File

@ -1,21 +1,21 @@
---
title: 'Error Handling'
description: 'Learn how to catch and handle errors in Nuxt.'
navigation.icon: i-ph-bug-beetle-duotone
navigation.icon: i-ph-bug-beetle
---
Nuxt 3 is a full-stack framework, which means there are several sources of unpreventable user runtime errors that can happen in different contexts:
Nuxt is a full-stack framework, which means there are several sources of unpreventable user runtime errors that can happen in different contexts:
- Errors during the Vue rendering lifecycle (SSR & CSR)
- Errors during Nitro server lifecycle ([`server/`](/docs/guide/directory-structure/server) directory)
- Server and client startup errors (SSR + CSR)
- Errors during Nitro server lifecycle ([`server/`](/docs/guide/directory-structure/server) directory)
- Errors downloading JS chunks
::callout
::tip
**SSR** stands for **Server-Side Rendering** and **CSR** for **Client-Side Rendering**.
::
## Vue Rendering Lifecycle
## Vue Errors
You can hook into Vue errors using [`onErrorCaptured`](https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured).
@ -36,7 +36,7 @@ export default defineNuxtPlugin((nuxtApp) => {
})
```
::callout
::note
Note that the `vue:error` hook is based on [`onErrorCaptured`](https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured) lifecycle hook.
::
@ -51,11 +51,11 @@ This includes:
- mounting the app (on client-side), though you should handle this case with `onErrorCaptured` or with `vue:error`
- processing the `app:mounted` hook
## Nitro Server Lifecycle
## Nitro Server Errors
You cannot currently define a server-side handler for these errors, but can render an error page, see the [Render an Error Page](#error-page) section.
## Errors with JS chunks
## Errors with JS Chunks
You might encounter chunk loading errors due to a network connectivity failure or a new deployment (which invalidates your old, hashed JS chunk URLs). Nuxt provides built-in support for handling chunk loading errors by performing a hard reload when a chunk fails to load during route navigation.
@ -63,7 +63,7 @@ You can change this behavior by setting `experimental.emitRouteChunkError` to `f
## Error Page
::callout
::note
When Nuxt encounters a fatal error (any unhandled error on the server, or an error created with `fatal: true` on the client) it will either render a JSON response (if requested with `Accept: application/json` header) or trigger a full-screen error page.
::
@ -121,11 +121,15 @@ export default defineNuxtPlugin(nuxtApp => {
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
::important
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
::note
Rendering an error page is an entirely separate page load, meaning any registered middleware will run again. You can use [`useError`](#useerror) in middleware to check if an error is being handled.
::
::note
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.
::
@ -146,10 +150,10 @@ Read more about `useError` composable.
### `createError`
```ts [TS Signature]
function createError (err: { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error
function createError (err: string | { cause, data, message, name, stack, statusCode, statusMessage, fatal }): Error
```
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.
Create an error object with additional metadata. You can pass a string to be set as the error `message` or an object containing error properties. 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`](#clearerror).
@ -207,7 +211,7 @@ This component is responsible for handling errors that occur within its default
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.)
::callout
::tip
If you navigate to another route, the error will be cleared automatically.
::

View File

@ -1,7 +1,7 @@
---
title: 'Server'
description: Build full-stack applications with Nuxt's server framework. You can fetch data from your database or another server, create APIs, or even generate static server-side content like a sitemap or a RSS feed - all from a single codebase.
navigation.icon: i-ph-computer-tower-duotone
navigation.icon: i-ph-computer-tower
---
:read-more{to="/docs/guide/directory-structure/server"}
@ -20,6 +20,10 @@ Using Nitro gives Nuxt superpowers:
Nitro is internally using [h3](https://github.com/unjs/h3), a minimal H(TTP) framework built for high performance and portability.
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=DkvgJa-X31k" target="_blank"}
Watch a video from Alexander Lichter to understand the responsibilities of Nuxt and Nitro in your application.
::
## Server Endpoints & Middleware
You can easily manage the server-only part of your Nuxt app, from API endpoints to middleware.
@ -83,9 +87,9 @@ export default defineNuxtConfig({
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 Nuxt specific to change the behavior when rendering your pages to HTML.
In addition, there are some route rules (for example, `ssr`, `appMiddleware`, and `experimentalNoScripts`) that are Nuxt specific to change the behavior when rendering your pages to HTML.
Some route rules (`redirect` and `prerender`) also affect client-side behavior.
Some route rules (`appMiddleware`, `redirect` and `prerender`) also affect client-side behavior.
Nitro is used to build the app for server side rendering, as well as pre-rendering.

View File

@ -1,10 +1,10 @@
---
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
navigation.icon: i-ph-stack
---
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.
One of the core features of Nuxt 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.
## Use Cases
@ -14,12 +14,19 @@ One of the core features of Nuxt 3 is the layers and extending support. You can
- Create Nuxt module presets
- Share standard setup across projects
- Create Nuxt themes
- Enhance code organization by implementing a modular architecture and support Domain-Driven Design (DDD) pattern in large scale projects.
## 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.
By default, any layers within your project in the `~/layers` directory will be automatically registered as layers in your project
```ts twoslash [nuxt.config.ts]
::note
Layer auto-registration was introduced in Nuxt v3.12.0
::
In addition, you can extend from a layer by adding the [extends](/docs/api/nuxt-config#extends) property to your [`nuxt.config`](/docs/guide/directory-structure/nuxt-config) file.
```ts [nuxt.config.ts]
export default defineNuxtConfig({
extends: [
'../base', // Extend from a local layer
@ -29,12 +36,29 @@ export default defineNuxtConfig({
})
```
You can also pass an authentication token if you are extending from a private GitHub repository:
```ts [nuxt.config.ts]
export default defineNuxtConfig({
extends: [
// per layer configuration
['github:my-themes/private-awesome', { auth: process.env.GITHUB_TOKEN }]
]
})
```
Nuxt uses [unjs/c12](https://c12.unjs.io) and [unjs/giget](https://giget.unjs.io) for extending remote layers. Check the documentation for more information and all available options.
::read-more{to="/docs/guide/going-further/layers"}
Read more about layers in the **Layer Author Guide**.
::
::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.
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=lnFCM7c9f7I" target="_blank"}
Watch a video from Learn Vue about Nuxt Layers.
::
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=fr5yo3aVkfA" target="_blank"}
Watch a video from Alexander Lichter about Nuxt Layers.
::
## Examples

View File

@ -0,0 +1,193 @@
---
title: "Prerendering"
description: Nuxt allows pages to be statically rendered at build time to improve certain performance or SEO metrics
navigation.icon: i-ph-code-block
---
Nuxt allows for select pages from your application to be rendered at build time. Nuxt will serve the prebuilt pages when requested instead of generating them on the fly.
:read-more{title="Nuxt rendering modes" to="/docs/guide/concepts/rendering"}
## 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`.
This will build your site, stand up a nuxt instance, and, by default, prerender the root page `/` along with any of your site's pages it links to, any of your site's pages they link to, and so on.
::package-managers
```bash [npm]
npx nuxi generate
```
```bash [yarn]
yarn dlx nuxi generate
```
```bash [pnpm]
pnpm dlx nuxi generate
```
```bash [bun]
bun x nuxi generate
```
::
You can now deploy the `.output/public` directory to any static hosting service or preview it locally with `npx serve .output/public`.
Working of the Nitro crawler:
1. Load the HTML of your application's root route (`/`), any non-dynamic pages in your `~/pages` directory, and any other routes in the `nitro.prerender.routes` array.
2. Save the HTML and `payload.json` to the `~/.output/public/` directory to be served statically.
3. Find all anchor tags (`<a href="...">`) in the HTML to navigate to other routes.
4. Repeat steps 1-3 for each anchor tag found until there are no more anchor tags to crawl.
This is important to understand since pages that are not linked to a discoverable page can't be pre-rendered automatically.
::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 twoslash [nuxt.config.ts]
export default defineNuxtConfig({
nitro: {
prerender: {
routes: ["/user/1", "/user/2"],
ignore: ["/dynamic"],
},
},
});
```
You can combine this with the `crawlLinks` option to pre-render a set of routes that the crawler can't discover like your `/sitemap.xml` or `/robots.txt`:
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
nitro: {
prerender: {
crawlLinks: true,
routes: ["/sitemap.xml", "/robots.txt"],
},
},
});
```
Setting `nitro.prerender` to `true` is similar to `nitro.prerender.crawlLinks` to `true`.
::read-more{to="https://nitro.unjs.io/config#prerender"}
Read more about pre-rendering in the Nitro documentation.
::
Lastly, you can manually configure this using routeRules.
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
routeRules: {
// Set prerender to true to configure it to be prerendered
"/rss.xml": { prerender: true },
// Set it to false to configure it to be skipped for prerendering
"/this-DOES-NOT-get-prerendered": { prerender: false },
// Everything under /blog gets prerendered as long as it
// is linked to from another page
"/blog/**": { prerender: true },
},
});
```
::read-more{to="https://nitro.unjs.io/config/#routerules"}
Read more about Nitro's `routeRules` configuration.
::
As a shorthand, you can also configure this in a page file using [`defineRouteRules`](/docs/api/utils/define-route-rules).
::read-more{to="/docs/guide/going-further/experimental-features#inlinerouterules" icon="i-ph-star"}
This feature is experimental and in order to use it you must enable the `experimental.inlineRouteRules` option in your `nuxt.config`.
::
```vue [pages/index.vue]
<script setup>
// Or set at the page level
defineRouteRules({
prerender: true,
});
</script>
<template>
<div>
<h1>Homepage</h1>
<p>Pre-rendered at build time</p>
</div>
</template>
```
This will be translated to:
```ts [nuxt.config.ts]
export default defineNuxtConfig({
routeRules: {
"/": { prerender: true },
},
});
```
## Runtime prerender configuration
### `prerenderRoutes`
You can use this at runtime within a [Nuxt context](/docs/guide/going-further/nuxt-app#the-nuxt-context) to add more routes for Nitro to prerender.
```vue [pages/index.vue]
<script setup>
prerenderRoutes(["/some/other/url"]);
</script>
<template>
<div>
<h1>This will register other routes for prerendering when prerendered</h1>
</div>
</template>
```
:read-more{title="prerenderRoutes" to="/docs/api/utils/prerender-routes"}
### `prerender:routes` Nuxt hook
This is called before prerendering for additional routes to be registered.
```ts [nitro.config.ts]
export default defineNuxtConfig({
hooks: {
async "prerender:routes"(ctx) {
const { pages } = await fetch("https://api.some-cms.com/pages").then(
(res) => res.json(),
);
for (const page of pages) {
ctx.routes.add(`/${page.name}`);
}
},
},
});
```
### `prerender:generate` Nitro hook
This is called for each route during prerendering. You can use this for fine grained handling of each route that gets prerendered.
```ts [nitro.config.ts]
export default defineNuxtConfig({
nitro: {
hooks: {
"prerender:generate"(route) {
if (route.route?.includes("private")) {
route.skip = true;
}
},
},
},
});
```

View File

@ -1,3 +1,3 @@
title: Get Started
titleTemplate: '%s · Get Started with Nuxt'
icon: i-ph-rocket-launch-duotone
icon: i-ph-rocket-launch

View File

@ -7,13 +7,16 @@ surround: false
---
::card-group{class="sm:grid-cols-1"}
::card{icon="i-ph-medal-duotone" title="Key Concepts" to="/docs/guide/concepts"}
::card{icon="i-ph-medal" 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"}
::card{icon="i-ph-folders" 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"}
::card{icon="i-ph-star" title="Going Further" to="/docs/guide/going-further"}
Master Nuxt with advanced concepts like experimental features, hooks, modules, and more.
::
::card{icon="i-ph-book-open" title="Recipes" to="/docs/guide/recipes"}
Find solutions to common problems and learn how to implement them in your Nuxt project.
::
::

View File

@ -15,15 +15,15 @@ Thanks to its opinionated directory structure, Nuxt can auto-import your [`compo
Contrary to a classic global declaration, Nuxt preserves typings, IDEs completions and hints, and **only includes what is used in your production code**.
::callout{color="blue" icon="i-ph-lightbulb-duotone"}
::note
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).
::
::callout
::note
In the [`server`](/docs/guide/directory-structure/server) directory, Nuxt auto-imports exported functions and variables from `server/utils/`.
::
::callout
::note
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.
::
@ -33,8 +33,8 @@ Nuxt auto-imports functions and composables to perform [data fetching](/docs/get
```vue twoslash
<script setup lang="ts">
/* useAsyncData() and $fetch() are auto-imported */
const { data, refresh } = await useFetch('/api/hello')
/* useFetch() is auto-imported */
const { data, refresh, status } = await useFetch('/api/hello')
</script>
```
@ -60,7 +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.
::read-more{to="/docs/guide/going-further/experimental-features#asynccontext" icon="i-ph-star-duotone"}
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=ofuKRZLtOdY" target="_blank"}
Watch a video from Alexander Lichter about handling async code in composables and fixing `Nuxt instance is unavailable` in your app.
::
::tip
When using a composable that requires the Nuxt context inside a non-SFC component, you need to wrap your component with `defineNuxtComponent` instead of `defineComponent`
::
::read-more{to="/docs/guide/going-further/experimental-features#asynccontext" icon="i-ph-star"}
Checkout the `asyncContext` experimental feature to use Nuxt composables in async functions.
::
@ -84,7 +92,7 @@ export const useMyComposable = () => {
```ts twoslash [composables/example.ts]
export const useMyComposable = () => {
// Because your composable is called in the right place in the lifecycle,
// useRuntimeConfig will also work
// useRuntimeConfig will work here
const config = useRuntimeConfig()
// ...
@ -101,6 +109,11 @@ Nuxt directly auto-imports files created in defined directories:
:link-example{to="/docs/examples/features/auto-imports"}
::warning
**Auto-imported `ref` and `computed` won't be unwrapped in a component `<template>`.** :br
This is due to how Vue works with refs that aren't top-level to the template. You can read more about it [in the Vue documentation](https://vuejs.org/guide/essentials/reactivity-fundamentals.html#caveat-when-unwrapping-in-templates).
::
### Explicit Imports
Nuxt exposes every auto-import with the `#imports` alias that can be used to make the import explicit if needed:
@ -150,7 +163,7 @@ export default defineNuxtConfig({
Nuxt also allows auto-importing from third-party packages.
::callout
::tip
If you are using the Nuxt module for that package, it is likely that the module has already configured auto-imports for that package.
::
@ -168,3 +181,7 @@ export default defineNuxtConfig({
}
})
```
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=FT2LQJ2NvVI" target="_blank"}
Watch a video from Alexander Lichter on how to easily set up custom auto imports.
::

View File

@ -1,11 +1,11 @@
---
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."
description: "Nuxt uses Vue.js and adds features such as component auto-imports, file-based routing and composables for an SSR-friendly usage."
---
Nuxt integrates Vue 3, the new major release of Vue that enables new patterns for Nuxt users.
::callout
::note
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).
::
@ -39,7 +39,7 @@ Most applications need multiple pages and a way to navigate between them. This i
## Differences with Nuxt 2 / Vue 2
Nuxt 3 is based on Vue 3. The new major Vue version introduces several changes that Nuxt takes advantage of:
Nuxt 3+ is based on Vue 3. The new major Vue version introduces several changes that Nuxt takes advantage of:
- Better performance
- Composition API
@ -89,15 +89,15 @@ const increment = () => count.value++
</script>
```
The goal of Nuxt 3 is to provide a great developer experience around the Composition API.
The goal of Nuxt is to provide a great developer experience around the Composition API.
- Use auto-imported [Reactivity functions](https://vuejs.org/api/reactivity-core.html) from Vue and Nuxt 3 [built-in composables](/docs/api/composables/use-async-data).
- Use auto-imported [Reactivity functions](https://vuejs.org/api/reactivity-core.html) from Vue and Nuxt [built-in composables](/docs/api/composables/use-async-data).
- Write your own auto-imported reusable functions in the [`composables/` directory](/docs/guide/directory-structure/composables).
### TypeScript Support
Both Vue 3 and Nuxt 3 are written in TypeScript. A fully typed codebase prevents mistakes and documents APIs usage. This doesnt mean that you have to write your application in TypeScript to take advantage of it. With Nuxt 3, you can opt-in by renaming your file from `.js` to `.ts` , or add `<script setup lang="ts">` in a component.
Both Vue 3 and Nuxt 3+ are written in TypeScript. A fully typed codebase prevents mistakes and documents APIs usage. This doesnt mean that you have to write your application in TypeScript to take advantage of it. With Nuxt 3, you can opt-in by renaming your file from `.js` to `.ts` , or add `<script setup lang="ts">` in a component.
::read-more{to="/docs/guide/concepts/typescript"}
Read the details about TypeScript in Nuxt 3
Read the details about TypeScript in Nuxt
::

View File

@ -31,11 +31,11 @@ Universal rendering allows a Nuxt application to provide quick page load times w
Universal rendering is very versatile and can fit almost any use case, and is especially appropriate for any content-oriented websites: **blogs, marketing websites, portfolios, e-commerce sites, and marketplaces.**
::callout
::tip
For more examples about writing Vue code without hydration mismatch, see [the Vue docs](https://vuejs.org/guide/scaling-up/ssr.html#hydration-mismatch).
::
::callout{icon="i-ph-warning-duotone" color="amber"}
::important
When importing a library that relies on browser APIs and has side effects, make sure the component importing it is only called client-side. Bundlers do not treeshake imports of modules containing side effects.
::
@ -64,18 +64,48 @@ export default defineNuxtConfig({
})
```
::callout
::note
If you do use `ssr: false`, you should also place an HTML file in `~/app/spa-loading-template.html` with some HTML you would like to use to render a loading screen that will be rendered until your app is hydrated.
:read-more{title="SPA Loading Template" to="/docs/api/configuration/nuxt-config#spaloadingtemplate"}
::
::tip{to="https://www.youtube.com/watch?v=7Lr0QTP1Ro8" icon="i-logos-youtube-icon" target="_blank"}
Watch a video from Alexander Lichter about **Building a plain SPA with Nuxt!?**.
::
### Deploying a Static Client-Rendered App
If you deploy your app to [static hosting](/docs/getting-started/deployment#static-hosting) with the `nuxi generate` or `nuxi build --prerender` commands, then by default, Nuxt will render every page as a separate static HTML file.
If you are using purely client-side rendering, then this might be unnecessary. You might only need a single `index.html` file, plus `200.html` and `404.html` fallbacks, which you can tell your static web host to serve up for all requests.
In order to achieve this we can change how the routes are prerendered. Just add this to [your hooks](/docs/api/advanced/hooks#nuxt-hooks-build-time) in your `nuxt.config.ts`:
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
hooks: {
'prerender:routes' ({ routes }) {
routes.clear() // Do not generate any routes (except the defaults)
}
},
})
```
This will produce three files:
- `index.html`
- `200.html`
- `404.html`
The `200.html` and `404.html` might be useful for the hosting provider you are using.
## Hybrid Rendering
Hybrid rendering allows different caching rules per route using **Route Rules** and decides how the server should respond to a new request on a given URL.
Previously every route/page of a Nuxt application and server must use the same rendering mode, universal or client-side. In various cases, some pages could be generated at build time, while others should be client-side rendered. For example, think of a content website with an admin section. Every content page should be primarily static and generated once, but the admin section requires registration and behaves more like a dynamic application.
Nuxt 3 includes route rules and hybrid rendering support. Using route rules you can define rules for a group of nuxt routes, change rendering mode or assign a cache strategy based on route!
Nuxt includes route rules and hybrid rendering support. Using route rules you can define rules for a group of nuxt routes, change rendering mode or assign a cache strategy based on route!
Nuxt server will automatically register corresponding middleware and wrap routes with cache handlers using [Nitro caching layer](https://nitro.unjs.io/guide/cache).
@ -86,7 +116,7 @@ export default defineNuxtConfig({
'/': { prerender: true },
// Products page generated on demand, revalidates in background, cached until API response changes
'/products': { swr: true },
// Product page generated on demand, revalidates in background, cached for 1 hour (3600 seconds)
// Product pages generated on demand, revalidates in background, cached for 1 hour (3600 seconds)
'/products/**': { swr: 3600 },
// Blog posts page generated on demand, revalidates in background, cached on CDN for 1 hour (3600 seconds)
'/blog': { isr: 3600 },
@ -106,17 +136,18 @@ export default defineNuxtConfig({
The different properties you can use are the following:
- `redirect: string`{lang=ts} - Define server-side redirects.
- `ssr: boolean`{lang=ts} - Disables server-side rendering for sections of your app and make them SPA-only with `ssr: false`
- `ssr: boolean`{lang=ts} - Disables server-side rendering of the HTML for sections of your app and make them render only in the browser with `ssr: false`
- `cors: boolean`{lang=ts} - Automatically adds cors headers with `cors: true` - you can customize the output by overriding with `headers`
- `headers: object`{lang=ts} - Add specific headers to sections of your site - for example, your assets
- `swr: number|boolean`{lang=ts} - Add cache headers to the server response and cache it on the server or reverse proxy for a configurable TTL (time to live). The `node-server` preset of Nitro is able to cache the full response. When the TTL expired, the cached response will be sent while the page will be regenerated in the background. If true is used, a `stale-while-revalidate` header is added without a MaxAge.
- `isr: number|boolean`{lang=ts} - The behavior is the same as `swr` except that we are able to add the response to the CDN cache on platforms that support this (currently Netlify or Vercel). If `true` is used, the content persists until the next deploy inside the CDN.
- `prerender:boolean`{lang=ts} - Prerenders routes at build time and includes them in your build as static assets
- `swr: number | boolean`{lang=ts} - Add cache headers to the server response and cache it on the server or reverse proxy for a configurable TTL (time to live). The `node-server` preset of Nitro is able to cache the full response. When the TTL expired, the cached response will be sent while the page will be regenerated in the background. If true is used, a `stale-while-revalidate` header is added without a MaxAge.
- `isr: number | boolean`{lang=ts} - The behavior is the same as `swr` except that we are able to add the response to the CDN cache on platforms that support this (currently Netlify or Vercel). If `true` is used, the content persists until the next deploy inside the CDN.
- `prerender: boolean`{lang=ts} - Prerenders routes at build time and includes them in your build as static assets
- `experimentalNoScripts: boolean`{lang=ts} - Disables rendering of Nuxt scripts and JS resource hints for sections of your site.
- `appMiddleware: string | string[] | Record<string, boolean>`{lang=ts} - Allows you to define middleware that should or should not run for page paths within the Vue app part of your application (that is, not your Nitro routes)
Whenever possible, route rules will be automatically applied to the deployment platform's native rules for optimal performances (Netlify and Vercel are currently supported).
::callout{icon="i-ph-warning-duotone" color="amber"}
::important
Note that Hybrid Rendering is not available when using [`nuxt generate`](/docs/api/commands/generate).
::
@ -137,7 +168,7 @@ Note that Hybrid Rendering is not available when using [`nuxt generate`](/docs/a
## Edge-Side Rendering
Edge-Side Rendering (ESR) is a powerful feature introduced in Nuxt 3 that allows the rendering of your Nuxt application closer to your users via edge servers of a Content Delivery Network (CDN). By leveraging ESR, you can ensure improved performance and reduced latency, thereby providing an enhanced user experience.
Edge-Side Rendering (ESR) is a powerful feature introduced in Nuxt that allows the rendering of your Nuxt application closer to your users via edge servers of a Content Delivery Network (CDN). By leveraging ESR, you can ensure improved performance and reduced latency, thereby providing an enhanced user experience.
With ESR, the rendering process is pushed to the 'edge' of the network - the CDN's edge servers. Note that ESR is more a deployment target than an actual rendering mode.
@ -172,7 +203,7 @@ You can explore open source examples deployed on some of the platform mentioned
target: _blank
ui.icon.base: text-black dark:text-white
---
An editable website with universal rendering based on CloudFlare KV.
An editable website with universal rendering based on Cloudflare KV.
::
::

View File

@ -1,13 +1,13 @@
---
title: Server Engine
description: 'Nuxt 3 is powered by a new server engine: Nitro.'
description: 'Nuxt is powered by a new server engine: Nitro.'
---
While building Nuxt 3, we created a new server engine: [Nitro](https://nitro.unjs.io).
It is shipped with many features:
- Cross-platform support for Node.js, Browsers, service-workers and more.
- Cross-platform support for Node.js, browsers, service workers and more.
- Serverless support out-of-the-box.
- API routes support.
- Automatic code-splitting and async-loaded chunks.
@ -51,9 +51,9 @@ You can access these types when using [`$fetch()`](/docs/api/utils/dollarfetch)
Nitro produces a standalone server dist that is independent of `node_modules`.
The server in Nuxt 2 is not standalone and requires part of Nuxt core to be involved by running `nuxt start` (with the [`nuxt-start`](https://www.npmjs.com/package/nuxt-start) or [`nuxt`](https://www.npmjs.com/package/nuxt) distributions) or custom programmatic usage, which is fragile and prone to breakage and not suitable for serverless and service-worker environments.
The server in Nuxt 2 is not standalone and requires part of Nuxt core to be involved by running `nuxt start` (with the [`nuxt-start`](https://www.npmjs.com/package/nuxt-start) or [`nuxt`](https://www.npmjs.com/package/nuxt) distributions) or custom programmatic usage, which is fragile and prone to breakage and not suitable for serverless and service worker environments.
Nuxt 3 generates this dist when running `nuxt build` into a [`.output`](/docs/guide/directory-structure/output) directory.
Nuxt generates this dist when running `nuxt build` into a [`.output`](/docs/guide/directory-structure/output) directory.
The output contains runtime code to run your Nuxt server in any environment (including experimental browser service workers!) and serve your static files, making it a true hybrid framework for the JAMstack. In addition, Nuxt implements a native storage layer, supporting multi-source drivers and local assets.

View File

@ -37,7 +37,7 @@ export default defineNuxtConfig({
})
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
Nuxt modules are now build-time-only, and the `buildModules` property used in Nuxt 2 is deprecated in favor of `modules`.
::

View File

@ -1,6 +1,6 @@
---
title: 'ES Modules'
description: "Nuxt 3 (and Bridge) uses Native ES Modules."
description: "Nuxt uses native ES modules."
---
This guide helps explain what ES Modules are and how to make a Nuxt app (or upstream library) compatible with ESM.
@ -190,7 +190,7 @@ import { default as pkg } from 'cjs-pkg'
import('cjs-pkg').then(m => m.default || m).then(console.log)
```
For handling more complex situations and more safety, we recommend and internally use [mlly](https://github.com/unjs/mlly) in Nuxt 3 that can preserve named exports.
For handling more complex situations and more safety, we recommend and internally use [mlly](https://github.com/unjs/mlly) in Nuxt that can preserve named exports.
```js
import { interopDefault } from 'mlly'

View File

@ -1,6 +1,6 @@
---
title: 'TypeScript'
description: "Nuxt 3 is fully typed and provides helpful shortcuts to ensure you have access to accurate type information when you are coding."
description: "Nuxt is fully typed and provides helpful shortcuts to ensure you have access to accurate type information when you are coding."
---
## Type-checking
@ -9,16 +9,16 @@ By default, Nuxt doesn't check types when you run [`nuxi dev`](/docs/api/command
To enable type-checking at build or development time, install `vue-tsc` and `typescript` as development dependency:
::code-group
```bash [yarn]
yarn add --dev vue-tsc typescript
```
::package-managers
```bash [npm]
npm install --save-dev vue-tsc typescript
```
```bash [yarn]
yarn add --dev vue-tsc typescript
```
```bash [pnpm]
pnpm add -D vue-tsc typescript
```
@ -51,7 +51,7 @@ When you run `nuxi dev` or `nuxi build`, Nuxt generates the following files for
### `.nuxt/nuxt.d.ts`
This file contains the types of any modules you are using, as well as the key types that Nuxt 3 requires. Your IDE should recognize these types automatically.
This file contains the types of any modules you are using, as well as the key types that Nuxt requires. Your IDE should recognize these types automatically.
Some of the references in the file are to files that are only generated within your `buildDir` (`.nuxt`) and therefore for full typings, you will need to run `nuxi dev` or `nuxi build`.
@ -61,29 +61,33 @@ This file contains the recommended basic TypeScript configuration for your proje
[Read more about how to extend this configuration](/docs/guide/directory-structure/tsconfig).
::callout
::tip{icon="i-ph-video" to="https://youtu.be/umLI7SlPygY" target="_blank"}
Watch a video from Daniel Roe explaining built-in Nuxt aliases.
::
::note
Nitro also [auto-generates types](/docs/guide/concepts/server-engine#typed-api-routes) for API routes. Plus, Nuxt also generates types for globally available components and [auto-imports from your composables](/docs/guide/directory-structure/composables), plus other core functionality.
::
::callout
::note
Keep in mind that all options extended from `./.nuxt/tsconfig.json` will be overwritten by the options defined in your `tsconfig.json`.
Overwriting options such as `"compilerOptions.paths"` with your own configuration will lead TypeScript to not factor in the module resolutions from `./.nuxt/tsconfig.json`. This can lead to module resolutions such as `#imports` not being recognized.
:br :br
In case you need to extend options provided by `./.nuxt/tsconfig.json` further, you can use the [`alias` property](/docs/api/nuxt-config#alias) within your `nuxt.config`. `nuxi` will pick them up and extend `./.nuxt/tsconfig.json` accordingly.
::
## Stricter Checks
## Strict Checks
TypeScript comes with certain checks to give you more safety and analysis of your program.
Once youve converted your codebase to TypeScript and felt familiar with it, you can start enabling these checks for greater safety ([read more](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html#getting-stricter-checks)).
[Strict checks](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html#getting-stricter-checks) are enabled by default in Nuxt to give you greater type safety.
In order to enable strict type checking, you have to update `nuxt.config`:
If you are currently converting your codebase to TypeScript, you may want to temporarily disable strict checks by setting `strict` to `false` in your `nuxt.config`:
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
typescript: {
strict: true
strict: false
}
})
```

View File

@ -5,76 +5,20 @@ description: "Nuxt supports ESLint out of the box"
## ESLint
The recommended approach for Nuxt is to enable ESLint support using [`@nuxt/eslint-config`](https://github.com/nuxt/eslint-config).
The recommended approach for Nuxt is to enable ESLint support using the [`@nuxt/eslint`](https://eslint.nuxt.com/packages/module) module, that will setup project-aware ESLint configuration for you.
At the moment, this configuration will not format your files; you can set up Prettier or another tool to do so.
:::callout{icon="i-ph-lightbulb"}
The module is designed for the [new ESLint flat config format](https://eslint.org/docs/latest/use/configure/configuration-files-new) with is the [default format since ESLint v9](https://eslint.org/blog/2024/04/eslint-v9.0.0-released/).
::alert{type=info}
We're currently working to refactor the Nuxt ESLint configuration. Subscribe to the [Nuxt ESLint roadmap](https://github.com/nuxt/eslint-config/issues/303) to follow updates.
::
If you are using the legacy `.eslintrc` config, you will need to [configure manually with `@nuxt/eslint-config`](https://eslint.nuxt.com/packages/config#legacy-config-format). We highly recommend you to migrate over the flat config to be future-proof.
:::
### Install Dependencies
## Quick Setup
Install both ESLint and the Nuxt configuration as development dependencies.
::code-group
```bash [yarn]
yarn add --dev eslint @nuxt/eslint-config
```bash
npx nuxi module add eslint
```
```bash [npm]
npm install --save-dev eslint @nuxt/eslint-config
```
Start your Nuxt app, a `eslint.config.mjs` file will be generated under your project root. You can customize it as needed.
```bash [pnpm]
pnpm add -D eslint @nuxt/eslint-config
```
```bash [bun]
bun add -D eslint @nuxt/eslint-config
```
::
### Configuration
Add `.eslintrc.cjs` to the root folder of your Nuxt app.
```js
module.exports = {
root: true,
extends: ['@nuxt/eslint-config'],
}
```
### Modify package.json
Add the below to lint commands to your `package.json` script section:
```json
"scripts": {
...
"lint": "eslint .",
"lint:fix": "eslint . --fix",
...
},
```
Run the `lint` command to check if the code style is correct or run `lint:fix` to automatically fix issues.
### Configuring VS Code
Install the [VS Code ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint).
In VS Code press `ctrl+shift+p` (`cmd+shift+p` on Mac) to open the command prompt, find `Open Workspace Settings (JSON)`, add the below lines to the JSON and save:
```json
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}
```
You're good to go! On save, your files will be linted and auto-fixed.
You can learn more about the module and customizations in [Nuxt ESLint's documentation](https://eslint.nuxt.com/packages/module).

View File

@ -1,3 +1,3 @@
title: Key Concepts
titleTemplate: '%s · Nuxt Concepts'
icon: i-ph-medal-duotone
icon: i-ph-medal

View File

@ -2,10 +2,10 @@
title: ".nuxt"
description: "Nuxt uses the .nuxt/ directory in development to generate your Vue application."
head.title: ".nuxt/"
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
::callout{icon="i-ph-warning-duotone" color="amber"}
::important
This directory should be added to your [`.gitignore`](/docs/guide/directory-structure/gitignore) file to avoid pushing the dev build output to your repository.
::
@ -15,6 +15,6 @@ Nuxt also provides a Virtual File System (VFS) for modules to add templates to t
You can explore the generated files by opening the [Nuxt DevTools](https://devtools.nuxt.com) in development mode and navigating to the **Virtual Files** tab.
::callout{icon="i-ph-warning-duotone" color="amber"}
::warning
You should not touch any files inside since the whole directory will be re-created when running [`nuxt dev`](/docs/api/commands/dev).
::

View File

@ -2,10 +2,10 @@
title: ".output"
description: "Nuxt creates the .output/ directory when building your application for production."
head.title: ".output/"
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
::callout{icon="i-ph-warning-duotone" color="amber"}
::important
This directory should be added to your [`.gitignore`](/docs/guide/directory-structure/gitignore) file to avoid pushing the build output to your repository.
::
@ -13,6 +13,6 @@ Use this directory to deploy your Nuxt application to production.
:read-more{to="/docs/getting-started/deployment"}
::callout{icon="i-ph-warning-duotone" color="amber"}
::warning
You should not touch any files inside since the whole directory will be re-created when running [`nuxt build`](/docs/api/commands/build).
::

View File

@ -2,7 +2,7 @@
title: "assets"
description: "The assets/ directory is used to add all the website's assets that the build tool will process."
head.title: "assets/"
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
The directory usually contains the following types of files:

View File

@ -2,15 +2,15 @@
title: "components"
head.title: "components/"
description: "The components/ directory is where you put all your Vue components."
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
Nuxt automatically imports any components in this directory (along with components that are registered by any modules you may be using).
```bash [Directory Structure]
| components/
--| AppHeader.vue
--| AppFooter.vue
-| components/
---| AppHeader.vue
---| AppFooter.vue
```
```html [app.vue]
@ -28,10 +28,10 @@ Nuxt automatically imports any components in this directory (along with componen
If you have a component in nested directories such as:
```bash [Directory Structure]
| components/
--| base/
----| foo/
------| Button.vue
-| components/
---| base/
-----| foo/
-------| Button.vue
```
... then the component's name will be based on its own path directory and filename, with duplicate segments being removed. Therefore, the component's name will be:
@ -40,7 +40,7 @@ If you have a component in nested directories such as:
<BaseFooButton />
```
::callout
::note
For clarity, we recommend that the component's filename matches its name. So, in the example above, you could rename `Button.vue` to be `BaseFooButton.vue`.
::
@ -78,10 +78,14 @@ const MyButton = resolveComponent('MyButton')
</template>
```
::callout
::important
If you are using `resolveComponent` to handle dynamic components, make sure not to insert anything but the name of the component, which must be a string and not a variable.
::
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=4kq8E5IUM2U" target="\_blank"}
Watch Daniel Roe's short video about `resolveComponent`.
::
Alternatively, though not recommended, you can register all your components globally, which will create async chunks for all your components and make them available throughout your application.
```diff
@ -95,7 +99,7 @@ Alternatively, though not recommended, you can register all your components glob
You can also selectively register some components globally by placing them in a `~/components/global` directory, or by using a `.global.vue` suffix in the filename. As noted above, each global component is rendered in a separate chunk, so be careful not to overuse this feature.
::callout
::note
The `global` option can also be set per component directory.
::
@ -166,6 +170,10 @@ export default defineNuxtConfig({
})
```
::note
Any nested directories need to be added first as they are scanned in order.
::
## npm Packages
If you want to auto-import components from an npm package, you can use [`addComponent`](/docs/api/kit/components#addcomponent) in a [local module](/docs/guide/directory-structure/modules) to register them.
@ -198,10 +206,6 @@ export default defineNuxtModule({
::
::callout
Any nested directories need to be added first as they are scanned in order.
::
## Component Extensions
By default, any file with an extension specified in the [extensions key of `nuxt.config.ts`](/docs/api/nuxt-config#extensions) is treated as a component.
@ -236,26 +240,30 @@ If a component is meant to be rendered only client-side, you can add the `.clien
</template>
```
::callout
::note
This feature only works with Nuxt auto-imports and `#components` imports. Explicitly importing these components from their real paths does not convert them into client-only components.
::
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
`.client` components are rendered only after being mounted. To access the rendered template using `onMounted()`, add `await nextTick()` in the callback of the `onMounted()` hook.
::
::read-more{to="/docs/api/components/client-only"}
You can also achieve a similar result with the `<ClientOnly>` component.
::
## Server Components
Server components allow server-rendering individual components within your client-side apps. It's possible to use server components within Nuxt, even if you are generating a static site. That makes it possible to build complex sites that mix dynamic components, server-rendered HTML and even static chunks of markup.
Server components can either be used on their own or paired with a [client component](#paired-with-a-client-component).
::callout{color="blue" icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=u1yyXe86xJM" target="_blank"}
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=u1yyXe86xJM" target="_blank"}
Watch Learn Vue video about Nuxt Server Components.
::
::callout{color="blue" icon="i-ph-article-duotone" to="https://roe.dev/blog/nuxt-server-components" target="_blank"}
Read Daniel Roe's guide to Nuxt server components
::tip{icon="i-ph-article" to="https://roe.dev/blog/nuxt-server-components" target="_blank"}
Read Daniel Roe's guide to Nuxt Server Components.
::
### Standalone server components
@ -277,8 +285,8 @@ export default defineNuxtConfig({
Now you can register server-only components with the `.server` suffix and use them anywhere in your application automatically.
```bash [Directory Structure]
| components/
--| HighlightedMarkdown.server.vue
-| components/
---| HighlightedMarkdown.server.vue
```
```vue [pages/example.vue]
@ -295,6 +303,18 @@ Now you can register server-only components with the `.server` suffix and use th
Server-only components use [`<NuxtIsland>`](/docs/api/components/nuxt-island) under the hood, meaning that `lazy` prop and `#fallback` slot are both passed down to it.
::alert{type=warning}
Server components (and islands) must have a single root element. (HTML comments are considered elements as well.)
::
::alert{type=warning}
Be careful when nesting islands within other islands as each island adds some extra overhead.
::
::alert{type=warning}
Most features for server-only components and island components, such as slots and client components, are only available for single file components.
::
#### Client components within server components
::alert{type=info}
@ -314,7 +334,7 @@ You can partially hydrate a component by setting a `nuxt-client` attribute on th
```
::alert{type=info}
This only works within a server component. Slots for client components are not available yet.
This only works within a server component. Slots for client components are working only with `experimental.componentIsland.selectiveClient` set to `'deep'` and since they are rendered server-side, they are not interactive once client-side.
::
#### Server Component Context
@ -330,7 +350,7 @@ This means:
Within an island component, you can access its island context through `nuxtApp.ssrContext.islandContext`. Note that while island components are still marked as experimental, the format of this context may change.
::callout
::note
Slots can be interactive and are wrapped within a `<div>` with `display: contents;`
::
@ -339,9 +359,9 @@ Slots can be interactive and are wrapped within a `<div>` with `display: content
In this case, the `.server` + `.client` components are two 'halves' of a component and can be used in advanced use cases for separate implementations of a component on server and client side.
```bash [Directory Structure]
| components/
--| Comments.client.vue
--| Comments.server.vue
-| components/
---| Comments.client.vue
---| Comments.server.vue
```
```vue [pages/example.vue]
@ -353,89 +373,12 @@ In this case, the `.server` + `.client` components are two 'halves' of a compone
</template>
```
## `<ClientOnly>` Component
## Built-In Nuxt Components
Nuxt provides the [`<ClientOnly>`](/docs/api/components/client-only) component for purposely rendering a component only on client side.
There are a number of components that Nuxt provides, including `<ClientOnly>` and `<DevOnly>`. You can read more about them in the API documentation.
```vue [pages/example.vue]
<template>
<div>
<Sidebar />
<ClientOnly>
<!-- this component will only be rendered on client-side -->
<Comments />
</ClientOnly>
</div>
</template>
```
Use a slot as fallback until `<ClientOnly>` is mounted on client side.
```vue [pages/example.vue]
<template>
<div>
<Sidebar />
<!-- This renders the "span" element on the server side -->
<ClientOnly fallbackTag="span">
<!-- this component will only be rendered on client side -->
<Comments />
<template #fallback>
<!-- this will be rendered on server side -->
<p>Loading comments...</p>
</template>
</ClientOnly>
</div>
</template>
```
<!-- TODO: Add back after passing treeshakeClientOnly experiment -->
<!--
::callout
Make sure not to _nest_ `<ClientOnly>` components or other client-only components. Nuxt performs an optimization to remove the contents of these components from the server-side render, which can break in this case.
::read-more{to="/docs/api"}
::
-->
## `<DevOnly>` Component
Nuxt provides the `<DevOnly>` component to render a component only during development.
The content will not be included in production builds and tree-shaken.
```vue [pages/example.vue]
<template>
<div>
<Sidebar />
<DevOnly>
<!-- this component will only be rendered during development -->
<LazyDebugBar />
<!-- if you ever require to have a replacement during production -->
<!-- be sure to test these using `nuxt preview` -->
<template #fallback>
<div><!-- empty div for flex.justify-between --></div>
</template>
</DevOnly>
</div>
</template>
```
## `<NuxtClientFallback>` Component
Nuxt provides the `<NuxtClientFallback>` component to render its content on the client if any of its children trigger an error in SSR.
You can specify a `fallbackTag` to make it render a specific tag if it fails to render on the server.
```vue [pages/example.vue]
<template>
<div>
<Sidebar />
<!-- this component will be rendered on client-side -->
<NuxtClientFallback fallback-tag="span">
<Comments />
<BrokeInSSR />
</NuxtClientFallback>
</div>
</template>
```
## Library Authors
@ -446,15 +389,15 @@ You can use the `components:dirs` hook to extend the directory list without requ
Imagine a directory structure like this:
```bash [Directory Structure]
| node_modules/
-| node_modules/
---| awesome-ui/
------| components/
---------| Alert.vue
---------| Button.vue
------| nuxt.js
| pages/
-----| components/
-------| Alert.vue
-------| Button.vue
-----| nuxt.js
-| pages/
---| index.vue
| nuxt.config.js
-| nuxt.config.js
```
Then in `awesome-ui/nuxt.js` you can use the `components:dirs` hook:

View File

@ -2,7 +2,7 @@
title: 'composables'
head.title: 'composables/'
description: Use the composables/ directory to auto-import your Vue composables into your application.
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
## Usage
@ -52,7 +52,7 @@ Under the hood, Nuxt auto generates the file `.nuxt/imports.d.ts` to declare the
Be aware that you have to run [`nuxi prepare`](/docs/api/commands/prepare), [`nuxi dev`](/docs/api/commands/dev) or [`nuxi build`](/docs/api/commands/build) in order to let Nuxt generate the types.
::callout
::note
If you create a composable without having the dev server running, TypeScript will throw an error, such as `Cannot find name 'useBar'.`
::
@ -85,11 +85,11 @@ export const useHello = () => {
Nuxt only scans files at the top level of the [`composables/` directory](/docs/guide/directory-structure/composables), e.g.:
```bash [Directory Structure]
| composables/
-| composables/
---| index.ts // scanned
---| useFoo.ts // scanned
-----| nested/
-------| utils.ts // not scanned
---| nested/
-----| utils.ts // not scanned
```
Only `composables/index.ts` and `composables/useFoo.ts` would be searched for imports.

View File

@ -2,7 +2,7 @@
title: 'content'
head.title: 'content/'
description: Use the content/ directory to create a file-based CMS for your application.
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
[Nuxt Content](https://content.nuxt.com) reads the [`content/` directory](/docs/guide/directory-structure/content) in your project and parses `.md`, `.yml`, `.csv` and `.json` files to create a file-based CMS for your application.
@ -49,6 +49,6 @@ To render content pages, add a [catch-all route](/docs/guide/directory-structure
## Documentation
::callout
::tip{ icon="i-ph-book" }
Head over to <https://content.nuxt.com> to learn more about the Content module features, such as how to build queries and use Vue components in your Markdown files with the MDC syntax.
::

View File

@ -2,10 +2,10 @@
title: "layouts"
head.title: "layouts/"
description: "Nuxt provides a layouts framework to extract common UI patterns into reusable layouts."
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
::callout{icon="i-ph-rocket-launch-duotone"}
::tip{icon="i-ph-rocket-launch" color="gray" }
For best performance, components placed in this directory will be automatically loaded via asynchronous import when used.
::
@ -25,19 +25,19 @@ To use a layout:
- Set a `layout` property in your page with [definePageMeta](/docs/api/utils/define-page-meta).
- Set the `name` prop of `<NuxtLayout>`.
::callout{color="blue" icon="i-ph-info-duotone"}
::note
The layout name is normalized to kebab-case, so `someLayout` becomes `some-layout`.
::
::callout{color="blue" icon="i-ph-info-duotone"}
::note
If no layout is specified, `layouts/default.vue` will be used.
::
::callout{icon="i-ph-lightbulb-duotone"}
::important
If you only have a single layout in your application, we recommend using [`app.vue`](/docs/guide/directory-structure/app) instead.
::
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
Unlike other components, your layouts must have a single root element to allow Nuxt to apply transitions between layout changes - and this root element cannot be a `<slot />`.
::
@ -175,6 +175,6 @@ definePageMeta({
::
::callout
::important
If you use `<NuxtLayout>` within your pages, make sure it is not the root element (or [disable layout/page transitions](/docs/getting-started/transitions#disable-transitions)).
::

View File

@ -2,7 +2,7 @@
title: "middleware"
description: "Nuxt provides middleware to run code before navigating to a particular route."
head.title: "middleware/"
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
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.
@ -15,11 +15,11 @@ There are three kinds of route middleware:
The first two kinds of route middleware can be defined in [`definePageMeta`](/docs/api/utils/define-page-meta).
::callout
::note
Name of middleware are normalized to kebab-case: `myMiddleware` becomes `my-middleware`.
::
::callout
::note
Route middleware run within the Vue part of your Nuxt app. Despite the similar name, they are completely different from [server middleware](/docs/guide/directory-structure/server#server-middleware), which are run in the Nitro server part of your app.
::
@ -59,7 +59,7 @@ Possible return values are:
:read-more{to="/docs/api/utils/navigate-to"}
:read-more{to="/docs/api/utils/abort-navigation"}
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
We recommend using the helper functions above for performing redirects or stopping navigation. Other possible return values described in [the vue-router docs](https://router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards) may work but there may be breaking changes in future.
::
@ -72,11 +72,11 @@ Middleware runs in the following order:
For example, assuming you have the following middleware and component:
```text [middleware/ directory]
middleware/
--| analytics.global.ts
--| setup.global.ts
--| auth.ts
```bash [middleware/ directory]
-| middleware/
---| analytics.global.ts
---| setup.global.ts
---| auth.ts
```
```vue twoslash [pages/profile.vue]
@ -105,14 +105,14 @@ By default, global middleware is executed alphabetically based on the filename.
However, there may be times you want to define a specific order. For example, in the last scenario, `setup.global.ts` may need to run before `analytics.global.ts`. In that case, we recommend prefixing global middleware with 'alphabetical' numbering.
```text [Directory structure]
middleware/
--| 01.setup.global.ts
--| 02.analytics.global.ts
--| auth.ts
```bash [Directory structure]
-| middleware/
---| 01.setup.global.ts
---| 02.analytics.global.ts
---| auth.ts
```
::callout{color="blue" icon="i-ph-info-duotone"}
::note
In case you're new to 'alphabetical' numbering, remember that filenames are sorted as strings, not as numeric values. For example, `10.new.global.ts` would come before `2.new.global.ts`. This is why the example prefixes single digit numbers with `0`.
::
@ -125,15 +125,19 @@ However, if you want to avoid this behaviour you can do so:
```ts twoslash [middleware/example.ts]
export default defineNuxtRouteMiddleware(to => {
// skip middleware on server
if (process.server) return
if (import.meta.server) return
// skip middleware on client side entirely
if (process.client) return
if (import.meta.client) return
// or only skip middleware on initial client load
const nuxtApp = useNuxtApp()
if (process.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
})
```
::note
Rendering an error page is an entirely separate page load, meaning any registered middleware will run again. You can use [`useError`](/docs/getting-started/error-handling#useerror) in middleware to check if an error is being handled.
::
## Adding Middleware Dynamically
It is possible to add global or named route middleware manually using the [`addRouteMiddleware()`](/docs/api/utils/add-route-middleware) helper function, such as from within a plugin.

View File

@ -2,7 +2,7 @@
title: 'modules'
head.title: 'modules/'
description: Use the modules/ directory to automatically register local modules within your application.
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
It is a good place to place any local modules you develop while building your application.
@ -46,7 +46,11 @@ export default defineEventHandler(() => {
When starting Nuxt, the `hello` module will be registered and the `/api/hello` route will be available.
Local modules are registered in alphabetical order. You can change the order by adding a number to the front of each directory name:
Modules are executed in the following sequence:
- First, the modules defined in [`nuxt.config.ts`](/docs/api/nuxt-config#modules-1) are loaded.
- Then, modules found in the `modules/` directory are executed, and they load in alphabetical order.
You can change the order of local module by adding a number to the front of each directory name:
```bash [Directory structure]
modules/
@ -56,3 +60,7 @@ modules/
```
:read-more{to="/docs/guide/going-further/modules"}
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/creating-your-first-module-from-scratch?friend=nuxt" target="_blank"}
Watch Vue School video about Nuxt private modules.
::

View File

@ -2,11 +2,11 @@
title: "node_modules"
description: "The package manager stores the dependencies of your project in the node_modules/ directory."
head.title: "node_modules/"
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
The package manager ([`npm`](https://docs.npmjs.com/cli/commands/npm) or [`yarn`](https://yarnpkg.com) or [`pnpm`](https://pnpm.io/cli/install) or [`bun`](https://bun.sh/package-manager)) creates this directory to store the dependencies of your project.
::callout
::important
This directory should be added to your [`.gitignore`](/docs/guide/directory-structure/gitignore) file to avoid pushing the dependencies to your repository.
::

View File

@ -2,11 +2,11 @@
title: "pages"
description: "Nuxt provides file-based routing to create routes within your web application."
head.title: "pages/"
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
::callout
To reduce your application's bundle size, this directory is **optional**, meaning that [`vue-router`](https://router.vuejs.org) won't be included if you only use [`app.vue`](/docs/guide/directory-structure/app). To force the pages system, set `pages: true` in `nuxt.config` or have a [`app/router.options.ts`](/docs/guide/directory-structure/pages#router-options).
::note
To reduce your application's bundle size, this directory is **optional**, meaning that [`vue-router`](https://router.vuejs.org) won't be included if you only use [`app.vue`](/docs/guide/directory-structure/app). To force the pages system, set `pages: true` in `nuxt.config` or have a [`app/router.options.ts`](/docs/guide/recipes/custom-routing#using-approuteroptions).
::
## Usage
@ -57,7 +57,7 @@ If you are using [`app.vue`](/docs/guide/directory-structure/app), make sure to
</template>
```
Pages **must have a single root element** to allow [route transitions](/docs/getting-started/transitions) between pages, HTML comments are considered elements as well.
Pages **must have a single root element** to allow [route transitions](/docs/getting-started/transitions) between pages. HTML comments are considered elements as well.
This means that when the route is server-rendered, or statically generated, you will be able to see its contents correctly, but when you navigate towards that route during client-side navigation the transition between routes will fail and you'll see that the route will not be rendered.
@ -130,7 +130,7 @@ if (route.params.group === 'admins' && !route.params.id) {
</script>
```
::callout
::note
Named parent routes will take priority over nested dynamic routes. For the `/foo/hello` route, `~/pages/foo.vue` will take priority over `~/pages/foo/[slug].vue`. :br Use `~/pages/foo/index.vue` and `~/pages/foo/[slug].vue` to match `/foo` and `/foo/hello` with different pages,.
::
@ -159,7 +159,7 @@ Example:
```bash [Directory Structure]
-| pages/
---| parent/
------| child.vue
-----| child.vue
---| parent.vue
```
@ -193,6 +193,14 @@ To display the `child.vue` component, you have to insert the `<NuxtPage>` compon
</template>
```
```vue {}[pages/parent/child.vue]
<script setup lang="ts">
const props = defineProps(['foobar'])
console.log(props.foobar)
</script>
```
### Child Route Keys
If you want more control over when the `<NuxtPage>` component is re-rendered (for example, for transitions), you can either pass a string or function via the `pageKey` prop, or you can define a `key` value via `definePageMeta`:
@ -208,7 +216,7 @@ If you want more control over when the `<NuxtPage>` component is re-rendered (fo
Or alternatively:
```vue twoslash {}[pages/child.vue]
```vue twoslash {}[pages/parent/child.vue]
<script setup lang="ts">
definePageMeta({
key: route => route.fullPath
@ -218,6 +226,22 @@ definePageMeta({
:link-example{to="/docs/examples/routing/pages"}
## Route Groups
In some cases, you may want to group a set of routes together in a way which doesn't affect file-based routing. For this purpose, you can put files in a folder which is wrapped in parentheses - `(` and `)`.
For example:
```bash [Directory structure]
-| pages/
---| index.vue
---| (marketing)/
-----| about.vue
-----| contact.vue
```
This will produce `/`, `/about` and `/contact` pages in your app. The `marketing` group is ignored for purposes of your URL structure.
## Page Metadata
You might want to define metadata for each route in your app. You can do this using the `definePageMeta` macro, which will work both in `<script>` and in `<script setup>`:
@ -334,9 +358,9 @@ Learn more about `<NuxtLink>` usage.
## Programmatic Navigation
Nuxt 3 allows programmatic navigation through the `navigateTo()` utility method. Using this utility method, you will be able to programmatically navigate the user in your app. This is great for taking input from the user and navigating them dynamically throughout your application. In this example, we have a simple method called `navigate()` that gets called when the user submits a search form.
Nuxt allows programmatic navigation through the `navigateTo()` utility method. Using this utility method, you will be able to programmatically navigate the user in your app. This is great for taking input from the user and navigating them dynamically throughout your application. In this example, we have a simple method called `navigate()` that gets called when the user submits a search form.
::callout{color="blue" icon="i-ph-info-duotone"}
::note
Ensure to always `await` on `navigateTo` or chain its result by returning from functions.
::
@ -357,13 +381,25 @@ function navigate(){
</script>
```
## Custom routing
## Client-Only Pages
You can define a page as [client only](/docs/guide/directory-structure/components#client-components) by giving it a `.client.vue` suffix. None of the content of this page will be rendered on the server.
## Server-Only Pages
You can define a page as [server only](/docs/guide/directory-structure/components#server-components) by giving it a `.server.vue` suffix. While you will be able to navigate to the page using client-side navigation, controlled by `vue-router`, it will be rendered with a server component automatically, meaning the code required to render the page will not be in your client-side bundle.
::alert{type=warning}
Server-only pages must have a single root element. (HTML comments are considered elements as well.)
::
## Custom Routing
As your app gets bigger and more complex, your routing might require more flexibility. For this reason, Nuxt directly exposes the router, routes and router options for customization in different ways.
:read-more{to="/docs/guide/going-further/custom-routing"}
:read-more{to="/docs/guide/recipes/custom-routing"}
## Multiple pages directories
## Multiple Pages Directories
By default, all your pages should be in one `pages` directory at the root of your project.
@ -372,7 +408,7 @@ However, you can use [Nuxt Layers](/docs/getting-started/layers) to create group
```bash [Directory Structure]
-| some-app/
---| nuxt.config.ts
---| pages
---| pages/
-----| app-page.vue
-| nuxt.config.ts
```

View File

@ -2,16 +2,16 @@
title: "plugins"
description: "Nuxt has a plugins system to use Vue plugins and more at the creation of your Vue application."
head.title: "plugins/"
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
Nuxt automatically reads the files in the `plugins/` directory and loads them at the creation of the Vue application.
::callout{color="blue" icon="i-ph-info-duotone"}
All plugins inside are auto-registered, you don't need not add them to your `nuxt.config` separately.
::note
All plugins inside are auto-registered, you don't need to add them to your `nuxt.config` separately.
::
::callout{color="yellow" icon="i-ph-lightbulb-duotone"}
::note
You can use `.server` or `.client` suffix in the file name to load a plugin only on the server or client side.
::
@ -76,9 +76,14 @@ export default defineNuxtPlugin({
})
```
::callout
If you are using the object-syntax, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. :br
For example, setting `enforce: process.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=2aXZyXB1QGQ" target="_blank"}
Watch a video from Alexander Lichter about the Object Syntax for Nuxt plugins.
::
::note
If you are using the object-syntax, the properties are statically analyzed to produce a more optimized build. So you should not define them at runtime. :br
For example, setting `enforce: import.meta.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
Nuxt does statically pre-load any hook listeners when using object-syntax, allowing you to define hooks without needing to worry about order of plugin registration.
::
## Registration Order
@ -95,7 +100,7 @@ In this example, `02.myOtherPlugin.ts` will be able to access anything that was
This is useful in situations where you have a plugin that depends on another plugin.
::callout{color="blue" icon="i-ph-info-duotone"}
::note
In case you're new to 'alphabetical' numbering, remember that filenames are sorted as strings, not as numeric values. For example, `10.myPlugin.ts` would come before `2.myOtherPlugin.ts`. This is why the example prefixes single digit numbers with `0`.
::
@ -103,7 +108,7 @@ In case you're new to 'alphabetical' numbering, remember that filenames are sort
### Parallel Plugins
By default, Nuxt loads plugins sequentially. You can define a plugin as `parallel` so Nuxt won't wait the end of the plugin's execution before loading the next plugin.
By default, Nuxt loads plugins sequentially. You can define a plugin as `parallel` so Nuxt won't wait until the end of the plugin's execution before loading the next plugin.
```ts twoslash [plugins/my-plugin.ts]
export default defineNuxtPlugin({
@ -117,7 +122,7 @@ export default defineNuxtPlugin({
### Plugins With Dependencies
If a plugin needs to await a parallel plugin before it runs, you can add the plugin's name to the `dependsOn` array.
If a plugin needs to wait for another plugin before it runs, you can add the plugin's name to the `dependsOn` array.
```ts twoslash [plugins/depending-on-my-plugin.ts]
export default defineNuxtPlugin({
@ -141,13 +146,13 @@ export default defineNuxtPlugin((nuxtApp) => {
However, keep in mind there are some limitations and differences:
::callout
::important
**If a composable depends on another plugin registered later, it might not work.** :br
Plugins are called in order sequentially and before everything else. You might use a composable that depends on another plugin which has not been called yet.
::
::callout
::important
**If a composable depends on the Vue.js lifecycle, it won't work.** :br
Normally, Vue.js composables are bound to the current component instance while plugins are only bound to [`nuxtApp`](/docs/api/composables/use-nuxt-app) instance.
@ -196,11 +201,11 @@ const { $hello } = useNuxtApp()
</template>
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
Note that we highly recommend using [`composables`](/docs/guide/directory-structure/composables) instead of providing helpers to avoid polluting the global namespace and keep your main bundle entry small.
::
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
**If your plugin provides a `ref` or `computed`, it will not be unwrapped in a component `<template>`.** :br
This is due to how Vue works with refs that aren't top-level to the template. You can read more about it [in the Vue documentation](https://vuejs.org/guide/essentials/reactivity-fundamentals.html#caveat-when-unwrapping-in-templates).
::
@ -209,7 +214,7 @@ This is due to how Vue works with refs that aren't top-level to the template. Yo
If you return your helpers from the plugin, they will be typed automatically; you'll find them typed for the return of `useNuxtApp()` and within your templates.
::callout
::note
If you need to use a provided helper _within_ another plugin, you can call [`useNuxtApp()`](/docs/api/composables/use-nuxt-app) to get the typed version. But in general, this should be avoided unless you are certain of the plugins' order.
::
@ -231,7 +236,7 @@ declare module 'vue' {
export {}
```
::callout
::note
If you are using WebStorm, you may need to augment `@vue/runtime-core` until [this issue](https://youtrack.jetbrains.com/issue/WEB-59818/VUE-TypeScript-WS-PS-does-not-correctly-display-type-of-globally-injected-properties) is resolved.
::
@ -241,13 +246,13 @@ If you want to use Vue plugins, like [vue-gtag](https://github.com/MatteoGabriel
First, install the Vue plugin dependency:
::code-group
```bash [yarn]
yarn add --dev vue-gtag-next
```
::package-managers
```bash [npm]
npm install --save-dev vue-gtag-next
```
```bash [yarn]
yarn add --dev vue-gtag-next
```
```bash [pnpm]
pnpm add -D vue-gtag-next
```
@ -289,7 +294,7 @@ export default defineNuxtPlugin((nuxtApp) => {
})
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
If you register a Vue directive, you _must_ register it on both client and server side unless you are only using it when rendering one side. If the directive only makes sense from a client side, you can always move it to `~/plugins/my-directive.client.ts` and provide a 'stub' directive for the server in `~/plugins/my-directive.server.ts`.
::

View File

@ -2,7 +2,7 @@
title: "public"
description: "The public/ directory is used to serve your website's static assets."
head.title: "public/"
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
Files contained within the `public/` directory are served at the root and are not modified by the build process. This is suitable for files that have to keep their names (e.g. `robots.txt`) _or_ likely won't change (e.g. `favicon.ico`).
@ -22,6 +22,6 @@ useSeoMeta({
</script>
```
::callout{to="https://v2.nuxt.com/docs/directory-structure/static" target="_blank"}
::tip{to="https://v2.nuxt.com/docs/directory-structure/static" target="_blank"}
This is known as the [`static/`] directory in Nuxt 2.
::

View File

@ -2,7 +2,7 @@
title: server
head.title: 'server/'
description: The server/ directory is used to register API and server handlers to your application.
navigation.icon: i-ph-folder-duotone
navigation.icon: i-ph-folder
---
Nuxt automatically scans files inside these directories to register API and server handlers with Hot Module Replacement (HMR) support.
@ -55,7 +55,7 @@ export default defineEventHandler(() => 'Hello World!')
Given the example above, the `/hello` route will be accessible at <http://localhost:3000/hello>.
::callout
::note
Note that currently server routes do not support the full functionality of dynamic routes as [pages](/docs/guide/directory-structure/pages#dynamic-routes) do.
::
@ -65,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.
::callout
::note
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.
::
@ -130,7 +130,7 @@ export const defineWrappedResponseHandler = <T extends EventHandlerRequest, D> (
## Server Types
::callout
::tip
This feature is available from Nuxt >= 3.5
::
@ -158,7 +158,7 @@ export default defineEventHandler((event) => {
})
```
::callout{icon="i-ph-lightbulb" color="green"}
::tip
Alternatively, use `getValidatedRouterParams` with a schema validator such as Zod for runtime and type safety.
::
@ -234,7 +234,7 @@ export default defineEventHandler(async (event) => {
})
```
::callout{icon="i-ph-lightbulb" color="green" to="https://unjs.io/blog/2023-08-15-h3-towards-the-edge-of-the-web#runtime-type-safe-request-utils"}
::tip{to="https://unjs.io/blog/2023-08-15-h3-towards-the-edge-of-the-web#runtime-type-safe-request-utils"}
Alternatively, use `readValidatedBody` with a schema validator such as Zod for runtime and type safety.
::
@ -251,7 +251,7 @@ async function submit() {
</script>
```
::callout
::note
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.
::
@ -267,7 +267,7 @@ export default defineEventHandler((event) => {
})
```
::callout{icon="i-ph-lightbulb" color="green" to="https://unjs.io/blog/2023-08-15-h3-towards-the-edge-of-the-web#runtime-type-safe-request-utils"}
::tip{to="https://unjs.io/blog/2023-08-15-h3-towards-the-edge-of-the-web#runtime-type-safe-request-utils"}
Alternatively, use `getValidatedQuery` with a schema validator such as Zod for runtime and type safety.
::
@ -333,7 +333,7 @@ NUXT_GITHUB_TOKEN='<my-super-token>'
```
::
::callout
::note
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.
::
@ -347,13 +347,29 @@ export default defineEventHandler((event) => {
})
```
### Forwarding Context & Headers
By default, neither the headers from the incoming request nor the request context are forwarded when
making fetch requests in server routes. You can use `event.$fetch` to forward the request context and headers when making fetch requests in server routes.
```ts [server/api/forward.ts]
export default defineEventHandler((event) => {
return event.$fetch('/api/forwarded')
})
```
::note
Headers that are **not meant to be forwarded** will **not be included** in the request. These headers include, for example:
`transfer-encoding`, `connection`, `keep-alive`, `upgrade`, `expect`, `host`, `accept`
::
## Advanced Usage
### Nitro Config
You can use `nitro` key in `nuxt.config` to directly set [Nitro configuration](https://nitro.unjs.io/config).
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
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.
::
@ -380,7 +396,7 @@ export default useBase('/api/hello', router.handler)
### Sending Streams
::callout
::tip
This is an experimental feature and is available in all environments.
::
@ -409,7 +425,7 @@ export default fromNodeMiddleware((req, res) => {
})
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
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.
::
@ -420,7 +436,7 @@ export default fromNodeMiddleware((req, res, next) => {
})
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
Never combine `next()` callback with a legacy middleware that is `async` or returns a `Promise`.
::

View File

@ -2,7 +2,7 @@
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
navigation.icon: i-ph-folder
---
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.
@ -39,11 +39,11 @@ You can now use auto imported utility functions in `.js`, `.ts` and `.vue` files
:link-example{to="/docs/examples/features/auto-imports"}
::callout
::tip
The way `utils/` auto-imports work and are scanned is identical to the [`composables/`](/docs/guide/directory-structure/composables) directory.
::
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
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.
::

View File

@ -2,10 +2,10 @@
title: ".env"
description: "A .env file specifies your build/dev-time environment variables."
head.title: ".env"
navigation.icon: i-ph-file-duotone
navigation.icon: i-ph-file
---
::callout{icon="i-ph-warning-duotone" color="amber"}
::important
This file should be added to your [`.gitignore`](/docs/guide/directory-structure/gitignore) file to avoid pushing secrets to your repository.
::
@ -19,7 +19,7 @@ In addition to any process environment variables, if you have a `.env` file in y
MY_ENV_VARIABLE=hello
```
::callout
::note
Note that removing a variable from `.env` or removing the `.env` file entirely will not unset values that have already been set.
::
@ -33,11 +33,29 @@ 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
::important
In your application code, you should use [Runtime Config](/docs/guide/going-further/runtime-config) instead of plain env variables.
::
## Production
**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.
Your `.env` files will not be read at this point. How you do this is different for every environment.
This design decision was made to ensure compatibility across various deployment environments, some of which may not have a traditional file system available, such as serverless platforms or edge networks like Cloudflare Workers.
Since `.env` files are not used in production, you must explicitly set environment variables using the tools and methods provided by your hosting environment. Here are some common approaches:
* You can pass the environment variables as arguments using the terminal:
`$ DATABASE_HOST=mydatabaseconnectionstring node .output/server/index.mjs`
* You can set environment variables in shell configuration files like `.bashrc` or `.profile`.
* Many cloud service providers, such as Vercel, Netlify, and AWS, provide interfaces for setting environment variables via their dashboards, CLI tools or configuration files.
## Production Preview
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.
@ -51,7 +69,7 @@ Note that for a purely static site, it is not possible to set runtime configurat
:read-more{to="/docs/guide/going-further/runtime-config"}
::callout
::note
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.
:read-more{to="/docs/guide/directory-structure/app-config"}
::

View File

@ -2,7 +2,7 @@
title: ".gitignore"
description: "A .gitignore file specifies intentionally untracked files that git should ignore."
head.title: ".gitignore"
navigation.icon: i-ph-file-duotone
navigation.icon: i-ph-file
---
A `.gitignore` file specifies intentionally untracked files that git should ignore.

View File

@ -2,14 +2,14 @@
title: .nuxtignore
head.title: '.nuxtignore'
description: The .nuxtignore file lets Nuxt ignore files in your projects root directory during the build phase.
navigation.icon: i-ph-file-duotone
navigation.icon: i-ph-file
---
The `.nuxtignore` file tells Nuxt to ignore files in your projects root directory ([`rootDir`](/docs/api/nuxt-config#rootdir)) during the build phase.
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.
::callout
::tip
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.
::

View File

@ -2,10 +2,10 @@
title: app.config.ts
head.title: 'app.config.ts'
description: Expose reactive configuration within your application with the App Config file.
navigation.icon: i-ph-file-duotone
navigation.icon: i-ph-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).
Nuxt 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.
@ -15,7 +15,7 @@ export default defineAppConfig({
})
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::caution
Do not put any secret values inside `app.config` file. It is exposed to the user client bundle.
::
@ -72,7 +72,7 @@ export {}
If you want to type the result of calling [`useAppConfig()`](/docs/api/composables/use-app-config), then you will want to extend `AppConfig`.
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
Be careful when typing `AppConfig` as you will overwrite the types Nuxt infers from your actually defined app config.
::
@ -98,8 +98,8 @@ Nuxt uses a custom merging strategy for the `AppConfig` within [the layers](/doc
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.
::callout
The Function Merger should only be used in the base `app.config` of your application.
::note
The function merger can only be used in the extended layers and not the main `app.config` in project.
::
Here's an example of how you can use:
@ -121,3 +121,37 @@ export default defineAppConfig({
```
::
## Known Limitations
As of Nuxt v3.3, the `app.config.ts` file is shared with Nitro, which results in the following limitations:
1. You cannot import Vue components directly in `app.config.ts`.
2. Some auto-imports are not available in the Nitro context.
These limitations occur because Nitro processes the app config without full Vue component support.
While it's possible to use Vite plugins in the Nitro config as a workaround, this approach is not recommended:
```ts [nuxt.config.ts]
export default defineNuxtConfig({
nitro: {
vite: {
plugins: [vue()]
}
}
})
```
::warning
Using this workaround may lead to unexpected behavior and bugs. The Vue plugin is one of many that are not available in the Nitro context.
::
Related issues:
- [Issue #19858](https://github.com/nuxt/nuxt/issues/19858)
- [Issue #19854](https://github.com/nuxt/nuxt/issues/19854)
::info
Nitro v3 will resolve these limitations by removing support for the app config.
You can track the progress in [this pull request](https://github.com/unjs/nitro/pull/2521).
::

View File

@ -2,7 +2,7 @@
title: "app.vue"
description: "The app.vue file is the main component of your Nuxt application."
head.title: "app.vue"
navigation.icon: i-ph-file-duotone
navigation.icon: i-ph-file
---
## Minimal Usage
@ -31,11 +31,11 @@ If you have a [`pages/`](/docs/guide/directory-structure/pages) directory, to di
</template>
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
Since [`<NuxtPage>`](/docs/api/components/nuxt-page) internally uses Vue's [`<Suspense>`](https://vuejs.org/guide/built-ins/suspense.html#suspense) component, it cannot be set as a root element.
::
::callout{color="blue" icon="i-ph-info-duotone"}
::note
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.
::

View File

@ -2,7 +2,7 @@
title: "error.vue"
description: "The error.vue file is the error page in your Nuxt application."
head.title: "error.vue"
navigation.icon: i-ph-file-duotone
navigation.icon: i-ph-file
---
During the lifespan of your application, some errors may appear unexpectedly at runtime. In such case, we can use the `error.vue` file to override the default error files and display the error nicely.
@ -24,7 +24,7 @@ const props = defineProps({
</template>
```
::callout
::note
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. That being said, you can still use layouts in the error file, by utilizing the [`NuxtLayout`](/docs/api/components/nuxt-layout) component and specifying the name of the layout.
::

View File

@ -2,7 +2,7 @@
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
navigation.icon: i-ph-file
---
The `nuxt.config` file extension can either be `.js`, `.ts` or `.mjs`.
@ -13,7 +13,7 @@ export default defineNuxtConfig({
})
```
::callout
::tip
`defineNuxtConfig` helper is globally available without import.
::
@ -33,7 +33,7 @@ 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).
The `.nuxtrc` file can be used to configure Nuxt with a flat syntax. It is based on [`unjs/rc9`](https://github.com/unjs/rc9).
``` [.nuxtrc]
ssr=false

View File

@ -2,7 +2,7 @@
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
navigation.icon: i-ph-file
---
The minimal `package.json` of your Nuxt application should looks like:

View File

@ -2,7 +2,7 @@
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
navigation.icon: i-ph-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.
@ -15,10 +15,10 @@ You can benefit from this by creating a `tsconfig.json` in the root of your proj
}
```
::callout
::note
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
::note
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`.
::

View File

@ -1,3 +1,3 @@
title: Directory Structure
titleTemplate: '%s · Nuxt Directory Structure'
icon: i-ph-folders-duotone
icon: i-ph-folders

View File

@ -7,7 +7,7 @@ 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](/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
Note that these features are experimental and could be removed or modified in the future.
::
@ -53,24 +53,10 @@ export default defineNuxtConfig({
})
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
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 twoslash [nuxt.config.ts]
export default 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.
@ -91,7 +77,7 @@ Allows Nuxt app state to be restored from `sessionStorage` when reloading the pa
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"}
::important
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.
::
@ -118,11 +104,11 @@ export default defineNuxtConfig({
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{to="/docs/api/utils/define-route-rules" icon="i-ph-function"}
Read more in `defineRouteRules` utility.
::
:read-more{to="/docs/guide/concepts/rendering#hybrid-rendering" icon="i-ph-medal-duotone"}
:read-more{to="/docs/guide/concepts/rendering#hybrid-rendering" icon="i-ph-medal"}
## renderJsonPayloads
@ -238,44 +224,6 @@ export default defineNuxtConfig({
You can follow the server components roadmap on GitHub.
::
## configSchema
Enables config schema support.
*Enabled by default.*
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
configSchema: true
}
})
```
## polyfillVueUseHead
Adds a compatibility layer for modules, plugins, or user code relying on the old `@vueuse/head` API.
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
polyfillVueUseHead: false
}
})
```
## respectNoSSRHeader
Allow disabling Nuxt SSR responses by setting the `x-nuxt-no-ssr` header.
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
respectNoSSRHeader: false
}
})
```
## localLayerAliases
Resolve `~`, `~~`, `@` and `@@` aliases located within layers with respect to their layer source and root directories.
@ -306,6 +254,10 @@ Out of the box, this will enable typed usage of [`navigateTo`](/docs/api/utils/n
You can even get typed params within a page by using `const route = useRoute('route-name')`.
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=SXk-L19gTZk" target="_blank"}
Watch a video from Daniel Roe explaining type-safe routing in Nuxt.
::
## watcher
Set an alternative watcher that will be used as the watching service for Nuxt.
@ -340,6 +292,10 @@ export default defineNuxtConfig({
})
```
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=1jUupYHVvrU" target="_blank"}
Watch a video from Alexander Lichter about the experimental `sharedPrerenderData` setting.
::
It is particularly important when enabling this feature to make sure that any unique key of your data
is always resolvable to the same data. For example, if you are using `useAsyncData` to fetch
data related to a particular page, you should provide a key that uniquely matches that data. (`useFetch`
@ -378,6 +334,16 @@ This option allows exposing some route metadata defined in `definePageMeta` at b
This only works with static or strings/arrays rather than variables or conditional assignment. See [original issue](https://github.com/nuxt/nuxt/issues/24770) for more information and context.
You can disable this feature if it causes issues in your project.
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
scanPageMeta: false
}
})
```
## cookieStore
Enables CookieStore support to listen for cookie updates (if supported by the browser) and refresh `useCookie` ref values.
@ -393,3 +359,62 @@ export default defineNuxtConfig({
::read-more{icon="i-simple-icons-mdnwebdocs" color="gray" to="https://developer.mozilla.org/en-US/docs/Web/API/CookieStore" target="_blank"}
Read more about the **CookieStore**.
::
## buildCache
Caches Nuxt build artifacts based on a hash of the configuration and source files.
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
buildCache: true
}
})
```
When enabled, changes to the following files will trigger a full rebuild:
```bash [Directory structure]
.nuxtrc
.npmrc
package.json
package-lock.json
yarn.lock
pnpm-lock.yaml
tsconfig.json
bun.lockb
```
In addition, any changes to files within `srcDir` will trigger a rebuild of the Vue client/server bundle. Nitro will always be rebuilt (though work is in progress to allow Nitro to announce its cacheable artifacts and their hashes).
::note
A maximum of 10 cache tarballs are kept.
::
## normalizeComponentNames
Ensure that auto-generated Vue component names match the full component name
you would use to auto-import the component.
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
experimental: {
normalizeComponentNames: true
}
})
```
By default, if you haven't set it manually, Vue will assign a component name that matches
the filename of the component.
```bash [Directory structure]
├─ components/
├─── SomeFolder/
├───── MyComponent.vue
```
In this case, the component name would be `MyComponent`, as far as Vue is concerned. If you wanted to use `<KeepAlive>` with it, or identify it in the Vue DevTools, you would need to use this component.
But in order to auto-import it, you would need to use `SomeFolderMyComponent`.
By setting `experimental.normalizeComponentNames`, these two values match, and Vue will generate a component name that matches the Nuxt pattern for component naming.

View File

@ -37,6 +37,50 @@ export default defineNuxtConfig({
There is also a `future` namespace for early opting-in to new features that will become default in a future (possibly major) version of the framework.
### compatibilityVersion
::important
This configuration option is available in Nuxt v3.12+.
::
This enables early access to Nuxt features or flags.
Setting `compatibilityVersion` to `4` changes defaults throughout your
Nuxt configuration to opt-in to Nuxt v4 behaviour, but you can granularly re-enable Nuxt v3 behaviour
when testing (see example). Please file issues if so, so that we can
address in Nuxt or in the ecosystem.
```ts
export default defineNuxtConfig({
future: {
compatibilityVersion: 4,
},
// To re-enable _all_ Nuxt v3 behaviour, set the following options:
srcDir: '.',
dir: {
app: 'app'
},
experimental: {
sharedPrerenderData: false,
compileTemplate: true,
resetAsyncDataToUndefined: true,
templateUtils: true,
relativeWatchPaths: true,
normalizeComponentNames: false
defaults: {
useAsyncData: {
deep: true
}
}
},
unhead: {
renderSSRHeadOptions: {
omitLineBreaks: false
}
}
})
```
### typescriptBundlerResolution
This enables 'Bundler' module resolution mode for TypeScript, which is the recommended setting

View File

@ -29,7 +29,7 @@ console.log(runtimeConfig.apiSecret)
console.log(runtimeConfig.public.apiBase)
```
::callout
::tip
Public runtime config is accessible in Vue templates with `$config.public`.
::
@ -43,7 +43,7 @@ Instead of passing non-serializable objects or functions into your application f
The most common way to provide configuration is by using [Environment Variables](https://medium.com/chingu/an-introduction-to-environment-variables-and-how-to-use-them-f602f66d15fa).
::callout
::note
Nuxi CLI has built-in support for reading your `.env` file in development, build and generate. But when you run your built server, **your `.env` file will not be read**.
:read-more{to="/docs/guide/directory-structure/env"}
::
@ -56,11 +56,15 @@ There are two key requirements:
1. Only a specially-named environment variable can override a runtime config property. That is, an uppercase environment variable starting with `NUXT_` which uses `_` to separate keys and case changes.
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
Setting the default of `runtimeConfig` values to *differently named environment variables* (for example setting `myVar` to `process.env.OTHER_VARIABLE`) will only work during build-time and will break on runtime.
It is advised to use environment variables that match the structure of your `runtimeConfig` object.
::
::tip{icon="i-ph-video" to="https://youtu.be/_FYV5WfiWvs" target="_blank"}
Watch a video from Alexander Lichter showcasing the top mistake developers make using runtimeConfig.
::
#### Example
```sh [.env]
@ -85,12 +89,12 @@ export default defineNuxtConfig({
Within the Vue part of your Nuxt app, you will need to call [`useRuntimeConfig()`](/docs/api/composables/use-runtime-config) to access the runtime config.
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
The behavior is different between the client-side and server-side:
- On client-side, only keys in `runtimeConfig.public` are available, and the object is both writable and reactive.
- On server-side, the entire runtime config is available on the server-side, but it is read-only to avoid context sharing.
- On server-side, the entire runtime config is available, but it is read-only to avoid context sharing.
::
```vue [pages/index.vue]
@ -98,7 +102,7 @@ The behavior is different between the client-side and server-side:
const config = useRuntimeConfig()
console.log('Runtime config:', config)
if (process.server) {
if (import.meta.server) {
console.log('API secret:', config.apiSecret)
}
</script>
@ -110,7 +114,7 @@ if (process.server) {
</template>
```
::callout{icon="i-ph-flag-duotone" color="red"}
::caution
**Security note:** Be careful not to expose runtime config keys to the client-side by either rendering them or passing them to `useState`.
::
@ -142,7 +146,7 @@ export default defineEventHandler(async (event) => {
})
```
::callout
::note
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.
::
@ -164,3 +168,7 @@ declare module 'nuxt/schema' {
// It is always important to ensure you import/export something when augmenting a type
export {}
```
::note
`nuxt/schema` is provided as a convenience for end-users to access the version of the schema used by Nuxt in their project. Module authors should instead augment `@nuxt/schema`.
::

View File

@ -11,10 +11,16 @@ You can use these 'nightly' releases to beta test new features and changes.
The build and publishing method and quality of these 'nightly' releases are the same as stable ones. The only difference is that you should often check the GitHub repository for updates. There is a slight chance of regressions not being caught during the review process and by the automated tests. Therefore, we internally use this channel to double-check everything before each release.
::callout
::note
Features that are only available on the nightly release channel are marked with an alert in the documentation.
::
::alert{type="warning"}
The `latest` nightly release channel is currently tracking the Nuxt v4 branch, meaning that it is particularly likely to have breaking changes right now - be careful!
You can opt in to the 3.x branch nightly releases with `"nuxt": "npm:nuxt-nightly@3x"`.
::
## Opting In
Update `nuxt` dependency inside `package.json`:
@ -47,7 +53,7 @@ Remove lockfile (`package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, or `bun.loc
## Using Nightly `nuxi`
::callout
::note
All cli dependencies are bundled because of the building method for reducing `nuxi` package size. :br You can get dependency updates and CLI improvements using the nightly release channel.
::

View File

@ -3,7 +3,7 @@ title: "Lifecycle Hooks"
description: "Nuxt provides a powerful hooking system to expand almost every aspect using hooks."
---
::callout
::tip
The hooking system is powered by [unjs/hookable](https://github.com/unjs/hookable).
::
@ -90,7 +90,7 @@ declare module '#app' {
}
}
declare module 'nitropack' {
declare module 'nitro/types' {
interface NitroRuntimeHooks {
'your-nitro-hook': () => void;
}

View File

@ -13,10 +13,25 @@ With modules, you can encapsulate, properly test, and share custom solutions as
We recommend you get started with Nuxt Modules using our [starter template](https://github.com/nuxt/starter/tree/module):
```bash [Terminal]
::package-managers
```bash [npm]
npx nuxi init -t module my-module
```
```bash [yarn]
yarn dlx nuxi init -t module my-module
```
```bash [pnpm]
pnpm dlx nuxi init -t module my-module
```
```bash [bun]
bun x nuxi init -t module my-module
```
::
This will create a `my-module` project with all the boilerplate necessary to develop and publish your module.
**Next steps:**
@ -30,6 +45,10 @@ This will create a `my-module` project with all the boilerplate necessary to dev
Learn how to perform basic tasks with the module starter.
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/navigating-the-official-starter-template?friend=nuxt" target="_blank"}
Watch Vue School video about Nuxt module starter template.
::
#### How to Develop
While your module source code lives inside the `src` directory, in most cases, to develop a module, you need a Nuxt application. That's what the `playground` directory is about. It's a Nuxt application you can tinker with that is already configured to run with your module.
@ -39,7 +58,7 @@ You can interact with the playground like with any Nuxt application.
- Launch its development server with `npm run dev`, it should reload itself as you make changes to your module in the `src` directory
- Build it with `npm run dev:build`
::callout{color="blue" icon="i-ph-info-duotone"}
::note
All other `nuxi` commands can be used against the `playground` directory (e.g. `nuxi <COMMAND> playground`). Feel free to declare additional `dev:*` scripts within your `package.json` referencing them for convenience.
::
@ -50,7 +69,7 @@ The module starter comes with a basic test suite:
- A linter powered by [ESLint](https://eslint.org), run it with `npm run lint`
- A test runner powered by [Vitest](https://vitest.dev), run it with `npm run test` or `npm run test:watch`
::callout
::tip
Feel free to augment this default test strategy to better suit your needs.
::
@ -60,19 +79,19 @@ Nuxt Modules come with their own builder provided by [`@nuxt/module-builder`](ht
You can build your module by running `npm run prepack`.
::callout
::tip
While building your module can be useful in some cases, most of the time you won't need to build it on your own: the `playground` takes care of it while developing, and the release script also has you covered when publishing.
::
#### How to Publish
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
Before publishing your module to npm, makes sure you have an [npmjs.com](https://www.npmjs.com) account and that you're authenticated to it locally with `npm login`.
::
While you can publish your module by bumping its version and using the `npm publish` command, the module starter comes with a release script that helps you make sure you publish a working version of your module to npm and more.
To use the release script, first, commit all your changes (we recommend you follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0) to also take advantage of automatic version bump and changelog update), then run the release script with `npm run release`.
To use the release script, first, commit all your changes (we recommend you follow [Conventional Commits](https://www.conventionalcommits.org) to also take advantage of automatic version bump and changelog update), then run the release script with `npm run release`.
When running the release script, the following will happen:
@ -85,7 +104,7 @@ When running the release script, the following will happen:
- Publishing the module to npm (for that purpose, the module will be built again to ensure its updated version number is taken into account in the published artifact)
- Pushing a git tag representing the newly published version to your git remote origin
::callout
::tip
As with other scripts, feel free to fine-tune the default `release` script in your `package.json` to better suit your needs.
::
@ -104,7 +123,7 @@ In either case, their anatomy is similar.
#### Module Definition
::callout
::note
When using the starter, your module definition is available at `src/module.ts`.
::
@ -151,7 +170,7 @@ export default defineNuxtModule({
// Compatibility constraints
compatibility: {
// Semver version of supported nuxt versions
nuxt: '^3.0.0'
nuxt: '>=3.0.0'
}
},
// Default configuration options for your module, can also be a function returning those
@ -179,7 +198,7 @@ Ultimately `defineNuxtModule` returns a wrapper function with the lower level `(
#### Runtime Directory
::callout
::note
When using the starter, the runtime directory is available at `src/runtime`.
::
@ -203,15 +222,15 @@ Or any other kind of asset you want to inject in users' Nuxt applications:
You'll then be able to inject all those assets inside the application from your [module definition](#module-definition).
::callout
::tip
Learn more about asset injection in [the recipes section](#recipes).
::
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
Published modules cannot leverage auto-imports for assets within their runtime directory. Instead, they have to import them explicitly from `#imports` or alike.
:br :br
Indeed, auto-imports are not enabled for files within `node_modules` (the location where a published module will eventually live) for performance reasons.
:br :br
If you are using the module starter, auto-imports will not be enabled in your playground either.
::
@ -255,6 +274,10 @@ export default defineNuxtModule({
When you need to handle more complex configuration alterations, you should consider using [defu](https://github.com/unjs/defu).
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/extending-and-altering-nuxt-configuration-and-options?friend=nuxt" target="_blank"}
Watch Vue School video about altering Nuxt configuration.
::
#### Exposing Options to Runtime
Because modules aren't part of the application runtime, their options aren't either. However, in many cases, you might need access to some of these module options within your runtime code. We recommend exposing the needed config using Nuxt's [`runtimeConfig`](/docs/api/nuxt-config#runtimeconfig).
@ -282,12 +305,16 @@ You can then access your module options in a plugin, component, the application
const options = useRuntimeConfig().public.myModule
```
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
Be careful not to expose any sensitive module configuration on the public runtime config, such as private API keys, as they will end up in the public bundle.
::
:read-more{to="/docs/guide/going-further/runtime-config"}
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/passing-and-exposing-module-options?friend=nuxt" target="_blank"}
Watch Vue School video about passing and exposing Nuxt module options.
::
#### Injecting Plugins With `addPlugin`
Plugins are a common way for a module to add runtime logic. You can use the `addPlugin` utility to register them from your module.
@ -511,9 +538,14 @@ export default defineNuxtModule({
:read-more{to="/docs/api/advanced/hooks"}
::callout
**Module cleanup**
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/nuxt-lifecycle-hooks?friend=nuxt" target="_blank"}
Watch Vue School video about using Nuxt lifecycle hooks in modules.
::
::note
**Module cleanup**
:br
:br
If your module opens, handles, or starts a watcher, you should close it when the Nuxt lifecycle is done. The `close` hook is available for this.
```ts
@ -527,7 +559,6 @@ export default defineNuxtModule({
}
})
```
::
#### Adding Templates/Virtual Files
@ -567,7 +598,7 @@ export default defineNuxtModule({
interface MyModuleNitroRules {
myModule?: { foo: 'bar' }
}
declare module 'nitropack' {
declare module 'nitro/types' {
interface NitroRouteRules extends MyModuleNitroRules {}
interface NitroRouteConfig extends MyModuleNitroRules {}
}
@ -605,9 +636,9 @@ Testing helps ensuring your module works as expected given various setup. Find i
#### Unit and Integration
::callout
::tip
We're still discussing and exploring how to ease unit and integration testing on Nuxt Modules.
:br :br
[Check out this RFC to join the conversation](https://github.com/nuxt/nuxt/discussions/18399).
::
@ -661,7 +692,7 @@ describe('ssr', async () => {
describe('csr', async () => { /* ... */ })
```
::callout
::tip
An example of such a workflow is available on [the module starter](https://github.com/nuxt/starter/blob/module/test/basic.test.ts).
::
@ -683,7 +714,7 @@ As we've seen, Nuxt Modules can be asynchronous. For example, you may want to de
However, be careful with asynchronous behaviors as Nuxt will wait for your module to setup before going to the next module and starting the development server, build process, etc. Prefer deferring time-consuming logic to Nuxt hooks.
::callout{color="amber" icon="i-ph-warning-duotone"}
::warning
If your module takes more than **1 second** to setup, Nuxt will emit a warning about it.
::
@ -733,6 +764,10 @@ The module starter comes with a default set of tools and configurations (e.g. ES
[Nuxt Module ecosystem](/modules) represents more than 15 million monthly NPM downloads and provides extended functionalities and integrations with all sort of tools. You can be part of this ecosystem!
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/exploring-nuxt-modules-ecosystem-and-module-types?friend=nuxt" target="_blank"}
Watch Vue School video about Nuxt module types.
::
### Module Types
**Official modules** are modules prefixed (scoped) with `@nuxt/` (e.g. [`@nuxt/content`](https://content.nuxtjs.org)). They are made and maintained actively by the Nuxt team. Like with the framework, contributions from the community are more than welcome to help make them better!

View File

@ -15,6 +15,10 @@ Discover all Nuxt Kit utilities.
You can install the latest Nuxt Kit by adding it to the `dependencies` section of your `package.json`. However, please consider always explicitly installing the `@nuxt/kit` package even if it is already installed by Nuxt.
::note
`@nuxt/kit` and `@nuxt/schema` are key dependencies for Nuxt. If you are installing it separately, make sure that the versions of `@nuxt/kit` and `@nuxt/schema` are equal to or greater than your `nuxt` version to avoid any unexpected behavior.
::
```json [package.json]
{
"dependencies": {
@ -31,7 +35,7 @@ import { useNuxt } from '@nuxt/kit'
:read-more{to="/docs/api/kit"}
::callout
::note
Nuxt Kit utilities are only available for modules and not meant to be imported in runtime (components, Vue composables, pages, plugins, or server routes).
::

View File

@ -96,11 +96,15 @@ export default defineNuxtConfig({
})
```
::callout
::tip
If you want to extend a private remote source, you need to add the environment variable `GIGET_AUTH=<token>` to provide a token.
::
::callout{color="blue" icon="i-ph-info-duotone"}
::tip
If you want to extend a remote source from a self-hosted GitHub or GitLab instance, you need to supply its URL with the `GIGET_GITHUB_URL=<url>` or `GIGET_GITLAB_URL=<url>` environment variable - or directly configure it with [the `auth` option](https://github.com/unjs/c12#extending-config-layer-from-remote-sources) in your `nuxt.config`.
::
::note
When using git remote sources, if a layer has npm dependencies and you wish to install them, you can do so by specifying `install: true` in your layer options.
```ts [nuxt.config.ts]
@ -144,13 +148,13 @@ To publish a layer directory as an npm package, you want to make sure that the `
}
```
::callout
::important
Make sure any dependency imported in the layer is **explicitly added** to the `dependencies`. The `nuxt` dependency, and anything only used for testing the layer before publishing, should remain in the `devDependencies` field.
::
Now you can proceed to publish the module to npm, either publicly or privately.
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
When publishing the layer as a private npm package, you need to make sure you log in, to authenticate with npm to download the node module.
::

View File

@ -26,7 +26,7 @@ nuxi dev --inspect
```
This will start Nuxt in `dev` mode with debugger active. If everything is working correctly a Node.js icon will appear on your Chrome DevTools and you can attach to the debugger.
::callout{color="amber" icon="i-ph-warning-duotone"}
::important
Note that the Node.js and Chrome processes need to be run on the same platform. This doesn't work inside of Docker.
::
@ -38,6 +38,10 @@ It is possible to debug your Nuxt app in your IDE while you are developing it.
You may need to update the config below with a path to your web browser. For more information, visit the [VS Code documentation about debug configuration](https://go.microsoft.com/fwlink/?linkid=830387).
::important
If you use `pnpm`, you will need to have `nuxi` installed as a devDependency for the configuration below to work.
::
```json5
{
// Use IntelliSense to learn about possible attributes.

View File

@ -1,3 +1,3 @@
title: Going Further
titleTemplate: '%s · Nuxt Advanced'
icon: i-ph-star-duotone
icon: i-ph-star

Some files were not shown because too many files have changed in this diff Show More