Merge remote-tracking branch 'origin/main' into feat/islands-use-cache

This commit is contained in:
Julien Huang 2024-06-13 22:42:04 +02:00
commit c62776b2e4
615 changed files with 25858 additions and 11826 deletions

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,10 +1,10 @@
blank_issues_enabled: true
contact_links:
- name: 📚 Nuxt 3 Documentation
url: https://nuxt.com/docs/
url: https://nuxt.com/docs
about: Check the documentation for usage of Nuxt 3
- name: 📚 Nuxt 2 Documentation
url: https://v2.nuxt.com/
url: https://v2.nuxt.com
about: Check the documentation for usage of Nuxt 2
- name: 💬 Discussions
url: https://github.com/nuxt/nuxt/discussions

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!
----------------------------------------------------------------------->

View File

@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:

View File

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
@ -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
- name: Lint (code)
run: pnpm lint:fix
- uses: autofix-ci/action@ea32e3a12414e6d3183163c3424a7d7a8631ad84

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,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
@ -48,7 +46,7 @@ jobs:
run: pnpm build
- name: Run benchmarks
uses: CodSpeedHQ/action@2e04019f4572c19684929a755da499f19a00b25b # v2.2.1
uses: CodSpeedHQ/action@0b631f8998f2389eb5144632b6f9f8fabd33a86e # v2.4.1
with:
run: pnpm vitest bench
token: ${{ secrets.CODSPEED_TOKEN }}

View File

@ -1,4 +1,4 @@
name: Release
name: changelog
on:
push:
@ -15,12 +15,12 @@ concurrency:
cancel-in-progress: ${{ github.event_name != 'push' }}
jobs:
update-changelog:
update:
if: github.repository_owner == 'nuxt' && !contains(github.event.head_commit.message, 'v3.')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- run: corepack enable

View File

@ -18,17 +18,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@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Lychee link checker
uses: lycheeverse/lychee-action@c053181aa0c3d17606addfe97a9075a32723548a # for v1.8.0
uses: lycheeverse/lychee-action@25a231001d1723960a301b7d4c82884dc7ef857d # for v1.8.0
with:
# arguments with file types to check
args: >-

View File

@ -20,8 +20,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,7 +35,7 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
@ -57,7 +55,7 @@ jobs:
run: pnpm build
- name: Cache dist
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
retention-days: 3
name: dist
@ -74,7 +72,7 @@ jobs:
- build
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
@ -85,19 +83,19 @@ jobs:
run: pnpm install
- name: Initialize CodeQL
uses: github/codeql-action/init@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5
uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
with:
languages: javascript
queries: +security-and-quality
- name: Restore dist cache
uses: actions/download-artifact@87c55149d96e628cc2ef7e6fc2aab372015aec85 # v4.1.3
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: dist
path: packages
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5
uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
with:
category: "/language:javascript"
@ -113,7 +111,7 @@ jobs:
module: ["bundler", "node"]
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
@ -124,7 +122,7 @@ jobs:
run: pnpm install
- name: Restore dist cache
uses: actions/download-artifact@87c55149d96e628cc2ef7e6fc2aab372015aec85 # v4.1.3
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: dist
path: packages
@ -144,7 +142,7 @@ jobs:
timeout-minutes: 10
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
@ -168,7 +166,7 @@ jobs:
needs:
- build
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
@ -200,8 +198,18 @@ jobs:
builder: ["vite", "webpack"]
context: ["async", "default"]
manifest: ["manifest-on", "manifest-off"]
version: ["v4", "v3"]
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,7 +218,7 @@ jobs:
timeout-minutes: 15
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:
@ -220,34 +228,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@87c55149d96e628cc2ef7e6fc2aab372015aec85 # v4.1.3
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: dist
path: packages
@ -259,9 +244,11 @@ 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_V4: ${{ matrix.version == 'v4' }}
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@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0
- uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.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 }}
@ -283,7 +270,7 @@ jobs:
timeout-minutes: 20
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- run: corepack enable
@ -296,7 +283,7 @@ jobs:
run: pnpm install
- name: Restore dist cache
uses: actions/download-artifact@87c55149d96e628cc2ef7e6fc2aab372015aec85 # v4.1.3
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: dist
path: packages
@ -322,7 +309,7 @@ jobs:
timeout-minutes: 20
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- run: corepack enable
@ -335,7 +322,7 @@ jobs:
run: pnpm install
- name: Restore dist cache
uses: actions/download-artifact@87c55149d96e628cc2ef7e6fc2aab372015aec85 # v4.1.3
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: 'Dependency Review'
uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce # v4.1.3
uses: actions/dependency-review-action@72eb03d02c7872a771aacd928f3123ac62ad6d3a # v4.3.3

View File

@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
with:

View File

@ -21,7 +21,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
# From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions
- name: Check workflow files
run: |

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:
@ -22,16 +22,16 @@ jobs:
steps:
- name: Ensure action is by maintainer
uses: octokit/request-action@89697eb6635e52c6e1e5559f15b5c91ba5100cb0 # v2.1.9
uses: octokit/request-action@872c5c97b3c85c23516a572f02b31401ef82415d # v2.3.1
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
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
ref: refs/pull/${{ github.event.issue.number }}/merge
ref: ${{ github.event.issue.pull_request.head.sha }}
fetch-depth: 0
- run: corepack enable

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

@ -0,0 +1,40 @@
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.')
permissions:
id-token: write
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
- run: corepack enable
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
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

@ -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:

View File

@ -10,7 +10,7 @@ jobs:
reproduire:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp
with:
label: needs reproduction

View File

@ -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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
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@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
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@47b3d888fe66b639e431abf22ebca059152f1eea # v3.24.5
uses: github/codeql-action/upload-sarif@23acc5c183826b7a8a97bce3cecc52db901f8251 # v3.25.10
if: github.repository == 'nuxt/nuxt' && success()
with:
sarif_file: results.sarif

View File

@ -20,7 +20,7 @@ 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@cfb60706e18bc85e8aec535e3c577abe8f70378e # v5.5.2
with:
scopes: |
kit
@ -28,6 +28,7 @@ jobs:
nuxt
schema
test-utils
ui-templates
vite
webpack
deps

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

View File

