mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 07:05:11 +00:00
Merge remote-tracking branch 'origin/main' into feat/hook-pages-resolved
This commit is contained in:
commit
166f8785ef
@ -1,4 +1,4 @@
|
||||
FROM node:lts
|
||||
FROM node:lts@sha256:fffa89e023a3351904c04284029105d9e2ac7020886d683775a298569591e5bb
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -fy libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdbus-1-3 libdrm2 libxkbcommon0 libatspi2.0-0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 && \
|
||||
|
10
.github/codeql/codeql-config.yml
vendored
Normal file
10
.github/codeql/codeql-config.yml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
paths:
|
||||
- 'packages/*/dist/**'
|
||||
- 'packages/nuxt/bin/**'
|
||||
- 'packages/schema/schema/**'
|
||||
paths-ignore:
|
||||
- 'test/**'
|
||||
- '**/*.test.js'
|
||||
- '**/*.test.ts'
|
||||
- '**/*.test.tsx'
|
||||
- '**/__tests__/**'
|
4
.github/workflows/autofix-docs.yml
vendored
4
.github/workflows/autofix-docs.yml
vendored
@ -17,9 +17,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
4
.github/workflows/autofix.yml
vendored
4
.github/workflows/autofix.yml
vendored
@ -13,9 +13,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
4
.github/workflows/benchmark.yml
vendored
4
.github/workflows/benchmark.yml
vendored
@ -29,9 +29,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
6
.github/workflows/cache-cleanup.yml
vendored
6
.github/workflows/cache-cleanup.yml
vendored
@ -6,6 +6,8 @@ on:
|
||||
types:
|
||||
- closed
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
@ -20,14 +22,14 @@ jobs:
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
echo "Fetching list of cache keys"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
|
||||
cacheKeysForPR=$(gh actions-cache list -R "$REPO" -B "$BRANCH" -L 100 | cut -f 1 )
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
gh actions-cache delete "$cacheKey" -R "$REPO" -B "$BRANCH" --confirm
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
|
12
.github/workflows/changelog.yml
vendored
12
.github/workflows/changelog.yml
vendored
@ -6,9 +6,7 @@ on:
|
||||
- main
|
||||
- 3.x
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
|
||||
@ -19,12 +17,16 @@ jobs:
|
||||
if: github.repository_owner == 'nuxt' && !contains(github.event.head_commit.message, 'v3.') && !contains(github.event.head_commit.message, 'v4.')
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
77
.github/workflows/ci.yml
vendored
77
.github/workflows/ci.yml
vendored
@ -37,9 +37,9 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
@ -57,7 +57,7 @@ jobs:
|
||||
run: pnpm build
|
||||
|
||||
- name: Cache dist
|
||||
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
uses: actions/upload-artifact@84480863f228bb9747b473957fcc9e309aa96097 # v4.4.2
|
||||
with:
|
||||
retention-days: 3
|
||||
name: dist
|
||||
@ -70,36 +70,30 @@ jobs:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
needs:
|
||||
- build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
||||
with:
|
||||
languages: javascript
|
||||
config: |
|
||||
paths:
|
||||
- 'packages/*/src/**'
|
||||
- 'packages/nuxt/bin/**'
|
||||
- 'packages/schema/schema/**'
|
||||
paths-ignore:
|
||||
- 'test/**'
|
||||
- '**/*.spec.ts'
|
||||
- '**/*.test.ts'
|
||||
- '**/__snapshots__/**'
|
||||
languages: javascript-typescript
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Restore dist cache
|
||||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
|
||||
with:
|
||||
name: dist
|
||||
path: packages
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
||||
with:
|
||||
category: "/language:javascript"
|
||||
category: "/language:javascript-typescript"
|
||||
|
||||
typecheck:
|
||||
runs-on: ${{ matrix.os }}
|
||||
@ -113,9 +107,9 @@ jobs:
|
||||
module: ["bundler", "node"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
@ -144,9 +138,9 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
@ -168,9 +162,9 @@ jobs:
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
@ -197,7 +191,7 @@ jobs:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
env: ["dev", "built"]
|
||||
builder: ["vite", "webpack"]
|
||||
builder: ["vite", "rspack", "webpack"]
|
||||
context: ["async", "default"]
|
||||
manifest: ["manifest-on", "manifest-off"]
|
||||
payload: ["json", "js"]
|
||||
@ -205,12 +199,18 @@ jobs:
|
||||
exclude:
|
||||
- builder: "webpack"
|
||||
payload: "js"
|
||||
- builder: "rspack"
|
||||
payload: "js"
|
||||
- manifest: "manifest-off"
|
||||
payload: "js"
|
||||
- context: "default"
|
||||
payload: "js"
|
||||
- os: windows-latest
|
||||
payload: "js"
|
||||
- env: "dev"
|
||||
builder: "rspack"
|
||||
- manifest: "manifest-off"
|
||||
builder: "rspack"
|
||||
- env: "dev"
|
||||
builder: "webpack"
|
||||
- manifest: "manifest-off"
|
||||
@ -219,9 +219,9 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: "pnpm"
|
||||
@ -248,7 +248,7 @@ jobs:
|
||||
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@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
|
||||
- uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
|
||||
if: github.event_name != 'push' && matrix.env == 'built' && matrix.builder == 'vite' && matrix.context == 'default' && matrix.os == 'ubuntu-latest' && matrix.manifest == 'manifest-on'
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
@ -262,7 +262,6 @@ jobs:
|
||||
github.event_name == 'push' &&
|
||||
github.repository == 'nuxt/nuxt' &&
|
||||
!contains(github.event.head_commit.message, '[skip-release]') &&
|
||||
!startsWith(github.event.head_commit.message, 'chore') &&
|
||||
!startsWith(github.event.head_commit.message, 'docs')
|
||||
needs:
|
||||
- lint
|
||||
@ -272,11 +271,11 @@ jobs:
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
@ -313,11 +312,11 @@ jobs:
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
2
.github/workflows/dependency-review.yml
vendored
2
.github/workflows/dependency-review.yml
vendored
@ -17,6 +17,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
|
||||
|
6
.github/workflows/docs-check-links.yml
vendored
6
.github/workflows/docs-check-links.yml
vendored
@ -19,17 +19,17 @@ jobs:
|
||||
steps:
|
||||
# Cache lychee results (e.g. to avoid hitting rate limits)
|
||||
- name: Restore lychee cache
|
||||
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
|
||||
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
|
||||
with:
|
||||
path: .lycheecache
|
||||
key: cache-lychee-${{ github.sha }}
|
||||
restore-keys: cache-lychee-
|
||||
|
||||
# check links with Lychee
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
|
||||
- name: Lychee link checker
|
||||
uses: lycheeverse/lychee-action@d4128702eae98bbc5ecf74df0165a8156c80920a # for v1.8.0
|
||||
uses: lycheeverse/lychee-action@731bf1a2affebd80fab6515ba61d2648a76929a4 # for v1.8.0
|
||||
with:
|
||||
# arguments with file types to check
|
||||
args: >-
|
||||
|
4
.github/workflows/docs.yml
vendored
4
.github/workflows/docs.yml
vendored
@ -21,9 +21,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
28
.github/workflows/label-issue.yml
vendored
Normal file
28
.github/workflows/label-issue.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: chore
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
add-issue-labels:
|
||||
name: Add labels
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'nuxt/nuxt'
|
||||
steps:
|
||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
// add 'pending triage' label if issue is created with no labels
|
||||
if (context.payload.issue.labels.length === 0) {
|
||||
github.rest.issues.addLabels({
|
||||
issue_number: context.payload.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['pending triage']
|
||||
})
|
||||
}
|
2
.github/workflows/label-pr.yml
vendored
2
.github/workflows/label-pr.yml
vendored
@ -8,6 +8,8 @@ on:
|
||||
- main
|
||||
- 3.x
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
add-pr-labels:
|
||||
name: Add PR labels
|
||||
|
4
.github/workflows/lint-sherif.yml
vendored
4
.github/workflows/lint-sherif.yml
vendored
@ -23,9 +23,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
8
.github/workflows/lint-workflows.yml
vendored
8
.github/workflows/lint-workflows.yml
vendored
@ -23,9 +23,9 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
# From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions
|
||||
- name: Check workflow files
|
||||
run: |
|
||||
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/590d3bd9dde0c91f7a66071d40eb84716526e5a6/scripts/download-actionlint.bash) 1.6.25
|
||||
./actionlint -color -shellcheck=""
|
||||
uses: docker://rhysd/actionlint:1.7.3@sha256:7617f05bd698cd2f1c3aedc05bc733ccec92cca0738f3e8722c32c5b42c70ae6
|
||||
with:
|
||||
args: -color
|
||||
|
3
.github/workflows/notify-nuxt-bridge.yml
vendored
3
.github/workflows/notify-nuxt-bridge.yml
vendored
@ -4,6 +4,9 @@ on:
|
||||
types: [closed]
|
||||
paths:
|
||||
- "packages/nuxt/src/app/composables/**"
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
notify:
|
||||
if: github.event.pull_request.merged == true
|
||||
|
10
.github/workflows/release-pr.yml
vendored
10
.github/workflows/release-pr.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Ensure action is by maintainer
|
||||
uses: octokit/request-action@872c5c97b3c85c23516a572f02b31401ef82415d # v2.3.1
|
||||
uses: octokit/request-action@dad4362715b7fb2ddedf9772c8670824af564f0d # v2.4.0
|
||||
id: check_role
|
||||
with:
|
||||
route: GET /repos/nuxt/nuxt/collaborators/${{ github.event.comment.user.login }}
|
||||
@ -39,7 +39,7 @@ jobs:
|
||||
GH_REPO: ${{ github.repository }}
|
||||
COMMENT_AT: ${{ github.event.comment.created_at }}
|
||||
run: |
|
||||
pr="$(gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/${GH_REPO}/pulls/${PR_NUMBER})"
|
||||
pr="$(gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/"${GH_REPO}"/pulls/"${PR_NUMBER}")"
|
||||
head_sha="$(echo "$pr" | jq -r .head.sha)"
|
||||
updated_at="$(echo "$pr" | jq -r .updated_at)"
|
||||
|
||||
@ -47,14 +47,14 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "head_sha=$head_sha" >> $GITHUB_OUTPUT
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT"
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
ref: ${{ steps.pr.outputs.head_sha }}
|
||||
fetch-depth: 1
|
||||
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -19,11 +19,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
- uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
|
||||
with:
|
||||
node-version: 20
|
||||
registry-url: "https://registry.npmjs.org/"
|
||||
|
2
.github/workflows/reproduire.yml
vendored
2
.github/workflows/reproduire.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
reproduire:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp
|
||||
with:
|
||||
label: needs reproduction
|
||||
|
6
.github/workflows/scorecards.yml
vendored
6
.github/workflows/scorecards.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@ -59,7 +59,7 @@ 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@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
|
||||
uses: actions/upload-artifact@84480863f228bb9747b473957fcc9e309aa96097 # v4.4.2
|
||||
if: github.repository == 'nuxt/nuxt' && success()
|
||||
with:
|
||||
name: SARIF file
|
||||
@ -68,7 +68,7 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3.26.6
|
||||
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
|
||||
if: github.repository == 'nuxt/nuxt' && success()
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
5
.github/workflows/semantic-pull-requests.yml
vendored
5
.github/workflows/semantic-pull-requests.yml
vendored
@ -7,12 +7,12 @@ on:
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
semantic-pr:
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs
|
||||
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
|
||||
if: github.repository == 'nuxt/nuxt' && !startsWith(github.head_ref, 'v')
|
||||
@ -26,6 +26,7 @@ jobs:
|
||||
kit
|
||||
nuxi
|
||||
nuxt
|
||||
rspack
|
||||
schema
|
||||
test-utils
|
||||
ui-templates
|
||||
|
4
.github/workflows/stackblitz-link.yml
vendored
4
.github/workflows/stackblitz-link.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
stackblitz:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: huang-julien/reproduire-sur-stackblitz@v1.0.1
|
||||
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
- uses: huang-julien/reproduire-sur-stackblitz@9ceccbfbb0f2f9a9a8db2d1f0dd909cf5cfe67aa # v1.0.2
|
||||
with:
|
||||
reproduction-heading: '### Reproduction'
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: Introduction
|
||||
description: Nuxt's goal is to make web development intuitive and performant with a great Developer Experience in mind.
|
||||
navigation:
|
||||
icon: i-ph-info-duotone
|
||||
icon: i-ph-info
|
||||
---
|
||||
|
||||
Nuxt is a free and [open-source framework](https://github.com/nuxt/nuxt) with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with [Vue.js](https://vuejs.org).
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Deployment'
|
||||
description: Learn how to deploy your Nuxt application to any hosting provider.
|
||||
navigation.icon: i-ph-cloud-duotone
|
||||
navigation.icon: i-ph-cloud
|
||||
---
|
||||
|
||||
A Nuxt application can be deployed on a Node.js server, pre-rendered for static hosting, or deployed to serverless or edge (CDN) environments.
|
||||
@ -64,6 +64,10 @@ By default, the workload gets distributed to the workers with the round robin st
|
||||
|
||||
:read-more{to="https://nitro.unjs.io/deploy/node" title="the Nitro documentation for node-server preset"}
|
||||
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=0x1H6K5yOfs" target="\_blank"}
|
||||
Watch Daniel Roe's short video on the topic.
|
||||
::
|
||||
|
||||
## Static Hosting
|
||||
|
||||
There are two ways to deploy a Nuxt application to any static hosting services:
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Testing
|
||||
description: How to test your Nuxt application.
|
||||
navigation.icon: i-ph-check-circle-duotone
|
||||
navigation.icon: i-ph-check-circle
|
||||
---
|
||||
|
||||
::tip
|
||||
@ -10,7 +10,7 @@ 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"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=yGzwk9xi9gU" target="_blank"}
|
||||
Watch a video from Alexander Lichter about getting started with the `@nuxt/test-utils`.
|
||||
::
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
---
|
||||
title: Upgrade Guide
|
||||
description: 'Learn how to upgrade to the latest Nuxt version.'
|
||||
navigation.icon: i-ph-arrow-circle-up-duotone
|
||||
navigation.icon: i-ph-arrow-circle-up
|
||||
---
|
||||
|
||||
|
||||
## Upgrading Nuxt
|
||||
|
||||
### Latest release
|
||||
@ -43,11 +42,11 @@ You can opt in to the 3.x branch nightly releases with `"nuxt": "npm:nuxt-nightl
|
||||
|
||||
## 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).
|
||||
The release date of Nuxt 4 is **to be announced**. It is dependent on having enough time after Nitro's major release to be properly tested in the community. You can follow progress towards Nitro's release in [this PR](https://github.com/unjs/nitro/pull/2521).
|
||||
|
||||
Until then, it is possible to test many of Nuxt 4's breaking changes from Nuxt version 3.12+.
|
||||
Until the release, it is possible to test many of Nuxt 4's breaking changes from Nuxt version 3.12+.
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=r4wFKlcJK6c" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=r4wFKlcJK6c" target="_blank"}
|
||||
Watch a video from Alexander Lichter showing how to opt in to Nuxt 4's breaking changes already.
|
||||
::
|
||||
|
||||
@ -73,6 +72,7 @@ export default defineNuxtConfig({
|
||||
// resetAsyncDataToUndefined: true,
|
||||
// templateUtils: true,
|
||||
// relativeWatchPaths: true,
|
||||
// normalizeComponentNames: false
|
||||
// defaults: {
|
||||
// useAsyncData: {
|
||||
// deep: true
|
||||
@ -178,6 +178,7 @@ nuxt.config.ts
|
||||
1. Create a new directory called `app/`.
|
||||
1. Move your `assets/`, `components/`, `composables/`, `layouts/`, `middleware/`, `pages/`, `plugins/` and `utils/` folders under it, as well as `app.vue`, `error.vue`, `app.config.ts`. If you have an `app/router-options.ts` or `app/spa-loading-template.html`, these paths remain the same.
|
||||
1. Make sure your `nuxt.config.ts`, `content/`, `layers/`, `modules/`, `public/` and `server/` folders remain outside the `app/` folder, in the root of your project.
|
||||
1. Remember to update any third-party configuration files to work with the new directory structure, such as your `tailwindcss` or `eslint` configuration (if required - `@nuxtjs/tailwindcss` should automatically configure `tailwindcss` correctly).
|
||||
|
||||
::tip
|
||||
You can automate this migration by running `npx codemod@latest nuxt/4/file-structure`
|
||||
@ -198,6 +199,43 @@ export default defineNuxtConfig({
|
||||
})
|
||||
```
|
||||
|
||||
#### Normalized Component Names
|
||||
|
||||
🚦 **Impact Level**: Moderate
|
||||
|
||||
Vue will now generate component names that match the Nuxt pattern for component naming.
|
||||
|
||||
##### What Changed
|
||||
|
||||
By default, if you haven't set it manually, Vue will assign a component name that matches
|
||||
the filename of the component.
|
||||
|
||||
```bash [Directory structure]
|
||||
├─ components/
|
||||
├─── SomeFolder/
|
||||
├───── MyComponent.vue
|
||||
```
|
||||
|
||||
In this case, the component name would be `MyComponent`, as far as Vue is concerned. If you wanted to use `<KeepAlive>` with it, or identify it in the Vue DevTools, you would need to use this name.
|
||||
|
||||
But in order to auto-import it, you would need to use `SomeFolderMyComponent`.
|
||||
|
||||
With this change, these two values will match, and Vue will generate a component name that matches the Nuxt pattern for component naming.
|
||||
|
||||
##### Migration Steps
|
||||
|
||||
Ensure that you use the updated name in any tests which use `findComponent` from `@vue/test-utils` and in any `<KeepAlive>` which depends on the name of your component.
|
||||
|
||||
Alternatively, for now, you can disable this behaviour with:
|
||||
|
||||
```ts twoslash [nuxt.config.ts]
|
||||
export default defineNuxtConfig({
|
||||
experimental: {
|
||||
normalizeComponentNames: false
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Shared Prerender Data
|
||||
|
||||
🚦 **Impact Level**: Medium
|
||||
@ -407,7 +445,7 @@ We have already proactively migrated the public Nuxt modules which we are aware
|
||||
|
||||
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
|
||||
```diff
|
||||
+ import { relative, resolve } from 'node:fs'
|
||||
// ...
|
||||
nuxt.hook('builder:watch', async (event, path) => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Installation'
|
||||
description: 'Get started with Nuxt quickly with our online starters or start locally with your terminal.'
|
||||
navigation.icon: i-ph-play-duotone
|
||||
navigation.icon: i-ph-play
|
||||
---
|
||||
|
||||
## Play Online
|
||||
@ -94,7 +94,7 @@ bun run dev -o
|
||||
```
|
||||
::
|
||||
|
||||
::tip{icon="i-ph-check-circle-duotone"}
|
||||
::tip{icon="i-ph-check-circle"}
|
||||
Well done! A browser window should automatically open for <http://localhost:3000>.
|
||||
::
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
---
|
||||
title: Configuration
|
||||
description: Nuxt is configured with sensible defaults to make you productive.
|
||||
navigation.icon: i-ph-gear-duotone
|
||||
navigation.icon: i-ph-gear
|
||||
---
|
||||
|
||||
|
||||
By default, Nuxt is configured to cover most use cases. The [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file can override or extend this default configuration.
|
||||
|
||||
## Nuxt Configuration
|
||||
@ -29,7 +28,7 @@ Every option is described in the **Configuration Reference**.
|
||||
You don't have to use TypeScript to build an application with Nuxt. However, it is strongly recommended to use the `.ts` extension for the `nuxt.config` file. This way you can benefit from hints in your IDE to avoid typos and mistakes while editing your configuration.
|
||||
::
|
||||
|
||||
### Environment overrides
|
||||
### Environment Overrides
|
||||
|
||||
You can configure fully typed, per-environment overrides in your nuxt.config
|
||||
|
||||
@ -46,7 +45,7 @@ export default defineNuxtConfig({
|
||||
})
|
||||
```
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=DFZI2iVCrNc" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=DFZI2iVCrNc" target="_blank"}
|
||||
Watch a video from Alexander Lichter about the env-aware `nuxt.config.ts`.
|
||||
::
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Views'
|
||||
description: 'Nuxt provides several component layers to implement the user interface of your application.'
|
||||
navigation.icon: i-ph-layout-duotone
|
||||
navigation.icon: i-ph-layout
|
||||
---
|
||||
|
||||
## `app.vue`
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Assets'
|
||||
description: 'Nuxt offers two options for your assets.'
|
||||
navigation.icon: i-ph-image-duotone
|
||||
navigation.icon: i-ph-image
|
||||
---
|
||||
|
||||
Nuxt uses two directories to handle assets like stylesheets, fonts or images.
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Styling'
|
||||
description: 'Learn how to style your Nuxt application.'
|
||||
navigation.icon: i-ph-palette-duotone
|
||||
navigation.icon: i-ph-palette
|
||||
---
|
||||
|
||||
Nuxt is highly flexible when it comes to styling. Write your own styles, or reference local and external stylesheets.
|
||||
@ -530,7 +530,7 @@ export default defineNuxtConfig({
|
||||
hooks: {
|
||||
'build:manifest': (manifest) => {
|
||||
// find the app entry, css list
|
||||
const css = manifest['node_modules/nuxt/dist/app/entry.js']?.css
|
||||
const css = Object.values(manifest).find(options => options.isEntry)?.css
|
||||
if (css) {
|
||||
// start from the end of the array and go to the beginning
|
||||
for (let i = css.length - 1; i >= 0; i--) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Routing'
|
||||
description: Nuxt file-system routing creates a route for every file in the pages/ directory.
|
||||
navigation.icon: i-ph-signpost-duotone
|
||||
navigation.icon: i-ph-signpost
|
||||
---
|
||||
|
||||
One core feature of Nuxt is the file system router. Every Vue file inside the [`pages/`](/docs/guide/directory-structure/pages) directory creates a corresponding URL (or route) that displays the contents of the file. By using dynamic imports for each page, Nuxt leverages code-splitting to ship the minimum amount of JavaScript for the requested route.
|
||||
@ -15,7 +15,7 @@ This file system routing uses naming conventions to create dynamic and nested ro
|
||||
::code-group
|
||||
|
||||
```bash [Directory Structure]
|
||||
| pages/
|
||||
-| pages/
|
||||
---| about.vue
|
||||
---| index.vue
|
||||
---| posts/
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: SEO and Meta
|
||||
description: Improve your Nuxt app's SEO with powerful head config, composables and components.
|
||||
navigation.icon: i-ph-file-search-duotone
|
||||
navigation.icon: i-ph-file-search
|
||||
---
|
||||
|
||||
## Defaults
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Transitions'
|
||||
description: Apply transitions between pages and layouts with Vue or native browser View Transitions.
|
||||
navigation.icon: i-ph-exclude-square-duotone
|
||||
navigation.icon: i-ph-exclude-square
|
||||
---
|
||||
|
||||
::note
|
||||
|
@ -1,28 +1,24 @@
|
||||
---
|
||||
title: 'Data fetching'
|
||||
description: Nuxt provides composables to handle data fetching within your application.
|
||||
navigation.icon: i-ph-plugs-connected-duotone
|
||||
navigation.icon: i-ph-plugs-connected
|
||||
---
|
||||
|
||||
Nuxt comes with two composables and a built-in library to perform data-fetching in browser or server environments: `useFetch`, [`useAsyncData`](/docs/api/composables/use-async-data) and `$fetch`.
|
||||
|
||||
In a nutshell:
|
||||
|
||||
- [`useFetch`](/docs/api/composables/use-fetch) is the most straightforward way to handle data fetching in a component setup function.
|
||||
- [`$fetch`](/docs/api/utils/dollarfetch) is great to make network requests based on user interaction.
|
||||
- [`useAsyncData`](/docs/api/composables/use-async-data), combined with `$fetch`, offers more fine-grained control.
|
||||
- [`$fetch`](/docs/api/utils/dollarfetch) is the simplest way to make a network request.
|
||||
- [`useFetch`](/docs/api/composables/use-fetch) is wrapper around `$fetch` that fetches data only once in [universal rendering](/docs/guide/concepts/rendering#universal-rendering).
|
||||
- [`useAsyncData`](/docs/api/composables/use-async-data) is similar to `useFetch` but offers more fine-grained control.
|
||||
|
||||
Both `useFetch` and `useAsyncData` share a common set of options and patterns that we will detail in the last sections.
|
||||
|
||||
Before that, it's imperative to know why these composables exist in the first place.
|
||||
## The need for `useFetch` and `useAsyncData`
|
||||
|
||||
## Why use specific composables for data fetching?
|
||||
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 can cause hydration issues, increase the time to interactivity and cause unpredictable behavior.
|
||||
|
||||
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
|
||||
|
||||
The [`useFetch`](/docs/api/composables/use-fetch) and [`useAsyncData`](/docs/api/composables/use-async-data) composables ensure that once an API call is made on the server, the data is properly forwarded to the client in the payload.
|
||||
The [`useFetch`](/docs/api/composables/use-fetch) and [`useAsyncData`](/docs/api/composables/use-async-data) composables solve this problem by ensuring that if an API call is made on the server, the data is forwarded to the client in the payload.
|
||||
|
||||
The payload is a JavaScript object accessible through [`useNuxtApp().payload`](/docs/api/composables/use-nuxt-app#payload). It is used on the client to avoid refetching the same data when the code is executed in the browser [during hydration](/docs/guide/concepts/rendering#universal-rendering).
|
||||
|
||||
@ -30,41 +26,45 @@ The payload is a JavaScript object accessible through [`useNuxtApp().payload`](/
|
||||
Use the [Nuxt DevTools](https://devtools.nuxt.com) to inspect this data in the **Payload tab**.
|
||||
::
|
||||
|
||||
```vue [app.vue]
|
||||
<script setup lang="ts">
|
||||
const { data } = await useFetch('/api/data')
|
||||
|
||||
async function handleFormSubmit() {
|
||||
const res = await $fetch('/api/submit', {
|
||||
method: 'POST',
|
||||
body: {
|
||||
// My form data
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="data == null">
|
||||
No data
|
||||
</div>
|
||||
<div v-else>
|
||||
<form @submit="handleFormSubmit">
|
||||
<!-- form input tags -->
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
In the example above, `useFetch` would make sure that the request would occur in the server and is properly forwarded to the browser. `$fetch` has no such mechanism and is a better option to use when the request is solely made from the browser.
|
||||
|
||||
### Suspense
|
||||
|
||||
Nuxt uses Vue’s [`<Suspense>`](https://vuejs.org/guide/built-ins/suspense) component under the hood to prevent navigation before every async data is available to the view. The data fetching composables can help you leverage this feature and use what suits best on a per-calls basis.
|
||||
Nuxt uses Vue’s [`<Suspense>`](https://vuejs.org/guide/built-ins/suspense) component under the hood to prevent navigation before every async data is available to the view. The data fetching composables can help you leverage this feature and use what suits best on a per-call basis.
|
||||
|
||||
::note
|
||||
You can add the [`<NuxtLoadingIndicator>`](/docs/api/components/nuxt-loading-indicator) to add a progress bar between page navigations.
|
||||
::
|
||||
|
||||
## `useFetch`
|
||||
|
||||
The [`useFetch`](/docs/api/composables/use-fetch) composable is the most straightforward way to perform data fetching.
|
||||
|
||||
```vue twoslash [app.vue]
|
||||
<script setup lang="ts">
|
||||
const { data: count } = await useFetch('/api/count')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p>Page visits: {{ count }}</p>
|
||||
</template>
|
||||
```
|
||||
|
||||
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](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.
|
||||
Nuxt includes the [ofetch](https://github.com/unjs/ofetch) library, and is auto-imported as the `$fetch` alias globally across your application.
|
||||
|
||||
```vue twoslash [pages/todos.vue]
|
||||
<script setup lang="ts">
|
||||
@ -80,7 +80,7 @@ async function addTodo() {
|
||||
```
|
||||
|
||||
::warning
|
||||
Beware that using only `$fetch` will not provide [network calls de-duplication and navigation prevention](#why-use-specific-composables-for-data-fetching). :br
|
||||
Beware that using only `$fetch` will not provide [network calls de-duplication and navigation prevention](#the-need-for-usefetch-and-useasyncdata). :br
|
||||
It is recommended to use `$fetch` for client-side interactions (event based) or combined with [`useAsyncData`](#useasyncdata) when fetching the initial component data.
|
||||
::
|
||||
|
||||
@ -88,6 +88,30 @@ It is recommended to use `$fetch` for client-side interactions (event based) or
|
||||
Read more about `$fetch`.
|
||||
::
|
||||
|
||||
## `useFetch`
|
||||
|
||||
The [`useFetch`](/docs/api/composables/use-fetch) composable uses `$fetch` under-the-hood to make SSR-safe network calls in the setup function.
|
||||
|
||||
```vue twoslash [app.vue]
|
||||
<script setup lang="ts">
|
||||
const { data: count } = await useFetch('/api/count')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p>Page visits: {{ count }}</p>
|
||||
</template>
|
||||
```
|
||||
|
||||
This composable is a wrapper around the [`useAsyncData`](/docs/api/composables/use-async-data) composable and `$fetch` utility.
|
||||
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=njsGVmcWviY" target="_blank"}
|
||||
Watch the video from Alexander Lichter to avoid using `useFetch` the wrong way!
|
||||
::
|
||||
|
||||
:read-more{to="/docs/api/composables/use-fetch"}
|
||||
|
||||
:link-example{to="/docs/examples/features/data-fetching"}
|
||||
|
||||
## `useAsyncData`
|
||||
|
||||
The `useAsyncData` composable is responsible for wrapping async logic and returning the result once it is resolved.
|
||||
@ -97,7 +121,7 @@ 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"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=0X-aOpSGabA" target="_blank"}
|
||||
Watch a video from Alexander Lichter to dig deeper into the difference between `useFetch` and `useAsyncData`.
|
||||
::
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
---
|
||||
title: 'State Management'
|
||||
description: Nuxt provides powerful state management libraries and the useState composable to create a reactive and SSR-friendly shared state.
|
||||
navigation.icon: i-ph-database-duotone
|
||||
navigation.icon: i-ph-database
|
||||
---
|
||||
|
||||
Nuxt provides the [`useState`](/docs/api/composables/use-state) composable to create a reactive and SSR-friendly shared state across components.
|
||||
|
||||
[`useState`](/docs/api/composables/use-state) is an SSR-friendly [`ref`](https://vuejs.org/api/reactivity-core.html#ref) replacement. Its value will be preserved after server-side rendering (during client-side hydration) and shared across all components using a unique key.
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=mv0WcBABcIk" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=mv0WcBABcIk" target="_blank"}
|
||||
Watch a video from Alexander Lichter about why and when to use `useState()`.
|
||||
::
|
||||
|
||||
@ -27,7 +27,7 @@ Never define `const state = ref()` outside of `<script setup>` or `setup()` func
|
||||
For example, doing `export myState = ref({})` would result in state shared across requests on the server and can lead to memory leaks.
|
||||
::
|
||||
|
||||
::tip{icon="i-ph-check-circle-duotone"}
|
||||
::tip{icon="i-ph-check-circle"}
|
||||
Instead use `const useX = () => useState('x')`
|
||||
::
|
||||
|
||||
@ -212,7 +212,7 @@ 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"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=dZSNW07sO-A" target="_blank"}
|
||||
Watch a video from Daniel Roe on how to deal with global state and SSR in Nuxt.
|
||||
::
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Error Handling'
|
||||
description: 'Learn how to catch and handle errors in Nuxt.'
|
||||
navigation.icon: i-ph-bug-beetle-duotone
|
||||
navigation.icon: i-ph-bug-beetle
|
||||
---
|
||||
|
||||
Nuxt is a full-stack framework, which means there are several sources of unpreventable user runtime errors that can happen in different contexts:
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Server'
|
||||
description: Build full-stack applications with Nuxt's server framework. You can fetch data from your database or another server, create APIs, or even generate static server-side content like a sitemap or a RSS feed - all from a single codebase.
|
||||
navigation.icon: i-ph-computer-tower-duotone
|
||||
navigation.icon: i-ph-computer-tower
|
||||
---
|
||||
|
||||
:read-more{to="/docs/guide/directory-structure/server"}
|
||||
@ -20,7 +20,7 @@ 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"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=DkvgJa-X31k" target="_blank"}
|
||||
Watch a video from Alexander Lichter to understand the responsibilities of Nuxt and Nitro in your application.
|
||||
::
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: 'Layers'
|
||||
description: Nuxt provides a powerful system that allows you to extend the default files, configs, and much more.
|
||||
navigation.icon: i-ph-stack-duotone
|
||||
navigation.icon: i-ph-stack
|
||||
---
|
||||
|
||||
One of the core features of Nuxt is the layers and extending support. You can extend a default Nuxt application to reuse components, utils, and configuration. The layers structure is almost identical to a standard Nuxt application which makes them easy to author and maintain.
|
||||
@ -53,11 +53,11 @@ Nuxt uses [unjs/c12](https://c12.unjs.io) and [unjs/giget](https://giget.unjs.io
|
||||
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"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=lnFCM7c9f7I" target="_blank"}
|
||||
Watch a video from Learn Vue about Nuxt Layers.
|
||||
::
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=fr5yo3aVkfA" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=fr5yo3aVkfA" target="_blank"}
|
||||
Watch a video from Alexander Lichter about Nuxt Layers.
|
||||
::
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
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
|
||||
navigation.icon: i-ph-code-block
|
||||
---
|
||||
|
||||
Nuxt allows for select pages from your application to be rendered at build time. Nuxt will serve the prebuilt pages when requested instead of generating them on the fly.
|
||||
@ -105,7 +105,7 @@ 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"}
|
||||
::read-more{to="/docs/guide/going-further/experimental-features#inlinerouterules" icon="i-ph-star"}
|
||||
This feature is experimental and in order to use it you must enable the `experimental.inlineRouteRules` option in your `nuxt.config`.
|
||||
::
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: Get Started
|
||||
titleTemplate: '%s · Get Started with Nuxt'
|
||||
icon: i-ph-rocket-launch-duotone
|
||||
icon: i-ph-rocket-launch
|
||||
|
@ -7,16 +7,16 @@ surround: false
|
||||
---
|
||||
|
||||
::card-group{class="sm:grid-cols-1"}
|
||||
::card{icon="i-ph-medal-duotone" title="Key Concepts" to="/docs/guide/concepts"}
|
||||
::card{icon="i-ph-medal" title="Key Concepts" to="/docs/guide/concepts"}
|
||||
Discover the main concepts behind Nuxt, from auto-import, hybrid rendering to its TypeScript support.
|
||||
::
|
||||
::card{icon="i-ph-folders-duotone" title="Directory Structure" to="/docs/guide/directory-structure"}
|
||||
::card{icon="i-ph-folders" title="Directory Structure" to="/docs/guide/directory-structure"}
|
||||
Learn about Nuxt directory structure and what benefits each directory or file offers.
|
||||
::
|
||||
::card{icon="i-ph-star-duotone" title="Going Further" to="/docs/guide/going-further"}
|
||||
::card{icon="i-ph-star" title="Going Further" to="/docs/guide/going-further"}
|
||||
Master Nuxt with advanced concepts like experimental features, hooks, modules, and more.
|
||||
::
|
||||
::card{icon="i-ph-book-open-duotone" title="Recipes" to="/docs/guide/recipes"}
|
||||
::card{icon="i-ph-book-open" title="Recipes" to="/docs/guide/recipes"}
|
||||
Find solutions to common problems and learn how to implement them in your Nuxt project.
|
||||
::
|
||||
::
|
||||
|
@ -33,7 +33,7 @@ Nuxt auto-imports functions and composables to perform [data fetching](/docs/get
|
||||
|
||||
```vue twoslash
|
||||
<script setup lang="ts">
|
||||
/* useAsyncData() and $fetch() are auto-imported */
|
||||
/* useFetch() is auto-imported */
|
||||
const { data, refresh, status } = await useFetch('/api/hello')
|
||||
</script>
|
||||
```
|
||||
@ -60,11 +60,15 @@ That means that (with very few exceptions) you cannot use them outside a Nuxt pl
|
||||
|
||||
If you get an error message like `Nuxt instance is unavailable` then it probably means you are calling a Nuxt composable in the wrong place in the Vue or Nuxt lifecycle.
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=ofuKRZLtOdY" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=ofuKRZLtOdY" target="_blank"}
|
||||
Watch a video from Alexander Lichter about handling async code in composables and fixing `Nuxt instance is unavailable` in your app.
|
||||
::
|
||||
|
||||
::read-more{to="/docs/guide/going-further/experimental-features#asynccontext" icon="i-ph-star-duotone"}
|
||||
::tip
|
||||
When using a composable that requires the Nuxt context inside a non-SFC component, you need to wrap your component with `defineNuxtComponent` instead of `defineComponent`
|
||||
::
|
||||
|
||||
::read-more{to="/docs/guide/going-further/experimental-features#asynccontext" icon="i-ph-star"}
|
||||
Checkout the `asyncContext` experimental feature to use Nuxt composables in async functions.
|
||||
::
|
||||
|
||||
@ -178,6 +182,6 @@ export default defineNuxtConfig({
|
||||
})
|
||||
```
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=FT2LQJ2NvVI" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=FT2LQJ2NvVI" target="_blank"}
|
||||
Watch a video from Alexander Lichter on how to easily set up custom auto imports.
|
||||
::
|
||||
|
@ -11,18 +11,41 @@ By default, Nuxt uses **universal rendering** to provide better user experience,
|
||||
|
||||
## Universal Rendering
|
||||
|
||||
When the browser requests a URL with universal (server-side + client-side) rendering enabled, the server returns a fully rendered HTML page to the browser. Whether the page has been generated in advance and cached or is rendered on the fly, at some point, Nuxt has run the JavaScript (Vue.js) code in a server environment, producing an HTML document. Users immediately get the content of our application, contrary to client-side rendering. This step is similar to traditional **server-side rendering** performed by PHP or Ruby applications.
|
||||
This step is similar to traditional **server-side rendering** performed by PHP or Ruby applications. When the browser requests a URL with universal rendering enabled, Nuxt runs the JavaScript (Vue.js) code in a server environment and returns a fully rendered HTML page to the browser. Nuxt may also return a fully rendered HTML page from a cache if the page was generated in advance. Users immediately get the entirety of the initial content of the application, contrary to client-side rendering.
|
||||
|
||||
To not lose the benefits of the client-side rendering method, such as dynamic interfaces and pages transitions, the Client (browser) loads the JavaScript code that runs on the Server in the background once the HTML document has been downloaded. The browser interprets it again (hence **Universal rendering**) and Vue.js takes control of the document and enables interactivity.
|
||||
|
||||
Making a static page interactive in the browser is called "Hydration".
|
||||
Once the HTML document has been downloaded, the browser interprets this and Vue.js takes control of the document. The same JavaScript code that once ran on the server runs on the client (browser) **again** in the background now enabling interactivity (hence **Universal rendering**) by binding its listeners to the HTML. This is called **Hydration**. When hydration is complete, the page can enjoy benefits such as dynamic interfaces and page transitions.
|
||||
|
||||
Universal rendering allows a Nuxt application to provide quick page load times while preserving the benefits of client-side rendering. Furthermore, as the content is already present in the HTML document, crawlers can index it without overhead.
|
||||
|
||||
![Users can access the static content when the HTML document is loaded. Hydration then allows page's interactivity](/assets/docs/concepts/rendering/ssr.svg)
|
||||
|
||||
**What's server-rendered and what's client-rendered?**
|
||||
|
||||
It is normal to ask which parts of a Vue file runs on the server and/or the client in universal rendering mode.
|
||||
|
||||
```vue [app.vue]
|
||||
<script setup lang="ts">
|
||||
const counter = ref(0); // executes in server and client environments
|
||||
|
||||
const handleClick = () => {
|
||||
counter.value++; // executes only in a client environment
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p>Count: {{ counter }}</p>
|
||||
<button @click="handleClick">Increment</button>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
On the initial request, the `counter` ref is initialized in the server since it is rendered inside the `<p>` tag. The contents of `handleClick` is never executed here. During hydration in the browser, the `counter` ref is re-initialized. The `handleClick` finally binds itself to the button; Therefore it is reasonable to deduce that the body of `handleClick` will always run in a browser environment.
|
||||
|
||||
[Middlewares](/docs/guide/directory-structure/middleware) and [pages](/docs/guide/directory-structure/pages) run in the server and on the client during hydration. [Plugins](/docs/guide/directory-structure/plugins) can be rendered on the server or client or both. [Components](/docs/guide/directory-structure/components) can be forced to run on the client only as well. [Composables](/docs/guide/directory-structure/composables) and [utilities](/docs/guide/directory-structure/utils) are rendered based on the context of their usage.
|
||||
|
||||
**Benefits of server-side rendering:**
|
||||
- **Performance**: Users can get immediate access to the page's content because browsers can display static content much faster than JavaScript-generated content. At the same time, Nuxt preserves the interactivity of a web application when the hydration process happens.
|
||||
- **Performance**: Users can get immediate access to the page's content because browsers can display static content much faster than JavaScript-generated content. At the same time, Nuxt preserves the interactivity of a web application during the hydration process.
|
||||
- **Search Engine Optimization**: Universal rendering delivers the entire HTML content of the page to the browser as a classic server application. Web crawlers can directly index the page's content, which makes Universal rendering a great choice for any content that you want to index quickly.
|
||||
|
||||
**Downsides of server-side rendering:**
|
||||
@ -116,7 +139,7 @@ export default defineNuxtConfig({
|
||||
'/': { prerender: true },
|
||||
// Products page generated on demand, revalidates in background, cached until API response changes
|
||||
'/products': { swr: true },
|
||||
// Product page generated on demand, revalidates in background, cached for 1 hour (3600 seconds)
|
||||
// Product pages generated on demand, revalidates in background, cached for 1 hour (3600 seconds)
|
||||
'/products/**': { swr: 3600 },
|
||||
// Blog posts page generated on demand, revalidates in background, cached on CDN for 1 hour (3600 seconds)
|
||||
'/blog': { isr: 3600 },
|
||||
@ -136,7 +159,7 @@ export default defineNuxtConfig({
|
||||
|
||||
The different properties you can use are the following:
|
||||
- `redirect: string`{lang=ts} - Define server-side redirects.
|
||||
- `ssr: boolean`{lang=ts} - Disables server-side rendering for sections of your app and make them SPA-only with `ssr: false`
|
||||
- `ssr: boolean`{lang=ts} - Disables server-side rendering of the HTML for sections of your app and make them render only in the browser with `ssr: false`
|
||||
- `cors: boolean`{lang=ts} - Automatically adds cors headers with `cors: true` - you can customize the output by overriding with `headers`
|
||||
- `headers: object`{lang=ts} - Add specific headers to sections of your site - for example, your assets
|
||||
- `swr: number | boolean`{lang=ts} - Add cache headers to the server response and cache it on the server or reverse proxy for a configurable TTL (time to live). The `node-server` preset of Nitro is able to cache the full response. When the TTL expired, the cached response will be sent while the page will be regenerated in the background. If true is used, a `stale-while-revalidate` header is added without a MaxAge.
|
||||
|
@ -51,7 +51,7 @@ You can access these types when using [`$fetch()`](/docs/api/utils/dollarfetch)
|
||||
|
||||
Nitro produces a standalone server dist that is independent of `node_modules`.
|
||||
|
||||
The server in Nuxt 2 is not standalone and requires part of Nuxt core to be involved by running `nuxt start` (with the [`nuxt-start`](https://www.npmjs.com/package/nuxt-start) or [`nuxt`](https://www.npmjs.com/package/nuxt) distributions) or custom programmatic usage, which is fragile and prone to breakage and not suitable for serverless and service-worker environments.
|
||||
The server in Nuxt 2 is not standalone and requires part of Nuxt core to be involved by running `nuxt start` (with the [`nuxt-start`](https://www.npmjs.com/package/nuxt-start) or [`nuxt`](https://www.npmjs.com/package/nuxt) distributions) or custom programmatic usage, which is fragile and prone to breakage and not suitable for serverless and service worker environments.
|
||||
|
||||
Nuxt generates this dist when running `nuxt build` into a [`.output`](/docs/guide/directory-structure/output) directory.
|
||||
|
||||
|
@ -61,7 +61,7 @@ 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"}
|
||||
::tip{icon="i-ph-video" to="https://youtu.be/umLI7SlPygY" target="_blank"}
|
||||
Watch a video from Daniel Roe explaining built-in Nuxt aliases.
|
||||
::
|
||||
|
||||
|
@ -7,7 +7,7 @@ description: "Nuxt supports ESLint out of the box"
|
||||
|
||||
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.
|
||||
|
||||
:::callout{icon="i-ph-lightbulb-duotone"}
|
||||
:::callout{icon="i-ph-lightbulb"}
|
||||
The module is designed for the [new ESLint flat config format](https://eslint.org/docs/latest/use/configure/configuration-files-new) with is the [default format since ESLint v9](https://eslint.org/blog/2024/04/eslint-v9.0.0-released/).
|
||||
|
||||
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.
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: Key Concepts
|
||||
titleTemplate: '%s · Nuxt Concepts'
|
||||
icon: i-ph-medal-duotone
|
||||
icon: i-ph-medal
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: ".nuxt"
|
||||
description: "Nuxt uses the .nuxt/ directory in development to generate your Vue application."
|
||||
head.title: ".nuxt/"
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
::important
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: ".output"
|
||||
description: "Nuxt creates the .output/ directory when building your application for production."
|
||||
head.title: ".output/"
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
::important
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "assets"
|
||||
description: "The assets/ directory is used to add all the website's assets that the build tool will process."
|
||||
head.title: "assets/"
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
The directory usually contains the following types of files:
|
||||
|
@ -2,15 +2,15 @@
|
||||
title: "components"
|
||||
head.title: "components/"
|
||||
description: "The components/ directory is where you put all your Vue components."
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
Nuxt automatically imports any components in this directory (along with components that are registered by any modules you may be using).
|
||||
|
||||
```bash [Directory Structure]
|
||||
| components/
|
||||
--| AppHeader.vue
|
||||
--| AppFooter.vue
|
||||
-| components/
|
||||
---| AppHeader.vue
|
||||
---| AppFooter.vue
|
||||
```
|
||||
|
||||
```html [app.vue]
|
||||
@ -28,10 +28,10 @@ Nuxt automatically imports any components in this directory (along with componen
|
||||
If you have a component in nested directories such as:
|
||||
|
||||
```bash [Directory Structure]
|
||||
| components/
|
||||
--| base/
|
||||
----| foo/
|
||||
------| Button.vue
|
||||
-| components/
|
||||
---| base/
|
||||
-----| foo/
|
||||
-------| Button.vue
|
||||
```
|
||||
|
||||
... then the component's name will be based on its own path directory and filename, with duplicate segments being removed. Therefore, the component's name will be:
|
||||
@ -82,6 +82,10 @@ const MyButton = resolveComponent('MyButton')
|
||||
If you are using `resolveComponent` to handle dynamic components, make sure not to insert anything but the name of the component, which must be a string and not a variable.
|
||||
::
|
||||
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=4kq8E5IUM2U" target="\_blank"}
|
||||
Watch Daniel Roe's short video about `resolveComponent`.
|
||||
::
|
||||
|
||||
Alternatively, though not recommended, you can register all your components globally, which will create async chunks for all your components and make them available throughout your application.
|
||||
|
||||
```diff
|
||||
@ -166,6 +170,10 @@ export default defineNuxtConfig({
|
||||
})
|
||||
```
|
||||
|
||||
::note
|
||||
Any nested directories need to be added first as they are scanned in order.
|
||||
::
|
||||
|
||||
## npm Packages
|
||||
|
||||
If you want to auto-import components from an npm package, you can use [`addComponent`](/docs/api/kit/components#addcomponent) in a [local module](/docs/guide/directory-structure/modules) to register them.
|
||||
@ -198,10 +206,6 @@ export default defineNuxtModule({
|
||||
|
||||
::
|
||||
|
||||
::note
|
||||
Any nested directories need to be added first as they are scanned in order.
|
||||
::
|
||||
|
||||
## Component Extensions
|
||||
|
||||
By default, any file with an extension specified in the [extensions key of `nuxt.config.ts`](/docs/api/nuxt-config#extensions) is treated as a component.
|
||||
@ -254,11 +258,11 @@ Server components allow server-rendering individual components within your clien
|
||||
|
||||
Server components can either be used on their own or paired with a [client component](#paired-with-a-client-component).
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=u1yyXe86xJM" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=u1yyXe86xJM" target="_blank"}
|
||||
Watch Learn Vue video about Nuxt Server Components.
|
||||
::
|
||||
|
||||
::tip{icon="i-ph-article-duotone" to="https://roe.dev/blog/nuxt-server-components" target="_blank"}
|
||||
::tip{icon="i-ph-article" to="https://roe.dev/blog/nuxt-server-components" target="_blank"}
|
||||
Read Daniel Roe's guide to Nuxt Server Components.
|
||||
::
|
||||
|
||||
@ -281,8 +285,8 @@ export default defineNuxtConfig({
|
||||
Now you can register server-only components with the `.server` suffix and use them anywhere in your application automatically.
|
||||
|
||||
```bash [Directory Structure]
|
||||
| components/
|
||||
--| HighlightedMarkdown.server.vue
|
||||
-| components/
|
||||
---| HighlightedMarkdown.server.vue
|
||||
```
|
||||
|
||||
```vue [pages/example.vue]
|
||||
@ -355,9 +359,9 @@ Slots can be interactive and are wrapped within a `<div>` with `display: content
|
||||
In this case, the `.server` + `.client` components are two 'halves' of a component and can be used in advanced use cases for separate implementations of a component on server and client side.
|
||||
|
||||
```bash [Directory Structure]
|
||||
| components/
|
||||
--| Comments.client.vue
|
||||
--| Comments.server.vue
|
||||
-| components/
|
||||
---| Comments.client.vue
|
||||
---| Comments.server.vue
|
||||
```
|
||||
|
||||
```vue [pages/example.vue]
|
||||
@ -385,15 +389,15 @@ You can use the `components:dirs` hook to extend the directory list without requ
|
||||
Imagine a directory structure like this:
|
||||
|
||||
```bash [Directory Structure]
|
||||
| node_modules/
|
||||
-| node_modules/
|
||||
---| awesome-ui/
|
||||
------| components/
|
||||
---------| Alert.vue
|
||||
---------| Button.vue
|
||||
------| nuxt.js
|
||||
| pages/
|
||||
-----| components/
|
||||
-------| Alert.vue
|
||||
-------| Button.vue
|
||||
-----| nuxt.js
|
||||
-| pages/
|
||||
---| index.vue
|
||||
| nuxt.config.js
|
||||
-| nuxt.config.js
|
||||
```
|
||||
|
||||
Then in `awesome-ui/nuxt.js` you can use the `components:dirs` hook:
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 'composables'
|
||||
head.title: 'composables/'
|
||||
description: Use the composables/ directory to auto-import your Vue composables into your application.
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
## Usage
|
||||
@ -85,11 +85,11 @@ export const useHello = () => {
|
||||
Nuxt only scans files at the top level of the [`composables/` directory](/docs/guide/directory-structure/composables), e.g.:
|
||||
|
||||
```bash [Directory Structure]
|
||||
| composables/
|
||||
-| composables/
|
||||
---| index.ts // scanned
|
||||
---| useFoo.ts // scanned
|
||||
-----| nested/
|
||||
-------| utils.ts // not scanned
|
||||
---| nested/
|
||||
-----| utils.ts // not scanned
|
||||
```
|
||||
|
||||
Only `composables/index.ts` and `composables/useFoo.ts` would be searched for imports.
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 'content'
|
||||
head.title: 'content/'
|
||||
description: Use the content/ directory to create a file-based CMS for your application.
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
[Nuxt Content](https://content.nuxt.com) reads the [`content/` directory](/docs/guide/directory-structure/content) in your project and parses `.md`, `.yml`, `.csv` and `.json` files to create a file-based CMS for your application.
|
||||
|
@ -2,10 +2,10 @@
|
||||
title: "layouts"
|
||||
head.title: "layouts/"
|
||||
description: "Nuxt provides a layouts framework to extract common UI patterns into reusable layouts."
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
::tip{icon="i-ph-rocket-launch-duotone" color="gray" }
|
||||
::tip{icon="i-ph-rocket-launch" color="gray" }
|
||||
For best performance, components placed in this directory will be automatically loaded via asynchronous import when used.
|
||||
::
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "middleware"
|
||||
description: "Nuxt provides middleware to run code before navigating to a particular route."
|
||||
head.title: "middleware/"
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
Nuxt provides a customizable **route middleware** framework you can use throughout your application, ideal for extracting code that you want to run before navigating to a particular route.
|
||||
@ -72,11 +72,11 @@ Middleware runs in the following order:
|
||||
|
||||
For example, assuming you have the following middleware and component:
|
||||
|
||||
```text [middleware/ directory]
|
||||
middleware/
|
||||
--| analytics.global.ts
|
||||
--| setup.global.ts
|
||||
--| auth.ts
|
||||
```bash [middleware/ directory]
|
||||
-| middleware/
|
||||
---| analytics.global.ts
|
||||
---| setup.global.ts
|
||||
---| auth.ts
|
||||
```
|
||||
|
||||
```vue twoslash [pages/profile.vue]
|
||||
@ -105,11 +105,11 @@ By default, global middleware is executed alphabetically based on the filename.
|
||||
|
||||
However, there may be times you want to define a specific order. For example, in the last scenario, `setup.global.ts` may need to run before `analytics.global.ts`. In that case, we recommend prefixing global middleware with 'alphabetical' numbering.
|
||||
|
||||
```text [Directory structure]
|
||||
middleware/
|
||||
--| 01.setup.global.ts
|
||||
--| 02.analytics.global.ts
|
||||
--| auth.ts
|
||||
```bash [Directory structure]
|
||||
-| middleware/
|
||||
---| 01.setup.global.ts
|
||||
---| 02.analytics.global.ts
|
||||
---| auth.ts
|
||||
```
|
||||
|
||||
::note
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 'modules'
|
||||
head.title: 'modules/'
|
||||
description: Use the modules/ directory to automatically register local modules within your application.
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
It is a good place to place any local modules you develop while building your application.
|
||||
@ -61,6 +61,6 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/creating-your-first-module-from-scratch?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about Nuxt private modules.
|
||||
::
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "node_modules"
|
||||
description: "The package manager stores the dependencies of your project in the node_modules/ directory."
|
||||
head.title: "node_modules/"
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
The package manager ([`npm`](https://docs.npmjs.com/cli/commands/npm) or [`yarn`](https://yarnpkg.com) or [`pnpm`](https://pnpm.io/cli/install) or [`bun`](https://bun.sh/package-manager)) creates this directory to store the dependencies of your project.
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "pages"
|
||||
description: "Nuxt provides file-based routing to create routes within your web application."
|
||||
head.title: "pages/"
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
::note
|
||||
@ -159,7 +159,7 @@ Example:
|
||||
```bash [Directory Structure]
|
||||
-| pages/
|
||||
---| parent/
|
||||
------| child.vue
|
||||
-----| child.vue
|
||||
---| parent.vue
|
||||
```
|
||||
|
||||
@ -408,7 +408,7 @@ However, you can use [Nuxt Layers](/docs/getting-started/layers) to create group
|
||||
```bash [Directory Structure]
|
||||
-| some-app/
|
||||
---| nuxt.config.ts
|
||||
---| pages
|
||||
---| pages/
|
||||
-----| app-page.vue
|
||||
-| nuxt.config.ts
|
||||
```
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "plugins"
|
||||
description: "Nuxt has a plugins system to use Vue plugins and more at the creation of your Vue application."
|
||||
head.title: "plugins/"
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
Nuxt automatically reads the files in the `plugins/` directory and loads them at the creation of the Vue application.
|
||||
@ -76,7 +76,7 @@ export default defineNuxtPlugin({
|
||||
})
|
||||
```
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=2aXZyXB1QGQ" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=2aXZyXB1QGQ" target="_blank"}
|
||||
Watch a video from Alexander Lichter about the Object Syntax for Nuxt plugins.
|
||||
::
|
||||
|
||||
@ -108,7 +108,7 @@ In case you're new to 'alphabetical' numbering, remember that filenames are sort
|
||||
|
||||
### Parallel Plugins
|
||||
|
||||
By default, Nuxt loads plugins sequentially. You can define a plugin as `parallel` so Nuxt won't wait the end of the plugin's execution before loading the next plugin.
|
||||
By default, Nuxt loads plugins sequentially. You can define a plugin as `parallel` so Nuxt won't wait until the end of the plugin's execution before loading the next plugin.
|
||||
|
||||
```ts twoslash [plugins/my-plugin.ts]
|
||||
export default defineNuxtPlugin({
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "public"
|
||||
description: "The public/ directory is used to serve your website's static assets."
|
||||
head.title: "public/"
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
Files contained within the `public/` directory are served at the root and are not modified by the build process. This is suitable for files that have to keep their names (e.g. `robots.txt`) _or_ likely won't change (e.g. `favicon.ico`).
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: server
|
||||
head.title: 'server/'
|
||||
description: The server/ directory is used to register API and server handlers to your application.
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
Nuxt automatically scans files inside these directories to register API and server handlers with Hot Module Replacement (HMR) support.
|
||||
@ -347,6 +347,22 @@ export default defineEventHandler((event) => {
|
||||
})
|
||||
```
|
||||
|
||||
### Forwarding Context & Headers
|
||||
|
||||
By default, neither the headers from the incoming request nor the request context are forwarded when
|
||||
making fetch requests in server routes. You can use `event.$fetch` to forward the request context and headers when making fetch requests in server routes.
|
||||
|
||||
```ts [server/api/forward.ts]
|
||||
export default defineEventHandler((event) => {
|
||||
return event.$fetch('/api/forwarded')
|
||||
})
|
||||
```
|
||||
|
||||
::note
|
||||
Headers that are **not meant to be forwarded** will **not be included** in the request. These headers include, for example:
|
||||
`transfer-encoding`, `connection`, `keep-alive`, `upgrade`, `expect`, `host`, `accept`
|
||||
::
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Nitro Config
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: 'utils'
|
||||
head.title: 'utils/'
|
||||
description: Use the utils/ directory to auto-import your utility functions throughout your application.
|
||||
navigation.icon: i-ph-folder-duotone
|
||||
navigation.icon: i-ph-folder
|
||||
---
|
||||
|
||||
The main purpose of the [`utils/` directory](/docs/guide/directory-structure/utils) is to allow a semantic distinction between your Vue composables and other auto-imported utility functions.
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: ".env"
|
||||
description: "A .env file specifies your build/dev-time environment variables."
|
||||
head.title: ".env"
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
::important
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: ".gitignore"
|
||||
description: "A .gitignore file specifies intentionally untracked files that git should ignore."
|
||||
head.title: ".gitignore"
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
A `.gitignore` file specifies intentionally untracked files that git should ignore.
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: .nuxtignore
|
||||
head.title: '.nuxtignore'
|
||||
description: The .nuxtignore file lets Nuxt ignore files in your project’s root directory during the build phase.
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
The `.nuxtignore` file tells Nuxt to ignore files in your project’s root directory ([`rootDir`](/docs/api/nuxt-config#rootdir)) during the build phase.
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: app.config.ts
|
||||
head.title: 'app.config.ts'
|
||||
description: Expose reactive configuration within your application with the App Config file.
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
Nuxt provides an `app.config` config file to expose reactive configuration within your application with the ability to update it at runtime within lifecycle or using a nuxt plugin and editing it with HMR (hot-module-replacement).
|
||||
@ -121,3 +121,37 @@ export default defineAppConfig({
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
## Known Limitations
|
||||
|
||||
As of Nuxt v3.3, the `app.config.ts` file is shared with Nitro, which results in the following limitations:
|
||||
|
||||
1. You cannot import Vue components directly in `app.config.ts`.
|
||||
2. Some auto-imports are not available in the Nitro context.
|
||||
|
||||
These limitations occur because Nitro processes the app config without full Vue component support.
|
||||
|
||||
While it's possible to use Vite plugins in the Nitro config as a workaround, this approach is not recommended:
|
||||
|
||||
```ts [nuxt.config.ts]
|
||||
export default defineNuxtConfig({
|
||||
nitro: {
|
||||
vite: {
|
||||
plugins: [vue()]
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::warning
|
||||
Using this workaround may lead to unexpected behavior and bugs. The Vue plugin is one of many that are not available in the Nitro context.
|
||||
::
|
||||
|
||||
Related issues:
|
||||
- [Issue #19858](https://github.com/nuxt/nuxt/issues/19858)
|
||||
- [Issue #19854](https://github.com/nuxt/nuxt/issues/19854)
|
||||
|
||||
::info
|
||||
Nitro v3 will resolve these limitations by removing support for the app config.
|
||||
You can track the progress in [this pull request](https://github.com/unjs/nitro/pull/2521).
|
||||
::
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "app.vue"
|
||||
description: "The app.vue file is the main component of your Nuxt application."
|
||||
head.title: "app.vue"
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
## Minimal Usage
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "error.vue"
|
||||
description: "The error.vue file is the error page in your Nuxt application."
|
||||
head.title: "error.vue"
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
During the lifespan of your application, some errors may appear unexpectedly at runtime. In such case, we can use the `error.vue` file to override the default error files and display the error nicely.
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "nuxt.config.ts"
|
||||
description: "Nuxt can be easily configured with a single nuxt.config file."
|
||||
head.title: "nuxt.config.ts"
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
The `nuxt.config` file extension can either be `.js`, `.ts` or `.mjs`.
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: package.json
|
||||
head.title: package.json
|
||||
description: The package.json file contains all the dependencies and scripts for your application.
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
The minimal `package.json` of your Nuxt application should looks like:
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: "tsconfig.json"
|
||||
description: "Nuxt generates a .nuxt/tsconfig.json file with sensible defaults and your aliases."
|
||||
head.title: "tsconfig.json"
|
||||
navigation.icon: i-ph-file-duotone
|
||||
navigation.icon: i-ph-file
|
||||
---
|
||||
|
||||
Nuxt [automatically generates](/docs/guide/concepts/typescript) a `.nuxt/tsconfig.json` file with the resolved aliases you are using in your Nuxt project, as well as with other sensible defaults.
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: Directory Structure
|
||||
titleTemplate: '%s · Nuxt Directory Structure'
|
||||
icon: i-ph-folders-duotone
|
||||
icon: i-ph-folders
|
||||
|
@ -104,11 +104,11 @@ export default defineNuxtConfig({
|
||||
|
||||
Matching route rules will be created, based on the page's `path`.
|
||||
|
||||
::read-more{to="/docs/api/utils/define-route-rules" icon="i-ph-function-duotone"}
|
||||
::read-more{to="/docs/api/utils/define-route-rules" icon="i-ph-function"}
|
||||
Read more in `defineRouteRules` utility.
|
||||
::
|
||||
|
||||
:read-more{to="/docs/guide/concepts/rendering#hybrid-rendering" icon="i-ph-medal-duotone"}
|
||||
:read-more{to="/docs/guide/concepts/rendering#hybrid-rendering" icon="i-ph-medal"}
|
||||
|
||||
## renderJsonPayloads
|
||||
|
||||
@ -254,7 +254,7 @@ 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"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=SXk-L19gTZk" target="_blank"}
|
||||
Watch a video from Daniel Roe explaining type-safe routing in Nuxt.
|
||||
::
|
||||
|
||||
@ -292,7 +292,7 @@ export default defineNuxtConfig({
|
||||
})
|
||||
```
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=1jUupYHVvrU" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=1jUupYHVvrU" target="_blank"}
|
||||
Watch a video from Alexander Lichter about the experimental `sharedPrerenderData` setting.
|
||||
::
|
||||
|
||||
@ -390,3 +390,31 @@ In addition, any changes to files within `srcDir` will trigger a rebuild of the
|
||||
::note
|
||||
A maximum of 10 cache tarballs are kept.
|
||||
::
|
||||
|
||||
## normalizeComponentNames
|
||||
|
||||
Ensure that auto-generated Vue component names match the full component name
|
||||
you would use to auto-import the component.
|
||||
|
||||
```ts twoslash [nuxt.config.ts]
|
||||
export default defineNuxtConfig({
|
||||
experimental: {
|
||||
normalizeComponentNames: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
By default, if you haven't set it manually, Vue will assign a component name that matches
|
||||
the filename of the component.
|
||||
|
||||
```bash [Directory structure]
|
||||
├─ components/
|
||||
├─── SomeFolder/
|
||||
├───── MyComponent.vue
|
||||
```
|
||||
|
||||
In this case, the component name would be `MyComponent`, as far as Vue is concerned. If you wanted to use `<KeepAlive>` with it, or identify it in the Vue DevTools, you would need to use this component.
|
||||
|
||||
But in order to auto-import it, you would need to use `SomeFolderMyComponent`.
|
||||
|
||||
By setting `experimental.normalizeComponentNames`, these two values match, and Vue will generate a component name that matches the Nuxt pattern for component naming.
|
||||
|
@ -61,9 +61,12 @@ export default defineNuxtConfig({
|
||||
app: 'app'
|
||||
},
|
||||
experimental: {
|
||||
sharedPrerenderData: false,
|
||||
compileTemplate: true,
|
||||
resetAsyncDataToUndefined: true,
|
||||
templateUtils: true,
|
||||
relativeWatchPaths: true,
|
||||
normalizeComponentNames: false
|
||||
defaults: {
|
||||
useAsyncData: {
|
||||
deep: true
|
||||
|
@ -61,7 +61,7 @@ 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"}
|
||||
::tip{icon="i-ph-video" to="https://youtu.be/_FYV5WfiWvs" target="_blank"}
|
||||
Watch a video from Alexander Lichter showcasing the top mistake developers make using runtimeConfig.
|
||||
::
|
||||
|
||||
|
@ -45,7 +45,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/navigating-the-official-starter-template?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about Nuxt module starter template.
|
||||
::
|
||||
|
||||
@ -274,7 +274,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/extending-and-altering-nuxt-configuration-and-options?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about altering Nuxt configuration.
|
||||
::
|
||||
|
||||
@ -311,7 +311,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/passing-and-exposing-module-options?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about passing and exposing Nuxt module options.
|
||||
::
|
||||
|
||||
@ -538,7 +538,7 @@ export default defineNuxtModule({
|
||||
|
||||
:read-more{to="/docs/api/advanced/hooks"}
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/nuxt-lifecycle-hooks?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/nuxt-lifecycle-hooks?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about using Nuxt lifecycle hooks in modules.
|
||||
::
|
||||
|
||||
@ -764,7 +764,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/exploring-nuxt-modules-ecosystem-and-module-types?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about Nuxt module types.
|
||||
::
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: Going Further
|
||||
titleTemplate: '%s · Nuxt Advanced'
|
||||
icon: i-ph-star-duotone
|
||||
icon: i-ph-star
|
||||
|
@ -22,7 +22,7 @@ export default {
|
||||
{
|
||||
name: 'home',
|
||||
path: '/',
|
||||
component: () => import('~/pages/home.vue').then(r => r.default || r)
|
||||
component: () => import('~/pages/home.vue')
|
||||
}
|
||||
],
|
||||
} satisfies RouterConfig
|
||||
|
@ -31,14 +31,8 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
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}`
|
||||
}
|
||||
// note that this relies on ofetch >= 1.4.0 - you may need to refresh your lockfile
|
||||
options.headers.set('Authorization', `Bearer ${session.value?.token}`)
|
||||
}
|
||||
},
|
||||
async onResponseError({ response }) {
|
||||
@ -96,6 +90,28 @@ const { data: modules } = await useAPI('/modules')
|
||||
</script>
|
||||
```
|
||||
|
||||
If you want to customize the type of any error returned, you can also do so:
|
||||
|
||||
```ts
|
||||
import type { FetchError } from 'ofetch'
|
||||
import type { UseFetchOptions } from 'nuxt/app'
|
||||
|
||||
interface CustomError {
|
||||
message: string
|
||||
statusCode: number
|
||||
}
|
||||
|
||||
export function useAPI<T>(
|
||||
url: string | (() => string),
|
||||
options?: UseFetchOptions<T>,
|
||||
) {
|
||||
return useFetch<T, FetchError<CustomError>>(url, {
|
||||
...options,
|
||||
$fetch: useNuxtApp().$api
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
::note
|
||||
This example demonstrates how to use a custom `useFetch`, but the same structure is identical for a custom `useAsyncData`.
|
||||
::
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: Recipes
|
||||
titleTemplate: '%s · Recipes'
|
||||
icon: i-ph-cooking-pot-duotone
|
||||
icon: i-ph-cooking-pot
|
||||
|
@ -1,2 +1,2 @@
|
||||
title: 'Guide'
|
||||
icon: i-ph-book-open-duotone
|
||||
icon: i-ph-book-open
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: 'Components'
|
||||
titleTemplate: '%s · Nuxt Components'
|
||||
icon: i-ph-cube-duotone
|
||||
icon: i-ph-cube
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: 'Composables'
|
||||
titleTemplate: '%s · Nuxt Composables'
|
||||
icon: i-ph-arrows-left-right-duotone
|
||||
icon: i-ph-arrows-left-right
|
||||
|
@ -114,7 +114,7 @@ function useAsyncData<DataT, DataE>(
|
||||
key: string,
|
||||
handler: (nuxtApp?: NuxtApp) => Promise<DataT>,
|
||||
options?: AsyncDataOptions<DataT>
|
||||
): Promise<AsyncData<DataT, DataE>
|
||||
): Promise<AsyncData<DataT, DataE>>
|
||||
|
||||
type AsyncDataOptions<DataT> = {
|
||||
server?: boolean
|
||||
|
@ -50,8 +50,8 @@ You can also use [interceptors](https://github.com/unjs/ofetch#%EF%B8%8F-interce
|
||||
const { data, status, error, refresh, clear } = await useFetch('/api/auth/login', {
|
||||
onRequest({ request, options }) {
|
||||
// Set the request headers
|
||||
options.headers = options.headers || {}
|
||||
options.headers.authorization = '...'
|
||||
// note that this relies on ofetch >= 1.4.0 - you may need to refresh your lockfile
|
||||
options.headers.set('Authorization', '...')
|
||||
},
|
||||
onRequestError({ request, options, error }) {
|
||||
// Handle the request errors
|
||||
@ -70,7 +70,11 @@ const { data, status, error, refresh, clear } = 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"}
|
||||
::warning
|
||||
If you encounter the `data` variable destructured from a `useFetch` returns a string and not a JSON parsed object then make sure your component doesn't include an import statement like `import { useFetch } from '@vueuse/core`.
|
||||
::
|
||||
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=njsGVmcWviY" target="_blank"}
|
||||
Watch the video from Alexander Lichter to avoid using `useFetch` the wrong way!
|
||||
::
|
||||
|
||||
@ -143,7 +147,7 @@ If you have not fetched data on the server (for example, with `server: false`),
|
||||
|
||||
```ts [Signature]
|
||||
function useFetch<DataT, ErrorT>(
|
||||
url: string | Request | Ref<string | Request> | () => string | Request,
|
||||
url: string | Request | Ref<string | Request> | (() => string) | Request,
|
||||
options?: UseFetchOptions<DataT>
|
||||
): Promise<AsyncData<DataT, ErrorT>>
|
||||
|
||||
|
@ -138,7 +138,7 @@ Nuxt exposes the following properties through `ssrContext`:
|
||||
|
||||
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.
|
||||
|
||||
::tip{icon="i-ph-video-duotone" to="https://www.youtube.com/watch?v=8w6ffRBs8a4" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=8w6ffRBs8a4" target="_blank"}
|
||||
Watch a video from Alexander Lichter about serializing payloads, especially with regards to classes.
|
||||
::
|
||||
|
||||
|
52
docs/3.api/2.composables/use-request-fetch.md
Normal file
52
docs/3.api/2.composables/use-request-fetch.md
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
title: 'useRequestFetch'
|
||||
description: 'Forward the request context and headers for server-side fetch requests with the useRequestFetch composable.'
|
||||
links:
|
||||
- label: Source
|
||||
icon: i-simple-icons-github
|
||||
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/ssr.ts
|
||||
size: xs
|
||||
---
|
||||
|
||||
You can use `useRequestFetch` to forward the request context and headers when making server-side fetch requests.
|
||||
|
||||
When making a client-side fetch request, the browser automatically sends the necessary headers.
|
||||
However, when making a request during server-side rendering, because the request is made on the server, we need to forward the headers manually.
|
||||
|
||||
::note
|
||||
Headers that are **not meant to be forwarded** will **not be included** in the request. These headers include, for example:
|
||||
`transfer-encoding`, `connection`, `keep-alive`, `upgrade`, `expect`, `host`, `accept`
|
||||
::
|
||||
|
||||
::tip
|
||||
The [`useFetch`](/docs/api/composables/use-fetch) composable uses `useRequestFetch` under the hood to automatically forward the request context and headers.
|
||||
::
|
||||
|
||||
::code-group
|
||||
|
||||
```vue [pages/index.vue]
|
||||
<script setup lang="ts">
|
||||
// This will forward the user's headers to the `/api/foo` event handler
|
||||
// Result: { cookies: { foo: 'bar' } }
|
||||
const requestFetch = useRequestFetch()
|
||||
const { data: forwarded } = await useAsyncData(() => requestFetch('/api/cookies'))
|
||||
|
||||
// This will NOT forward anything
|
||||
// Result: { cookies: {} }
|
||||
const { data: notForwarded } = await useAsyncData(() => $fetch('/api/cookies'))
|
||||
</script>
|
||||
```
|
||||
|
||||
```ts [server/api/cookies.ts]
|
||||
export default defineEventHandler((event) => {
|
||||
const cookies = parseCookies(event)
|
||||
|
||||
return { cookies }
|
||||
})
|
||||
```
|
||||
|
||||
::
|
||||
|
||||
::tip
|
||||
In the browser during client-side navigation, `useRequestFetch` will behave just like regular [`$fetch`](/docs/api/utils/dollarfetch).
|
||||
::
|
48
docs/3.api/2.composables/use-response-header.md
Normal file
48
docs/3.api/2.composables/use-response-header.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
title: "useResponseHeader"
|
||||
description: "Use useResponseHeader to set a server response header."
|
||||
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.14+.
|
||||
::
|
||||
|
||||
You can use the built-in [`useResponseHeader`](/docs/api/composables/use-response-header) composable to set any server response header within your pages, components, and plugins.
|
||||
|
||||
```ts
|
||||
// Set the a custom response header
|
||||
const header = useResponseHeader('X-My-Header');
|
||||
header.value = 'my-value';
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
We can use `useResponseHeader` to easily set a response header on a per-page basis.
|
||||
|
||||
```vue [pages/test.vue]
|
||||
<script setup>
|
||||
// pages/test.vue
|
||||
const header = useResponseHeader('X-My-Header');
|
||||
header.value = 'my-value';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1>Test page with custom header</h1>
|
||||
<p>The response from the server for this "/test" page will have a custom "X-My-Header" header.</p>
|
||||
</template>
|
||||
```
|
||||
|
||||
We can use `useResponseHeader` for example in Nuxt [middleware](/docs/guide/directory-structure/middleware) to set a response header for all pages.
|
||||
|
||||
```ts [middleware/my-header-middleware.ts]
|
||||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
const header = useResponseHeader('X-My-Always-Header');
|
||||
header.value = `I'm Always here!`;
|
||||
});
|
||||
|
||||
```
|
@ -25,7 +25,7 @@ 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"}
|
||||
::tip{icon="i-ph-video" to="https://www.youtube.com/watch?v=mv0WcBABcIk" target="_blank"}
|
||||
Watch a video from Alexander Lichter about why and when to use `useState()`.
|
||||
::
|
||||
|
||||
|
@ -10,11 +10,11 @@ links:
|
||||
|
||||
Nuxt uses [ofetch](https://github.com/unjs/ofetch) to expose globally the `$fetch` helper for making HTTP requests within your Vue app or API routes.
|
||||
|
||||
::tip{icon="i-ph-rocket-launch-duotone" color="gray"}
|
||||
::tip{icon="i-ph-rocket-launch" color="gray"}
|
||||
During server-side rendering, calling `$fetch` to fetch your internal [API routes](/docs/guide/directory-structure/server) will directly call the relevant function (emulating the request), **saving an additional API call**.
|
||||
::
|
||||
|
||||
::note{color="blue" icon="i-ph-info-duotone"}
|
||||
::note{color="blue" icon="i-ph-info"}
|
||||
Using `$fetch` in components without wrapping it with [`useAsyncData`](/docs/api/composables/use-async-data) causes fetching the data twice: initially on the server, then again on the client-side during hydration, because `$fetch` does not transfer state from the server to the client. Thus, the fetch will be executed on both sides because the client has to get the data again.
|
||||
::
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: 'Utils'
|
||||
titleTemplate: '%s · Nuxt Utils'
|
||||
navigation.icon: i-ph-function-duotone
|
||||
navigation.icon: i-ph-function
|
||||
|
@ -8,7 +8,7 @@ links:
|
||||
size: xs
|
||||
---
|
||||
|
||||
::read-more{to="/docs/guide/going-further/experimental-features#inlinerouterules" icon="i-ph-star-duotone"}
|
||||
::read-more{to="/docs/guide/going-further/experimental-features#inlinerouterules" icon="i-ph-star"}
|
||||
This feature is experimental and in order to use it you must enable the `experimental.inlineRouteRules` option in your `nuxt.config`.
|
||||
::
|
||||
|
||||
@ -47,6 +47,6 @@ When running [`nuxt build`](/docs/api/commands/build), the home page will be pre
|
||||
|
||||
For more control, such as if you are using a custom `path` or `alias` set in the page's [`definePageMeta`](/docs/api/utils/define-page-meta), you should set `routeRules` directly within your `nuxt.config`.
|
||||
|
||||
::read-more{to="/docs/guide/concepts/rendering#hybrid-rendering" icon="i-ph-medal-duotone"}
|
||||
::read-more{to="/docs/guide/concepts/rendering#hybrid-rendering" icon="i-ph-medal"}
|
||||
Read more about the `routeRules`.
|
||||
::
|
||||
|
@ -10,7 +10,7 @@ links:
|
||||
|
||||
Preloading routes loads the components of a given route that the user might navigate to in future. This ensures that the components are available earlier and less likely to block the navigation, improving performance.
|
||||
|
||||
::tip{icon="i-ph-rocket-launch-duotone" color="gray"}
|
||||
::tip{icon="i-ph-rocket-launch" color="gray"}
|
||||
Nuxt already automatically preloads the necessary routes if you're using the `NuxtLink` component.
|
||||
::
|
||||
|
||||
|
@ -14,7 +14,7 @@ links:
|
||||
|
||||
By default, it will also save the current `state` of your app (that is, any state you could access with `useState`).
|
||||
|
||||
::read-more{to="/docs/guide/going-further/experimental-features#restorestate" icon="i-ph-star-duotone"}
|
||||
::read-more{to="/docs/guide/going-further/experimental-features#restorestate" icon="i-ph-star"}
|
||||
You can enable experimental restoration of this state by enabling the `experimental.restoreState` option in your `nuxt.config` file.
|
||||
::
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
title: 'Commands'
|
||||
icon: i-ph-terminal-window-duotone
|
||||
icon: i-ph-terminal-window
|
||||
titleTemplate: '%s · Nuxt Commands'
|
||||
|
@ -211,7 +211,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/resolving-paths-and-injecting-assets-to-the-app?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about createResolver.
|
||||
::
|
||||
|
||||
|
@ -18,7 +18,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/expanding-nuxt-s-auto-imports?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about Auto-imports Nuxt Kit utilities.
|
||||
::
|
||||
|
||||
|
@ -10,7 +10,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/injecting-components-and-component-directories?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about injecting components.
|
||||
::
|
||||
|
||||
|
@ -12,7 +12,7 @@ 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 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/extend-and-alter-nuxt-pages?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about extendPages.
|
||||
::
|
||||
|
||||
@ -71,7 +71,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/adding-route-rules-and-route-middlewares?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about adding route rules and route middelwares.
|
||||
::
|
||||
|
||||
@ -192,7 +192,7 @@ 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?friend=nuxt" target="_blank"}
|
||||
::tip{icon="i-ph-video" to="https://vueschool.io/lessons/adding-route-rules-and-route-middlewares?friend=nuxt" target="_blank"}
|
||||
Watch Vue School video about adding route rules and route middelwares.
|
||||
::
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user