@ -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,44 @@ 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="nuxt-2">⛰️ Nuxt 2</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).
## Follow us
If you expect to be using Nuxt 2 beyond the EOL (End of Life) date (June 30, 2024), and still need a maintained version that can satisfy security and browser compatibility requirements, make sure to check out [HeroDevs NES (Never-Ending Support) Nuxt 2](https://www.herodevs.com/support/nuxt-nes?utm_source=nuxt-github&utm_medium=nuxt-readme).
## <a name="professional-support">🛟 Professional Support</a>
- Technical audit & consulting: [Nuxt Experts](https://nuxt.com/enterprise/support)
- Custom development & more: [Nuxt Agencies Partners](https://nuxt.com/enterprise/agencies)
## <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>
</p>
## License
## <a name="license">⚖️ License</a>
[MIT](./LICENSE)

View File

@ -10,6 +10,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.

View File

@ -71,62 +71,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

View File

@ -10,13 +10,17 @@ If you are a module author, you can find more specific information in the [Modul
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-duotone" 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]
@ -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.
@ -155,21 +164,32 @@ export default defineVitestConfig({
`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:
```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' })
@ -194,13 +214,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 () => {
@ -210,13 +232,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' })
@ -337,8 +357,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'
}))
```
@ -347,13 +367,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
@ -364,7 +384,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 () => {
@ -386,9 +406,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
::code-group
```bash [yarn]
yarn add --dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
```
```bash [npm]
npm i --save-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
::code-group
```bash [yarn]
yarn test
```
```bash [npm]
npm run 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
@ -454,7 +563,7 @@ 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'`
### APIs
@ -493,11 +602,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'
@ -505,3 +614,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).
::code-group
```bash [yarn]
yarn add --dev @playwright/test @nuxt/test-utils
```
```bash [npm]
npm i --save-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

@ -5,11 +5,11 @@ navigation.icon: i-ph-arrow-circle-up-duotone
---
## 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]
npx nuxi upgrade
@ -17,7 +17,451 @@ npx nuxi upgrade
### Nightly Release Channel
To use the latest Nuxt 3 build and test features before their release, read about the [nightly release channel](/docs/guide/going-further/nightly-release-channel) guide.
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.
## Testing Nuxt 4
Nuxt 4 is planned to be released **on or before June 14** (though obviously this is dependent on having enough time after Nitro's major release to be properly tested in the community, so be aware that this is not an exact date).
Until then, it is possible to test many of Nuxt 4's breaking changes from Nuxt version 3.12 or via the nightly release channel.
::tip{icon="i-ph-video-duotone" 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, opt in to the nightly release channel [following these steps](/docs/guide/going-further/nightly-release-channel#opting-in).
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,
// 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`.
::
#### 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`
* `modules` and `public` are resolved relative to `<rootDir>` by default
* 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
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`, `modules/`, `public/` and `server/` folders remain outside the `app/` folder, in the root of your project.
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'
}
})
```
#### 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 encounter any issues you can revert back to the previous behavior with:
```ts twoslash [nuxt.config.ts]
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]
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' })
}
```
#### 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]
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
}
}
}
})
```
#### 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))
// ...
})
```
#### 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
```
#### Removal of Experimental Features
🚦 **Impact Level**: Minimal
##### What Changed
Four experimental features are no longer configurable in Nuxt 4:
* `treeshakeClientOnly` will be `true` (default since v3.0)
* `configSchema` will be `true` (default since v3.3)
* `polyfillVueUseHead` will be `false` (default since v3.4)
* `respectNoSSRHeader` will be `false` (default since v3.4)
##### 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
@ -26,7 +470,7 @@ In the table below, there is a quick comparison between 3 versions of Nuxt:
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 | ✅

View File

@ -6,14 +6,14 @@ navigation.icon: i-ph-play-duotone
## 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,7 +22,7 @@ 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
::note
@ -30,17 +30,6 @@ Start with one of our starters and themes directly by opening [nuxt.new](https:/
: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
}
})
```
::
::
@ -62,6 +51,10 @@ bunx 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,33 +67,6 @@ 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
```
::
::note
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:

View File

@ -46,6 +46,10 @@ export default defineNuxtConfig({
})
```
::tip{icon="i-ph-video-duotone" 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 +139,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 +153,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

@ -96,6 +96,16 @@ If you only have a single layout in your application, we recommend using [`app.v
::code-group
```vue [app.vue]
<template>
<div>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</div>
</template>
```
```vue [layouts/default.vue]
<template>
<div>

View File

@ -113,7 +113,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 +154,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
```
::
@ -243,7 +244,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.
@ -421,7 +422,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 +431,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 +459,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

View File

@ -6,7 +6,7 @@ navigation.icon: i-ph-file-search-duotone
## 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({
@ -174,7 +174,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

@ -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
@ -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-duotone" 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">
@ -76,7 +80,7 @@ async function addTodo() {
```
::warning
Beware that using only `$fetch` will not provide [network calls de-duplication and navigation prevention](#why-using-specific-composables). :br
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.
::
@ -93,6 +97,10 @@ The `useAsyncData` composable is responsible for wrapping async logic and return
It's developer experience sugar for the most common use case.
::
::tip{icon="i-ph-video-duotone" 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]
@ -122,7 +130,7 @@ 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">
@ -150,6 +158,7 @@ Read more about `useAsyncData`.
- `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 `pending` to `false`, 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"`).
@ -283,7 +292,7 @@ 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>
```
@ -294,6 +303,21 @@ The `execute` function is an alias for `refresh` that works in exactly the same
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.
@ -599,3 +623,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

@ -8,6 +8,10 @@ Nuxt provides the [`useState`](/docs/api/composables/use-state) composable to cr
[`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.
::tip{icon="i-ph-video-duotone" 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.
::
@ -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-duotone" 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

@ -7,15 +7,15 @@ navigation.icon: i-ph-bug-beetle-duotone
Nuxt 3 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
::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).
@ -51,7 +51,7 @@ 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.
@ -125,6 +125,10 @@ When you are ready to remove the error page, you can call the [`clearError`](/do
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.
::
::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.
::

View File

@ -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-duotone" 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

@ -14,12 +14,13 @@ 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.
```ts twoslash [nuxt.config.ts]
```ts [nuxt.config.ts]
export default defineNuxtConfig({
extends: [
'../base', // Extend from a local layer
@ -29,12 +30,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**.
::
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=lnFCM7c9f7I" target="_blank"}
Watch Learn Vue video about Nuxt Layers.
Watch a video from Learn Vue about Nuxt Layers.
::
::tip{icon="i-ph-video-duotone" 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,177 @@
---
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-duotone
---
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.
```bash [Terminal]
npx 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-duotone"}
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

@ -16,4 +16,7 @@ surround: false
::card{icon="i-ph-star-duotone" title="Going Further" to="/docs/guide/going-further"}
Master Nuxt with advanced concepts like experimental features, hooks, modules, and more.
::
::card{icon="i-ph-book-open-duotone" title="Recipes" to="/docs/guide/recipes"}
Find solutions to common problems and learn how to implement them in your Nuxt project.
::
::

View File

@ -60,6 +60,10 @@ 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.
::tip{icon="i-ph-video-duotone" 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.
::
::read-more{to="/docs/guide/going-further/experimental-features#asynccontext" icon="i-ph-star-duotone"}
Checkout the `asyncContext` experimental feature to use Nuxt composables in async functions.
::
@ -84,7 +88,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()
// ...
@ -168,3 +172,7 @@ export default defineNuxtConfig({
}
})
```
::tip{icon="i-ph-video-duotone" 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,6 +1,6 @@
---
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.

View File

@ -69,6 +69,36 @@ If you do use `ssr: false`, you should also place an HTML file in `~/app/spa-loa
: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.
@ -109,10 +139,11 @@ The different properties you can use are the following:
- `ssr: boolean`{lang=ts} - Disables server-side rendering for sections of your app and make them SPA-only 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).

View File

@ -9,22 +9,26 @@ 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:
::alert{type="warning"}
You may experience issues with the latest `vue-tsc` and `vite-plugin-checker`, used internally when type checking. For now, you may need to stay on v1 of `vue-tsc`, and follow these upstream issues for updates: [fi3ework/vite-plugin-checker#306](https://github.com/fi3ework/vite-plugin-checker/issues/306) and [vuejs/language-tools#3969](https://github.com/vuejs/language-tools/issues/3969).
::
::code-group
```bash [yarn]
yarn add --dev vue-tsc typescript
yarn add --dev vue-tsc@^1 typescript
```
```bash [npm]
npm install --save-dev vue-tsc typescript
npm install --save-dev vue-tsc@^1 typescript
```
```bash [pnpm]
pnpm add -D vue-tsc typescript
pnpm add -D vue-tsc@^1 typescript
```
```bash [bun]
bun add -D vue-tsc typescript
bun add -D vue-tsc@^1 typescript
```
::
@ -61,6 +65,10 @@ This file contains the recommended basic TypeScript configuration for your proje
[Read more about how to extend this configuration](/docs/guide/directory-structure/tsconfig).
::tip{icon="i-ph-video-duotone" 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.
::
@ -72,18 +80,18 @@ Overwriting options such as `"compilerOptions.paths"` with your own configuratio
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 3 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-duotone"}
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

@ -244,6 +244,10 @@ This feature only works with Nuxt auto-imports and `#components` imports. Explic
`.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.
@ -255,7 +259,7 @@ Watch Learn Vue video about Nuxt Server Components.
::
::tip{icon="i-ph-article-duotone" to="https://roe.dev/blog/nuxt-server-components" target="_blank"}
Read Daniel Roe's guide to Nuxt server components
Read Daniel Roe's guide to Nuxt Server Components.
::
### Standalone server components
@ -295,6 +299,10 @@ 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}
Most features for server-only components and island components, such as slots and client components, are only available for single file components.
::
@ -318,7 +326,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
@ -357,89 +365,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 -->
<!--
::note
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

View File

@ -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

@ -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-duotone" to="https://vueschool.io/lessons/creating-your-first-module-from-scratch" target="_blank"}
Watch Vue School video about Nuxt private modules.
::

View File

@ -6,7 +6,7 @@ navigation.icon: i-ph-folder-duotone
---
::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/directory-structure/pages#router-options).
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/going-further/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.
@ -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
@ -357,12 +365,16 @@ function navigate(){
</script>
```
## 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.
::note
You will also need to enable `experimental.componentIslands` in order to make this possible.
::alert{type=warning}
Server-only pages must have a single root element. (HTML comments are considered elements as well.)
::
## Custom Routing

View File

@ -76,9 +76,14 @@ export default defineNuxtPlugin({
})
```
::tip{icon="i-ph-video-duotone" 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 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.
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
@ -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({

View File

@ -33,11 +33,25 @@ 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
## 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.

View File

@ -99,7 +99,7 @@ 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.
::note
The Function Merger should only be used in the base `app.config` of your application.
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:

View File

@ -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

@ -306,6 +306,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-duotone" 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 +344,10 @@ export default defineNuxtConfig({
})
```
::tip{icon="i-ph-video-duotone" 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 +386,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.

View File

@ -37,6 +37,47 @@ 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: {
compileTemplate: true,
templateUtils: true,
relativeWatchPaths: true,
defaults: {
useAsyncData: {
deep: true
}
}
},
unhead: {
renderSSRHeadOptions: {
omitLineBreaks: false
}
}
})
```
### typescriptBundlerResolution
This enables 'Bundler' module resolution mode for TypeScript, which is the recommended setting

View File

@ -61,6 +61,10 @@ Setting the default of `runtimeConfig` values to *differently named environment
It is advised to use environment variables that match the structure of your `runtimeConfig` object.
::
::tip{icon="i-ph-video-duotone" to="https://youtu.be/_FYV5WfiWvs" target="_blank"}
Watch a video from Alexander Lichter showcasing the top mistake developers make using runtimeConfig.
::
#### Example
```sh [.env]
@ -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>
@ -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

@ -30,6 +30,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-duotone" to="https://vueschool.io/lessons/navigating-the-official-starter-template" 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.
@ -72,7 +76,7 @@ Before publishing your module to npm, makes sure you have an [npmjs.com](https:/
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:
@ -255,6 +259,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-duotone" to="https://vueschool.io/lessons/extending-and-altering-nuxt-configuration-and-options" 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).
@ -288,6 +296,10 @@ Be careful not to expose any sensitive module configuration on the public runtim
:read-more{to="/docs/guide/going-further/runtime-config"}
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/passing-and-exposing-module-options" 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,6 +523,10 @@ export default defineNuxtModule({
:read-more{to="/docs/api/advanced/hooks"}
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/nuxt-lifecycle-hooks" target="_blank"}
Watch Vue School video about using Nuxt lifecycle hooks in modules.
::
::note
**Module cleanup**
:br
@ -733,6 +749,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-duotone" to="https://vueschool.io/lessons/exploring-nuxt-modules-ecosystem-and-module-types" 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": {

View File

@ -100,6 +100,10 @@ export default defineNuxtConfig({
If you want to extend a private remote source, you need to add the environment variable `GIGET_AUTH=<token>` to provide a token.
::
::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.

View File

@ -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

@ -105,7 +105,7 @@ export default defineNuxtConfig({
const resolver = createResolver(import.meta.url)
// add a route
files.push({
path: resolver.resolve('./runtime/app/router-options')
path: resolver.resolve('./runtime/app/router-options'),
optional: true
})
}
@ -172,6 +172,6 @@ import { createMemoryHistory } from 'vue-router'
export default <RouterConfig> {
// https://router.vuejs.org/api/interfaces/routeroptions.html
history: base => process.client ? createMemoryHistory(base) : null /* default */
history: base => import.meta.client ? createMemoryHistory(base) : null /* default */
}
```

View File

@ -0,0 +1,65 @@
---
navigation.title: 'Vite Plugins'
title: Using Vite Plugins in Nuxt
description: Learn how to integrate Vite plugins into your Nuxt project.
---
While Nuxt modules offer extensive functionality, sometimes a specific Vite plugin might meet your needs more directly.
First, we need to install the Vite plugin, for our example, we'll use `@rollup/plugin-yaml`:
::code-group
```bash [npm]
npm install @rollup/plugin-yaml
```
```bash [yarn]
yarn add @rollup/plugin-yaml
```
```bash [pnpm]
pnpm add @rollup/plugin-yaml
```
```bash [bun]
bun add @rollup/plugin-yaml
```
::
Next, we need to import and add it to our [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file:
```ts [nuxt.config.ts]
import yaml from '@rollup/plugin-yaml'
export default defineNuxtConfig({
vite: {
plugins: [
yaml()
]
}
})
```
Now we installed and configured our Vite plugin, we can start using YAML files directly in our project.
For example, we can have a `config.yaml` that stores configuration data and import this data in our Nuxt components:
::code-group
```yaml [data/hello.yaml]
greeting: "Hello, Nuxt with Vite!"
```
```vue [components/Hello.vue]
<script setup>
import config from '~/data/hello.yaml'
</script>
<template>
<h1>{{ config.greeting }}</h1>
</template>
```
::

View File

@ -0,0 +1,105 @@
---
navigation.title: 'Custom useFetch'
title: Custom useFetch in Nuxt
description: How to create a custom fetcher for calling your external API in Nuxt 3.
---
When working with Nuxt, you might be making the frontend and fetching an external API, and you might want to set some default options for fetching from your API.
The [`$fetch`](/docs/api/utils/dollarfetch) utility function (used by the [`useFetch`](/docs/api/composables/use-fetch) composable) is intentionally not globally configurable. This is important so that fetching behavior throughout your application remains consistent, and other integrations (like modules) can rely on the behavior of core utilities like `$fetch`.
However, Nuxt provides a way to create a custom fetcher for your API (or multiple fetchers if you have multiple APIs to call).
## Custom `$fetch`
Let's create a custom `$fetch` instance with a [Nuxt plugin](/docs/guide/directory-structure/plugins).
::note
`$fetch` is a configured instance of [ofetch](https://github.com/unjs/ofetch) which supports adding the base URL of your Nuxt server as well as direct function calls during SSR (avoiding HTTP roundtrips).
::
Let's pretend here that:
- The main API is https://api.nuxt.com
- We are storing the JWT token in a session with [nuxt-auth-utils](https://github.com/atinux/nuxt-auth-utils)
- If the API responds with a `401` status code, we redirect the user to the `/login` page
```ts [plugins/api.ts]
export default defineNuxtPlugin(() => {
const { session } = useUserSession()
const api = $fetch.create({
baseURL: 'https://api.nuxt.com',
onRequest({ request, options, error }) {
if (session.value?.token) {
const headers = options.headers ||= {}
if (Array.isArray(headers)) {
headers.push(['Authorization', `Bearer ${session.value?.token}`])
} else if (headers instanceof Headers) {
headers.set('Authorization', `Bearer ${session.value?.token}`)
} else {
headers.Authorization = `Bearer ${session.value?.token}`
}
}
},
async onResponseError({ response }) {
if (response.status === 401) {
await navigateTo('/login')
}
}
})
// Expose to useNuxtApp().$api
return {
provide: {
api
}
}
})
```
With this Nuxt plugin, `$api` is exposed from `useNuxtApp()` to make API calls directly from the Vue components:
```vue [app.vue]
<script setup>
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
</script>
```
::callout
Wrapping with [`useAsyncData`](/docs/api/composables/use-async-data) **avoid double data fetching when doing server-side rendering** (server & client on hydration).
::
## Custom `useFetch`
Now that `$api` has the logic we want, let's create a `useAPI` composable to replace the usage of `useAsyncData` + `$api`:
```ts [composables/useAPI.ts]
import type { UseFetchOptions } from 'nuxt/app'
export function useAPI<T>(
url: string | (() => string),
options: Omit<UseFetchOptions<T>, 'default'> & { default: () => T | Ref<T> },
) {
return useFetch(url, {
...options,
$fetch: useNuxtApp().$api
})
}
```
Let's use the new composable and have a nice and clean component:
```vue [app.vue]
<script setup>
const { data: modules } = await useAPI('/modules')
</script>
```
::callout{icon="i-simple-icons-youtube" color="red" to="https://www.youtube.com/watch?v=jXH8Tr-exhI"}
Watch a video about custom `$fetch` and Repository Pattern in Nuxt.
::
::note
We are currently discussing to find a cleaner way to let you create a custom fetcher, see https://github.com/nuxt/nuxt/issues/14736.
::

View File

@ -0,0 +1,3 @@
title: Recipes
titleTemplate: '%s · Recipes'
icon: i-ph-cooking-pot-duotone

View File

@ -8,7 +8,11 @@ links:
size: xs
---
The `<ClientOnly>` component renders its slot only in client-side. To import a component only on the client, register the component in a client-side only plugin.
The `<ClientOnly>` component is used for purposely rendering a component only on client side.
::note
The content of the default slot will be tree-shaken out of the server build. (This does mean that any CSS used by components within it may not be inlined when rendering the initial HTML.)
::
## Props
@ -19,6 +23,7 @@ The `<ClientOnly>` component renders its slot only in client-side. To import a c
<template>
<div>
<Sidebar />
<!-- The <Comment> component will only be rendered on client-side -->
<ClientOnly fallback-tag="span" fallback="Loading comments...">
<Comment />
</ClientOnly>
@ -28,14 +33,16 @@ The `<ClientOnly>` component renders its slot only in client-side. To import a c
## Slots
- `#fallback`: specify a content to be displayed server-side.
- `#fallback`: specify a content to be rendered on the server and displayed until `<ClientOnly>` is mounted in the browser.
```vue
```vue [pages/example.vue]
<template>
<div>
<Sidebar />
<ClientOnly>
<!-- ... -->
<!-- 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>

View File

@ -0,0 +1,51 @@
---
title: '<DevOnly>'
description: Render components only during development with the <DevOnly> component.
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/components/dev-only.ts
size: xs
---
Nuxt provides the `<DevOnly>` component to render a component only during development.
The content will not be included in production builds.
```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>
```
## Slots
- `#fallback`: if you ever require to have a replacement during production.
```vue
<template>
<div>
<Sidebar />
<DevOnly>
<!-- this component will only be rendered during development -->
<LazyDebugBar />
<!-- be sure to test these using `nuxt preview` -->
<template #fallback>
<div><!-- empty div for flex.justify-between --></div>
</template>
</DevOnly>
</div>
</template>
```

View File

@ -12,10 +12,25 @@ links:
size: xs
---
Nuxt provides the `<NuxtClientFallback>` component to render its content on the client if any of its children trigger an error in SSR.
::note{to="/docs/guide/going-further/experimental-features#clientfallback"}
This component is experimental and in order to use it you must enable the `experimental.clientFallback` option in your `nuxt.config`.
::
```vue [pages/example.vue]
<template>
<div>
<Sidebar />
<!-- this component will be rendered on client-side -->
<NuxtClientFallback fallback-tag="span">
<Comments />
<BrokeInSSR />
</NuxtClientFallback>
</div>
</template>
```
## Events
- `@ssr-error`: Event emitted when a child triggers an error in SSR. Note that this will only be triggered on the server.
@ -30,7 +45,7 @@ This component is experimental and in order to use it you must enable the `exper
## Props
- `placeholderTag` | `fallbackTag`: Specify a fallback tag to be rendered if the slot fails to render.
- `placeholderTag` | `fallbackTag`: Specify a fallback tag to be rendered if the slot fails to render on the server.
- **type**: `string`
- **default**: `div`
- `placeholder` | `fallback`: Specify fallback content to be rendered if the slot fails to render.

View File

@ -0,0 +1,56 @@
---
title: '<NuxtRouteAnnouncer>'
description: 'Add a hidden element with the page title for assistive technologies.'
navigation:
badge: New
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/components/nuxt-route-announcer.ts
size: xs
---
::important
This component is available in Nuxt v3.12+.
::
## Usage
Add `<NuxtRouteAnnouncer/>` in your [`app.vue`](/docs/guide/directory-structure/app) or [`layouts/`](/docs/guide/directory-structure/layouts) to enhance accessibility by informing assistive technologies about page's title changes. This ensures that navigational changes are announced to users relying on screen readers.
```vue [app.vue]
<template>
<NuxtRouteAnnouncer />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
```
## Slots
You can pass custom HTML or components through the route announcer default slot.
```vue
<template>
<NuxtRouteAnnouncer>
<template #default="{ message }">
<p>{{ message }} was loaded.</p>
</template>
</NuxtRouteAnnouncer>
</template>
```
## Props
- `atomic`: Controls if screen readers announce only changes or the entire content. Set to true for full content readout on updates, false for changes only. (default `false`)
- `politeness`: Sets the urgency for screen reader announcements: `off` (disable the announcement), `polite` (waits for silence), or `assertive` (interrupts immediately). (default `polite`)
::callout
This component is optional. :br
To achieve full customization, you can implement your own one based on [its source code](https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/components/nuxt-route-announcer.ts).
::
::callout
You can hook into the underlying announcer instance using [the `useRouteAnnouncer` composable](/docs/api/composables/use-route-announcer), which allows you to set a custom announcement message.
::

View File

@ -86,6 +86,18 @@ function logFoo () {
</template>
````
````vue [my-page.vue]
<script setup lang="ts">
const foo = () => {
console.log('foo method called')
}
defineExpose({
foo,
})
</script>
````
## Custom Props
In addition, `<NuxtPage>` also accepts custom props that you may need to pass further down the hierarchy.

View File

@ -55,6 +55,10 @@ Please note the layout name is normalized to kebab-case, so if your layout file
Read more about dynamic layouts.
::
- `fallback`: If an invalid layout is passed to the `name` prop, no layout will be rendered. Specify a `fallback` layout to be rendered in this scenario. It **must** match the name of the corresponding layout file in the [`layouts/`](/docs/guide/directory-structure/layouts) directory.
- **type**: `string`
- **default**: `null`
## Additional Props
`NuxtLayout` also accepts any additional props that you may need to pass to the layout. These custom props are then made accessible as attributes.
@ -83,6 +87,8 @@ console.log(layoutCustomProps.title) // I am a custom layout
`<NuxtLayout />` renders incoming content via `<slot />`, which is then wrapped around Vues `<Transition />` component to activate layout transition. For this to work as expected, it is recommended that `<NuxtLayout />` is **not** the root element of the page component.
::code-group
```vue [pages/index.vue]
<template>
<div>
@ -93,13 +99,27 @@ console.log(layoutCustomProps.title) // I am a custom layout
</template>
```
```vue [layouts/custom.vue]
<template>
<div>
<!-- named slot -->
<slot name="header" />
<slot />
</div>
</template>
```
::
:read-more{to="/docs/getting-started/transitions"}
## Layout's Ref
To get the ref of a layout component, access it through `ref.value.layoutRef`.
````vue [app.vue]
::code-group
```vue [app.vue]
<script setup lang="ts">
const layout = ref()
@ -109,8 +129,28 @@ function logFoo () {
</script>
<template>
<NuxtLayout ref="layout" />
<NuxtLayout ref="layout">
default layout
</NuxtLayout>
</template>
````
```
```vue [layouts/default.vue]
<script setup lang="ts">
const foo = () => console.log('foo')
defineExpose({
foo
})
</script>
<template>
<div>
default layout
<slot />
</div>
</template>
```
::
:read-more{to="/docs/guide/directory-structure/layouts"}

View File

@ -25,6 +25,22 @@ In this example, we use `<NuxtLink>` component to link to another page of the ap
</template>
```
### Passing Params to Dynamic Routes
In this example, we pass the `id` param to link to the route `~/pages/posts/[id].vue`.
```vue [pages/index.vue]
<template>
<NuxtLink :to="{ name: 'posts-id', params: { id: 123 } }">
Post 123
</NuxtLink>
</template>
```
::tip
Check out the Pages panel in Nuxt DevTools to see the route name and the params it might take.
::
### Handling 404s
When using `<NuxtLink>` for `/public` directory files or when pointing to a different app on the same domain, you should use the `external` prop.

View File

@ -30,6 +30,7 @@ You can pass custom HTML or components through the loading indicator's default s
## Props
- `color`: The color of the loading bar. It can be set to `false` to turn off explicit color styling.
- `errorColor`: The color of the loading bar when `error` is set to `true`.
- `height`: Height of the loading bar, in pixels (default `3`).
- `duration`: Duration of the loading bar, in milliseconds (default `2000`).
- `throttle`: Throttle the appearing and hiding, in milliseconds (default `200`).

View File

@ -12,10 +12,6 @@ When rendering an island component, the content of the island component is stati
Changing the island component props triggers a refetch of the island component to re-render it again.
::read-more{to="/docs/guide/going-further/experimental-features#componentislands" icon="i-ph-star-duotone"}
This component is experimental and in order to use it you must enable the `experimental.componentIslands` option in your `nuxt.config`.
::
::note
Global styles of your application are sent with the response.
::
@ -63,3 +59,11 @@ Some slots are reserved to `NuxtIsland` for special cases.
- `refresh()`
- **type**: `() => Promise<void>`
- **description**: force refetch the server component by refetching it.
## Events
- `error`
- **parameters**:
- **error**:
- **type**: `unknown`
- **description**: emitted when when `NuxtIsland` fails to fetch the new island.

View File

@ -0,0 +1,61 @@
---
title: "onPrehydrate"
description: "Use onPrehydrate to run a callback on the client immediately before
Nuxt hydrates the page."
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/ssr.ts
size: xs
---
::important
This composable is available in Nuxt v3.12+.
::
`onPrehydrate` is a composable lifecycle hook that allows you to run a callback on the client immediately before
Nuxt hydrates the page.
::note
This is an advanced utility and should be used with care. For example, [`nuxt-time`](https://github.com/danielroe/nuxt-time/pull/251) and [`@nuxtjs/color-mode`](https://github.com/nuxt-modules/color-mode/blob/main/src/script.js) manipulate the DOM to avoid hydration mismatches.
::
## Usage
`onPrehydrate` can be called directly in the setup function of a Vue component (for example, in `<script setup>`), or in a plugin.
It will only have an effect when it is called on the server, and it will not be included in your client build.
## Parameters
- `callback`: A function that will be stringified and inlined in the HTML. It should not have any external
dependencies (such as auto-imports) or refer to variables defined outside the callback. The callback will run
before Nuxt runtime initializes so it should not rely on the Nuxt or Vue context.
## Example
```vue twoslash [app.vue]
<script setup lang="ts">
declare const window: Window
// ---cut---
// onPrehydrate is guaranteed to run before Nuxt hydrates
onPrehydrate(() => {
console.log(window)
})
// As long as it only has one root node, you can access the element
onPrehydrate((el) => {
console.log(el.outerHTML)
// <div data-v-inspector="app.vue:15:3" data-prehydrate-id=":b3qlvSiBeH:"> Hi there </div>
})
// For _very_ advanced use cases (such as not having a single root node) you
// can access/set `data-prehydrate-id` yourself
const prehydrateId = onPrehydrate((el) => {})
</script>
<template>
<div>
Hi there
</div>
</template>
```

View File

@ -1,6 +1,6 @@
---
title: 'useAsyncData'
description: useAsyncData provides access to data that resolves asynchronously in a SSR-friendly composable.
description: useAsyncData provides access to data that resolves asynchronously in an SSR-friendly composable.
links:
- label: Source
icon: i-simple-icons-github
@ -119,10 +119,10 @@ type AsyncDataOptions<DataT> = {
deep?: boolean
dedupe?: 'cancel' | 'defer'
default?: () => DataT | Ref<DataT> | null
transform?: (input: DataT) => DataT
transform?: (input: DataT) => DataT | Promise<DataT>
pick?: string[]
watch?: WatchSource[]
getCachedData?: (key: string) => DataT
getCachedData?: (key: string, nuxtApp: NuxtApp) => DataT
}
type AsyncData<DataT, ErrorT> = {
@ -130,6 +130,7 @@ type AsyncData<DataT, ErrorT> = {
pending: Ref<boolean>
refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
clear: () => void
error: Ref<ErrorT | null>
status: Ref<AsyncDataRequestStatus>
};

View File

@ -59,13 +59,10 @@ Use these options to set the expiration of the cookie.
The given number will be converted to an integer by rounding down. By default, no maximum age is set.
`expires`: Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1).
By default, no expiration is set. Most clients will consider this a "non-persistent cookie" and
will delete it on a condition like exiting a web browser application.
By default, no expiration is set. Most clients will consider this a "non-persistent cookie" and will delete it on a condition like exiting a web browser application.
::note
The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
`maxAge` is set, then `maxAge` takes precedence, but not all clients may obey this,
so if both are set, they should point to the same date and time!
The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and `maxAge` is set, then `maxAge` takes precedence, but not all clients may obey this, so if both are set, they should point to the same date and time!
::
::note
@ -74,22 +71,29 @@ If neither of `expires` and `maxAge` is set, the cookie will be session-only and
### `httpOnly`
Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6). When truthy,
the `HttpOnly` attribute is set; otherwise it is not. By default, the `HttpOnly` attribute is not set.
Specifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6). When truthy, the `HttpOnly` attribute is set; otherwise it is not. By default, the `HttpOnly` attribute is not set.
::warning
Be careful when setting this to `true`, as compliant clients will not allow client-side
JavaScript to see the cookie in `document.cookie`.
Be careful when setting this to `true`, as compliant clients will not allow client-side JavaScript to see the cookie in `document.cookie`.
::
### `secure`
Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5). When truthy,
the `Secure` attribute is set; otherwise it is not. By default, the `Secure` attribute is not set.
Specifies the `boolean` value for the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5). When truthy, the `Secure` attribute is set; otherwise it is not. By default, the `Secure` attribute is not set.
::warning
Be careful when setting this to `true`, as compliant clients will not send the cookie back to
the server in the future if the browser does not have an HTTPS connection. This can lead to hydration errors.
Be careful when setting this to `true`, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection. This can lead to hydration errors.
::
### `partitioned`
Specifies the `boolean` value for the [`Partitioned` `Set-Cookie`](https://datatracker.ietf.org/doc/html/draft-cutler-httpbis-partitioned-cookies#section-2.1) attribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the `Partitioned` attribute is not set.
::note
This is an attribute that has not yet been fully standardized, and may change in the future.
This also means many clients may ignore this attribute until they understand it.
More information can be found in the [proposal](https://github.com/privacycg/CHIPS).
::
### `domain`
@ -114,23 +118,18 @@ More information about the different enforcement levels can be found in [the spe
### `encode`
Specifies a function that will be used to encode a cookie's value. Since the value of a cookie
has a limited character set (and must be a simple string), this function can be used to encode
a value into a string suited for a cookie's value.
Specifies a function that will be used to encode a cookie's value. Since the value of a cookie has a limited character set (and must be a simple string), this function can be used to encode a value into a string suited for a cookie's value.
The default encoder is the `JSON.stringify` + `encodeURIComponent`.
### `decode`
Specifies a function that will be used to decode a cookie's value. Since the value of a cookie
has a limited character set (and must be a simple string), this function can be used to decode
a previously encoded cookie value into a JavaScript string or other object.
Specifies a function that will be used to decode a cookie's value. Since the value of a cookie has a limited character set (and must be a simple string), this function can be used to decode a previously encoded cookie value into a JavaScript string or other object.
The default decoder is `decodeURIComponent` + [destr](https://github.com/unjs/destr).
::note
If an error is thrown from this function, the original, non-decoded cookie value will
be returned as the cookie's value.
If an error is thrown from this function, the original, non-decoded cookie value will be returned as the cookie's value.
::
### `default`

View File

@ -1,6 +1,6 @@
---
title: 'useFetch'
description: 'Fetch data from an API endpoint with a SSR-friendly composable.'
description: 'Fetch data from an API endpoint with an SSR-friendly composable.'
links:
- label: Source
icon: i-simple-icons-github
@ -66,6 +66,10 @@ const { data, pending, error, refresh } = await useFetch('/api/auth/login', {
`useFetch` is a reserved function name transformed by the compiler, so you should not name your own function `useFetch`.
::
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=njsGVmcWviY" target="_blank"}
Watch the video from Alexander Lichter to avoid using `useFetch` the wrong way!
::
:link-example{to="/docs/examples/advanced/use-custom-fetch-composable"}
:read-more{to="/docs/getting-started/data-fetching"}
@ -83,6 +87,8 @@ const { data, pending, error, refresh } = await useFetch('/api/auth/login', {
- `headers`: Request headers.
- `baseURL`: Base URL for the request.
- `timeout`: Milliseconds to automatically abort request
- `cache`: Handles cache control according to [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/fetch#cache)
- You can pass boolean to disable the cache or you can pass one of the following values: `default`, `no-store`, `reload`, `no-cache`, `force-cache`, and `only-if-cached`.
::note
All fetch options can be given a `computed` or `ref` value. These will be watched and new requests made automatically with any new values if they are updated.
@ -97,7 +103,7 @@ All fetch options can be given a `computed` or `ref` value. These will be watche
- `transform`: a function that can be used to alter `handler` function result after resolving
- `getCachedData`: Provide a function which returns cached data. A _null_ or _undefined_ return value will trigger a fetch. By default, this is: `key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key]`, which only caches data when `payloadExtraction` is enabled.
- `pick`: only pick specified keys in this array from the `handler` function result
- `watch`: watch an array of reactive sources and auto-refresh the fetch result when they change. Fetch options and URL are watched by default. You can completely ignore reactive sources by using `watch: false`. Together with `immediate: false`, this allows for a fully-manual `useFetch`.
- `watch`: watch an array of reactive sources and auto-refresh the fetch result when they change. Fetch options and URL are watched by default. You can completely ignore reactive sources by using `watch: false`. Together with `immediate: false`, this allows for a fully-manual `useFetch`. (You can [see an example here](/docs/getting-started/data-fetching#watch) of using `watch`.)
- `deep`: return data in a deep ref object (it is `true` by default). It can be set to `false` to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive.
- `dedupe`: avoid fetching same key more than once at a time (defaults to `cancel`). Possible options:
- `cancel` - cancels existing requests when a new one is made
@ -107,6 +113,10 @@ All fetch options can be given a `computed` or `ref` value. These will be watche
If you provide a function or ref as the `url` parameter, or if you provide functions as arguments to the `options` parameter, then the `useFetch` call will not match other `useFetch` calls elsewhere in your codebase, even if the options seem to be identical. If you wish to force a match, you may provide your own key in `options`.
::
::note
If you use `useFetch` to call an (external) HTTPS URL with a self-signed certificate in development, you will need to set `NODE_TLS_REJECT_UNAUTHORIZED=0` in your environment.
::
::tip{icon="i-simple-icons-youtube" color="gray" to="https://www.youtube.com/watch?v=aQPR0xn-MMk" target="_blank"}
Learn how to use `transform` and `getCachedData` to avoid superfluous calls to an API and cache data for visitors on the client.
::
@ -144,11 +154,11 @@ type UseFetchOptions<DataT> = {
server?: boolean
lazy?: boolean
immediate?: boolean
getCachedData?: (key: string) => DataT
getCachedData?: (key: string, nuxtApp: NuxtApp) => DataT
deep?: boolean
dedupe?: 'cancel' | 'defer'
default?: () => DataT
transform?: (input: DataT) => DataT
transform?: (input: DataT) => DataT | Promise<DataT>
pick?: string[]
watch?: WatchSource[] | false
}
@ -158,6 +168,7 @@ type AsyncData<DataT, ErrorT> = {
pending: Ref<boolean>
refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
clear: () => void
error: Ref<ErrorT | null>
status: Ref<AsyncDataRequestStatus>
}

View File

@ -1,6 +1,11 @@
---
title: "useId"
description: Generate an SSR-friendly unique identifier that can be passed to accessibility attributes.
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/id.ts
size: xs
---
::important
@ -19,11 +24,15 @@ const id = useId()
<template>
<div>
<label :for="id">Email</label>
<input :id="id" name="email" type="email"/>
<input :id="id" name="email" type="email" />
</div>
</template>
```
::note
`useId` must be used in a component with a single root element, as it uses this root element's attributes to pass the id from server to client.
::
## Parameters
`useId` does not take any parameters.

View File

@ -44,4 +44,4 @@ watch(count, (newCount) => {
`useLazyAsyncData` is a reserved function name transformed by the compiler, so you should not name your own function `useLazyAsyncData`.
::
:read-more{to="/docs/getting-started/data-fetching#uselazyasyncdata"}
:read-more{to="/docs/getting-started/data-fetching"}

View File

@ -26,6 +26,11 @@ It hooks into [`page:loading:start`](/docs/api/advanced/hooks#app-hooks-runtime)
- **type**: `Ref<boolean>`
- **description**: The loading state
### `error`
- **type**: `Ref<boolean>`
- **description**: The error state
### `progress`
- **type**: `Ref<number>`
@ -39,7 +44,7 @@ Set `isLoading` to true and start to increase the `progress` value.
### `finish()`
Set the `progress` value to `100`, stop all timers and intervals then reset the loading state `500` ms later.
Set the `progress` value to `100`, stop all timers and intervals then reset the loading state `500` ms later. `finish` accepts a `{ force: true }` option to skip the interval before the state is reset, and `{ error: true }` to change the loading bar color and set the error property to true.
### `clear()`

View File

@ -18,6 +18,14 @@ const nuxtApp = useNuxtApp()
If runtime context is unavailable in your scope, `useNuxtApp` will throw an exception when called. You can use [`tryUseNuxtApp`](#tryusenuxtapp) instead for composables that do not require `nuxtApp`, or to simply check if context is available or not without an exception.
<!--
note
By default, the shared runtime context of Nuxt is namespaced under the [`buildId`](/docs/api/nuxt-config#buildid) option. It allows the support of multiple runtime contexts.
## Params
- `appName`: an optional application name. If you do not provide it, the Nuxt `buildId` option is used. Otherwise, it must match with an existing `buildId`. -->
## Methods
### `provide (name, value)`
@ -51,7 +59,7 @@ export default defineNuxtPlugin((nuxtApp) => {
})
nuxtApp.hook('vue:error', (..._args) => {
console.log('vue:error')
// if (process.client) {
// if (import.meta.client) {
// console.log(..._args)
// }
})
@ -120,7 +128,7 @@ Nuxt exposes the following properties through `ssrContext`:
export const useColor = () => useState<string>('color', () => 'pink')
export default defineNuxtPlugin((nuxtApp) => {
if (process.server) {
if (import.meta.server) {
const color = useColor()
}
})
@ -128,9 +136,13 @@ Nuxt exposes the following properties through `ssrContext`:
It is also possible to use more advanced types, such as `ref`, `reactive`, `shallowRef`, `shallowReactive` and `NuxtError`.
Since [Nuxt v3.4](https://nuxt.com/blog/v3-4#payload-enhancements), it is possible to define your own serializer/deserializer for types that are not supported by Nuxt.
Since [Nuxt v3.4](https://nuxt.com/blog/v3-4#payload-enhancements), it is possible to define your own reducer/reviver for types that are not supported by Nuxt.
In the example below, we define a serializer for the [Luxon](https://moment.github.io/luxon/#/) DateTime class.
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=8w6ffRBs8a4" target="_blank"}
Watch a video from Alexander Lichter about serializing payloads, especially with regards to classes.
::
In the example below, we define a reducer (or a serializer) and a reviver (or deserializer) for the [Luxon](https://moment.github.io/luxon/#/) DateTime class, using a payload plugin.
```ts [plugins/date-time-payload.ts]
/**
@ -159,7 +171,7 @@ export default defineComponent({
setup (_props, { slots, emit }) {
const nuxtApp = useNuxtApp()
onErrorCaptured((err) => {
if (process.client && !nuxtApp.isHydrating) {
if (import.meta.client && !nuxtApp.isHydrating) {
// ...
}
})
@ -278,3 +290,7 @@ export function useStandType() {
}
}
```
<!-- ### Params
- `appName`: an optional application name. If you do not provide it, the Nuxt `buildId` option is used. Otherwise, it must match with an existing `buildId`. -->

View File

@ -0,0 +1,99 @@
---
title: "usePreviewMode"
description: "Use usePreviewMode to check and control preview mode in Nuxt"
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/preview.ts
size: xs
---
# `usePreviewMode`
Preview mode allows you to see how your changes would be displayed on a live site without revealing them to users.
You can use the built-in `usePreviewMode` composable to access and control preview state in Nuxt. If the composable detects preview mode it will automatically force any updates necessary for [`useAsyncData`](/docs/api/composables/use-async-data) and [`useFetch`](/docs/api/composables/use-fetch) to rerender preview content.
```js
const { enabled, state } = usePreviewMode()
```
## Options
### Custom `enable` check
You can specify a custom way to enable preview mode. By default the `usePreviewMode` composable will enable preview mode if there is a `preview` param in url that is equal to `true` (for example, `http://localhost:3000?preview=true`). You can wrap the `usePreviewMode` into custom composable, to keep options consistent across usages and prevent any errors.
```js
export function useMyPreviewMode () {
return usePreviewMode({
shouldEnable: () => {
return !!route.query.customPreview
}
});
}
```
### Modify default state
`usePreviewMode` will try to store the value of a `token` param from url in state. You can modify this state and it will be available for all [`usePreviewMode`](/docs/api/composables/use-preview-mode) calls.
```js
const data1 = ref('data1')
const { enabled, state } = usePreviewMode({
getState: (currentState) => {
return { data1, data2: 'data2' }
}
})
```
::note
The `getState` function will append returned values to current state, so be careful not to accidentally overwrite important state.
::
## Example
The example below creates a page where part of a content is rendered only in preview mode.
```vue [pages/some-page.vue]
<script setup>
const { enabled, state } = usePreviewMode()
const { data } = await useFetch('/api/preview', {
query: {
apiKey: state.token
}
})
</script>
<template>
<div>
Some base content
<p v-if="enabled">
Only preview content: {{ state.token }}
<br>
<button @click="enabled = false">
disable preview mode
</button>
</p>
</div>
</template>
```
Now you can generate your site and serve it:
```bash [Terminal]
npx nuxi generate
npx nuxi preview
```
Then you can see your preview page by adding the query param `preview` to the end of the page you want to see once:
```js
?preview=true
```
::note
`usePreviewMode` should be tested locally with `nuxi generate` and then `nuxi preview` rather than `nuxi dev`. (The [preview command](/docs/api/commands/preview) is not related to preview mode.)
::

View File

@ -10,6 +10,12 @@ links:
`useRequestURL` is a helper function that returns an [URL object](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) working on both server-side and client-side.
::important
When utilizing [Hybrid Rendering](/docs/guide/concepts/rendering#hybrid-rendering) with cache strategies, all incoming request headers are dropped when handling the cached responses via the [Nitro caching layer](https://nitro.unjs.io/guide/cache) (meaning `useRequestURL` will return `localhost` for the `host`).
You can define the [`cache.varies` option](https://nitro.unjs.io/guide/cache#options) to specify headers that will be considered when caching and serving the responses, such as `host` and `x-forwarded-host` for multi-tenant environments.
::
::code-group
```vue [pages/about.vue]

View File

@ -0,0 +1,60 @@
---
title: 'useRouteAnnouncer'
description: This composable observes the page title changes and updates the announcer message accordingly.
navigation:
badge: New
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/route-announcer.ts
size: xs
---
::important
This composable is available in Nuxt v3.12+.
::
## Description
A composable which observes the page title changes and updates the announcer message accordingly. Used by [`<NuxtRouteAnnouncer>`](/docs/api/components/nuxt-route-announcer) and controllable.
It hooks into Unhead's [`dom:rendered`](https://unhead.unjs.io/api/core/hooks#dom-hooks) to read the page's title and set it as the announcer message.
## Parameters
- `politeness`: Sets the urgency for screen reader announcements: `off` (disable the announcement), `polite` (waits for silence), or `assertive` (interrupts immediately). (default `polite`).
## Properties
### `message`
- **type**: `Ref<string>`
- **description**: The message to announce
### `politeness`
- **type**: `Ref<string>`
- **description**: Screen reader announcement urgency level `off`, `polite`, or `assertive`
## Methods
### `set(message, politeness = "polite")`
Sets the message to announce with its urgency level.
### `polite(message)`
Sets the message with `politeness = "polite"`
### `assertive(message)`
Sets the message with `politeness = "assertive"`
## Example
```ts
<script setup lang="ts">
const { message, politeness, set, polite, assertive } = useRouteAnnouncer({
politeness: 'assertive'
})
</script>
```

View File

@ -46,6 +46,6 @@ useSeoMeta({
## Parameters
There are over 100 parameters. See the [full list of parameters in the source code](https://github.com/harlan-zw/zhead/blob/main/src/metaFlat.ts).
There are over 100 parameters. See the [full list of parameters in the source code](https://github.com/harlan-zw/zhead/blob/main/packages/zhead/src/metaFlat.ts#L1035).
:read-more{to="/docs/getting-started/seo-meta"}

View File

@ -25,6 +25,10 @@ Because the data inside `useState` will be serialized to JSON, it is important t
`useState` is a reserved function name transformed by the compiler, so you should not name your own function `useState`.
::
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=mv0WcBABcIk" target="_blank"}
Watch a video from Alexander Lichter about why and when to use `useState()`.
::
## Using `shallowRef`
If you don't need your state to be deeply reactive, you can combine `useState` with [`shallowRef`](https://vuejs.org/api/reactivity-advanced.html#shallowref). This can improve performance when your state contains large objects and arrays.

View File

@ -55,3 +55,7 @@ function contactForm() {
::tip
`$fetch` is the preferred way to make HTTP calls in Nuxt instead of [@nuxt/http](https://github.com/nuxt/http) and [@nuxtjs/axios](https://github.com/nuxt-community/axios-module) that are made for Nuxt 2.
::
::note
If you use `$fetch` to call an (external) HTTPS URL with a self-signed certificate in development, you will need to set `NODE_TLS_REJECT_UNAUTHORIZED=0` in your environment.
::

View File

@ -129,7 +129,7 @@ interface PageMeta {
- **Type**: `boolean | (to: RouteLocationNormalized, from: RouteLocationNormalized) => boolean`
Tell Nuxt to scroll to the top before rendering the page or not. If you want to overwrite the default scroll behavior of Nuxt, you can do so in `~/app/router.options.ts` (see [docs](/docs/guide/directory-structure/pages/#router-options)) for more info.
Tell Nuxt to scroll to the top before rendering the page or not. If you want to overwrite the default scroll behavior of Nuxt, you can do so in `~/app/router.options.ts` (see [custom routing](/docs/guide/going-further/custom-routing#using-approuteroptions)) for more info.
**`[key: string]`**
@ -200,7 +200,7 @@ The two routes "/test-category" and "/1234-post" match both `[postId]-[postSlug]
To make sure that we are only matching digits (`\d+`) for `postId` in the `[postId]-[postSlug]` route, we can add the following to the `[postId]-[postSlug].vue` page template:
```vue [pages/[postId]-[postSlug].vue]
```vue [pages/[postId\\]-[postSlug\\].vue]
<script setup lang="ts">
definePageMeta({
path: '/:postId(\\d+)-:postSlug'

View File

@ -52,6 +52,18 @@ export default defineNuxtRouteMiddleware((to, from) => {
### External URL
The `external` parameter in `navigateTo` influences how navigating to URLs is handled:
- **Without `external: true`**:
- Internal URLs navigate as expected.
- External URLs throw an error.
- **With `external: true`**:
- Internal URLs navigate with a full-page reload.
- External URLs navigate as expected.
#### Example
```vue
<script setup lang="ts">
// will throw an error;

View File

@ -14,6 +14,10 @@ When prerendering, you can hint to Nitro to prerender additional paths, even if
`prerenderRoutes` can only be called within the [Nuxt context](/docs/guide/going-further/nuxt-app#the-nuxt-context).
::
::note
`prerenderRoutes` has to be executed during prerendering. If the `prerenderRoutes` is used in dynamic pages/routes which are not prerendered, then it will not be executed.
::
```js
const route = useRoute()

View File

@ -9,7 +9,7 @@ links:
---
```bash [Terminal]
npx nuxi build [--prerender] [--dotenv] [--log-level] [rootDir]
npx nuxi build [--prerender] [--preset] [--dotenv] [--log-level] [rootDir]
```
The `build` command creates a `.output` directory with all your application, server and dependencies ready for production.
@ -18,9 +18,14 @@ Option | Default | Description
-------------------------|-----------------|------------------
`rootDir` | `.` | The root directory of the application to bundle.
`--prerender` | `false` | Pre-render every route of your application. (**note:** This is an experimental flag. The behavior might be changed.)
`--preset` | - | Set a [Nitro preset](https://nitro.unjs.io/deploy#changing-the-deployment-preset)
`--dotenv` | `.` | Point to another `.env` file to load, **relative** to the root directory.
`--log-level` | `info` | Specify build-time logging level, allowing `silent` \| `info` \| `verbose`.
::note
This command sets `process.env.NODE_ENV` to `production`.
::
::note
`--prerender` will always set the `preset` to `static`
::

View File

@ -18,11 +18,17 @@ The `init` command initializes a fresh Nuxt project using [unjs/giget](https://g
Option | Default | Description
-------------------------|-----------------|------------------
`--cwd` | | Current working directory
`--log-level` | | Log level
`--template, -t` | `v3` | Specify template name or git repository to use as a template. Format is `gh:org/name` to use a custom github template.
`--force` | `false` | Force clone to any existing directory.
`--offline` | `false` | Do not attempt to download from github and only use local cache.
`--prefer-offline` | `false` | Try local cache first to download templates.
`--shell` | `false` | Open shell in cloned directory (experimental).
`--force, -f` | `false` | Force clone to any existing directory.
`--offline` | `false` | Force offline mode (do not attempt to download template from GitHub and only use local cache).
`--prefer-offline` | `false` | Prefer offline mode (try local cache first to download templates).
`--no-install` | `false` | Skip installing dependencies.
`--git-init` | `false` | Initialize git repository.
`--shell` | `false` | Start shell after installation in project directory (experimental).
`--package-manager` | `npm` | Package manager choice (npm, pnpm, yarn, bun).
`--dir` | | Project directory.
## Environment variables

View File

@ -0,0 +1,27 @@
---
title: Runtime Config
description: Nuxt Kit provides a set of utilities to help you access and modify Nuxt runtime configuration.
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/nuxt/nuxt/blob/main/packages/kit/src/runtime-config.ts
size: xs
---
## `useRuntimeConfig`
At build-time, it is possible to access the resolved Nuxt [runtime config](/docs/guide/going-further/runtime-config).
### Type
```ts
function useRuntimeConfig (): Record<string, unknown>
```
## `updateRuntimeConfig`
It is also possible to update runtime configuration. This will be merged with the existing runtime configuration, and if Nitro has already been initialized it will trigger an HMR event to reload the Nitro runtime config.
```ts
function updateRuntimeConfig (config: Record<string, unknown>): void | Promise<void>
```

View File

@ -117,7 +117,7 @@ import { defineNuxtPlugin } from '#imports'
import metaConfig from '#build/meta.config.mjs'
export default defineNuxtPlugin((nuxtApp) => {
const createHead = process.server ? createServerHead : createClientHead
const createHead = import.meta.server ? createServerHead : createClientHead
const head = createHead()
head.push(metaConfig.globalMeta)

View File

@ -211,6 +211,10 @@ Type of path to resolve. If set to `'file'`, the function will try to resolve a
Creates resolver relative to base path.
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/resolving-paths-and-injecting-assets-to-the-app" target="_blank"}
Watch Vue School video about createResolver.
::
### Type
```ts

View File

@ -25,6 +25,12 @@ async function checkNuxtCompatibility(
interface NuxtCompatibility {
nuxt?: string;
bridge?: boolean;
builder?: {
// Set `false` if your module is not compatible with a builder
// or a semver-compatible string version constraint
vite?: false | string;
webpack?: false | string;
};
}
interface NuxtCompatibilityIssue {

View File

@ -18,6 +18,10 @@ These functions are designed for registering your own utils, composables and Vue
Nuxt auto-imports helper functions, composables and Vue APIs to use across your application without explicitly importing them. Based on the directory structure, every Nuxt application can also use auto-imports for its own composables and plugins. Composables or plugins can use these functions.
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/expanding-nuxt-s-auto-imports" target="_blank"}
Watch Vue School video about Auto-imports Nuxt Kit utilities.
::
## `addImports`
Add imports to the Nuxt application. It makes your imports available in the Nuxt application without the need to import them manually.

View File

@ -10,6 +10,10 @@ links:
Components are the building blocks of your Nuxt application. They are reusable Vue instances that can be used to create a user interface. In Nuxt, components from the components directory are automatically imported by default. However, if you need to import components from an alternative directory or wish to selectively import them as needed, `@nuxt/kit` provides the `addComponentsDir` and `addComponent` methods. These utils allow you to customize the component configuration to better suit your needs.
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/injecting-components-and-component-directories" target="_blank"}
Watch Vue School video about injecting components.
::
## `addComponentsDir`
Register a directory to be scanned for components and imported only when used. Keep in mind, that this does not register components globally, until you specify `global: true` option.
@ -37,6 +41,11 @@ interface ComponentsDir {
transpile?: 'auto' | boolean
}
// You can augment this interface (exported from `@nuxt/schema`) if needed
interface ComponentMeta {
[key: string]: unknown
}
interface Component {
pascalName: string
kebabName: string
@ -50,6 +59,7 @@ interface Component {
island?: boolean
mode?: 'client' | 'server' | 'all'
priority?: number
meta?: ComponentMeta
}
```

View File

@ -12,6 +12,10 @@ links:
In Nuxt 3, routes are automatically generated based on the structure of the files in the `pages` directory. However, there may be scenarios where you'd want to customize these routes. For instance, you might need to add a route for a dynamic page not generated by Nuxt, remove an existing route, or modify the configuration of a route. For such customizations, Nuxt 3 offers the `extendPages` feature, which allows you to extend and alter the pages configuration.
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/extend-and-alter-nuxt-pages" target="_blank"}
Watch Vue School video about extendPages.
::
### Type
```ts
@ -67,6 +71,10 @@ Nuxt is powered by the [Nitro](https://nitro.unjs.io) server engine. With Nitro,
You can read more about Nitro route rules in the [Nitro documentation](https://nitro.unjs.io/guide/routing#route-rules).
::
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/adding-route-rules-and-route-middlewares" target="_blank"}
Watch Vue School video about adding route rules and route middelwares.
::
### Type
```ts
@ -184,6 +192,10 @@ Route middlewares can be also defined in plugins via [`addRouteMiddleware`](/doc
Read more about route middlewares in the [Route middleware documentation](/docs/getting-started/routing#route-middleware).
::
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/adding-route-rules-and-route-middlewares" target="_blank"}
Watch Vue School video about adding route rules and route middelwares.
::
### Type
```ts

View File

@ -14,6 +14,10 @@ Plugins are self-contained code that usually add app-level functionality to Vue.
Registers a Nuxt plugin and to the plugins array.
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/injecting-plugins" target="_blank"}
Watch Vue School video about addPlugin.
::
### Type
```ts
@ -110,6 +114,10 @@ export default defineNuxtPlugin((nuxtApp) => {
Adds a template and registers as a nuxt plugin. This is useful for plugins that need to generate code at build time.
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/injecting-plugin-templates" target="_blank"}
Watch Vue School video about addPluginTemplate.
::
### Type
```ts
@ -243,7 +251,7 @@ export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VueFire, { firebaseApp })
<% if(options.ssr) { %>
if (process.server) {
if (import.meta.server) {
nuxtApp.payload.vuefire = useSSRInitialState(undefined, firebaseApp)
} else if (nuxtApp.payload?.vuefire) {
useSSRInitialState(nuxtApp.payload.vuefire, firebaseApp)

View File

@ -22,12 +22,15 @@ Hook | Arguments | Environment | Description
`app:beforeMount` | `vueApp` | Client | Called before mounting the app, called only on client side.
`app:mounted` | `vueApp` | Client | Called when Vue app is initialized and mounted in browser.
`app:suspense:resolve` | `appComponent` | Client | On [Suspense](https://vuejs.org/guide/built-ins/suspense.html#suspense) resolved event.
`app:manifest:update` | `{ id, timestamp }` | Client | Called when there is a newer version of your app detected.
`link:prefetch` | `to` | Client | Called when a `<NuxtLink>` is observed to be prefetched.
`page:start` | `pageComponent?` | Client | Called on [Suspense](https://vuejs.org/guide/built-ins/suspense.html#suspense) pending event.
`page:finish` | `pageComponent?` | Client | Called on [Suspense](https://vuejs.org/guide/built-ins/suspense.html#suspense) resolved event.
`page:loading:start` | - | Client | Called when the `setup()` of the new page is running.
`page:loading:end` | - | Client | Called after `page:finish`
`page:transition:finish`| `pageComponent?` | Client | After page transition [onAfterLeave](https://vuejs.org/guide/built-ins/transition.html#javascript-hooks) event.
`dev:ssr-logs` | `logs` | Client | Called with an array of server-side logs that have been passed to the client (if `features.devLogs` is enabled).
`page:view-transition:start` | `transition` | Client | Called after `document.startViewTransition` is called when [experimental viewTransition support is enabled](https://nuxt.com/docs/getting-started/transitions#view-transitions-api-experimental).
## Nuxt Hooks (build time)
@ -90,11 +93,12 @@ See [Nitro](https://nitro.unjs.io/guide/plugins#available-hooks) for all availab
Hook | Arguments | Description | Types
-----------------------|-----------------------|--------------------------------------|------------------
`dev:ssr-logs` | `{ path, logs }` | Server | Called at the end of a request cycle with an array of server-side logs.
`render:response` | `response, { event }` | Called before sending the response. | [response](https://github.com/nuxt/nuxt/blob/71ef8bd3ff207fd51c2ca18d5a8c7140476780c7/packages/nuxt/src/core/runtime/nitro/renderer.ts#L24), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
`render:html` | `html, { event }` | Called before constructing the HTML. | [html](https://github.com/nuxt/nuxt/blob/71ef8bd3ff207fd51c2ca18d5a8c7140476780c7/packages/nuxt/src/core/runtime/nitro/renderer.ts#L15), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
`render:island` | `islandResponse, { event, islandContext }` | Called before constructing the island HTML. | [islandResponse](https://github.com/nuxt/nuxt/blob/e50cabfed1984c341af0d0c056a325a8aec26980/packages/nuxt/src/core/runtime/nitro/renderer.ts#L28), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38), [islandContext](https://github.com/nuxt/nuxt/blob/e50cabfed1984c341af0d0c056a325a8aec26980/packages/nuxt/src/core/runtime/nitro/renderer.ts#L38)
`close` | - | Called when Nitro is closed. | -
`error` | `error, { event? }` | Called when an error occurs. | [error](https://github.com/unjs/nitro/blob/main/src/runtime/types.ts#L24), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
`error` | `error, { event? }` | Called when an error occurs. | [error](https://github.com/unjs/nitro/blob/d20ffcbd16fc4003b774445e1a01e698c2bb078a/src/types/runtime/nitro.ts#L48), [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
`request` | `event` | Called when a request is received. | [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38)
`beforeResponse` | `event, { body }` | Called before sending the response. | [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38), unknown
`afterResponse` | `event, { body }` | Called after sending the response. | [event](https://github.com/unjs/h3/blob/f6ceb5581043dc4d8b6eab91e9be4531e0c30f8e/src/types.ts#L38), unknown

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