mirror of
https://github.com/nuxt/nuxt.git
synced 2024-12-02 10:27:15 +00:00
Merge branch 'main' into docs/kit
This commit is contained in:
commit
f9487b6e08
@ -1,5 +0,0 @@
|
|||||||
dist
|
|
||||||
node_modules
|
|
||||||
schema
|
|
||||||
**/*.tmpl.*
|
|
||||||
sw.js
|
|
36
.eslintrc
36
.eslintrc
@ -1,13 +1,17 @@
|
|||||||
{
|
{
|
||||||
|
"ignorePatterns": [
|
||||||
|
"dist",
|
||||||
|
"node_modules",
|
||||||
|
"packages/schema/schema",
|
||||||
|
"**/*.tmpl.*",
|
||||||
|
"sw.js"
|
||||||
|
],
|
||||||
"$schema": "https://json.schemastore.org/eslintrc",
|
"$schema": "https://json.schemastore.org/eslintrc",
|
||||||
"globals": {
|
"globals": {
|
||||||
"NodeJS": true,
|
"NodeJS": true,
|
||||||
"$fetch": true
|
"$fetch": true
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": ["jsdoc", "no-only-tests"],
|
||||||
"jsdoc",
|
|
||||||
"no-only-tests"
|
|
||||||
],
|
|
||||||
"extends": [
|
"extends": [
|
||||||
"plugin:jsdoc/recommended",
|
"plugin:jsdoc/recommended",
|
||||||
"@nuxtjs/eslint-config-typescript",
|
"@nuxtjs/eslint-config-typescript",
|
||||||
@ -96,10 +100,28 @@
|
|||||||
"ignoreRestSiblings": true
|
"ignoreRestSiblings": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"jsdoc/check-tag-names": ["error", {
|
"jsdoc/check-tag-names": [
|
||||||
"definedTags": ["__NO_SIDE_EFFECTS__"]
|
"error",
|
||||||
}]
|
{
|
||||||
|
"definedTags": ["__NO_SIDE_EFFECTS__"]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["packages/schema/**"],
|
||||||
|
"rules": {
|
||||||
|
"jsdoc/no-undefined-types": "off",
|
||||||
|
"jsdoc/valid-types": "off",
|
||||||
|
"jsdoc/check-tag-names": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"definedTags": ["experimental"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"jsdoc": {
|
"jsdoc": {
|
||||||
"ignoreInternal": true,
|
"ignoreInternal": true,
|
||||||
|
2
.github/assets/twitter.svg
vendored
2
.github/assets/twitter.svg
vendored
@ -1 +1 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="39.4" height="32" viewBox="0 0 1231.051 1000"><path fill="#A1A1AA" d="M1231.051 118.453q-51.422 76.487-126.173 130.403q.738 14.46.738 32.687q0 101.273-29.53 202.791q-29.53 101.519-90.215 194.343q-60.685 92.824-144.574 164.468q-83.889 71.644-201.677 114.25q-117.788 42.606-252.474 42.606q-210.2 0-387.147-113.493q31.406 3.495 60.242 3.495q175.605 0 313.687-108.177q-81.877-1.501-146.654-50.409q-64.777-48.907-89.156-124.988q24.097 4.59 47.566 4.59q33.782 0 66.482-8.812q-87.378-17.5-144.975-87.04q-57.595-69.539-57.595-160.523v-3.126q53.633 29.696 114.416 31.592q-51.762-34.508-82.079-89.999q-30.319-55.491-30.319-120.102q0-68.143 34.151-126.908q95.022 116.607 230.278 186.392q135.258 69.786 290.212 77.514q-6.609-27.543-6.621-57.485q0-104.546 73.994-178.534Q747.623 0 852.169 0q109.456 0 184.392 79.711q85.618-16.959 160.333-61.349q-28.785 90.59-110.933 139.768q75.502-8.972 145.088-39.677z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><g><path fill="#A1A1AA" d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 947 B After Width: | Height: | Size: 285 B |
2
.github/workflows/autofix-docs.yml
vendored
2
.github/workflows/autofix-docs.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/autofix.yml
vendored
2
.github/workflows/autofix.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/changelogensets.yml
vendored
2
.github/workflows/changelogensets.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
26
.github/workflows/ci.yml
vendored
26
.github/workflows/ci.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -77,7 +77,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -86,7 +86,7 @@ jobs:
|
|||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v2.21.2
|
uses: github/codeql-action/init@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4
|
||||||
with:
|
with:
|
||||||
languages: javascript
|
languages: javascript
|
||||||
queries: +security-and-quality
|
queries: +security-and-quality
|
||||||
@ -98,7 +98,7 @@ jobs:
|
|||||||
path: packages
|
path: packages
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v2.21.2
|
uses: github/codeql-action/analyze@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4
|
||||||
with:
|
with:
|
||||||
category: "/language:javascript"
|
category: "/language:javascript"
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -144,7 +144,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -169,18 +169,18 @@ jobs:
|
|||||||
os: [ubuntu-latest, windows-latest]
|
os: [ubuntu-latest, windows-latest]
|
||||||
env: ['dev', 'built']
|
env: ['dev', 'built']
|
||||||
builder: ['vite', 'webpack']
|
builder: ['vite', 'webpack']
|
||||||
payload: ['json', 'js']
|
context: ['async', 'default']
|
||||||
node: [16]
|
node: [16]
|
||||||
exclude:
|
exclude:
|
||||||
- env: 'dev'
|
- env: 'dev'
|
||||||
builder: 'webpack'
|
builder: 'webpack'
|
||||||
|
|
||||||
timeout-minutes: 10
|
timeout-minutes: 15
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -231,8 +231,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TEST_ENV: ${{ matrix.env }}
|
TEST_ENV: ${{ matrix.env }}
|
||||||
TEST_BUILDER: ${{ matrix.builder }}
|
TEST_BUILDER: ${{ matrix.builder }}
|
||||||
TEST_PAYLOAD: ${{ matrix.payload }}
|
TEST_CONTEXT: ${{ matrix.context }}
|
||||||
SKIP_BUNDLE_SIZE: ${{ github.event_name != 'push' || matrix.env == 'dev' || matrix.builder == 'webpack' || matrix.payload == 'js' || runner.os == 'Windows' }}
|
SKIP_BUNDLE_SIZE: ${{ github.event_name != 'push' || matrix.env == 'dev' || matrix.builder == 'webpack' || matrix.context == 'default' || runner.os == 'Windows' }}
|
||||||
|
|
||||||
build-release:
|
build-release:
|
||||||
permissions:
|
permissions:
|
||||||
@ -254,7 +254,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
@ -293,7 +293,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/dependency-review.yml
vendored
2
.github/workflows/dependency-review.yml
vendored
@ -19,4 +19,4 @@ jobs:
|
|||||||
- name: 'Checkout Repository'
|
- name: 'Checkout Repository'
|
||||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- name: 'Dependency Review'
|
- name: 'Dependency Review'
|
||||||
uses: actions/dependency-review-action@1360a344ccb0ab6e9475edef90ad2f46bf8003b1 # v3.0.6
|
uses: actions/dependency-review-action@f6fff72a3217f580d5afd49a46826795305b63c7 # v3.0.8
|
||||||
|
2
.github/workflows/docs-e2e.yml
vendored
2
.github/workflows/docs-e2e.yml
vendored
@ -23,7 +23,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
|
||||||
|
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/nuxt2-edge.yml
vendored
2
.github/workflows/nuxt2-edge.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
|||||||
fetch-depth: 0 # All history
|
fetch-depth: 0 # All history
|
||||||
- name: fetch tags
|
- name: fetch tags
|
||||||
run: git fetch --depth=1 origin "+refs/tags/*:refs/tags/*"
|
run: git fetch --depth=1 origin "+refs/tags/*:refs/tags/*"
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
registry-url: 'https://registry.npmjs.org'
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
2
.github/workflows/release-pr.yml
vendored
2
.github/workflows/release-pr.yml
vendored
@ -35,7 +35,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- run: corepack enable
|
- run: corepack enable
|
||||||
- uses: actions/setup-node@e33196f7422957bea03ed53f6fbb155025ffc7b8 # v3.7.0
|
- uses: actions/setup-node@bea5baf987ba7aa777a8a0b4ace377a21c45c381 # v3.8.0
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
|
2
.github/workflows/reproduire-close.yml
vendored
2
.github/workflows/reproduire-close.yml
vendored
@ -21,4 +21,4 @@ jobs:
|
|||||||
remove-stale-when-updated: false
|
remove-stale-when-updated: false
|
||||||
close-issue-message: This issue was closed because it was open for 7 days without a reproduction.
|
close-issue-message: This issue was closed because it was open for 7 days without a reproduction.
|
||||||
close-issue-label: closed-by-bot
|
close-issue-label: closed-by-bot
|
||||||
operations-per-run: 100 #default 30
|
operations-per-run: 300 #default 30
|
||||||
|
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
@ -66,6 +66,6 @@ jobs:
|
|||||||
|
|
||||||
# Upload the results to GitHub's code scanning dashboard.
|
# Upload the results to GitHub's code scanning dashboard.
|
||||||
- name: "Upload to code-scanning"
|
- name: "Upload to code-scanning"
|
||||||
uses: github/codeql-action/upload-sarif@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v2.21.2
|
uses: github/codeql-action/upload-sarif@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
4
.github/workflows/semantic-pull-requests.yml
vendored
4
.github/workflows/semantic-pull-requests.yml
vendored
@ -6,8 +6,6 @@ on:
|
|||||||
- opened
|
- opened
|
||||||
- edited
|
- edited
|
||||||
- synchronize
|
- synchronize
|
||||||
branches-ignore:
|
|
||||||
- "v[0-9]*"
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@ -17,7 +15,7 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
pull-requests: read # for amannn/action-semantic-pull-request to analyze PRs
|
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
|
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
|
||||||
if: github.repository == 'nuxt/nuxt'
|
if: github.repository == 'nuxt/nuxt' && !startsWith(github.head_ref, 'v')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Semantic pull request
|
name: Semantic pull request
|
||||||
steps:
|
steps:
|
||||||
|
@ -149,7 +149,9 @@ const { pending, data: posts } = useLazyFetch('/api/posts')
|
|||||||
|
|
||||||
### Client-only fetching
|
### Client-only fetching
|
||||||
|
|
||||||
By default, data fetching composables will perform their asynchronous function on both client and server environments. Set the `server` option to `false` to only perform the call on the client-side. Combined with the `lazy` option, this can be useful for data that are not needed on the first render (for example, non-SEO sensitive data).
|
By default, data fetching composables will perform their asynchronous function on both client and server environments. Set the `server` option to `false` to only perform the call on the client-side. On initial load, the data will not be fetched before hydration is complete so you have to handle a pending state, though on subsequent client-side navigation the data will be awaited before loading the page.
|
||||||
|
|
||||||
|
Combined with the `lazy` option, this can be useful for data that is not needed on the first render (for example, non-SEO sensitive data).
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
/* This call will only be performed on the client */
|
/* This call will only be performed on the client */
|
||||||
@ -159,6 +161,8 @@ const { pending, data: posts } = useFetch('/api/comments', {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The `useFetch` composable is meant to be invoked in setup method or called directly at the top level of a function in lifecycle hooks, otherwise you should use `$fetch` method.
|
||||||
|
|
||||||
### Minimize payload size
|
### Minimize payload size
|
||||||
|
|
||||||
The `pick` option helps you to minimize the payload size stored in your HTML document by only selecting the fields that you want returned from the composables.
|
The `pick` option helps you to minimize the payload size stored in your HTML document by only selecting the fields that you want returned from the composables.
|
||||||
|
@ -74,12 +74,12 @@ export const useLocale = () => useState<string>('locale', () => useDefaultLocale
|
|||||||
|
|
||||||
export const useDefaultLocale = (fallback = 'en-US') => {
|
export const useDefaultLocale = (fallback = 'en-US') => {
|
||||||
const locale = ref(fallback)
|
const locale = ref(fallback)
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
|
const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
|
||||||
if (reqLocale) {
|
if (reqLocale) {
|
||||||
locale.value = reqLocale
|
locale.value = reqLocale
|
||||||
}
|
}
|
||||||
} else if (process.client) {
|
} else if (import.meta.client) {
|
||||||
const navLang = navigator.language
|
const navLang = navigator.language
|
||||||
if (navLang) {
|
if (navLang) {
|
||||||
locale.value = navLang
|
locale.value = navLang
|
||||||
|
@ -57,9 +57,36 @@ You can change this behavior by setting `experimental.emitRouteChunkError` to `f
|
|||||||
|
|
||||||
## Rendering an Error Page
|
## Rendering an Error Page
|
||||||
|
|
||||||
When Nuxt encounters a fatal error, whether during the server lifecycle, or when rendering your Vue application (both SSR and SPA), it will either render a JSON response (if requested with `Accept: application/json` header) or an HTML error page.
|
When Nuxt encounters a fatal error (any unhandled error on the server, or an error created with `fatal: true` on the client) it will either render a JSON response (if requested with `Accept: application/json` header) or trigger a full-screen error page.
|
||||||
|
|
||||||
You can customize this error page by adding `~/error.vue` in the source directory of your application, alongside `app.vue`. This page has a single prop - `error` which contains an error for you to handle.
|
This error may occur during the server lifecycle when:
|
||||||
|
|
||||||
|
* processing your Nuxt plugins
|
||||||
|
* rendering your Vue app into HTML
|
||||||
|
* a server API route throws an error
|
||||||
|
|
||||||
|
An error can also occur on the client side when:
|
||||||
|
|
||||||
|
* processing your Nuxt plugins
|
||||||
|
* before mounting the application (`app:beforeMount` hook)
|
||||||
|
* mounting your app if the error was not handled with `onErrorCaptured` or `vue:error` hook
|
||||||
|
* the Vue app is initialized and mounted in browser (`app:mounted`).
|
||||||
|
|
||||||
|
The lifecycle hooks are listed [here](/docs/api/advanced/hooks).
|
||||||
|
|
||||||
|
You can customize this error page by adding `~/error.vue` in the source directory of your application, alongside `app.vue`. Although it is called an 'error page' it's not a route and shouldn't be placed in your `~/pages` directory. For the same reason, you shouldn't use `definePageMeta` within this page.
|
||||||
|
|
||||||
|
The error page has a single prop - `error` which contains an error for you to handle.
|
||||||
|
|
||||||
|
The `error` object provides the fields: `url`, `statusCode`, `statusMessage`, `message`, `description` and `data`. If you have an error with custom fields they will be lost; you should assign them to `data` instead. For custom errors we highly recommend to use `onErrorCaptured` composable that can be called in a page/component setup function or `vue:error` runtime nuxt hook that can be configured in a nuxt plugin.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
export default defineNuxtPlugin(nuxtApp => {
|
||||||
|
nuxtApp.hook('vue:error', (err) => {
|
||||||
|
//
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
When you are ready to remove the error page, you can call the `clearError` helper function, which takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page).
|
When you are ready to remove the error page, you can call the `clearError` helper function, which takes an optional path to redirect to (for example, if you want to navigate to a 'safe' page).
|
||||||
|
|
||||||
|
@ -140,3 +140,26 @@ export default defineNuxtConfig({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Auto-import from third-party packages
|
||||||
|
|
||||||
|
Nuxt also allows auto-importing from third-party packages.
|
||||||
|
|
||||||
|
::alert
|
||||||
|
If you are using the Nuxt module for that package, it is likely that the module has already configured auto-imports for that package.
|
||||||
|
::
|
||||||
|
|
||||||
|
For example, you could enable the auto-import of the `useI18n` composable from the `vue-i18n` package like this:
|
||||||
|
|
||||||
|
```ts [nuxt.config.ts]
|
||||||
|
export default defineNuxtConfig({
|
||||||
|
imports: {
|
||||||
|
presets: [
|
||||||
|
{
|
||||||
|
from: 'vue-i18n',
|
||||||
|
imports: ['useI18n']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
@ -125,12 +125,12 @@ However, if you want to avoid this behaviour you can do so:
|
|||||||
```js
|
```js
|
||||||
export default defineNuxtRouteMiddleware(to => {
|
export default defineNuxtRouteMiddleware(to => {
|
||||||
// skip middleware on server
|
// skip middleware on server
|
||||||
if (process.server) return
|
if (import.meta.server) return
|
||||||
// skip middleware on client side entirely
|
// skip middleware on client side entirely
|
||||||
if (process.client) return
|
if (import.meta.client) return
|
||||||
// or only skip middleware on initial client load
|
// or only skip middleware on initial client load
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
if (process.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
|
if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ export default defineNuxtPlugin({
|
|||||||
```
|
```
|
||||||
|
|
||||||
::alert
|
::alert
|
||||||
If you are using an object-syntax plugin, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. For example, setting `enforce: process.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
|
If you are using an object-syntax plugin, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. For example, setting `enforce: import.meta.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
|
||||||
::
|
::
|
||||||
|
|
||||||
## Plugin Registration Order
|
## Plugin Registration Order
|
||||||
@ -223,4 +223,8 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
::alert{type=warning}
|
||||||
|
If you register a Vue directive, you _must_ register it on both client and server side unless you are only using it when rendering one side. If the directive only makes sense from a client side, you can always move it to `~/plugins/my-directive.client.ts` and provide a 'stub' directive for the server in `~/plugins/my-directive.server.ts`.
|
||||||
|
::
|
||||||
|
|
||||||
:ReadMore{link="https://vuejs.org/guide/reusability/custom-directives.html"}
|
:ReadMore{link="https://vuejs.org/guide/reusability/custom-directives.html"}
|
||||||
|
@ -152,7 +152,10 @@ Server routes can use dynamic parameters within brackets in the file name like `
|
|||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
```ts [server/api/hello/[name\\].ts]
|
```ts [server/api/hello/[name\\].ts]
|
||||||
export default defineEventHandler((event) => `Hello, ${event.context.params.name}!`)
|
export default defineEventHandler((event) => {
|
||||||
|
const name = getRouterParam(event, 'name')
|
||||||
|
return `Hello, ${name}!`
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
You can now universally call this API using `await $fetch('/api/hello/nuxt')` and get `Hello, nuxt!`.
|
You can now universally call this API using `await $fetch('/api/hello/nuxt')` and get `Hello, nuxt!`.
|
||||||
|
@ -29,6 +29,7 @@ export defineNuxtConfig({ experimental: { reactivityTransform: true } })
|
|||||||
```
|
```
|
||||||
|
|
||||||
::ReadMore{link="docs/getting-started/configuration#enabling-experimental-vue-features"}
|
::ReadMore{link="docs/getting-started/configuration#enabling-experimental-vue-features"}
|
||||||
|
::
|
||||||
|
|
||||||
## externalVue
|
## externalVue
|
||||||
|
|
||||||
@ -143,6 +144,7 @@ export defineNuxtConfig({ experimental: { viewTransition: true } })
|
|||||||
```
|
```
|
||||||
|
|
||||||
::ReadMore{link="docs/getting-started/transitions#view-transitions-api-experimental"}
|
::ReadMore{link="docs/getting-started/transitions#view-transitions-api-experimental"}
|
||||||
|
::
|
||||||
|
|
||||||
## writeEarlyHints
|
## writeEarlyHints
|
||||||
|
|
||||||
@ -161,6 +163,7 @@ export defineNuxtConfig({ experimental: { componentIslands: true } })
|
|||||||
```
|
```
|
||||||
|
|
||||||
::ReadMore{link="docs/guide/directory-structure/components#server-components"}
|
::ReadMore{link="docs/guide/directory-structure/components#server-components"}
|
||||||
|
::
|
||||||
|
|
||||||
You can follow the server components roadmap on [GitHub](https://github.com/nuxt/nuxt/issues/19772).
|
You can follow the server components roadmap on [GitHub](https://github.com/nuxt/nuxt/issues/19772).
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ The entire runtime config is available on the server-side, but it is read-only t
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const config = useRuntimeConfig()
|
const config = useRuntimeConfig()
|
||||||
console.log('Runtime config:', config)
|
console.log('Runtime config:', config)
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
console.log('API secret:', config.apiSecret)
|
console.log('API secret:', config.apiSecret)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -375,6 +375,40 @@ export default defineNuxtModule({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Injecting Server Routes With `addServerHandler`
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineNuxtModule, addServerHandler, createResolver } from '@nuxt/kit'
|
||||||
|
|
||||||
|
export default defineNuxtModule({
|
||||||
|
setup(options, nuxt) {
|
||||||
|
const resolver = createResolver(import.meta.url)
|
||||||
|
|
||||||
|
addServerHandler({
|
||||||
|
route: '/api/hello',
|
||||||
|
handler: resolver.resolve('./runtime/server/api/hello/index.get.ts')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also add a dynamic server route:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineNuxtModule, addServerHandler, createResolver } from '@nuxt/kit'
|
||||||
|
|
||||||
|
export default defineNuxtModule({
|
||||||
|
setup(options, nuxt) {
|
||||||
|
const resolver = createResolver(import.meta.url)
|
||||||
|
|
||||||
|
addServerHandler({
|
||||||
|
route: '/api/hello/:name',
|
||||||
|
handler: resolver.resolve('./runtime/server/api/hello/[name].get.ts')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
#### Injecting Other Assets
|
#### Injecting Other Assets
|
||||||
|
|
||||||
If your module should provide other kinds of assets, they can also be injected. Here's a simple example module injecting a stylesheet through Nuxt's `css` array.
|
If your module should provide other kinds of assets, they can also be injected. Here's a simple example module injecting a stylesheet through Nuxt's `css` array.
|
||||||
|
@ -138,6 +138,6 @@ import { createMemoryHistory } from 'vue-router'
|
|||||||
|
|
||||||
// https://router.vuejs.org/api/interfaces/routeroptions.html
|
// https://router.vuejs.org/api/interfaces/routeroptions.html
|
||||||
export default <RouterConfig> {
|
export default <RouterConfig> {
|
||||||
history: base => process.client ? createMemoryHistory(base) : null /* default */
|
history: base => import.meta.client ? createMemoryHistory(base) : null /* default */
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -38,11 +38,14 @@ type AsyncData<DataT, ErrorT> = {
|
|||||||
refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
|
refresh: (opts?: AsyncDataExecuteOptions) => Promise<void>
|
||||||
execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
|
execute: (opts?: AsyncDataExecuteOptions) => Promise<void>
|
||||||
error: Ref<ErrorT | null>
|
error: Ref<ErrorT | null>
|
||||||
|
status: Ref<AsyncDataRequestStatus>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AsyncDataExecuteOptions {
|
interface AsyncDataExecuteOptions {
|
||||||
dedupe?: boolean
|
dedupe?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AsyncDataRequestStatus = 'idle' | 'pending' | 'success' | 'error'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Params
|
## Params
|
||||||
@ -90,8 +93,10 @@ If you have not fetched data on the server (for example, with `server: false`),
|
|||||||
## Example
|
## Example
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
const { data, pending, error, refresh } = await useFetch('https://api.nuxtjs.dev/mountains',{
|
const route = useRoute()
|
||||||
pick: ['title']
|
|
||||||
|
const { data, pending, error, refresh } = await useFetch(`https://api.nuxtjs.dev/mountains/${route.params.slug}`, {
|
||||||
|
pick: ['title']
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -101,8 +106,8 @@ Using the `query` option, you can add search parameters to your query. This opti
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
const param1 = ref('value1')
|
const param1 = ref('value1')
|
||||||
const { data, pending, error, refresh } = await useFetch('https://api.nuxtjs.dev/mountains',{
|
const { data, pending, error, refresh } = await useFetch('https://api.nuxtjs.dev/mountains', {
|
||||||
query: { param1, param2: 'value2' }
|
query: { param1, param2: 'value2' }
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
})
|
})
|
||||||
nuxtApp.hook('vue:error', (..._args) => {
|
nuxtApp.hook('vue:error', (..._args) => {
|
||||||
console.log('vue:error')
|
console.log('vue:error')
|
||||||
// if (process.client) {
|
// if (import.meta.client) {
|
||||||
// console.log(..._args)
|
// console.log(..._args)
|
||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
@ -105,7 +105,7 @@ When accessing the same `payload.data` from [ssrcontext](#ssrcontext), you can a
|
|||||||
export const useColor = () => useState<string>('color', () => 'pink')
|
export const useColor = () => useState<string>('color', () => 'pink')
|
||||||
|
|
||||||
export default defineNuxtPlugin((nuxtApp) => {
|
export default defineNuxtPlugin((nuxtApp) => {
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
const color = useColor()
|
const color = useColor()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -137,7 +137,7 @@ export default defineComponent({
|
|||||||
setup (_props, { slots, emit }) {
|
setup (_props, { slots, emit }) {
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
onErrorCaptured((err) => {
|
onErrorCaptured((err) => {
|
||||||
if (process.client && !nuxtApp.isHydrating) {
|
if (import.meta.client && !nuxtApp.isHydrating) {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -41,6 +41,4 @@ useSeoMeta({
|
|||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
There are over 100+ parameters.
|
There are over 100 parameters. See the [full list of parameters in the source code](https://github.com/harlan-zw/zhead/blob/main/src/metaFlat.ts).
|
||||||
|
|
||||||
Full list of [`parameters`](https://github.com/harlan-zw/zhead/blob/main/src/metaFlat.ts)
|
|
||||||
|
@ -99,7 +99,7 @@ interface PageMeta {
|
|||||||
|
|
||||||
Validate whether a given route can validly be rendered with this page. Return true if it is valid, or false if not. If another match can't be found, this will mean a 404. You can also directly return an object with `statusCode`/`statusMessage` to respond immediately with an error (other matches will not be checked).
|
Validate whether a given route can validly be rendered with this page. Return true if it is valid, or false if not. If another match can't be found, this will mean a 404. You can also directly return an object with `statusCode`/`statusMessage` to respond immediately with an error (other matches will not be checked).
|
||||||
|
|
||||||
**`scrollTopTop`**
|
**`scrollToTop`**
|
||||||
|
|
||||||
- **Type**: `boolean | (to: RouteLocationNormalized, from: RouteLocationNormalized) => boolean`
|
- **Type**: `boolean | (to: RouteLocationNormalized, from: RouteLocationNormalized) => boolean`
|
||||||
|
|
||||||
|
@ -17,5 +17,5 @@ Option | Default | Description
|
|||||||
`--dotenv` | `.` | Point to another `.env` file to load, **relative** to the root directory.
|
`--dotenv` | `.` | Point to another `.env` file to load, **relative** to the root directory.
|
||||||
|
|
||||||
::alert{type=info}
|
::alert{type=info}
|
||||||
Read more about [pre-rendering and static hosting](/docs/1.getting-started/10.deployment.md#static-hosting).
|
Read more about [pre-rendering and static hosting](/docs/getting-started/deployment#static-hosting).
|
||||||
::
|
::
|
||||||
|
17
package.json
17
package.json
@ -20,7 +20,6 @@
|
|||||||
"play:preview": "nuxi preview playground",
|
"play:preview": "nuxi preview playground",
|
||||||
"test": "pnpm test:fixtures && pnpm test:fixtures:payload && pnpm test:fixtures:dev && pnpm test:fixtures:webpack && pnpm test:unit && pnpm typecheck",
|
"test": "pnpm test:fixtures && pnpm test:fixtures:payload && pnpm test:fixtures:dev && pnpm test:fixtures:webpack && pnpm test:unit && pnpm typecheck",
|
||||||
"test:fixtures": "nuxi prepare test/fixtures/basic && nuxi prepare test/fixtures/runtime-compiler && vitest run --dir test",
|
"test:fixtures": "nuxi prepare test/fixtures/basic && nuxi prepare test/fixtures/runtime-compiler && vitest run --dir test",
|
||||||
"test:fixtures:payload": "TEST_PAYLOAD=js pnpm test:fixtures",
|
|
||||||
"test:fixtures:dev": "TEST_ENV=dev pnpm test:fixtures",
|
"test:fixtures:dev": "TEST_ENV=dev pnpm test:fixtures",
|
||||||
"test:fixtures:webpack": "TEST_BUILDER=webpack pnpm test:fixtures",
|
"test:fixtures:webpack": "TEST_BUILDER=webpack pnpm test:fixtures",
|
||||||
"test:runtime": "vitest -c vitest.nuxt.config.ts",
|
"test:runtime": "vitest -c vitest.nuxt.config.ts",
|
||||||
@ -36,7 +35,7 @@
|
|||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
"nuxi": "workspace:*",
|
"nuxi": "workspace:*",
|
||||||
"nuxt": "workspace:*",
|
"nuxt": "workspace:*",
|
||||||
"vite": "4.4.8",
|
"vite": "4.4.9",
|
||||||
"vue": "3.3.4",
|
"vue": "3.3.4",
|
||||||
"magic-string": "^0.30.2"
|
"magic-string": "^0.30.2"
|
||||||
},
|
},
|
||||||
@ -46,7 +45,7 @@
|
|||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
"@nuxtjs/eslint-config-typescript": "12.0.0",
|
"@nuxtjs/eslint-config-typescript": "12.0.0",
|
||||||
"@types/fs-extra": "11.0.1",
|
"@types/fs-extra": "11.0.1",
|
||||||
"@types/node": "18.17.1",
|
"@types/node": "18.17.5",
|
||||||
"@types/semver": "7.5.0",
|
"@types/semver": "7.5.0",
|
||||||
"case-police": "0.6.1",
|
"case-police": "0.6.1",
|
||||||
"chalk": "5.3.0",
|
"chalk": "5.3.0",
|
||||||
@ -54,15 +53,15 @@
|
|||||||
"cheerio": "1.0.0-rc.12",
|
"cheerio": "1.0.0-rc.12",
|
||||||
"consola": "3.2.3",
|
"consola": "3.2.3",
|
||||||
"devalue": "4.3.2",
|
"devalue": "4.3.2",
|
||||||
"eslint": "8.46.0",
|
"eslint": "8.47.0",
|
||||||
"eslint-plugin-import": "2.28.0",
|
"eslint-plugin-import": "2.28.0",
|
||||||
"eslint-plugin-jsdoc": "41.1.2",
|
"eslint-plugin-jsdoc": "41.1.2",
|
||||||
"eslint-plugin-no-only-tests": "3.1.0",
|
"eslint-plugin-no-only-tests": "3.1.0",
|
||||||
"execa": "7.2.0",
|
"execa": "7.2.0",
|
||||||
"fs-extra": "11.1.1",
|
"fs-extra": "11.1.1",
|
||||||
"globby": "13.2.2",
|
"globby": "13.2.2",
|
||||||
"h3": "1.7.1",
|
"h3": "1.8.0",
|
||||||
"happy-dom": "10.7.0",
|
"happy-dom": "10.9.0",
|
||||||
"jiti": "1.19.1",
|
"jiti": "1.19.1",
|
||||||
"markdownlint-cli": "^0.33.0",
|
"markdownlint-cli": "^0.33.0",
|
||||||
"nitropack": "2.5.2",
|
"nitropack": "2.5.2",
|
||||||
@ -71,13 +70,13 @@
|
|||||||
"nuxt-vitest": "0.10.2",
|
"nuxt-vitest": "0.10.2",
|
||||||
"ofetch": "1.1.1",
|
"ofetch": "1.1.1",
|
||||||
"pathe": "1.1.1",
|
"pathe": "1.1.1",
|
||||||
"playwright-core": "1.36.2",
|
"playwright-core": "1.37.0",
|
||||||
"rimraf": "5.0.1",
|
"rimraf": "5.0.1",
|
||||||
"semver": "7.5.4",
|
"semver": "7.5.4",
|
||||||
"std-env": "3.3.3",
|
"std-env": "3.3.3",
|
||||||
"typescript": "5.1.6",
|
"typescript": "5.1.6",
|
||||||
"ufo": "1.2.0",
|
"ufo": "1.2.0",
|
||||||
"vite": "4.4.8",
|
"vite": "4.4.9",
|
||||||
"vitest": "0.33.0",
|
"vitest": "0.33.0",
|
||||||
"vitest-environment-nuxt": "0.10.2",
|
"vitest-environment-nuxt": "0.10.2",
|
||||||
"vue": "3.3.4",
|
"vue": "3.3.4",
|
||||||
@ -85,7 +84,7 @@
|
|||||||
"vue-router": "4.2.4",
|
"vue-router": "4.2.4",
|
||||||
"vue-tsc": "1.8.8"
|
"vue-tsc": "1.8.8"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@8.6.11",
|
"packageManager": "pnpm@8.6.12",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^14.18.0 || >=16.10.0"
|
"node": "^14.18.0 || >=16.10.0"
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
"lodash-es": "4.17.21",
|
"lodash-es": "4.17.21",
|
||||||
"nitropack": "2.5.2",
|
"nitropack": "2.5.2",
|
||||||
"unbuild": "latest",
|
"unbuild": "latest",
|
||||||
"vite": "4.4.8",
|
"vite": "4.4.9",
|
||||||
"vitest": "0.33.0",
|
"vitest": "0.33.0",
|
||||||
"webpack": "5.88.2"
|
"webpack": "5.88.2"
|
||||||
},
|
},
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
export function sequence<T, R> (
|
|
||||||
tasks: T[],
|
|
||||||
fn: (task: T) => R
|
|
||||||
) {
|
|
||||||
return tasks.reduce(
|
|
||||||
(promise, task): any => promise.then(() => fn(task)),
|
|
||||||
Promise.resolve()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parallel<T, R> (
|
|
||||||
tasks: T[],
|
|
||||||
fn: (task: T) => R
|
|
||||||
) {
|
|
||||||
return Promise.all(tasks.map(fn))
|
|
||||||
}
|
|
||||||
|
|
||||||
export function chainFn<Fn> (base: Fn, fn: Fn): Fn {
|
|
||||||
if (typeof fn !== 'function') {
|
|
||||||
return base
|
|
||||||
}
|
|
||||||
return function (this: any, ...args: any[]) {
|
|
||||||
if (typeof base !== 'function') {
|
|
||||||
return fn.apply(this, args)
|
|
||||||
}
|
|
||||||
let baseResult = base.apply(this, args)
|
|
||||||
// Allow function to mutate the first argument instead of returning the result
|
|
||||||
if (baseResult === undefined) {
|
|
||||||
[baseResult] = args
|
|
||||||
}
|
|
||||||
const fnResult = fn.call(
|
|
||||||
this,
|
|
||||||
baseResult,
|
|
||||||
...Array.prototype.slice.call(args, 1)
|
|
||||||
)
|
|
||||||
// Return mutated argument if no result was returned
|
|
||||||
if (fnResult === undefined) {
|
|
||||||
return baseResult
|
|
||||||
}
|
|
||||||
return fnResult
|
|
||||||
} as unknown as Fn
|
|
||||||
}
|
|
@ -25,6 +25,10 @@ export async function installModule (moduleToInstall: string | NuxtModule, inlin
|
|||||||
|
|
||||||
if (typeof moduleToInstall === 'string') {
|
if (typeof moduleToInstall === 'string') {
|
||||||
nuxt.options.build.transpile.push(normalizeModuleTranspilePath(moduleToInstall))
|
nuxt.options.build.transpile.push(normalizeModuleTranspilePath(moduleToInstall))
|
||||||
|
const directory = getDirectory(moduleToInstall)
|
||||||
|
if (directory !== moduleToInstall) {
|
||||||
|
nuxt.options.modulesDir.push(getDirectory(moduleToInstall))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nuxt.options._installedModules = nuxt.options._installedModules || []
|
nuxt.options._installedModules = nuxt.options._installedModules || []
|
||||||
@ -37,15 +41,19 @@ export async function installModule (moduleToInstall: string | NuxtModule, inlin
|
|||||||
|
|
||||||
// --- Internal ---
|
// --- Internal ---
|
||||||
|
|
||||||
export const normalizeModuleTranspilePath = (p: string) => {
|
function getDirectory (p: string) {
|
||||||
try {
|
try {
|
||||||
// we need to target directories instead of module file paths themselves
|
// we need to target directories instead of module file paths themselves
|
||||||
// /home/user/project/node_modules/module/index.js -> /home/user/project/node_modules/module
|
// /home/user/project/node_modules/module/index.js -> /home/user/project/node_modules/module
|
||||||
p = isAbsolute(p) && lstatSync(p).isFile() ? dirname(p) : p
|
return isAbsolute(p) && lstatSync(p).isFile() ? dirname(p) : p
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// maybe the path is absolute but does not exist, allow this to bubble up
|
// maybe the path is absolute but does not exist, allow this to bubble up
|
||||||
}
|
}
|
||||||
return p.split('node_modules/').pop() as string
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
export const normalizeModuleTranspilePath = (p: string) => {
|
||||||
|
return getDirectory(p).split('node_modules/').pop() as string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadNuxtModuleInstance (nuxtModule: string | NuxtModule, nuxt: Nuxt = useNuxt()) {
|
export async function loadNuxtModuleInstance (nuxtModule: string | NuxtModule, nuxt: Nuxt = useNuxt()) {
|
||||||
|
@ -128,7 +128,6 @@ export async function writeTypes (nuxt: Nuxt) {
|
|||||||
noEmit: true,
|
noEmit: true,
|
||||||
resolveJsonModule: true,
|
resolveJsonModule: true,
|
||||||
allowSyntheticDefaultImports: true,
|
allowSyntheticDefaultImports: true,
|
||||||
types: ['node'],
|
|
||||||
paths: {}
|
paths: {}
|
||||||
},
|
},
|
||||||
include: [
|
include: [
|
||||||
|
@ -36,12 +36,13 @@
|
|||||||
"execa": "7.2.0",
|
"execa": "7.2.0",
|
||||||
"flat": "5.0.2",
|
"flat": "5.0.2",
|
||||||
"giget": "1.1.2",
|
"giget": "1.1.2",
|
||||||
"h3": "1.7.1",
|
"h3": "1.8.0",
|
||||||
"jiti": "1.19.1",
|
"jiti": "1.19.1",
|
||||||
"listhen": "1.2.2",
|
"listhen": "1.3.0",
|
||||||
"mlly": "1.4.0",
|
"mlly": "1.4.0",
|
||||||
"mri": "1.2.0",
|
"mri": "1.2.0",
|
||||||
"ohash": "1.1.2",
|
"nitropack": "2.5.2",
|
||||||
|
"ohash": "1.1.3",
|
||||||
"pathe": "1.1.1",
|
"pathe": "1.1.1",
|
||||||
"perfect-debounce": "1.0.0",
|
"perfect-debounce": "1.0.0",
|
||||||
"pkg-types": "1.0.3",
|
"pkg-types": "1.0.3",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { relative, resolve } from 'pathe'
|
import { relative, resolve } from 'pathe'
|
||||||
import { consola } from 'consola'
|
import { consola } from 'consola'
|
||||||
|
import type { Nitro } from 'nitropack'
|
||||||
|
|
||||||
// we are deliberately inlining this code as a backup in case user has `@nuxt/schema<3.7`
|
// we are deliberately inlining this code as a backup in case user has `@nuxt/schema<3.7`
|
||||||
import { writeTypes as writeTypesLegacy } from '../../../kit/src/template'
|
import { writeTypes as writeTypesLegacy } from '../../../kit/src/template'
|
||||||
@ -38,8 +39,12 @@ export default defineNuxtCommand({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Use ? for backward compatibility for Nuxt <= RC.10
|
let nitro: Nitro | undefined
|
||||||
const nitro = useNitro?.()
|
// In Bridge, if nitro is not enabled, useNitro will throw an error
|
||||||
|
try {
|
||||||
|
// Use ? for backward compatibility for Nuxt <= RC.10
|
||||||
|
nitro = useNitro?.()
|
||||||
|
} catch {}
|
||||||
|
|
||||||
await clearBuildDir(nuxt.options.buildDir)
|
await clearBuildDir(nuxt.options.buildDir)
|
||||||
|
|
||||||
|
@ -134,11 +134,6 @@ export default defineNuxtCommand({
|
|||||||
|
|
||||||
await currentNuxt.ready()
|
await currentNuxt.ready()
|
||||||
|
|
||||||
distWatcher = chokidar.watch(resolve(currentNuxt.options.buildDir, 'dist'), { ignoreInitial: true, depth: 0 })
|
|
||||||
distWatcher.on('unlinkDir', () => {
|
|
||||||
dLoad(true, '.nuxt/dist directory has been removed')
|
|
||||||
})
|
|
||||||
|
|
||||||
const unsub = currentNuxt.hooks.hook('restart', async (options) => {
|
const unsub = currentNuxt.hooks.hook('restart', async (options) => {
|
||||||
unsub() // we use this instead of `hookOnce` for Nuxt Bridge support
|
unsub() // we use this instead of `hookOnce` for Nuxt Bridge support
|
||||||
if (options?.hard) { return hardRestart() }
|
if (options?.hard) { return hardRestart() }
|
||||||
@ -156,6 +151,12 @@ export default defineNuxtCommand({
|
|||||||
writeTypes(currentNuxt).catch(console.error),
|
writeTypes(currentNuxt).catch(console.error),
|
||||||
buildNuxt(currentNuxt)
|
buildNuxt(currentNuxt)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
distWatcher = chokidar.watch(resolve(currentNuxt.options.buildDir, 'dist'), { ignoreInitial: true, depth: 0 })
|
||||||
|
distWatcher.on('unlinkDir', () => {
|
||||||
|
dLoad(true, '.nuxt/dist directory has been removed')
|
||||||
|
})
|
||||||
|
|
||||||
currentHandler = toNodeListener(currentNuxt.server.app)
|
currentHandler = toNodeListener(currentNuxt.server.app)
|
||||||
if (isRestart && args.clear !== false) {
|
if (isRestart && args.clear !== false) {
|
||||||
showBanner()
|
showBanner()
|
||||||
|
@ -55,11 +55,12 @@
|
|||||||
"@nuxt/devalue": "^2.0.2",
|
"@nuxt/devalue": "^2.0.2",
|
||||||
"@nuxt/kit": "workspace:../kit",
|
"@nuxt/kit": "workspace:../kit",
|
||||||
"@nuxt/schema": "workspace:../schema",
|
"@nuxt/schema": "workspace:../schema",
|
||||||
"@nuxt/telemetry": "^2.3.2",
|
"@nuxt/telemetry": "^2.4.1",
|
||||||
"@nuxt/ui-templates": "^1.3.1",
|
"@nuxt/ui-templates": "^1.3.1",
|
||||||
"@nuxt/vite-builder": "workspace:../vite",
|
"@nuxt/vite-builder": "workspace:../vite",
|
||||||
"@unhead/ssr": "^1.2.2",
|
"@unhead/dom": "^1.3.3",
|
||||||
"@unhead/vue": "^1.2.2",
|
"@unhead/ssr": "^1.3.3",
|
||||||
|
"@unhead/vue": "^1.3.3",
|
||||||
"@vue/shared": "^3.3.4",
|
"@vue/shared": "^3.3.4",
|
||||||
"acorn": "8.10.0",
|
"acorn": "8.10.0",
|
||||||
"c12": "^1.4.2",
|
"c12": "^1.4.2",
|
||||||
@ -68,12 +69,12 @@
|
|||||||
"defu": "^6.1.2",
|
"defu": "^6.1.2",
|
||||||
"destr": "^2.0.1",
|
"destr": "^2.0.1",
|
||||||
"devalue": "^4.3.2",
|
"devalue": "^4.3.2",
|
||||||
"esbuild": "^0.18.17",
|
"esbuild": "^0.19.2",
|
||||||
"escape-string-regexp": "^5.0.0",
|
"escape-string-regexp": "^5.0.0",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
"fs-extra": "^11.1.1",
|
"fs-extra": "^11.1.1",
|
||||||
"globby": "^13.2.2",
|
"globby": "^13.2.2",
|
||||||
"h3": "^1.7.1",
|
"h3": "^1.8.0",
|
||||||
"hookable": "^5.5.3",
|
"hookable": "^5.5.3",
|
||||||
"jiti": "^1.19.1",
|
"jiti": "^1.19.1",
|
||||||
"klona": "^2.0.6",
|
"klona": "^2.0.6",
|
||||||
@ -84,18 +85,19 @@
|
|||||||
"nuxi": "workspace:../nuxi",
|
"nuxi": "workspace:../nuxi",
|
||||||
"nypm": "^0.2.2",
|
"nypm": "^0.2.2",
|
||||||
"ofetch": "^1.1.1",
|
"ofetch": "^1.1.1",
|
||||||
"ohash": "^1.1.2",
|
"ohash": "^1.1.3",
|
||||||
"pathe": "^1.1.1",
|
"pathe": "^1.1.1",
|
||||||
"perfect-debounce": "^1.0.0",
|
"perfect-debounce": "^1.0.0",
|
||||||
"pkg-types": "^1.0.3",
|
"pkg-types": "^1.0.3",
|
||||||
"prompts": "^2.4.2",
|
"prompts": "^2.4.2",
|
||||||
"scule": "^1.0.0",
|
"scule": "^1.0.0",
|
||||||
|
"std-env": "^3.3.3",
|
||||||
"strip-literal": "^1.3.0",
|
"strip-literal": "^1.3.0",
|
||||||
"ufo": "^1.2.0",
|
"ufo": "^1.2.0",
|
||||||
"ultrahtml": "^1.3.0",
|
"ultrahtml": "^1.3.0",
|
||||||
"uncrypto": "^0.1.3",
|
"uncrypto": "^0.1.3",
|
||||||
"unctx": "^2.3.1",
|
"unctx": "^2.3.1",
|
||||||
"unenv": "^1.6.1",
|
"unenv": "^1.7.1",
|
||||||
"unimport": "^3.1.3",
|
"unimport": "^3.1.3",
|
||||||
"unplugin": "^1.4.0",
|
"unplugin": "^1.4.0",
|
||||||
"unplugin-vue-router": "^0.6.4",
|
"unplugin-vue-router": "^0.6.4",
|
||||||
@ -112,7 +114,7 @@
|
|||||||
"@types/prompts": "2.4.4",
|
"@types/prompts": "2.4.4",
|
||||||
"@vitejs/plugin-vue": "4.2.3",
|
"@vitejs/plugin-vue": "4.2.3",
|
||||||
"unbuild": "latest",
|
"unbuild": "latest",
|
||||||
"vite": "4.4.8",
|
"vite": "4.4.9",
|
||||||
"vitest": "0.33.0"
|
"vitest": "0.33.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@ -122,6 +124,9 @@
|
|||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@parcel/watcher": {
|
"@parcel/watcher": {
|
||||||
"optional": true
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/node": {
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Polyfills for Safari support
|
// Polyfills for Safari support
|
||||||
// https://caniuse.com/requestidlecallback
|
// https://caniuse.com/requestidlecallback
|
||||||
export const requestIdleCallback: Window['requestIdleCallback'] = process.server
|
export const requestIdleCallback: Window['requestIdleCallback'] = import.meta.server
|
||||||
? (() => {}) as any
|
? (() => {}) as any
|
||||||
: (globalThis.requestIdleCallback || ((cb) => {
|
: (globalThis.requestIdleCallback || ((cb) => {
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
@ -11,6 +11,6 @@ export const requestIdleCallback: Window['requestIdleCallback'] = process.server
|
|||||||
return setTimeout(() => { cb(idleDeadline) }, 1)
|
return setTimeout(() => { cb(idleDeadline) }, 1)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
export const cancelIdleCallback: Window['cancelIdleCallback'] = process.server
|
export const cancelIdleCallback: Window['cancelIdleCallback'] = import.meta.server
|
||||||
? (() => {}) as any
|
? (() => {}) as any
|
||||||
: (globalThis.cancelIdleCallback || ((id) => { clearTimeout(id) }))
|
: (globalThis.cancelIdleCallback || ((id) => { clearTimeout(id) }))
|
||||||
|
@ -30,6 +30,8 @@ export default defineComponent({
|
|||||||
emits: ['ssr-error'],
|
emits: ['ssr-error'],
|
||||||
setup (props, ctx) {
|
setup (props, ctx) {
|
||||||
const mounted = ref(false)
|
const mounted = ref(false)
|
||||||
|
// This is deliberate - `uid` should not be provided by user but by a transform plugin and will not be reactive.
|
||||||
|
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||||
const ssrFailed = useState(`${props.uid}`)
|
const ssrFailed = useState(`${props.uid}`)
|
||||||
|
|
||||||
if (ssrFailed.value) {
|
if (ssrFailed.value) {
|
||||||
|
@ -3,7 +3,7 @@ import { defineComponent } from 'vue'
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'DevOnly',
|
name: 'DevOnly',
|
||||||
setup (_, props) {
|
setup (_, props) {
|
||||||
if (process.dev) {
|
if (import.meta.dev) {
|
||||||
return () => props.slots.default?.()
|
return () => props.slots.default?.()
|
||||||
}
|
}
|
||||||
return () => props.slots.fallback?.()
|
return () => props.slots.fallback?.()
|
||||||
|
@ -12,7 +12,7 @@ export default defineComponent({
|
|||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
|
|
||||||
onErrorCaptured((err, target, info) => {
|
onErrorCaptured((err, target, info) => {
|
||||||
if (process.client && !nuxtApp.isHydrating) {
|
if (import.meta.client && !nuxtApp.isHydrating) {
|
||||||
emit('error', err)
|
emit('error', err)
|
||||||
nuxtApp.hooks.callHook('vue:error', err, target, info)
|
nuxtApp.hooks.callHook('vue:error', err, target, info)
|
||||||
error.value = err
|
error.value = err
|
||||||
|
@ -36,11 +36,11 @@ const is404 = statusCode === 404
|
|||||||
|
|
||||||
const statusMessage = _error.statusMessage ?? (is404 ? 'Page Not Found' : 'Internal Server Error')
|
const statusMessage = _error.statusMessage ?? (is404 ? 'Page Not Found' : 'Internal Server Error')
|
||||||
const description = _error.message || _error.toString()
|
const description = _error.message || _error.toString()
|
||||||
const stack = process.dev && !is404 ? _error.description || `<pre>${stacktrace}</pre>` : undefined
|
const stack = import.meta.dev && !is404 ? _error.description || `<pre>${stacktrace}</pre>` : undefined
|
||||||
|
|
||||||
// TODO: Investigate side-effect issue with imports
|
// TODO: Investigate side-effect issue with imports
|
||||||
const _Error404 = defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-404.vue').then(r => r.default || r))
|
const _Error404 = defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-404.vue').then(r => r.default || r))
|
||||||
const _Error = process.dev
|
const _Error = import.meta.dev
|
||||||
? defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-dev.vue').then(r => r.default || r))
|
? defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-dev.vue').then(r => r.default || r))
|
||||||
: defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-500.vue').then(r => r.default || r))
|
: defineAsyncComponent(() => import('@nuxt/ui-templates/templates/error-500.vue').then(r => r.default || r))
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ const SLOTNAME_RE = /nuxt-ssr-slot-name="([^"]*)"/g
|
|||||||
const SLOT_FALLBACK_RE = /<div nuxt-slot-fallback-start="([^"]*)"[^>]*><\/div>(((?!<div nuxt-slot-fallback-end[^>]*>)[\s\S])*)<div nuxt-slot-fallback-end[^>]*><\/div>/g
|
const SLOT_FALLBACK_RE = /<div nuxt-slot-fallback-start="([^"]*)"[^>]*><\/div>(((?!<div nuxt-slot-fallback-end[^>]*>)[\s\S])*)<div nuxt-slot-fallback-end[^>]*><\/div>/g
|
||||||
|
|
||||||
let id = 0
|
let id = 0
|
||||||
const getId = process.client ? () => (id++).toString() : randomUUID
|
const getId = import.meta.client ? () => (id++).toString() : randomUUID
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'NuxtIsland',
|
name: 'NuxtIsland',
|
||||||
@ -54,7 +54,7 @@ export default defineComponent({
|
|||||||
const instance = getCurrentInstance()!
|
const instance = getCurrentInstance()!
|
||||||
const event = useRequestEvent()
|
const event = useRequestEvent()
|
||||||
// TODO: remove use of `$fetch.raw` when nitro 503 issues on windows dev server are resolved
|
// TODO: remove use of `$fetch.raw` when nitro 503 issues on windows dev server are resolved
|
||||||
const eventFetch = process.server ? event.fetch : process.dev ? $fetch.raw : globalThis.fetch
|
const eventFetch = import.meta.server ? event.fetch : import.meta.dev ? $fetch.raw : globalThis.fetch
|
||||||
const mounted = ref(false)
|
const mounted = ref(false)
|
||||||
onMounted(() => { mounted.value = true })
|
onMounted(() => { mounted.value = true })
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ export default defineComponent({
|
|||||||
nuxtApp.payload.data[key] = {
|
nuxtApp.payload.data[key] = {
|
||||||
__nuxt_island: {
|
__nuxt_island: {
|
||||||
key,
|
key,
|
||||||
...(process.server && process.env.prerender)
|
...(import.meta.server && import.meta.prerender)
|
||||||
? {}
|
? {}
|
||||||
: { params: { ...props.context, props: props.props ? JSON.stringify(props.props) : undefined } }
|
: { params: { ...props.context, props: props.props ? JSON.stringify(props.props) : undefined } }
|
||||||
},
|
},
|
||||||
@ -71,7 +71,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ssrHTML = ref<string>('')
|
const ssrHTML = ref<string>('')
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
const renderedHTML = getFragmentHTML(instance.vnode?.el ?? null).join('')
|
const renderedHTML = getFragmentHTML(instance.vnode?.el ?? null).join('')
|
||||||
if (renderedHTML && nuxtApp.isHydrating) {
|
if (renderedHTML && nuxtApp.isHydrating) {
|
||||||
setPayload(`${props.name}_${hashId.value}`, {
|
setPayload(`${props.name}_${hashId.value}`, {
|
||||||
@ -111,19 +111,19 @@ export default defineComponent({
|
|||||||
|
|
||||||
const url = remoteComponentIslands && props.source ? new URL(`/__nuxt_island/${key}`, props.source).href : `/__nuxt_island/${key}`
|
const url = remoteComponentIslands && props.source ? new URL(`/__nuxt_island/${key}`, props.source).href : `/__nuxt_island/${key}`
|
||||||
|
|
||||||
if (process.server && process.env.prerender) {
|
if (import.meta.server && import.meta.prerender) {
|
||||||
// Hint to Nitro to prerender the island component
|
// Hint to Nitro to prerender the island component
|
||||||
appendResponseHeader(event, 'x-nitro-prerender', url)
|
appendResponseHeader(event, 'x-nitro-prerender', url)
|
||||||
}
|
}
|
||||||
// TODO: Validate response
|
// TODO: Validate response
|
||||||
// $fetch handles the app.baseURL in dev
|
// $fetch handles the app.baseURL in dev
|
||||||
const r = await eventFetch(withQuery(process.dev && process.client ? url : joinURL(config.app.baseURL ?? '', url), {
|
const r = await eventFetch(withQuery(import.meta.dev && import.meta.client ? url : joinURL(config.app.baseURL ?? '', url), {
|
||||||
...props.context,
|
...props.context,
|
||||||
props: props.props ? JSON.stringify(props.props) : undefined
|
props: props.props ? JSON.stringify(props.props) : undefined
|
||||||
}))
|
}))
|
||||||
const result = process.server || !process.dev ? await r.json() : (r as FetchResponse<NuxtIslandResponse>)._data
|
const result = import.meta.server || !import.meta.dev ? await r.json() : (r as FetchResponse<NuxtIslandResponse>)._data
|
||||||
// TODO: support passing on more headers
|
// TODO: support passing on more headers
|
||||||
if (process.server && process.env.prerender) {
|
if (import.meta.server && import.meta.prerender) {
|
||||||
const hints = r.headers.get('x-nitro-prerender')
|
const hints = r.headers.get('x-nitro-prerender')
|
||||||
if (hints) {
|
if (hints) {
|
||||||
appendResponseHeader(event, 'x-nitro-prerender', hints)
|
appendResponseHeader(event, 'x-nitro-prerender', hints)
|
||||||
@ -149,7 +149,7 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
key.value++
|
key.value++
|
||||||
error.value = null
|
error.value = null
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
// must await next tick for Teleport to work correctly with static node re-rendering
|
// must await next tick for Teleport to work correctly with static node re-rendering
|
||||||
await nextTick()
|
await nextTick()
|
||||||
}
|
}
|
||||||
@ -165,13 +165,13 @@ export default defineComponent({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
watch(props, debounce(() => fetchComponent(), 100))
|
watch(props, debounce(() => fetchComponent(), 100))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.client && !nuxtApp.isHydrating && props.lazy) {
|
if (import.meta.client && !nuxtApp.isHydrating && props.lazy) {
|
||||||
fetchComponent()
|
fetchComponent()
|
||||||
} else if (process.server || !nuxtApp.isHydrating) {
|
} else if (import.meta.server || !nuxtApp.isHydrating) {
|
||||||
await fetchComponent()
|
await fetchComponent()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,10 +182,10 @@ export default defineComponent({
|
|||||||
const nodes = [createVNode(Fragment, {
|
const nodes = [createVNode(Fragment, {
|
||||||
key: key.value
|
key: key.value
|
||||||
}, [h(createStaticVNode(html.value || '<div></div>', 1))])]
|
}, [h(createStaticVNode(html.value || '<div></div>', 1))])]
|
||||||
if (uid.value && (mounted.value || nuxtApp.isHydrating || process.server)) {
|
if (uid.value && (mounted.value || nuxtApp.isHydrating || import.meta.server)) {
|
||||||
for (const slot in slots) {
|
for (const slot in slots) {
|
||||||
if (availableSlots.value.includes(slot)) {
|
if (availableSlots.value.includes(slot)) {
|
||||||
nodes.push(createVNode(Teleport, { to: process.client ? `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-slot-name='${slot}']` : `uid=${uid.value};slot=${slot}` }, {
|
nodes.push(createVNode(Teleport, { to: import.meta.client ? `[nuxt-ssr-component-uid='${uid.value}'] [nuxt-ssr-slot-name='${slot}']` : `uid=${uid.value};slot=${slot}` }, {
|
||||||
default: () => (slotProps.value[slot] ?? [undefined]).map((data: any) => slots[slot]?.(data))
|
default: () => (slotProps.value[slot] ?? [undefined]).map((data: any) => slots[slot]?.(data))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,10 @@ const LayoutLoader = defineComponent({
|
|||||||
layoutProps: Object
|
layoutProps: Object
|
||||||
},
|
},
|
||||||
async setup (props, context) {
|
async setup (props, context) {
|
||||||
|
// This is a deliberate hack - this component must always be called with an explicit key to ensure
|
||||||
|
// that setup reruns when the name changes.
|
||||||
|
|
||||||
|
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||||
const LayoutComponent = await layouts[props.name]().then((r: any) => r.default || r)
|
const LayoutComponent = await layouts[props.name]().then((r: any) => r.default || r)
|
||||||
|
|
||||||
return () => h(LayoutComponent, props.layoutProps, context.slots)
|
return () => h(LayoutComponent, props.layoutProps, context.slots)
|
||||||
@ -53,7 +57,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const hasLayout = layout.value && layout.value in layouts
|
const hasLayout = layout.value && layout.value in layouts
|
||||||
if (process.dev && layout.value && !hasLayout && layout.value !== 'default') {
|
if (import.meta.dev && layout.value && !hasLayout && layout.value !== 'default') {
|
||||||
console.warn(`Invalid layout \`${layout.value}\` selected.`)
|
console.warn(`Invalid layout \`${layout.value}\` selected.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +112,7 @@ const LayoutProvider = defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let vnode: VNode | undefined
|
let vnode: VNode | undefined
|
||||||
if (process.dev && process.client) {
|
if (import.meta.dev && import.meta.client) {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (['#comment', '#text'].includes(vnode?.el?.nodeName)) {
|
if (['#comment', '#text'].includes(vnode?.el?.nodeName)) {
|
||||||
@ -124,14 +128,14 @@ const LayoutProvider = defineComponent({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (!name || (typeof name === 'string' && !(name in layouts))) {
|
if (!name || (typeof name === 'string' && !(name in layouts))) {
|
||||||
if (process.dev && process.client && props.hasTransition) {
|
if (import.meta.dev && import.meta.client && props.hasTransition) {
|
||||||
vnode = context.slots.default?.() as VNode | undefined
|
vnode = context.slots.default?.() as VNode | undefined
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
return context.slots.default?.()
|
return context.slots.default?.()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.dev && process.client && props.hasTransition) {
|
if (import.meta.dev && import.meta.client && props.hasTransition) {
|
||||||
vnode = h(
|
vnode = h(
|
||||||
// @ts-expect-error seems to be an issue in vue types
|
// @ts-expect-error seems to be an issue in vue types
|
||||||
LayoutLoader,
|
LayoutLoader,
|
||||||
|
@ -51,7 +51,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
|||||||
const componentName = options.componentName || 'NuxtLink'
|
const componentName = options.componentName || 'NuxtLink'
|
||||||
|
|
||||||
const checkPropConflicts = (props: NuxtLinkProps, main: keyof NuxtLinkProps, sub: keyof NuxtLinkProps): void => {
|
const checkPropConflicts = (props: NuxtLinkProps, main: keyof NuxtLinkProps, sub: keyof NuxtLinkProps): void => {
|
||||||
if (process.dev && props[main] !== undefined && props[sub] !== undefined) {
|
if (import.meta.dev && props[main] !== undefined && props[sub] !== undefined) {
|
||||||
console.warn(`[${componentName}] \`${main}\` and \`${sub}\` cannot be used together. \`${sub}\` will be ignored.`)
|
console.warn(`[${componentName}] \`${main}\` and \`${sub}\` cannot be used together. \`${sub}\` will be ignored.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,10 +198,10 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
|||||||
|
|
||||||
// Prefetching
|
// Prefetching
|
||||||
const prefetched = ref(false)
|
const prefetched = ref(false)
|
||||||
const el = process.server ? undefined : ref<HTMLElement | null>(null)
|
const el = import.meta.server ? undefined : ref<HTMLElement | null>(null)
|
||||||
const elRef = process.server ? undefined : (ref: any) => { el!.value = props.custom ? ref?.$el?.nextElementSibling : ref?.$el }
|
const elRef = import.meta.server ? undefined : (ref: any) => { el!.value = props.custom ? ref?.$el?.nextElementSibling : ref?.$el }
|
||||||
|
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
checkPropConflicts(props, 'prefetch', 'noPrefetch')
|
checkPropConflicts(props, 'prefetch', 'noPrefetch')
|
||||||
const shouldPrefetch = props.prefetch !== false && props.noPrefetch !== true && props.target !== '_blank' && !isSlowConnection()
|
const shouldPrefetch = props.prefetch !== false && props.noPrefetch !== true && props.target !== '_blank' && !isSlowConnection()
|
||||||
if (shouldPrefetch) {
|
if (shouldPrefetch) {
|
||||||
@ -329,7 +329,7 @@ type CallbackFn = () => void
|
|||||||
type ObserveFn = (element: Element, callback: CallbackFn) => () => void
|
type ObserveFn = (element: Element, callback: CallbackFn) => () => void
|
||||||
|
|
||||||
function useObserver (): { observe: ObserveFn } | undefined {
|
function useObserver (): { observe: ObserveFn } | undefined {
|
||||||
if (process.server) { return }
|
if (import.meta.server) { return }
|
||||||
|
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
if (nuxtApp._observer) {
|
if (nuxtApp._observer) {
|
||||||
@ -370,7 +370,7 @@ function useObserver (): { observe: ObserveFn } | undefined {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isSlowConnection () {
|
function isSlowConnection () {
|
||||||
if (process.server) { return }
|
if (import.meta.server) { return }
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
|
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/connection
|
||||||
const cn = (navigator as any).connection as { saveData: boolean, effectiveType: string } | null
|
const cn = (navigator as any).connection as { saveData: boolean, effectiveType: string } | null
|
||||||
|
@ -26,6 +26,8 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup (props, { slots }) {
|
setup (props, { slots }) {
|
||||||
|
// TODO: use computed values in useLoadingIndicator
|
||||||
|
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||||
const indicator = useLoadingIndicator({
|
const indicator = useLoadingIndicator({
|
||||||
duration: props.duration,
|
duration: props.duration,
|
||||||
throttle: props.throttle
|
throttle: props.throttle
|
||||||
@ -52,14 +54,16 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
nuxtApp.hook('page:finish', indicator.finish)
|
const unsubPage = nuxtApp.hook('page:finish', indicator.finish)
|
||||||
nuxtApp.hook('vue:error', indicator.finish)
|
const unsubError = nuxtApp.hook('vue:error', indicator.finish)
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
const index = globalMiddleware.indexOf(indicator.start)
|
const index = globalMiddleware.indexOf(indicator.start)
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
globalMiddleware.splice(index, 1)
|
globalMiddleware.splice(index, 1)
|
||||||
}
|
}
|
||||||
|
unsubPage()
|
||||||
|
unsubError()
|
||||||
indicator.clear()
|
indicator.clear()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -99,7 +103,7 @@ function useLoadingIndicator (opts: {
|
|||||||
function start () {
|
function start () {
|
||||||
clear()
|
clear()
|
||||||
progress.value = 0
|
progress.value = 0
|
||||||
if (opts.throttle && process.client) {
|
if (opts.throttle && import.meta.client) {
|
||||||
_throttle = setTimeout(() => {
|
_throttle = setTimeout(() => {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
_startTimer()
|
_startTimer()
|
||||||
@ -127,7 +131,7 @@ function useLoadingIndicator (opts: {
|
|||||||
|
|
||||||
function _hide () {
|
function _hide () {
|
||||||
clear()
|
clear()
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
setTimeout(() => { progress.value = 0 }, 400)
|
setTimeout(() => { progress.value = 0 }, 400)
|
||||||
@ -136,7 +140,7 @@ function useLoadingIndicator (opts: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _startTimer () {
|
function _startTimer () {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
_timer = setInterval(() => { _increase(step.value) }, 100)
|
_timer = setInterval(() => { _increase(step.value) }, 100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,23 +16,23 @@ import { PageRouteSymbol } from '#app/components/injections'
|
|||||||
import AppComponent from '#build/app-component.mjs'
|
import AppComponent from '#build/app-component.mjs'
|
||||||
import ErrorComponent from '#build/error-component.mjs'
|
import ErrorComponent from '#build/error-component.mjs'
|
||||||
|
|
||||||
const IslandRenderer = process.server
|
const IslandRenderer = import.meta.server
|
||||||
? defineAsyncComponent(() => import('./island-renderer').then(r => r.default || r))
|
? defineAsyncComponent(() => import('./island-renderer').then(r => r.default || r))
|
||||||
: () => null
|
: () => null
|
||||||
|
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
const onResolve = nuxtApp.deferHydration()
|
const onResolve = nuxtApp.deferHydration()
|
||||||
|
|
||||||
const url = process.server ? nuxtApp.ssrContext.url : window.location.pathname
|
const url = import.meta.server ? nuxtApp.ssrContext.url : window.location.pathname
|
||||||
const SingleRenderer = process.test && process.dev && process.server && url.startsWith('/__nuxt_component_test__/') && /* #__PURE__ */ defineAsyncComponent(() => import('#build/test-component-wrapper.mjs')
|
const SingleRenderer = import.meta.test && import.meta.dev && import.meta.server && url.startsWith('/__nuxt_component_test__/') && /* #__PURE__ */ defineAsyncComponent(() => import('#build/test-component-wrapper.mjs')
|
||||||
.then(r => r.default(process.server ? url : window.location.href)))
|
.then(r => r.default(import.meta.server ? url : window.location.href)))
|
||||||
|
|
||||||
// Inject default route (outside of pages) as active route
|
// Inject default route (outside of pages) as active route
|
||||||
provide(PageRouteSymbol, useRoute())
|
provide(PageRouteSymbol, useRoute())
|
||||||
|
|
||||||
// vue:setup hook
|
// vue:setup hook
|
||||||
const results = nuxtApp.hooks.callHookWith(hooks => hooks.map(hook => hook()), 'vue:setup')
|
const results = nuxtApp.hooks.callHookWith(hooks => hooks.map(hook => hook()), 'vue:setup')
|
||||||
if (process.dev && results && results.some(i => i && 'then' in i)) {
|
if (import.meta.dev && results && results.some(i => i && 'then' in i)) {
|
||||||
console.error('[nuxt] Error in `vue:setup`. Callbacks must be synchronous.')
|
console.error('[nuxt] Error in `vue:setup`. Callbacks must be synchronous.')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ if (process.dev && results && results.some(i => i && 'then' in i)) {
|
|||||||
const error = useError()
|
const error = useError()
|
||||||
onErrorCaptured((err, target, info) => {
|
onErrorCaptured((err, target, info) => {
|
||||||
nuxtApp.hooks.callHook('vue:error', err, target, info).catch(hookError => console.error('[nuxt] Error in `vue:error` hook', hookError))
|
nuxtApp.hooks.callHook('vue:error', err, target, info).catch(hookError => console.error('[nuxt] Error in `vue:error` hook', hookError))
|
||||||
if (process.server || (isNuxtError(err) && (err.fatal || err.unhandled))) {
|
if (import.meta.server || (isNuxtError(err) && (err.fatal || err.unhandled))) {
|
||||||
const p = nuxtApp.runWithContext(() => showError(err))
|
const p = nuxtApp.runWithContext(() => showError(err))
|
||||||
onServerPrefetch(() => p)
|
onServerPrefetch(() => p)
|
||||||
return false // suppress error from breaking render
|
return false // suppress error from breaking render
|
||||||
@ -48,5 +48,5 @@ onErrorCaptured((err, target, info) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Component islands context
|
// Component islands context
|
||||||
const { islandContext } = process.server && nuxtApp.ssrContext
|
const islandContext = import.meta.server && nuxtApp.ssrContext.islandContext
|
||||||
</script>
|
</script>
|
||||||
|
@ -36,7 +36,7 @@ export const RouteProvider = defineComponent({
|
|||||||
provide(PageRouteSymbol, shallowReactive(route))
|
provide(PageRouteSymbol, shallowReactive(route))
|
||||||
|
|
||||||
let vnode: VNode
|
let vnode: VNode
|
||||||
if (process.dev && process.client && props.trackRootNodes) {
|
if (import.meta.dev && import.meta.client && props.trackRootNodes) {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (['#comment', '#text'].includes(vnode?.el?.nodeName)) {
|
if (['#comment', '#text'].includes(vnode?.el?.nodeName)) {
|
||||||
@ -48,7 +48,7 @@ export const RouteProvider = defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (process.dev && process.client) {
|
if (import.meta.dev && import.meta.client) {
|
||||||
vnode = h(props.vnode, { ref: props.vnodeRef })
|
vnode = h(props.vnode, { ref: props.vnodeRef })
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ export function vforToArray (source: any): any[] {
|
|||||||
} else if (isString(source)) {
|
} else if (isString(source)) {
|
||||||
return source.split('')
|
return source.split('')
|
||||||
} else if (typeof source === 'number') {
|
} else if (typeof source === 'number') {
|
||||||
if (process.dev && !Number.isInteger(source)) {
|
if (import.meta.dev && !Number.isInteger(source)) {
|
||||||
console.warn(`The v-for range expect an integer value but got ${source}.`)
|
console.warn(`The v-for range expect an integer value but got ${source}.`)
|
||||||
}
|
}
|
||||||
const array = []
|
const array = []
|
||||||
|
@ -222,7 +222,7 @@ export function useAsyncData<
|
|||||||
const fetchOnServer = options.server !== false && nuxt.payload.serverRendered
|
const fetchOnServer = options.server !== false && nuxt.payload.serverRendered
|
||||||
|
|
||||||
// Server side
|
// Server side
|
||||||
if (process.server && fetchOnServer && options.immediate) {
|
if (import.meta.server && fetchOnServer && options.immediate) {
|
||||||
const promise = initialFetch()
|
const promise = initialFetch()
|
||||||
if (getCurrentInstance()) {
|
if (getCurrentInstance()) {
|
||||||
onServerPrefetch(() => promise)
|
onServerPrefetch(() => promise)
|
||||||
@ -232,7 +232,7 @@ export function useAsyncData<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Client side
|
// Client side
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
// Setup hook callbacks once per instance
|
// Setup hook callbacks once per instance
|
||||||
const instance = getCurrentInstance()
|
const instance = getCurrentInstance()
|
||||||
if (instance && !instance._nuxtOnBeforeMountCbs) {
|
if (instance && !instance._nuxtOnBeforeMountCbs) {
|
||||||
@ -349,7 +349,7 @@ export function useNuxtData<DataT = any> (key: string): { data: Ref<DataT | null
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function refreshNuxtData (keys?: string | string[]): Promise<void> {
|
export async function refreshNuxtData (keys?: string | string[]): Promise<void> {
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ export interface ReloadNuxtAppOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function reloadNuxtApp (options: ReloadNuxtAppOptions = {}) {
|
export function reloadNuxtApp (options: ReloadNuxtAppOptions = {}) {
|
||||||
if (process.server) { return }
|
if (import.meta.server) { return }
|
||||||
const path = options.path || window.location.pathname
|
const path = options.path || window.location.pathname
|
||||||
|
|
||||||
let handledPath: Record<string, any> = {}
|
let handledPath: Record<string, any> = {}
|
||||||
|
@ -22,7 +22,7 @@ async function runLegacyAsyncData (res: Record<string, any> | Promise<Record<str
|
|||||||
}
|
}
|
||||||
if (data.value && typeof data.value === 'object') {
|
if (data.value && typeof data.value === 'object') {
|
||||||
Object.assign(await res, toRefs(reactive(data.value)))
|
Object.assign(await res, toRefs(reactive(data.value)))
|
||||||
} else if (process.dev) {
|
} else if (import.meta.dev) {
|
||||||
console.warn('[nuxt] asyncData should return an object', data)
|
console.warn('[nuxt] asyncData should return an object', data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
|||||||
|
|
||||||
const cookie = ref<T | undefined>(cookies[name] as any ?? opts.default?.())
|
const cookie = ref<T | undefined>(cookies[name] as any ?? opts.default?.())
|
||||||
|
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
const channel = typeof BroadcastChannel === 'undefined' ? null : new BroadcastChannel(`nuxt:cookies:${name}`)
|
const channel = typeof BroadcastChannel === 'undefined' ? null : new BroadcastChannel(`nuxt:cookies:${name}`)
|
||||||
if (getCurrentInstance()) { onUnmounted(() => { channel?.close() }) }
|
if (getCurrentInstance()) { onUnmounted(() => { channel?.close() }) }
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
|||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
} else if (process.server) {
|
} else if (import.meta.server) {
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
const writeFinalCookieValue = () => {
|
const writeFinalCookieValue = () => {
|
||||||
if (!isEqual(cookie.value, cookies[name])) {
|
if (!isEqual(cookie.value, cookies[name])) {
|
||||||
@ -79,9 +79,9 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
|||||||
}
|
}
|
||||||
|
|
||||||
function readRawCookies (opts: CookieOptions = {}): Record<string, string> | undefined {
|
function readRawCookies (opts: CookieOptions = {}): Record<string, string> | undefined {
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
return parse(useRequestEvent()?.node.req.headers.cookie || '', opts)
|
return parse(useRequestEvent()?.node.req.headers.cookie || '', opts)
|
||||||
} else if (process.client) {
|
} else if (import.meta.client) {
|
||||||
return parse(document.cookie, opts)
|
return parse(document.cookie, opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ function serializeCookie (name: string, value: any, opts: CookieSerializeOptions
|
|||||||
}
|
}
|
||||||
|
|
||||||
function writeClientCookie (name: string, value: any, opts: CookieSerializeOptions = {}) {
|
function writeClientCookie (name: string, value: any, opts: CookieSerializeOptions = {}) {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
document.cookie = serializeCookie(name, value, opts)
|
document.cookie = serializeCookie(name, value, opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ export const showError = (_err: string | Error | Partial<NuxtError>) => {
|
|||||||
try {
|
try {
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
const error = useError()
|
const error = useError()
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
nuxtApp.hooks.callHook('app:error', err)
|
nuxtApp.hooks.callHook('app:error', err)
|
||||||
}
|
}
|
||||||
error.value = error.value || err
|
error.value = error.value || err
|
||||||
|
@ -134,7 +134,7 @@ export function useFetch<
|
|||||||
const isLocalFetch = typeof _request.value === 'string' && _request.value.startsWith('/')
|
const isLocalFetch = typeof _request.value === 'string' && _request.value.startsWith('/')
|
||||||
let _$fetch = opts.$fetch || globalThis.$fetch
|
let _$fetch = opts.$fetch || globalThis.$fetch
|
||||||
// Use fetch with request context and headers for server direct API calls
|
// Use fetch with request context and headers for server direct API calls
|
||||||
if (process.server && !opts.$fetch && isLocalFetch) {
|
if (import.meta.server && !opts.$fetch && isLocalFetch) {
|
||||||
_$fetch = useRequestFetch()
|
_$fetch = useRequestFetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,13 +11,13 @@ import type { NuxtPayload } from '#app'
|
|||||||
export const useHydration = <K extends keyof NuxtPayload, T = NuxtPayload[K]> (key: K, get: () => T, set: (value: T) => void) => {
|
export const useHydration = <K extends keyof NuxtPayload, T = NuxtPayload[K]> (key: K, get: () => T, set: (value: T) => void) => {
|
||||||
const nuxt = useNuxtApp()
|
const nuxt = useNuxtApp()
|
||||||
|
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
nuxt.hooks.hook('app:rendered', () => {
|
nuxt.hooks.hook('app:rendered', () => {
|
||||||
nuxt.payload[key] = get()
|
nuxt.payload[key] = get()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
nuxt.hooks.hook('app:created', () => {
|
nuxt.hooks.hook('app:created', () => {
|
||||||
set(nuxt.payload[key] as T)
|
set(nuxt.payload[key] as T)
|
||||||
})
|
})
|
||||||
|
@ -13,7 +13,7 @@ interface LoadPayloadOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function loadPayload (url: string, opts: LoadPayloadOptions = {}): Record<string, any> | Promise<Record<string, any>> | null {
|
export function loadPayload (url: string, opts: LoadPayloadOptions = {}): Record<string, any> | Promise<Record<string, any>> | null {
|
||||||
if (process.server) { return null }
|
if (import.meta.server) { return null }
|
||||||
const payloadURL = _getPayloadURL(url, opts)
|
const payloadURL = _getPayloadURL(url, opts)
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
const cache = nuxtApp._payloadCache = nuxtApp._payloadCache || {}
|
const cache = nuxtApp._payloadCache = nuxtApp._payloadCache || {}
|
||||||
@ -55,7 +55,7 @@ function _getPayloadURL (url: string, opts: LoadPayloadOptions = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function _importPayload (payloadURL: string) {
|
async function _importPayload (payloadURL: string) {
|
||||||
if (process.server) { return null }
|
if (import.meta.server) { return null }
|
||||||
try {
|
try {
|
||||||
return renderJsonPayloads
|
return renderJsonPayloads
|
||||||
? parsePayload(await fetch(payloadURL).then(res => res.text()))
|
? parsePayload(await fetch(payloadURL).then(res => res.text()))
|
||||||
@ -74,7 +74,7 @@ export function isPrerendered () {
|
|||||||
|
|
||||||
let payloadCache: any = null
|
let payloadCache: any = null
|
||||||
export async function getNuxtClientPayload () {
|
export async function getNuxtClientPayload () {
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (payloadCache) {
|
if (payloadCache) {
|
||||||
@ -110,7 +110,7 @@ export function definePayloadReducer (
|
|||||||
name: string,
|
name: string,
|
||||||
reduce: (data: any) => any
|
reduce: (data: any) => any
|
||||||
) {
|
) {
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
useNuxtApp().ssrContext!._payloadReducers[name] = reduce
|
useNuxtApp().ssrContext!._payloadReducers[name] = reduce
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,10 +124,10 @@ export function definePayloadReviver (
|
|||||||
name: string,
|
name: string,
|
||||||
revive: (data: string) => any | undefined
|
revive: (data: string) => any | undefined
|
||||||
) {
|
) {
|
||||||
if (process.dev && getCurrentInstance()) {
|
if (import.meta.dev && getCurrentInstance()) {
|
||||||
console.warn('[nuxt] [definePayloadReviver] This function must be called in a Nuxt plugin that is `unshift`ed to the beginning of the Nuxt plugins array.')
|
console.warn('[nuxt] [definePayloadReviver] This function must be called in a Nuxt plugin that is `unshift`ed to the beginning of the Nuxt plugins array.')
|
||||||
}
|
}
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
useNuxtApp()._payloadRevivers[name] = revive
|
useNuxtApp()._payloadRevivers[name] = revive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import { useRouter } from './router'
|
|||||||
* @param components Pascal-cased name or names of components to prefetch
|
* @param components Pascal-cased name or names of components to prefetch
|
||||||
*/
|
*/
|
||||||
export const preloadComponents = async (components: string | string[]) => {
|
export const preloadComponents = async (components: string | string[]) => {
|
||||||
if (process.server) { return }
|
if (import.meta.server) { return }
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
|
|
||||||
components = Array.isArray(components) ? components : [components]
|
components = Array.isArray(components) ? components : [components]
|
||||||
@ -35,7 +35,7 @@ function _loadAsyncComponent (component: Component) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function preloadRouteComponents (to: RouteLocationRaw, router: Router & { _routePreloaded?: Set<string>; _preloadPromises?: Array<Promise<any>> } = useRouter()): Promise<void> {
|
export async function preloadRouteComponents (to: RouteLocationRaw, router: Router & { _routePreloaded?: Set<string>; _preloadPromises?: Array<Promise<any>> } = useRouter()): Promise<void> {
|
||||||
if (process.server) { return }
|
if (import.meta.server) { return }
|
||||||
|
|
||||||
const { path, matched } = router.resolve(to)
|
const { path, matched } = router.resolve(to)
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { useNuxtApp } from '../nuxt'
|
|||||||
import { requestIdleCallback } from '../compat/idle-callback'
|
import { requestIdleCallback } from '../compat/idle-callback'
|
||||||
|
|
||||||
export const onNuxtReady = (callback: () => any) => {
|
export const onNuxtReady = (callback: () => any) => {
|
||||||
if (process.server) { return }
|
if (import.meta.server) { return }
|
||||||
|
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
if (nuxtApp.isHydrating) {
|
if (nuxtApp.isHydrating) {
|
||||||
|
@ -17,7 +17,7 @@ export const useRouter: typeof _useRouter = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useRoute: typeof _useRoute = () => {
|
export const useRoute: typeof _useRoute = () => {
|
||||||
if (process.dev && isProcessingMiddleware()) {
|
if (import.meta.dev && isProcessingMiddleware()) {
|
||||||
console.warn('[nuxt] Calling `useRoute` within middleware may lead to misleading results. Instead, use the (to, from) arguments passed to the middleware to access the new and old routes.')
|
console.warn('[nuxt] Calling `useRoute` within middleware may lead to misleading results. Instead, use the (to, from) arguments passed to the middleware to access the new and old routes.')
|
||||||
}
|
}
|
||||||
if (hasInjectionContext()) {
|
if (hasInjectionContext()) {
|
||||||
@ -118,7 +118,7 @@ export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: Na
|
|||||||
|
|
||||||
// Early open handler
|
// Early open handler
|
||||||
if (options?.open) {
|
if (options?.open) {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
const { target = '_blank', windowFeatures = {} } = options.open
|
const { target = '_blank', windowFeatures = {} } = options.open
|
||||||
|
|
||||||
const features = Object.entries(windowFeatures)
|
const features = Object.entries(windowFeatures)
|
||||||
@ -146,7 +146,7 @@ export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: Na
|
|||||||
const inMiddleware = isProcessingMiddleware()
|
const inMiddleware = isProcessingMiddleware()
|
||||||
|
|
||||||
// Early redirect on client-side
|
// Early redirect on client-side
|
||||||
if (process.client && !isExternal && inMiddleware) {
|
if (import.meta.client && !isExternal && inMiddleware) {
|
||||||
return to
|
return to
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: Na
|
|||||||
|
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
|
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
if (nuxtApp.ssrContext) {
|
if (nuxtApp.ssrContext) {
|
||||||
const fullPath = typeof to === 'string' || isExternal ? toPath : router.resolve(to).fullPath || '/'
|
const fullPath = typeof to === 'string' || isExternal ? toPath : router.resolve(to).fullPath || '/'
|
||||||
const location = isExternal ? toPath : joinURL(useRuntimeConfig().app.baseURL, fullPath)
|
const location = isExternal ? toPath : joinURL(useRuntimeConfig().app.baseURL, fullPath)
|
||||||
@ -206,7 +206,7 @@ export const navigateTo = (to: RouteLocationRaw | undefined | null, options?: Na
|
|||||||
|
|
||||||
/** This will abort navigation within a Nuxt route middleware handler. */
|
/** This will abort navigation within a Nuxt route middleware handler. */
|
||||||
export const abortNavigation = (err?: string | Partial<NuxtError>) => {
|
export const abortNavigation = (err?: string | Partial<NuxtError>) => {
|
||||||
if (process.dev && !isProcessingMiddleware()) {
|
if (import.meta.dev && !isProcessingMiddleware()) {
|
||||||
throw new Error('abortNavigation() is only usable inside a route middleware handler.')
|
throw new Error('abortNavigation() is only usable inside a route middleware handler.')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,18 +222,18 @@ export const abortNavigation = (err?: string | Partial<NuxtError>) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const setPageLayout = (layout: unknown extends PageMeta['layout'] ? string : PageMeta['layout']) => {
|
export const setPageLayout = (layout: unknown extends PageMeta['layout'] ? string : PageMeta['layout']) => {
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
if (process.dev && getCurrentInstance() && useState('_layout').value !== layout) {
|
if (import.meta.dev && getCurrentInstance() && useState('_layout').value !== layout) {
|
||||||
console.warn('[warn] [nuxt] `setPageLayout` should not be called to change the layout on the server within a component as this will cause hydration errors.')
|
console.warn('[warn] [nuxt] `setPageLayout` should not be called to change the layout on the server within a component as this will cause hydration errors.')
|
||||||
}
|
}
|
||||||
useState('_layout').value = layout
|
useState('_layout').value = layout
|
||||||
}
|
}
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
if (process.dev && nuxtApp.isHydrating && nuxtApp.payload.serverRendered && useState('_layout').value !== layout) {
|
if (import.meta.dev && nuxtApp.isHydrating && nuxtApp.payload.serverRendered && useState('_layout').value !== layout) {
|
||||||
console.warn('[warn] [nuxt] `setPageLayout` should not be called to change the layout during hydration as this will cause hydration errors.')
|
console.warn('[warn] [nuxt] `setPageLayout` should not be called to change the layout during hydration as this will cause hydration errors.')
|
||||||
}
|
}
|
||||||
const inMiddleware = isProcessingMiddleware()
|
const inMiddleware = isProcessingMiddleware()
|
||||||
if (inMiddleware || process.server || nuxtApp.isHydrating) {
|
if (inMiddleware || import.meta.server || nuxtApp.isHydrating) {
|
||||||
const unsubscribe = useRouter().beforeResolve((to) => {
|
const unsubscribe = useRouter().beforeResolve((to) => {
|
||||||
to.meta.layout = layout as Exclude<PageMeta['layout'], Ref | false>
|
to.meta.layout = layout as Exclude<PageMeta['layout'], Ref | false>
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import type { H3Event } from 'h3'
|
import type { H3Event } from 'h3'
|
||||||
import { setResponseStatus as _setResponseStatus } from 'h3'
|
import { setResponseStatus as _setResponseStatus } from 'h3'
|
||||||
import type { NuxtApp } from '../nuxt'
|
import type { NuxtApp } from '../nuxt'
|
||||||
@ -7,7 +6,7 @@ import { useNuxtApp } from '../nuxt'
|
|||||||
export function useRequestHeaders<K extends string = string> (include: K[]): { [key in Lowercase<K>]?: string }
|
export function useRequestHeaders<K extends string = string> (include: K[]): { [key in Lowercase<K>]?: string }
|
||||||
export function useRequestHeaders (): Readonly<Record<string, string>>
|
export function useRequestHeaders (): Readonly<Record<string, string>>
|
||||||
export function useRequestHeaders (include?: any[]) {
|
export function useRequestHeaders (include?: any[]) {
|
||||||
if (process.client) { return {} }
|
if (import.meta.client) { return {} }
|
||||||
const headers = useNuxtApp().ssrContext?.event.node.req.headers ?? {}
|
const headers = useNuxtApp().ssrContext?.event.node.req.headers ?? {}
|
||||||
if (!include) { return headers }
|
if (!include) { return headers }
|
||||||
return Object.fromEntries(include.map(key => key.toLowerCase()).filter(key => headers[key]).map(key => [key, headers[key]]))
|
return Object.fromEntries(include.map(key => key.toLowerCase()).filter(key => headers[key]).map(key => [key, headers[key]]))
|
||||||
@ -18,7 +17,7 @@ export function useRequestEvent (nuxtApp: NuxtApp = useNuxtApp()): H3Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useRequestFetch (): typeof global.$fetch {
|
export function useRequestFetch (): typeof global.$fetch {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return globalThis.$fetch
|
return globalThis.$fetch
|
||||||
}
|
}
|
||||||
const event = useNuxtApp().ssrContext?.event as H3Event
|
const event = useNuxtApp().ssrContext?.event as H3Event
|
||||||
@ -29,7 +28,7 @@ export function setResponseStatus (event: H3Event, code?: number, message?: stri
|
|||||||
/** @deprecated Pass `event` as first option. */
|
/** @deprecated Pass `event` as first option. */
|
||||||
export function setResponseStatus (code: number, message?: string): void
|
export function setResponseStatus (code: number, message?: string): void
|
||||||
export function setResponseStatus (arg1: H3Event | number | undefined, arg2?: number | string, arg3?: string) {
|
export function setResponseStatus (arg1: H3Event | number | undefined, arg2?: number | string, arg3?: string) {
|
||||||
if (process.client) { return }
|
if (import.meta.client) { return }
|
||||||
if (arg1 && typeof arg1 !== 'number') {
|
if (arg1 && typeof arg1 !== 'number') {
|
||||||
return _setResponseStatus(arg1, arg2 as number | undefined, arg3)
|
return _setResponseStatus(arg1, arg2 as number | undefined, arg3)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import { useRequestEvent } from './ssr'
|
|||||||
import { useRuntimeConfig } from '#app'
|
import { useRuntimeConfig } from '#app'
|
||||||
|
|
||||||
export function useRequestURL () {
|
export function useRequestURL () {
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
const url = getRequestURL(useRequestEvent())
|
const url = getRequestURL(useRequestEvent())
|
||||||
url.pathname = joinURL(useRuntimeConfig().app.baseURL, url.pathname)
|
url.pathname = joinURL(useRuntimeConfig().app.baseURL, url.pathname)
|
||||||
return url
|
return url
|
||||||
|
@ -38,7 +38,7 @@ function deepAssign (obj: any, newObj: any) {
|
|||||||
export function useAppConfig (): AppConfig {
|
export function useAppConfig (): AppConfig {
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
if (!nuxtApp._appConfig) {
|
if (!nuxtApp._appConfig) {
|
||||||
nuxtApp._appConfig = (process.server ? klona(__appConfig) : reactive(__appConfig)) as AppConfig
|
nuxtApp._appConfig = (import.meta.server ? klona(__appConfig) : reactive(__appConfig)) as AppConfig
|
||||||
}
|
}
|
||||||
return nuxtApp._appConfig
|
return nuxtApp._appConfig
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ export function updateAppConfig (appConfig: DeepPartial<AppConfig>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HMR Support
|
// HMR Support
|
||||||
if (process.dev) {
|
if (import.meta.dev) {
|
||||||
function applyHMR (newConfig: AppConfig) {
|
function applyHMR (newConfig: AppConfig) {
|
||||||
const appConfig = useAppConfig()
|
const appConfig = useAppConfig()
|
||||||
if (newConfig && appConfig) {
|
if (newConfig && appConfig) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import type { CreateOptions } from '#app'
|
import type { CreateOptions } from '#app'
|
||||||
|
|
||||||
const entry = process.server
|
const entry = import.meta.server
|
||||||
? (ctx?: CreateOptions['ssrContext']) => import('#app/entry').then(m => m.default(ctx))
|
? (ctx?: CreateOptions['ssrContext']) => import('#app/entry').then(m => m.default(ctx))
|
||||||
: () => import('#app/entry').then(m => m.default)
|
: () => import('#app/entry').then(m => m.default)
|
||||||
|
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
entry()
|
entry()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import plugins from '#build/plugins'
|
|||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import RootComponent from '#build/root-component.mjs'
|
import RootComponent from '#build/root-component.mjs'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { appRootId } from '#build/nuxt.config.mjs'
|
import { vueAppRootContainer } from '#build/nuxt.config.mjs'
|
||||||
|
|
||||||
if (!globalThis.$fetch) {
|
if (!globalThis.$fetch) {
|
||||||
globalThis.$fetch = $fetch.create({
|
globalThis.$fetch = $fetch.create({
|
||||||
@ -26,7 +26,7 @@ if (!globalThis.$fetch) {
|
|||||||
|
|
||||||
let entry: Function
|
let entry: Function
|
||||||
|
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
entry = async function createNuxtAppServer (ssrContext: CreateOptions['ssrContext']) {
|
entry = async function createNuxtAppServer (ssrContext: CreateOptions['ssrContext']) {
|
||||||
const vueApp = createApp(RootComponent)
|
const vueApp = createApp(RootComponent)
|
||||||
|
|
||||||
@ -45,10 +45,10 @@ if (process.server) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
// TODO: temporary webpack 5 HMR fix
|
// TODO: temporary webpack 5 HMR fix
|
||||||
// https://github.com/webpack-contrib/webpack-hot-middleware/issues/390
|
// https://github.com/webpack-contrib/webpack-hot-middleware/issues/390
|
||||||
if (process.dev && import.meta.webpackHot) {
|
if (import.meta.dev && import.meta.webpackHot) {
|
||||||
import.meta.webpackHot.accept()
|
import.meta.webpackHot.accept()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ if (process.client) {
|
|||||||
try {
|
try {
|
||||||
await nuxt.hooks.callHook('app:created', vueApp)
|
await nuxt.hooks.callHook('app:created', vueApp)
|
||||||
await nuxt.hooks.callHook('app:beforeMount', vueApp)
|
await nuxt.hooks.callHook('app:beforeMount', vueApp)
|
||||||
vueApp.mount('#' + appRootId)
|
vueApp.mount(vueAppRootContainer)
|
||||||
await nuxt.hooks.callHook('app:mounted', vueApp)
|
await nuxt.hooks.callHook('app:mounted', vueApp)
|
||||||
await nextTick()
|
await nextTick()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -17,7 +17,9 @@ import type { RouteMiddleware } from '../../app'
|
|||||||
import type { NuxtError } from '../app/composables/error'
|
import type { NuxtError } from '../app/composables/error'
|
||||||
import type { AsyncDataRequestStatus } from '../app/composables/asyncData'
|
import type { AsyncDataRequestStatus } from '../app/composables/asyncData'
|
||||||
|
|
||||||
const nuxtAppCtx = /* #__PURE__ */ getContext<NuxtApp>('nuxt-app')
|
const nuxtAppCtx = /* #__PURE__ */ getContext<NuxtApp>('nuxt-app', {
|
||||||
|
asyncContext: !!process.env.NUXT_ASYNC_CONTEXT && process.server
|
||||||
|
})
|
||||||
|
|
||||||
type HookResult = Promise<void> | void
|
type HookResult = Promise<void> | void
|
||||||
|
|
||||||
@ -210,13 +212,13 @@ export function createNuxtApp (options: CreateOptions) {
|
|||||||
data: {},
|
data: {},
|
||||||
state: {},
|
state: {},
|
||||||
_errors: {},
|
_errors: {},
|
||||||
...(process.client ? window.__NUXT__ ?? {} : { serverRendered: true })
|
...(import.meta.client ? window.__NUXT__ ?? {} : { serverRendered: true })
|
||||||
}),
|
}),
|
||||||
static: {
|
static: {
|
||||||
data: {}
|
data: {}
|
||||||
},
|
},
|
||||||
runWithContext: (fn: any) => callWithNuxt(nuxtApp, fn),
|
runWithContext: (fn: any) => callWithNuxt(nuxtApp, fn),
|
||||||
isHydrating: process.client,
|
isHydrating: import.meta.client,
|
||||||
deferHydration () {
|
deferHydration () {
|
||||||
if (!nuxtApp.isHydrating) { return () => {} }
|
if (!nuxtApp.isHydrating) { return () => {} }
|
||||||
|
|
||||||
@ -244,7 +246,7 @@ export function createNuxtApp (options: CreateOptions) {
|
|||||||
nuxtApp.hooks = createHooks<RuntimeNuxtHooks>()
|
nuxtApp.hooks = createHooks<RuntimeNuxtHooks>()
|
||||||
nuxtApp.hook = nuxtApp.hooks.hook
|
nuxtApp.hook = nuxtApp.hooks.hook
|
||||||
|
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
async function contextCaller (hooks: HookCallback[], args: any[]) {
|
async function contextCaller (hooks: HookCallback[], args: any[]) {
|
||||||
for (const hook of hooks) {
|
for (const hook of hooks) {
|
||||||
await nuxtApp.runWithContext(() => hook(...args))
|
await nuxtApp.runWithContext(() => hook(...args))
|
||||||
@ -267,7 +269,7 @@ export function createNuxtApp (options: CreateOptions) {
|
|||||||
defineGetter(nuxtApp.vueApp, '$nuxt', nuxtApp)
|
defineGetter(nuxtApp.vueApp, '$nuxt', nuxtApp)
|
||||||
defineGetter(nuxtApp.vueApp.config.globalProperties, '$nuxt', nuxtApp)
|
defineGetter(nuxtApp.vueApp.config.globalProperties, '$nuxt', nuxtApp)
|
||||||
|
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
if (nuxtApp.ssrContext) {
|
if (nuxtApp.ssrContext) {
|
||||||
// Expose nuxt to the renderContext
|
// Expose nuxt to the renderContext
|
||||||
nuxtApp.ssrContext.nuxt = nuxtApp
|
nuxtApp.ssrContext.nuxt = nuxtApp
|
||||||
@ -291,7 +293,7 @@ export function createNuxtApp (options: CreateOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Listen to chunk load errors
|
// Listen to chunk load errors
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
window.addEventListener('nuxt.preloadError', (event) => {
|
window.addEventListener('nuxt.preloadError', (event) => {
|
||||||
nuxtApp.callHook('app:chunkError', { error: (event as Event & { payload: Error }).payload })
|
nuxtApp.callHook('app:chunkError', { error: (event as Event & { payload: Error }).payload })
|
||||||
})
|
})
|
||||||
@ -305,7 +307,7 @@ export function createNuxtApp (options: CreateOptions) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Expose runtime config
|
// Expose runtime config
|
||||||
const runtimeConfig = process.server ? options.ssrContext!.runtimeConfig : reactive(nuxtApp.payload.config!)
|
const runtimeConfig = import.meta.server ? options.ssrContext!.runtimeConfig : reactive(nuxtApp.payload.config!)
|
||||||
nuxtApp.provide('config', runtimeConfig)
|
nuxtApp.provide('config', runtimeConfig)
|
||||||
|
|
||||||
return nuxtApp
|
return nuxtApp
|
||||||
@ -329,7 +331,7 @@ export async function applyPlugins (nuxtApp: NuxtApp, plugins: Array<Plugin & Ob
|
|||||||
const parallels: Promise<any>[] = []
|
const parallels: Promise<any>[] = []
|
||||||
const errors: Error[] = []
|
const errors: Error[] = []
|
||||||
for (const plugin of plugins) {
|
for (const plugin of plugins) {
|
||||||
if (process.server && nuxtApp.ssrContext?.islandContext && plugin.env?.islands === false) { continue }
|
if (import.meta.server && nuxtApp.ssrContext?.islandContext && plugin.env?.islands === false) { continue }
|
||||||
const promise = applyPlugin(nuxtApp, plugin)
|
const promise = applyPlugin(nuxtApp, plugin)
|
||||||
if (plugin.parallel) {
|
if (plugin.parallel) {
|
||||||
parallels.push(promise.catch(e => errors.push(e)))
|
parallels.push(promise.catch(e => errors.push(e)))
|
||||||
@ -363,7 +365,7 @@ export function isNuxtPlugin (plugin: unknown) {
|
|||||||
*/
|
*/
|
||||||
export function callWithNuxt<T extends (...args: any[]) => any> (nuxt: NuxtApp | _NuxtApp, setup: T, args?: Parameters<T>) {
|
export function callWithNuxt<T extends (...args: any[]) => any> (nuxt: NuxtApp | _NuxtApp, setup: T, args?: Parameters<T>) {
|
||||||
const fn: () => ReturnType<T> = () => args ? setup(...args as Parameters<T>) : setup()
|
const fn: () => ReturnType<T> = () => args ? setup(...args as Parameters<T>) : setup()
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
return nuxt.vueApp.runWithContext(() => nuxtAppCtx.callAsync(nuxt as NuxtApp, fn))
|
return nuxt.vueApp.runWithContext(() => nuxtAppCtx.callAsync(nuxt as NuxtApp, fn))
|
||||||
} else {
|
} else {
|
||||||
// In client side we could assume nuxt app is singleton
|
// In client side we could assume nuxt app is singleton
|
||||||
@ -385,7 +387,7 @@ export function useNuxtApp (): NuxtApp {
|
|||||||
nuxtAppInstance = nuxtAppInstance || nuxtAppCtx.tryUse()
|
nuxtAppInstance = nuxtAppInstance || nuxtAppCtx.tryUse()
|
||||||
|
|
||||||
if (!nuxtAppInstance) {
|
if (!nuxtAppInstance) {
|
||||||
if (process.dev) {
|
if (import.meta.dev) {
|
||||||
throw new Error('[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#using-vue-and-nuxt-composables`.')
|
throw new Error('[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function. This is probably not a Nuxt bug. Find out more at `https://nuxt.com/docs/guide/concepts/auto-imports#using-vue-and-nuxt-composables`.')
|
||||||
} else {
|
} else {
|
||||||
throw new Error('[nuxt] instance unavailable')
|
throw new Error('[nuxt] instance unavailable')
|
||||||
|
@ -99,7 +99,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>({
|
|||||||
name: 'nuxt:router',
|
name: 'nuxt:router',
|
||||||
enforce: 'pre',
|
enforce: 'pre',
|
||||||
setup (nuxtApp) {
|
setup (nuxtApp) {
|
||||||
const initialURL = process.client
|
const initialURL = import.meta.client
|
||||||
? withoutBase(window.location.pathname, useRuntimeConfig().app.baseURL) + window.location.search + window.location.hash
|
? withoutBase(window.location.pathname, useRuntimeConfig().app.baseURL) + window.location.search + window.location.hash
|
||||||
: nuxtApp.ssrContext!.url
|
: nuxtApp.ssrContext!.url
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>({
|
|||||||
}
|
}
|
||||||
// Perform navigation
|
// Perform navigation
|
||||||
Object.assign(route, to)
|
Object.assign(route, to)
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
window.history[replace ? 'replaceState' : 'pushState']({}, '', joinURL(baseURL, to.fullPath))
|
window.history[replace ? 'replaceState' : 'pushState']({}, '', joinURL(baseURL, to.fullPath))
|
||||||
if (!nuxtApp.isHydrating) {
|
if (!nuxtApp.isHydrating) {
|
||||||
// Clear any existing errors
|
// Clear any existing errors
|
||||||
@ -150,7 +150,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>({
|
|||||||
await middleware(to, route)
|
await middleware(to, route)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (process.dev && !hooks.error.length) {
|
if (import.meta.dev && !hooks.error.length) {
|
||||||
console.warn('No error handlers registered to handle middleware errors. You can register an error handler with `router.onError()`', err)
|
console.warn('No error handlers registered to handle middleware errors. You can register an error handler with `router.onError()`', err)
|
||||||
}
|
}
|
||||||
for (const handler of hooks.error) {
|
for (const handler of hooks.error) {
|
||||||
@ -211,7 +211,7 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
window.addEventListener('popstate', (event) => {
|
window.addEventListener('popstate', (event) => {
|
||||||
const location = (event.target as Window).location
|
const location = (event.target as Window).location
|
||||||
router.replace(location.href.replace(location.origin, ''))
|
router.replace(location.href.replace(location.origin, ''))
|
||||||
@ -235,12 +235,12 @@ export default defineNuxtPlugin<{ route: Route, router: Router }>({
|
|||||||
}
|
}
|
||||||
nuxtApp._processingMiddleware = true
|
nuxtApp._processingMiddleware = true
|
||||||
|
|
||||||
if (process.client || !nuxtApp.ssrContext?.islandContext) {
|
if (import.meta.client || !nuxtApp.ssrContext?.islandContext) {
|
||||||
const middlewareEntries = new Set<RouteGuard>([...globalMiddleware, ...nuxtApp._middleware.global])
|
const middlewareEntries = new Set<RouteGuard>([...globalMiddleware, ...nuxtApp._middleware.global])
|
||||||
|
|
||||||
for (const middleware of middlewareEntries) {
|
for (const middleware of middlewareEntries) {
|
||||||
const result = await nuxtApp.runWithContext(() => middleware(to, from))
|
const result = await nuxtApp.runWithContext(() => middleware(to, from))
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
if (result === false || result instanceof Error) {
|
if (result === false || result instanceof Error) {
|
||||||
const error = result || createError({
|
const error = result || createError({
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
|
19
packages/nuxt/src/app/types/augments.d.ts
vendored
19
packages/nuxt/src/app/types/augments.d.ts
vendored
@ -1,17 +1,20 @@
|
|||||||
import type { NuxtApp, useNuxtApp } from '../nuxt'
|
import type { NuxtApp, useNuxtApp } from '../nuxt'
|
||||||
|
|
||||||
|
interface NuxtStaticBuildFlags {
|
||||||
|
browser: boolean
|
||||||
|
client: boolean
|
||||||
|
dev: boolean
|
||||||
|
server: boolean
|
||||||
|
test: boolean
|
||||||
|
}
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
namespace NodeJS {
|
namespace NodeJS {
|
||||||
interface Process {
|
interface Process extends NuxtStaticBuildFlags {}
|
||||||
browser: boolean
|
|
||||||
client: boolean
|
|
||||||
dev: boolean
|
|
||||||
mode: 'spa' | 'universal'
|
|
||||||
server: boolean
|
|
||||||
static: boolean
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ImportMeta extends NuxtStaticBuildFlags {}
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
__NUXT__?: Record<string, any>
|
__NUXT__?: Record<string, any>
|
||||||
useNuxtApp?: typeof useNuxtApp
|
useNuxtApp?: typeof useNuxtApp
|
||||||
|
@ -36,20 +36,25 @@ export default defineNuxtPlugin({
|
|||||||
export const componentsPluginTemplate: NuxtPluginTemplate<ComponentsTemplateContext> = {
|
export const componentsPluginTemplate: NuxtPluginTemplate<ComponentsTemplateContext> = {
|
||||||
filename: 'components.plugin.mjs',
|
filename: 'components.plugin.mjs',
|
||||||
getContents ({ app }) {
|
getContents ({ app }) {
|
||||||
const globalComponents = new Set<string>()
|
const lazyGlobalComponents = new Set<string>()
|
||||||
|
const syncGlobalComponents = new Set<string>()
|
||||||
for (const component of app.components) {
|
for (const component of app.components) {
|
||||||
if (component.global) {
|
if (component.global === 'sync') {
|
||||||
globalComponents.add(component.pascalName)
|
syncGlobalComponents.add(component.pascalName)
|
||||||
|
} else if (component.global) {
|
||||||
|
lazyGlobalComponents.add(component.pascalName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!globalComponents.size) { return emptyComponentsPlugin }
|
if (!lazyGlobalComponents.size && !syncGlobalComponents.size) { return emptyComponentsPlugin }
|
||||||
|
|
||||||
const components = [...globalComponents]
|
const lazyComponents = [...lazyGlobalComponents]
|
||||||
|
const syncComponents = [...syncGlobalComponents]
|
||||||
|
|
||||||
return `import { defineNuxtPlugin } from '#app/nuxt'
|
return `import { defineNuxtPlugin } from '#app/nuxt'
|
||||||
import { ${components.map(c => 'Lazy' + c).join(', ')} } from '#components'
|
import { ${[...lazyComponents.map(c => 'Lazy' + c), ...syncComponents].join(', ')} } from '#components'
|
||||||
const lazyGlobalComponents = [
|
const lazyGlobalComponents = [
|
||||||
${components.map(c => `["${c}", Lazy${c}]`).join(',\n')}
|
${lazyComponents.map(c => `["${c}", Lazy${c}]`).join(',\n')},
|
||||||
|
${syncComponents.map(c => `["${c}", ${c}]`).join(',\n')}
|
||||||
]
|
]
|
||||||
|
|
||||||
export default defineNuxtPlugin({
|
export default defineNuxtPlugin({
|
||||||
|
@ -90,7 +90,7 @@ async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (!app.mainComponent) {
|
if (!app.mainComponent) {
|
||||||
app.mainComponent = (await tryResolveModule('@nuxt/ui-templates/templates/welcome.vue', nuxt.options.modulesDir))!
|
app.mainComponent = (await tryResolveModule('@nuxt/ui-templates/templates/welcome.vue', nuxt.options.modulesDir)) ?? '@nuxt/ui-templates/templates/welcome.vue'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve root component
|
// Resolve root component
|
||||||
|
@ -6,9 +6,10 @@ import { isIgnored, tryResolveModule, useNuxt } from '@nuxt/kit'
|
|||||||
import { interopDefault } from 'mlly'
|
import { interopDefault } from 'mlly'
|
||||||
import { debounce } from 'perfect-debounce'
|
import { debounce } from 'perfect-debounce'
|
||||||
import { normalize, relative, resolve } from 'pathe'
|
import { normalize, relative, resolve } from 'pathe'
|
||||||
import type { Nuxt } from 'nuxt/schema'
|
import type { Nuxt, NuxtBuilder } from 'nuxt/schema'
|
||||||
|
|
||||||
import { generateApp as _generateApp, createApp } from './app'
|
import { generateApp as _generateApp, createApp } from './app'
|
||||||
|
import { checkForExternalConfigurationFiles } from './external-config-files'
|
||||||
|
|
||||||
export async function build (nuxt: Nuxt) {
|
export async function build (nuxt: Nuxt) {
|
||||||
const app = createApp(nuxt)
|
const app = createApp(nuxt)
|
||||||
@ -43,7 +44,7 @@ export async function build (nuxt: Nuxt) {
|
|||||||
|
|
||||||
await nuxt.callHook('build:before')
|
await nuxt.callHook('build:before')
|
||||||
if (!nuxt.options._prepare) {
|
if (!nuxt.options._prepare) {
|
||||||
await bundle(nuxt)
|
await Promise.all([checkForExternalConfigurationFiles(), bundle(nuxt)])
|
||||||
await nuxt.callHook('build:done')
|
await nuxt.callHook('build:done')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,23 +179,23 @@ async function bundle (nuxt: Nuxt) {
|
|||||||
? await loadBuilder(nuxt, nuxt.options.builder)
|
? await loadBuilder(nuxt, nuxt.options.builder)
|
||||||
: nuxt.options.builder
|
: nuxt.options.builder
|
||||||
|
|
||||||
return bundle(nuxt)
|
await bundle(nuxt)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
await nuxt.callHook('build:error', error)
|
await nuxt.callHook('build:error', error)
|
||||||
|
|
||||||
if (error.toString().includes('Cannot find module \'@nuxt/webpack-builder\'')) {
|
if (error.toString().includes('Cannot find module \'@nuxt/webpack-builder\'')) {
|
||||||
throw new Error([
|
throw new Error('Could not load `@nuxt/webpack-builder`. You may need to add it to your project dependencies, following the steps in `https://github.com/nuxt/framework/pull/2812`.')
|
||||||
'Could not load `@nuxt/webpack-builder`. You may need to add it to your project dependencies, following the steps in `https://github.com/nuxt/framework/pull/2812`.'
|
|
||||||
].join('\n'))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadBuilder (nuxt: Nuxt, builder: string) {
|
async function loadBuilder (nuxt: Nuxt, builder: string): Promise<NuxtBuilder> {
|
||||||
const builderPath = await tryResolveModule(builder, [nuxt.options.rootDir, import.meta.url])
|
const builderPath = await tryResolveModule(builder, [nuxt.options.rootDir, import.meta.url])
|
||||||
if (builderPath) {
|
|
||||||
return import(pathToFileURL(builderPath).href)
|
if (!builderPath) {
|
||||||
|
throw new Error(`Loading \`${builder}\` builder failed. You can read more about the nuxt \`builder\` option at: \`https://nuxt.com/docs/api/configuration/nuxt-config#builder\``)
|
||||||
}
|
}
|
||||||
|
return import(pathToFileURL(builderPath).href)
|
||||||
}
|
}
|
||||||
|
77
packages/nuxt/src/core/external-config-files.ts
Normal file
77
packages/nuxt/src/core/external-config-files.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { findPath } from '@nuxt/kit'
|
||||||
|
import { basename } from 'pathe'
|
||||||
|
import { generateApp as _generateApp } from './app'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for those external configuration files that are not compatible with Nuxt,
|
||||||
|
* and warns the user about them.
|
||||||
|
*
|
||||||
|
* @see {@link https://nuxt.com/docs/getting-started/configuration#external-configuration-files}
|
||||||
|
*/
|
||||||
|
export async function checkForExternalConfigurationFiles () {
|
||||||
|
const checkResults = await Promise.all([checkViteConfig(), checkWebpackConfig(), checkNitroConfig(), checkPostCSSConfig()])
|
||||||
|
const warningMessages = checkResults.filter(Boolean) as string[]
|
||||||
|
|
||||||
|
if (!warningMessages.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const foundOneExternalConfig = warningMessages.length === 1
|
||||||
|
if (foundOneExternalConfig) {
|
||||||
|
console.warn(warningMessages[0])
|
||||||
|
} else {
|
||||||
|
const warningsAsList = warningMessages.map(message => `- ${message}`).join('\n')
|
||||||
|
const warning = `Found multiple external configuration files: \n\n${warningsAsList}`
|
||||||
|
console.warn(warning)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkViteConfig () {
|
||||||
|
// https://github.com/vitejs/vite/blob/8fe69524d25d45290179175ba9b9956cbce87a91/packages/vite/src/node/constants.ts#L38
|
||||||
|
return await checkAndWarnAboutConfigFileExistence({
|
||||||
|
fileName: 'vite.config',
|
||||||
|
extensions: ['.js', '.mjs', '.ts', '.cjs', '.mts', '.cts'],
|
||||||
|
createWarningMessage: foundFile => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.vite\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#vite\`.`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkWebpackConfig () {
|
||||||
|
// https://webpack.js.org/configuration/configuration-languages/
|
||||||
|
return await checkAndWarnAboutConfigFileExistence({
|
||||||
|
fileName: 'webpack.config',
|
||||||
|
extensions: ['.js', '.mjs', '.ts', '.cjs', '.mts', '.cts', 'coffee'],
|
||||||
|
createWarningMessage: foundFile => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.webpack\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#webpack-1\`.`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkNitroConfig () {
|
||||||
|
// https://nitro.unjs.io/config#configuration
|
||||||
|
return await checkAndWarnAboutConfigFileExistence({
|
||||||
|
fileName: 'nitro.config',
|
||||||
|
extensions: ['.ts', '.mts'],
|
||||||
|
createWarningMessage: foundFile => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.nitro\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#nitro\`.`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkPostCSSConfig () {
|
||||||
|
return await checkAndWarnAboutConfigFileExistence({
|
||||||
|
fileName: 'postcss.config',
|
||||||
|
extensions: ['.js', '.cjs'],
|
||||||
|
createWarningMessage: foundFile => `Using \`${foundFile}\` is not supported together with Nuxt. Use \`options.postcss\` instead. You can read more in \`https://nuxt.com/docs/api/configuration/nuxt-config#postcss\`.`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CheckAndWarnAboutConfigFileExistenceOptions {
|
||||||
|
fileName: string,
|
||||||
|
extensions: string[],
|
||||||
|
createWarningMessage: (foundFile: string) => string
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkAndWarnAboutConfigFileExistence (options: CheckAndWarnAboutConfigFileExistenceOptions) {
|
||||||
|
const { fileName, extensions, createWarningMessage } = options
|
||||||
|
|
||||||
|
const configFile = await findPath(fileName, { extensions }).catch(() => null)
|
||||||
|
if (configFile) {
|
||||||
|
return createWarningMessage(basename(configFile))
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { addDependency } from 'nypm'
|
import { addDependency } from 'nypm'
|
||||||
import { resolvePackageJSON } from 'pkg-types'
|
import { resolvePackageJSON } from 'pkg-types'
|
||||||
import { logger } from '@nuxt/kit'
|
import { logger } from '@nuxt/kit'
|
||||||
|
import { isCI } from 'std-env'
|
||||||
import prompts from 'prompts'
|
import prompts from 'prompts'
|
||||||
|
|
||||||
export async function ensurePackageInstalled (rootDir: string, name: string, searchPaths?: string[]) {
|
export async function ensurePackageInstalled (rootDir: string, name: string, searchPaths?: string[]) {
|
||||||
@ -9,6 +10,9 @@ export async function ensurePackageInstalled (rootDir: string, name: string, sea
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`Package ${name} is missing`)
|
logger.info(`Package ${name} is missing`)
|
||||||
|
if (isCI) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
const { confirm } = await prompts({
|
const { confirm } = await prompts({
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
|
@ -45,7 +45,8 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
buildDir: nuxt.options.buildDir,
|
buildDir: nuxt.options.buildDir,
|
||||||
experimental: {
|
experimental: {
|
||||||
// @ts-expect-error `typescriptBundlerResolution` coming in next nitro version
|
// @ts-expect-error `typescriptBundlerResolution` coming in next nitro version
|
||||||
typescriptBundlerResolution: nuxt.options.experimental.typescriptBundlerResolution || nuxt.options.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowerCase() === 'bundler' || _nitroConfig.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowerCase() === 'bundler'
|
typescriptBundlerResolution: nuxt.options.experimental.typescriptBundlerResolution || nuxt.options.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowerCase() === 'bundler' || _nitroConfig.typescript?.tsConfig?.compilerOptions?.moduleResolution?.toLowerCase() === 'bundler',
|
||||||
|
asyncContext: nuxt.options.experimental.asyncContext
|
||||||
},
|
},
|
||||||
imports: {
|
imports: {
|
||||||
autoImport: nuxt.options.imports.autoImport as boolean,
|
autoImport: nuxt.options.imports.autoImport as boolean,
|
||||||
@ -191,6 +192,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) {
|
|||||||
'process.env.NUXT_INLINE_STYLES': !!nuxt.options.experimental.inlineSSRStyles,
|
'process.env.NUXT_INLINE_STYLES': !!nuxt.options.experimental.inlineSSRStyles,
|
||||||
'process.env.NUXT_JSON_PAYLOADS': !!nuxt.options.experimental.renderJsonPayloads,
|
'process.env.NUXT_JSON_PAYLOADS': !!nuxt.options.experimental.renderJsonPayloads,
|
||||||
'process.env.NUXT_COMPONENT_ISLANDS': !!nuxt.options.experimental.componentIslands,
|
'process.env.NUXT_COMPONENT_ISLANDS': !!nuxt.options.experimental.componentIslands,
|
||||||
|
'process.env.NUXT_ASYNC_CONTEXT': !!nuxt.options.experimental.asyncContext,
|
||||||
'process.dev': nuxt.options.dev,
|
'process.dev': nuxt.options.dev,
|
||||||
__VUE_PROD_DEVTOOLS__: false
|
__VUE_PROD_DEVTOOLS__: false
|
||||||
},
|
},
|
||||||
|
@ -25,6 +25,8 @@ import { addModuleTranspiles } from './modules'
|
|||||||
import { initNitro } from './nitro'
|
import { initNitro } from './nitro'
|
||||||
import schemaModule from './schema'
|
import schemaModule from './schema'
|
||||||
import { RemovePluginMetadataPlugin } from './plugins/plugin-metadata'
|
import { RemovePluginMetadataPlugin } from './plugins/plugin-metadata'
|
||||||
|
import { AsyncContextInjectionPlugin } from './plugins/async-context'
|
||||||
|
import { resolveDeepImportsPlugin } from './plugins/resolve-deep-imports'
|
||||||
|
|
||||||
export function createNuxt (options: NuxtOptions): Nuxt {
|
export function createNuxt (options: NuxtOptions): Nuxt {
|
||||||
const hooks = createHooks<NuxtHooks>()
|
const hooks = createHooks<NuxtHooks>()
|
||||||
@ -86,6 +88,9 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
addVitePlugin(() => ImportProtectionPlugin.vite(config))
|
addVitePlugin(() => ImportProtectionPlugin.vite(config))
|
||||||
addWebpackPlugin(() => ImportProtectionPlugin.webpack(config))
|
addWebpackPlugin(() => ImportProtectionPlugin.webpack(config))
|
||||||
|
|
||||||
|
// add resolver for modules used in virtual files
|
||||||
|
addVitePlugin(() => resolveDeepImportsPlugin(nuxt))
|
||||||
|
|
||||||
if (nuxt.options.experimental.localLayerAliases) {
|
if (nuxt.options.experimental.localLayerAliases) {
|
||||||
// Add layer aliasing support for ~, ~~, @ and @@ aliases
|
// Add layer aliasing support for ~, ~~, @ and @@ aliases
|
||||||
addVitePlugin(() => LayerAliasingPlugin.vite({
|
addVitePlugin(() => LayerAliasingPlugin.vite({
|
||||||
@ -139,6 +144,11 @@ async function initNuxt (nuxt: Nuxt) {
|
|||||||
addWebpackPlugin(() => DevOnlyPlugin.webpack({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client }))
|
addWebpackPlugin(() => DevOnlyPlugin.webpack({ sourcemap: nuxt.options.sourcemap.server || nuxt.options.sourcemap.client }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform initial composable call within `<script setup>` to preserve context
|
||||||
|
if (nuxt.options.experimental.asyncContext) {
|
||||||
|
addBuildPlugin(AsyncContextInjectionPlugin(nuxt))
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: [Experimental] Avoid emitting assets when flag is enabled
|
// TODO: [Experimental] Avoid emitting assets when flag is enabled
|
||||||
if (nuxt.options.experimental.noScripts && !nuxt.options.dev) {
|
if (nuxt.options.experimental.noScripts && !nuxt.options.dev) {
|
||||||
nuxt.hook('build:manifest', async (manifest) => {
|
nuxt.hook('build:manifest', async (manifest) => {
|
||||||
|
54
packages/nuxt/src/core/plugins/async-context.ts
Normal file
54
packages/nuxt/src/core/plugins/async-context.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { createUnplugin } from 'unplugin'
|
||||||
|
import MagicString from 'magic-string'
|
||||||
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
|
import type { Node } from 'estree-walker'
|
||||||
|
import { walk } from 'estree-walker'
|
||||||
|
import type { BlockStatement } from 'estree'
|
||||||
|
import { isVue } from '../utils'
|
||||||
|
|
||||||
|
export const AsyncContextInjectionPlugin = (nuxt: Nuxt) => createUnplugin(() => {
|
||||||
|
return {
|
||||||
|
name: 'nuxt:async-context-injection',
|
||||||
|
transformInclude (id) {
|
||||||
|
return isVue(id, { type: ['template', 'script'] })
|
||||||
|
},
|
||||||
|
transform (code) {
|
||||||
|
const s = new MagicString(code)
|
||||||
|
|
||||||
|
let importName: string
|
||||||
|
|
||||||
|
walk(this.parse(code) as Node, {
|
||||||
|
enter (node) {
|
||||||
|
// only interested in calls of defineComponent function
|
||||||
|
if (node.type === 'ImportDeclaration' && node.source.value === 'vue') {
|
||||||
|
importName = importName ?? node.specifiers.find(s => s.type === 'ImportSpecifier' && s.imported.name === 'defineComponent')?.local.name
|
||||||
|
}
|
||||||
|
// we only want to transform `async setup()` functions
|
||||||
|
if (node.type === 'CallExpression' && node.callee.type === 'Identifier' && node.callee.name === importName) {
|
||||||
|
walk(node, {
|
||||||
|
enter (setup) {
|
||||||
|
if (setup.type === 'Property' && setup.key.type === 'Identifier' && setup.key.name === 'setup') {
|
||||||
|
if (setup.value.type === 'FunctionExpression' && setup.value.async) {
|
||||||
|
const body: BlockStatement = setup.value.body
|
||||||
|
const { start, end } = body as BlockStatement & { start: number, end: number }
|
||||||
|
s.appendLeft(start, '{ return useNuxtApp().runWithContext(async () => ')
|
||||||
|
s.appendRight(end, ') }')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (s.hasChanged()) {
|
||||||
|
return {
|
||||||
|
code: s.toString(),
|
||||||
|
map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server
|
||||||
|
? s.generateMap({ hires: true })
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
30
packages/nuxt/src/core/plugins/resolve-deep-imports.ts
Normal file
30
packages/nuxt/src/core/plugins/resolve-deep-imports.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { parseNodeModulePath, resolvePath } from 'mlly'
|
||||||
|
import { isAbsolute, normalize } from 'pathe'
|
||||||
|
import type { Plugin } from 'vite'
|
||||||
|
import { resolveAlias } from '@nuxt/kit'
|
||||||
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
|
|
||||||
|
import { pkgDir } from '../../dirs'
|
||||||
|
|
||||||
|
export function resolveDeepImportsPlugin (nuxt: Nuxt): Plugin {
|
||||||
|
return {
|
||||||
|
name: 'nuxt:resolve-bare-imports',
|
||||||
|
enforce: 'post',
|
||||||
|
async resolveId (id, importer, options) {
|
||||||
|
if (!importer || isAbsolute(id) || !isAbsolute(importer) || id.startsWith('virtual:') || id.startsWith('/__skip_vite')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id = normalize(id)
|
||||||
|
id = resolveAlias(id, nuxt.options.alias)
|
||||||
|
const { dir } = parseNodeModulePath(importer)
|
||||||
|
return await this.resolve?.(id, dir || pkgDir, { skipSelf: true }) ?? await resolvePath(id, {
|
||||||
|
url: [dir || pkgDir, ...nuxt.options.modulesDir],
|
||||||
|
// TODO: respect nitro runtime conditions
|
||||||
|
conditions: options.ssr ? ['node', 'import', 'require'] : ['import', 'require']
|
||||||
|
}).catch(() => {
|
||||||
|
console.log('[nuxt] Could not resolve id', id, importer)
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ export default <NitroErrorHandler> async function errorhandler (error: H3Error,
|
|||||||
statusCode,
|
statusCode,
|
||||||
statusMessage,
|
statusMessage,
|
||||||
message,
|
message,
|
||||||
stack: process.dev && statusCode !== 404
|
stack: import.meta.dev && statusCode !== 404
|
||||||
? `<pre>${stack.map(i => `<span class="stack${i.internal ? ' internal' : ''}">${i.text}</span>`).join('\n')}</pre>`
|
? `<pre>${stack.map(i => `<span class="stack${i.internal ? ' internal' : ''}">${i.text}</span>`).join('\n')}</pre>`
|
||||||
: '',
|
: '',
|
||||||
data: error.data
|
data: error.data
|
||||||
@ -56,12 +56,12 @@ export default <NitroErrorHandler> async function errorhandler (error: H3Error,
|
|||||||
|
|
||||||
// Fallback to static rendered error page
|
// Fallback to static rendered error page
|
||||||
if (!res) {
|
if (!res) {
|
||||||
const { template } = process.dev
|
const { template } = import.meta.dev
|
||||||
// @ts-expect-error TODO: add legacy type support for subpath imports
|
// @ts-expect-error TODO: add legacy type support for subpath imports
|
||||||
? await import('@nuxt/ui-templates/templates/error-dev.mjs')
|
? await import('@nuxt/ui-templates/templates/error-dev.mjs')
|
||||||
// @ts-expect-error TODO: add legacy type support for subpath imports
|
// @ts-expect-error TODO: add legacy type support for subpath imports
|
||||||
: await import('@nuxt/ui-templates/templates/error-500.mjs')
|
: await import('@nuxt/ui-templates/templates/error-500.mjs')
|
||||||
if (process.dev) {
|
if (import.meta.dev) {
|
||||||
// TODO: Support `message` in template
|
// TODO: Support `message` in template
|
||||||
(errorObject as any).description = errorObject.message
|
(errorObject as any).description = errorObject.message
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
||||||
import {
|
import {
|
||||||
createRenderer,
|
createRenderer,
|
||||||
getPrefetchLinks,
|
getPrefetchLinks,
|
||||||
@ -16,12 +17,15 @@ import { joinURL, withoutTrailingSlash } from 'ufo'
|
|||||||
import { renderToString as _renderToString } from 'vue/server-renderer'
|
import { renderToString as _renderToString } from 'vue/server-renderer'
|
||||||
import { hash } from 'ohash'
|
import { hash } from 'ohash'
|
||||||
import { renderSSRHead } from '@unhead/ssr'
|
import { renderSSRHead } from '@unhead/ssr'
|
||||||
|
import type { HeadEntryOptions } from '@unhead/schema'
|
||||||
|
|
||||||
import { defineRenderHandler, getRouteRules, useRuntimeConfig, useStorage } from '#internal/nitro'
|
import { defineRenderHandler, getRouteRules, useRuntimeConfig, useStorage } from '#internal/nitro'
|
||||||
import { useNitroApp } from '#internal/nitro/app'
|
import { useNitroApp } from '#internal/nitro/app'
|
||||||
|
|
||||||
import type { Link, Script } from '@unhead/vue'
|
import type { Link, Script } from '@unhead/vue'
|
||||||
import { createServerHead } from '@unhead/vue'
|
import { createServerHead } from '@unhead/vue'
|
||||||
|
// @ts-expect-error virtual file
|
||||||
|
import unheadPlugins from '#internal/unhead-plugins.mjs'
|
||||||
// eslint-disable-next-line import/no-restricted-paths
|
// eslint-disable-next-line import/no-restricted-paths
|
||||||
import type { NuxtPayload, NuxtSSRContext } from '#app/nuxt'
|
import type { NuxtPayload, NuxtSSRContext } from '#app/nuxt'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
@ -34,6 +38,11 @@ globalThis.__buildAssetsURL = buildAssetsURL
|
|||||||
// @ts-expect-error private property consumed by vite-generated url helpers
|
// @ts-expect-error private property consumed by vite-generated url helpers
|
||||||
globalThis.__publicAssetsURL = publicAssetsURL
|
globalThis.__publicAssetsURL = publicAssetsURL
|
||||||
|
|
||||||
|
// Polyfill for unctx (https://github.com/unjs/unctx#native-async-context)
|
||||||
|
if (process.env.NUXT_ASYNC_CONTEXT && !('AsyncLocalStorage' in globalThis)) {
|
||||||
|
(globalThis as any).AsyncLocalStorage = AsyncLocalStorage
|
||||||
|
}
|
||||||
|
|
||||||
export interface NuxtRenderHTMLContext {
|
export interface NuxtRenderHTMLContext {
|
||||||
island?: boolean
|
island?: boolean
|
||||||
htmlAttrs: string[]
|
htmlAttrs: string[]
|
||||||
@ -108,10 +117,10 @@ const getSSRRenderer = lazyCachedFunction(async () => {
|
|||||||
async function renderToString (input: RenderToStringParams[0], context: RenderToStringParams[1]) {
|
async function renderToString (input: RenderToStringParams[0], context: RenderToStringParams[1]) {
|
||||||
const html = await _renderToString(input, context)
|
const html = await _renderToString(input, context)
|
||||||
// In development with vite-node, the manifest is on-demand and will be available after rendering
|
// In development with vite-node, the manifest is on-demand and will be available after rendering
|
||||||
if (process.dev && process.env.NUXT_VITE_NODE_OPTIONS) {
|
if (import.meta.dev && process.env.NUXT_VITE_NODE_OPTIONS) {
|
||||||
renderer.rendererContext.updateManifest(await getClientManifest())
|
renderer.rendererContext.updateManifest(await getClientManifest())
|
||||||
}
|
}
|
||||||
return `<${appRootTag} id="${appRootId}">${html}</${appRootTag}>`
|
return `<${appRootTag}${appRootId ? ` id="${appRootId}"` : ''}>${html}</${appRootTag}>`
|
||||||
}
|
}
|
||||||
|
|
||||||
return renderer
|
return renderer
|
||||||
@ -126,7 +135,7 @@ const getSPARenderer = lazyCachedFunction(async () => {
|
|||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
manifest,
|
manifest,
|
||||||
renderToString: () => `<${appRootTag} id="${appRootId}">${spaTemplate}</${appRootTag}>`,
|
renderToString: () => `<${appRootTag}${appRootId ? ` id="${appRootId}"` : ''}>${spaTemplate}</${appRootTag}>`,
|
||||||
buildAssetsURL
|
buildAssetsURL
|
||||||
}
|
}
|
||||||
// Create SPA renderer and cache the result for all requests
|
// Create SPA renderer and cache the result for all requests
|
||||||
@ -155,14 +164,14 @@ const getSPARenderer = lazyCachedFunction(async () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const payloadCache = process.env.prerender ? useStorage('internal:nuxt:prerender:payload') : null
|
const payloadCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:payload') : null
|
||||||
const islandCache = process.env.prerender ? useStorage('internal:nuxt:prerender:island') : null
|
const islandCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island') : null
|
||||||
const islandPropCache = process.env.prerender ? useStorage('internal:nuxt:prerender:island-props') : null
|
const islandPropCache = import.meta.prerender ? useStorage('internal:nuxt:prerender:island-props') : null
|
||||||
|
|
||||||
async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
|
async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
|
||||||
// TODO: Strict validation for url
|
// TODO: Strict validation for url
|
||||||
let url = event.node.req.url || ''
|
let url = event.node.req.url || ''
|
||||||
if (process.env.prerender && event.node.req.url && await islandPropCache!.hasItem(event.node.req.url)) {
|
if (import.meta.prerender && event.node.req.url && await islandPropCache!.hasItem(event.node.req.url)) {
|
||||||
// rehydrate props from cache so we can rerender island if cache does not have it any more
|
// rehydrate props from cache so we can rerender island if cache does not have it any more
|
||||||
url = await islandPropCache!.getItem(event.node.req.url) as string
|
url = await islandPropCache!.getItem(event.node.req.url) as string
|
||||||
}
|
}
|
||||||
@ -185,7 +194,7 @@ async function getIslandContext (event: H3Event): Promise<NuxtIslandContext> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const PAYLOAD_URL_RE = process.env.NUXT_JSON_PAYLOADS ? /\/_payload(\.[a-zA-Z0-9]+)?.json(\?.*)?$/ : /\/_payload(\.[a-zA-Z0-9]+)?.js(\?.*)?$/
|
const PAYLOAD_URL_RE = process.env.NUXT_JSON_PAYLOADS ? /\/_payload(\.[a-zA-Z0-9]+)?.json(\?.*)?$/ : /\/_payload(\.[a-zA-Z0-9]+)?.js(\?.*)?$/
|
||||||
const ROOT_NODE_REGEX = new RegExp(`^<${appRootTag} id="${appRootId}">([\\s\\S]*)</${appRootTag}>$`)
|
const ROOT_NODE_REGEX = new RegExp(`^<${appRootTag}${appRootId ? ` id="${appRootId}"` : ''}>([\\s\\S]*)</${appRootTag}>$`)
|
||||||
|
|
||||||
const PRERENDER_NO_SSR_ROUTES = new Set(['/index.html', '/200.html', '/404.html'])
|
const PRERENDER_NO_SSR_ROUTES = new Set(['/index.html', '/200.html', '/404.html'])
|
||||||
|
|
||||||
@ -213,7 +222,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
? await getIslandContext(event)
|
? await getIslandContext(event)
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
if (process.env.prerender && islandContext && event.node.req.url && await islandCache!.hasItem(event.node.req.url)) {
|
if (import.meta.prerender && islandContext && event.node.req.url && await islandCache!.hasItem(event.node.req.url)) {
|
||||||
return islandCache!.getItem(event.node.req.url) as Promise<Partial<RenderResponse>>
|
return islandCache!.getItem(event.node.req.url) as Promise<Partial<RenderResponse>>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +234,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
if (isRenderingPayload) {
|
if (isRenderingPayload) {
|
||||||
url = url.substring(0, url.lastIndexOf('/')) || '/'
|
url = url.substring(0, url.lastIndexOf('/')) || '/'
|
||||||
event.node.req.url = url
|
event.node.req.url = url
|
||||||
if (process.env.prerender && await payloadCache!.hasItem(url)) {
|
if (import.meta.prerender && await payloadCache!.hasItem(url)) {
|
||||||
return payloadCache!.getItem(url) as Promise<Partial<RenderResponse>>
|
return payloadCache!.getItem(url) as Promise<Partial<RenderResponse>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -233,8 +242,12 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
// Get route options (currently to apply `ssr: false`)
|
// Get route options (currently to apply `ssr: false`)
|
||||||
const routeOptions = getRouteRules(event)
|
const routeOptions = getRouteRules(event)
|
||||||
|
|
||||||
const head = createServerHead()
|
const head = createServerHead({
|
||||||
head.push(appHead)
|
plugins: unheadPlugins
|
||||||
|
})
|
||||||
|
// needed for hash hydration plugin to work
|
||||||
|
const headEntryOptions: HeadEntryOptions = { mode: 'server' }
|
||||||
|
head.push(appHead, headEntryOptions)
|
||||||
|
|
||||||
// Initialize ssr context
|
// Initialize ssr context
|
||||||
const ssrContext: NuxtSSRContext = {
|
const ssrContext: NuxtSSRContext = {
|
||||||
@ -245,7 +258,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
!!(process.env.NUXT_NO_SSR) ||
|
!!(process.env.NUXT_NO_SSR) ||
|
||||||
event.context.nuxt?.noSSR ||
|
event.context.nuxt?.noSSR ||
|
||||||
routeOptions.ssr === false ||
|
routeOptions.ssr === false ||
|
||||||
(process.env.prerender ? PRERENDER_NO_SSR_ROUTES.has(url) : false),
|
(import.meta.prerender ? PRERENDER_NO_SSR_ROUTES.has(url) : false),
|
||||||
head,
|
head,
|
||||||
error: !!ssrError,
|
error: !!ssrError,
|
||||||
nuxt: undefined!, /* NuxtApp */
|
nuxt: undefined!, /* NuxtApp */
|
||||||
@ -255,9 +268,9 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Whether we are prerendering route
|
// Whether we are prerendering route
|
||||||
const _PAYLOAD_EXTRACTION = process.env.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !ssrContext.noSSR && !islandContext
|
const _PAYLOAD_EXTRACTION = import.meta.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !ssrContext.noSSR && !islandContext
|
||||||
const payloadURL = _PAYLOAD_EXTRACTION ? joinURL(useRuntimeConfig().app.baseURL, url, process.env.NUXT_JSON_PAYLOADS ? '_payload.json' : '_payload.js') : undefined
|
const payloadURL = _PAYLOAD_EXTRACTION ? joinURL(useRuntimeConfig().app.baseURL, url, process.env.NUXT_JSON_PAYLOADS ? '_payload.json' : '_payload.js') : undefined
|
||||||
if (process.env.prerender) {
|
if (import.meta.prerender) {
|
||||||
ssrContext.payload.prerenderedAt = Date.now()
|
ssrContext.payload.prerenderedAt = Date.now()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,7 +278,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
const renderer = (process.env.NUXT_NO_SSR || ssrContext.noSSR) ? await getSPARenderer() : await getSSRRenderer()
|
const renderer = (process.env.NUXT_NO_SSR || ssrContext.noSSR) ? await getSPARenderer() : await getSSRRenderer()
|
||||||
|
|
||||||
// Render 103 Early Hints
|
// Render 103 Early Hints
|
||||||
if (process.env.NUXT_EARLY_HINTS && !isRenderingPayload && !process.env.prerender) {
|
if (process.env.NUXT_EARLY_HINTS && !isRenderingPayload && !import.meta.prerender) {
|
||||||
const { link } = renderResourceHeaders({}, renderer.rendererContext)
|
const { link } = renderResourceHeaders({}, renderer.rendererContext)
|
||||||
writeEarlyHints(event, link)
|
writeEarlyHints(event, link)
|
||||||
}
|
}
|
||||||
@ -291,7 +304,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
// Directly render payload routes
|
// Directly render payload routes
|
||||||
if (isRenderingPayload) {
|
if (isRenderingPayload) {
|
||||||
const response = renderPayloadResponse(ssrContext)
|
const response = renderPayloadResponse(ssrContext)
|
||||||
if (process.env.prerender) {
|
if (import.meta.prerender) {
|
||||||
await payloadCache!.setItem(url, response)
|
await payloadCache!.setItem(url, response)
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
@ -330,7 +343,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
? { rel: 'preload', as: 'fetch', crossorigin: 'anonymous', href: payloadURL }
|
? { rel: 'preload', as: 'fetch', crossorigin: 'anonymous', href: payloadURL }
|
||||||
: { rel: 'modulepreload', href: payloadURL }
|
: { rel: 'modulepreload', href: payloadURL }
|
||||||
]
|
]
|
||||||
})
|
}, headEntryOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Styles
|
// 2. Styles
|
||||||
@ -340,17 +353,17 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
({ rel: 'stylesheet', href: renderer.rendererContext.buildAssetsURL(resource.file) })
|
({ rel: 'stylesheet', href: renderer.rendererContext.buildAssetsURL(resource.file) })
|
||||||
),
|
),
|
||||||
style: inlinedStyles
|
style: inlinedStyles
|
||||||
})
|
}, headEntryOptions)
|
||||||
|
|
||||||
if (!NO_SCRIPTS) {
|
if (!NO_SCRIPTS) {
|
||||||
// 3. Resource Hints
|
// 3. Resource Hints
|
||||||
// TODO: add priorities based on Capo
|
// TODO: add priorities based on Capo
|
||||||
head.push({
|
head.push({
|
||||||
link: getPreloadLinks(ssrContext, renderer.rendererContext) as Link[]
|
link: getPreloadLinks(ssrContext, renderer.rendererContext) as Link[]
|
||||||
})
|
}, headEntryOptions)
|
||||||
head.push({
|
head.push({
|
||||||
link: getPrefetchLinks(ssrContext, renderer.rendererContext) as Link[]
|
link: getPrefetchLinks(ssrContext, renderer.rendererContext) as Link[]
|
||||||
})
|
}, headEntryOptions)
|
||||||
// 4. Payloads
|
// 4. Payloads
|
||||||
head.push({
|
head.push({
|
||||||
script: _PAYLOAD_EXTRACTION
|
script: _PAYLOAD_EXTRACTION
|
||||||
@ -361,6 +374,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
? renderPayloadJsonScript({ id: '__NUXT_DATA__', ssrContext, data: ssrContext.payload })
|
? renderPayloadJsonScript({ id: '__NUXT_DATA__', ssrContext, data: ssrContext.payload })
|
||||||
: renderPayloadScript({ ssrContext, data: ssrContext.payload })
|
: renderPayloadScript({ ssrContext, data: ssrContext.payload })
|
||||||
}, {
|
}, {
|
||||||
|
...headEntryOptions,
|
||||||
// this should come before another end of body scripts
|
// this should come before another end of body scripts
|
||||||
tagPosition: 'bodyClose',
|
tagPosition: 'bodyClose',
|
||||||
tagPriority: 'high'
|
tagPriority: 'high'
|
||||||
@ -376,7 +390,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
defer: resource.module ? null : true,
|
defer: resource.module ? null : true,
|
||||||
crossorigin: ''
|
crossorigin: ''
|
||||||
}))
|
}))
|
||||||
})
|
}, headEntryOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove certain tags for nuxt islands
|
// remove certain tags for nuxt islands
|
||||||
@ -428,7 +442,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
'x-powered-by': 'Nuxt'
|
'x-powered-by': 'Nuxt'
|
||||||
}
|
}
|
||||||
} satisfies RenderResponse
|
} satisfies RenderResponse
|
||||||
if (process.env.prerender) {
|
if (import.meta.prerender) {
|
||||||
await islandCache!.setItem(`/__nuxt_island/${islandContext!.name}_${islandContext!.id}`, response)
|
await islandCache!.setItem(`/__nuxt_island/${islandContext!.name}_${islandContext!.id}`, response)
|
||||||
await islandPropCache!.setItem(`/__nuxt_island/${islandContext!.name}_${islandContext!.id}`, event.node.req.url!)
|
await islandPropCache!.setItem(`/__nuxt_island/${islandContext!.name}_${islandContext!.id}`, event.node.req.url!)
|
||||||
}
|
}
|
||||||
@ -527,7 +541,7 @@ function renderPayloadJsonScript (opts: { id: string, ssrContext: NuxtSSRContext
|
|||||||
|
|
||||||
function renderPayloadScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
function renderPayloadScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
||||||
opts.data.config = opts.ssrContext.config
|
opts.data.config = opts.ssrContext.config
|
||||||
const _PAYLOAD_EXTRACTION = process.env.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !opts.ssrContext.noSSR
|
const _PAYLOAD_EXTRACTION = import.meta.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !opts.ssrContext.noSSR
|
||||||
if (_PAYLOAD_EXTRACTION) {
|
if (_PAYLOAD_EXTRACTION) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -280,10 +280,18 @@ export const appConfigTemplate: NuxtTemplate = {
|
|||||||
write: true,
|
write: true,
|
||||||
getContents: async ({ app, nuxt }) => {
|
getContents: async ({ app, nuxt }) => {
|
||||||
return `
|
return `
|
||||||
|
import { updateAppConfig } from '#app'
|
||||||
import { defuFn } from '${await _resolveId('defu')}'
|
import { defuFn } from '${await _resolveId('defu')}'
|
||||||
|
|
||||||
const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, null, 2)}
|
const inlineConfig = ${JSON.stringify(nuxt.options.appConfig, null, 2)}
|
||||||
|
|
||||||
|
// Vite - webpack is handled directly in #app/config
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.accept((newModule) => {
|
||||||
|
updateAppConfig(newModule.default)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
${app.configs.map((id: string, index: number) => `import ${`cfg${index}`} from ${JSON.stringify(id)}`).join('\n')}
|
${app.configs.map((id: string, index: number) => `import ${`cfg${index}`} from ${JSON.stringify(id)}`).join('\n')}
|
||||||
|
|
||||||
export default /* #__PURE__ */ defuFn(${app.configs.map((_id: string, index: number) => `cfg${index}`).concat(['inlineConfig']).join(', ')})
|
export default /* #__PURE__ */ defuFn(${app.configs.map((_id: string, index: number) => `cfg${index}`).concat(['inlineConfig']).join(', ')})
|
||||||
@ -313,7 +321,7 @@ export const publicPathTemplate: NuxtTemplate = {
|
|||||||
'}',
|
'}',
|
||||||
|
|
||||||
// On server these are registered directly in packages/nuxt/src/core/runtime/nitro/renderer.ts
|
// On server these are registered directly in packages/nuxt/src/core/runtime/nitro/renderer.ts
|
||||||
'if (process.client) {',
|
'if (import.meta.client) {',
|
||||||
' globalThis.__buildAssetsURL = buildAssetsURL',
|
' globalThis.__buildAssetsURL = buildAssetsURL',
|
||||||
' globalThis.__publicAssetsURL = publicAssetsURL',
|
' globalThis.__publicAssetsURL = publicAssetsURL',
|
||||||
'}'
|
'}'
|
||||||
@ -331,7 +339,8 @@ export const nuxtConfigTemplate = {
|
|||||||
`export const componentIslands = ${!!ctx.nuxt.options.experimental.componentIslands}`,
|
`export const componentIslands = ${!!ctx.nuxt.options.experimental.componentIslands}`,
|
||||||
`export const remoteComponentIslands = ${ctx.nuxt.options.experimental.componentIslands === 'local+remote'}`,
|
`export const remoteComponentIslands = ${ctx.nuxt.options.experimental.componentIslands === 'local+remote'}`,
|
||||||
`export const devPagesDir = ${ctx.nuxt.options.dev ? JSON.stringify(ctx.nuxt.options.dir.pages) : 'null'}`,
|
`export const devPagesDir = ${ctx.nuxt.options.dev ? JSON.stringify(ctx.nuxt.options.dir.pages) : 'null'}`,
|
||||||
`export const devRootDir = ${ctx.nuxt.options.dev ? JSON.stringify(ctx.nuxt.options.rootDir) : 'null'}`
|
`export const devRootDir = ${ctx.nuxt.options.dev ? JSON.stringify(ctx.nuxt.options.rootDir) : 'null'}`,
|
||||||
|
`export const vueAppRootContainer = ${ctx.nuxt.options.app.rootId ? `'#${ctx.nuxt.options.app.rootId}'` : `'body > ${ctx.nuxt.options.app.rootTag}'`}`
|
||||||
].join('\n\n')
|
].join('\n\n')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { resolve } from 'pathe'
|
import { resolve } from 'pathe'
|
||||||
import { addComponent, addImportsSources, addPlugin, defineNuxtModule, tryResolveModule } from '@nuxt/kit'
|
import { addComponent, addImportsSources, addPlugin, addTemplate, defineNuxtModule, tryResolveModule } from '@nuxt/kit'
|
||||||
import { distDir } from '../dirs'
|
import { distDir } from '../dirs'
|
||||||
|
|
||||||
const components = ['NoScript', 'Link', 'Base', 'Title', 'Meta', 'Style', 'Head', 'Html', 'Body']
|
const components = ['NoScript', 'Link', 'Base', 'Title', 'Meta', 'Style', 'Head', 'Html', 'Body']
|
||||||
@ -54,9 +54,26 @@ export default defineNuxtModule({
|
|||||||
addPlugin({ src: resolve(runtimeDir, 'plugins/vueuse-head-polyfill') })
|
addPlugin({ src: resolve(runtimeDir, 'plugins/vueuse-head-polyfill') })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nuxt.options.experimental.headCapoPlugin) {
|
addTemplate({
|
||||||
addPlugin({ src: resolve(runtimeDir, 'plugins/capo') })
|
filename: 'unhead-plugins.mjs',
|
||||||
}
|
getContents () {
|
||||||
|
if (!nuxt.options.experimental.headNext) {
|
||||||
|
return 'export default []'
|
||||||
|
}
|
||||||
|
// TODO don't use HashHydrationPlugin for SPA
|
||||||
|
return `import { CapoPlugin, HashHydrationPlugin } from '@unhead/vue'
|
||||||
|
const plugins = [HashHydrationPlugin()];
|
||||||
|
if (process.server) {
|
||||||
|
plugins.push(CapoPlugin({ track: true }));
|
||||||
|
}
|
||||||
|
export default plugins;`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// template is only exposed in nuxt context, expose in nitro context as well
|
||||||
|
nuxt.hooks.hook('nitro:config', (config) => {
|
||||||
|
config.virtual!['#internal/unhead-plugins.mjs'] = () => nuxt.vfs['#build/unhead-plugins']
|
||||||
|
})
|
||||||
|
|
||||||
// Add library-specific plugin
|
// Add library-specific plugin
|
||||||
addPlugin({ src: resolve(runtimeDir, 'plugins/unhead') })
|
addPlugin({ src: resolve(runtimeDir, 'plugins/unhead') })
|
||||||
|
@ -149,7 +149,7 @@ export const Title = defineComponent({
|
|||||||
name: 'Title',
|
name: 'Title',
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
setup: setupForUseMeta((_, { slots }) => {
|
setup: setupForUseMeta((_, { slots }) => {
|
||||||
if (process.dev) {
|
if (import.meta.dev) {
|
||||||
const defaultSlot = slots.default?.()
|
const defaultSlot = slots.default?.()
|
||||||
|
|
||||||
if (defaultSlot && (defaultSlot.length > 1 || typeof defaultSlot[0].children !== 'string')) {
|
if (defaultSlot && (defaultSlot.length > 1 || typeof defaultSlot[0].children !== 'string')) {
|
||||||
@ -217,7 +217,7 @@ export const Style = defineComponent({
|
|||||||
const style = { ...props }
|
const style = { ...props }
|
||||||
const textContent = slots.default?.()?.[0]?.children
|
const textContent = slots.default?.()?.[0]?.children
|
||||||
if (textContent) {
|
if (textContent) {
|
||||||
if (process.dev && typeof textContent !== 'string') {
|
if (import.meta.dev && typeof textContent !== 'string') {
|
||||||
console.error('<Style> can only take a string in its default slot.')
|
console.error('<Style> can only take a string in its default slot.')
|
||||||
}
|
}
|
||||||
style.children = textContent
|
style.children = textContent
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
import { CapoPlugin } from '@unhead/vue'
|
|
||||||
import { defineNuxtPlugin } from '#app/nuxt'
|
|
||||||
|
|
||||||
export default defineNuxtPlugin({
|
|
||||||
name: 'nuxt:head:capo',
|
|
||||||
setup (nuxtApp) {
|
|
||||||
nuxtApp.vueApp._context.provides.usehead.use(CapoPlugin({ track: true }))
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,27 +1,34 @@
|
|||||||
import { createHead as createClientHead } from '@unhead/vue'
|
import { createHead as createClientHead } from '@unhead/vue'
|
||||||
|
import { renderDOMHead } from '@unhead/dom'
|
||||||
import { defineNuxtPlugin } from '#app/nuxt'
|
import { defineNuxtPlugin } from '#app/nuxt'
|
||||||
|
|
||||||
|
// @ts-expect-error virtual file
|
||||||
|
import unheadPlugins from '#build/unhead-plugins.mjs'
|
||||||
|
|
||||||
export default defineNuxtPlugin({
|
export default defineNuxtPlugin({
|
||||||
name: 'nuxt:head',
|
name: 'nuxt:head',
|
||||||
setup (nuxtApp) {
|
setup (nuxtApp) {
|
||||||
const head = process.server ? nuxtApp.ssrContext!.head : createClientHead()
|
const head = import.meta.server
|
||||||
|
? nuxtApp.ssrContext!.head
|
||||||
|
: createClientHead({
|
||||||
|
plugins: unheadPlugins
|
||||||
|
})
|
||||||
// nuxt.config appHead is set server-side within the renderer
|
// nuxt.config appHead is set server-side within the renderer
|
||||||
nuxtApp.vueApp.use(head)
|
nuxtApp.vueApp.use(head)
|
||||||
|
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
// pause dom updates until page is ready and between page transitions
|
// pause dom updates until page is ready and between page transitions
|
||||||
let pauseDOMUpdates = true
|
let pauseDOMUpdates = true
|
||||||
const unpauseDom = () => {
|
const syncHead = async () => {
|
||||||
pauseDOMUpdates = false
|
pauseDOMUpdates = false
|
||||||
// trigger the debounced DOM update
|
await renderDOMHead(head)
|
||||||
head.hooks.callHook('entries:updated', head)
|
|
||||||
}
|
}
|
||||||
head.hooks.hook('dom:beforeRender', (context) => { context.shouldRender = !pauseDOMUpdates })
|
head.hooks.hook('dom:beforeRender', (context) => { context.shouldRender = !pauseDOMUpdates })
|
||||||
nuxtApp.hooks.hook('page:start', () => { pauseDOMUpdates = true })
|
nuxtApp.hooks.hook('page:start', () => { pauseDOMUpdates = true })
|
||||||
// wait for new page before unpausing dom updates (triggered after suspense resolved)
|
// wait for new page before unpausing dom updates (triggered after suspense resolved)
|
||||||
nuxtApp.hooks.hook('page:finish', unpauseDom)
|
nuxtApp.hooks.hook('page:finish', syncHead)
|
||||||
// unpause the DOM once the mount suspense is resolved
|
// unpause the DOM once the mount suspense is resolved
|
||||||
nuxtApp.hooks.hook('app:suspense:resolve', unpauseDom)
|
nuxtApp.hooks.hook('app:suspense:resolve', syncHead)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { addTemplate, addVitePlugin, addWebpackPlugin, defineNuxtModule, resolveAlias, updateTemplates, useNuxt } from '@nuxt/kit'
|
import { addTemplate, addVitePlugin, addWebpackPlugin, defineNuxtModule, resolveAlias, tryResolveModule, updateTemplates, useNuxt } from '@nuxt/kit'
|
||||||
import { isAbsolute, join, normalize, relative, resolve } from 'pathe'
|
import { isAbsolute, join, normalize, relative, resolve } from 'pathe'
|
||||||
import type { Import, Unimport } from 'unimport'
|
import type { Import, Unimport } from 'unimport'
|
||||||
import { createUnimport, scanDirExports } from 'unimport'
|
import { createUnimport, scanDirExports } from 'unimport'
|
||||||
import type { ImportPresetWithDeprecation, ImportsOptions } from 'nuxt/schema'
|
import type { ImportPresetWithDeprecation, ImportsOptions } from 'nuxt/schema'
|
||||||
|
|
||||||
|
import { lookupNodeModuleSubpath, parseNodeModulePath } from 'mlly'
|
||||||
import { TransformPlugin } from './transform'
|
import { TransformPlugin } from './transform'
|
||||||
import { defaultPresets } from './presets'
|
import { defaultPresets } from './presets'
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ export default defineNuxtModule<Partial<ImportsOptions>>({
|
|||||||
// Support for importing from '#imports'
|
// Support for importing from '#imports'
|
||||||
addTemplate({
|
addTemplate({
|
||||||
filename: 'imports.mjs',
|
filename: 'imports.mjs',
|
||||||
getContents: async () => await ctx.toExports() + '\nif (process.dev) { console.warn("[nuxt] `#imports` should be transformed with real imports. There seems to be something wrong with the imports plugin.") }'
|
getContents: async () => await ctx.toExports() + '\nif (import.meta.dev) { console.warn("[nuxt] `#imports` should be transformed with real imports. There seems to be something wrong with the imports plugin.") }'
|
||||||
})
|
})
|
||||||
nuxt.options.alias['#imports'] = join(nuxt.options.buildDir, 'imports')
|
nuxt.options.alias['#imports'] = join(nuxt.options.buildDir, 'imports')
|
||||||
|
|
||||||
@ -140,19 +141,29 @@ function addDeclarationTemplates (ctx: Unimport, options: Partial<ImportsOptions
|
|||||||
// Remove file extension for benefit of TypeScript
|
// Remove file extension for benefit of TypeScript
|
||||||
const stripExtension = (path: string) => path.replace(/\.[a-z]+$/, '')
|
const stripExtension = (path: string) => path.replace(/\.[a-z]+$/, '')
|
||||||
|
|
||||||
const resolved: Record<string, string> = {}
|
const resolvedImportPathMap = new Map<string, string>()
|
||||||
const r = ({ from }: Import) => {
|
const r = ({ from }: Import) => resolvedImportPathMap.get(from)
|
||||||
if (resolved[from]) {
|
async function cacheImportPaths (imports: Import[]) {
|
||||||
return resolved[from]
|
for (const i of imports) {
|
||||||
}
|
if (resolvedImportPathMap.has(i.from)) { continue }
|
||||||
let path = resolveAlias(from)
|
let path = resolveAlias(i.from)
|
||||||
if (isAbsolute(path)) {
|
if (!isAbsolute(path)) {
|
||||||
path = relative(join(nuxt.options.buildDir, 'types'), path)
|
path = await tryResolveModule(i.from, nuxt.options.modulesDir).then(async (r) => {
|
||||||
}
|
if (!r) { return r }
|
||||||
|
|
||||||
path = stripExtension(path)
|
const { dir, name } = parseNodeModulePath(r)
|
||||||
resolved[from] = path
|
if (!dir || !name) { return r }
|
||||||
return path
|
const subpath = await lookupNodeModuleSubpath(r)
|
||||||
|
return join(dir, name, subpath || '')
|
||||||
|
}) ?? path
|
||||||
|
}
|
||||||
|
if (isAbsolute(path)) {
|
||||||
|
path = relative(join(nuxt.options.buildDir, 'types'), path)
|
||||||
|
}
|
||||||
|
|
||||||
|
path = stripExtension(path)
|
||||||
|
resolvedImportPathMap.set(i.from, path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addTemplate({
|
addTemplate({
|
||||||
@ -162,10 +173,14 @@ function addDeclarationTemplates (ctx: Unimport, options: Partial<ImportsOptions
|
|||||||
|
|
||||||
addTemplate({
|
addTemplate({
|
||||||
filename: 'types/imports.d.ts',
|
filename: 'types/imports.d.ts',
|
||||||
getContents: async () => '// Generated by auto imports\n' + (
|
getContents: async () => {
|
||||||
options.autoImport
|
const imports = await ctx.getImports().then(r => r.filter(i => !i.type))
|
||||||
? await ctx.generateTypeDeclarations({ resolvePath: r })
|
await cacheImportPaths(imports)
|
||||||
: '// Implicit auto importing is disabled, you can use explicitly import from `#imports` instead.'
|
return '// Generated by auto imports\n' + (
|
||||||
)
|
options.autoImport
|
||||||
|
? await ctx.generateTypeDeclarations({ resolvePath: r })
|
||||||
|
: '// Implicit auto importing is disabled, you can use explicitly import from `#imports` instead.'
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { existsSync, readdirSync } from 'node:fs'
|
import { existsSync, readdirSync } from 'node:fs'
|
||||||
import { mkdir, readFile } from 'node:fs/promises'
|
import { mkdir, readFile } from 'node:fs/promises'
|
||||||
import { addComponent, addPlugin, addTemplate, addVitePlugin, addWebpackPlugin, defineNuxtModule, findPath, updateTemplates } from '@nuxt/kit'
|
import { addBuildPlugin, addComponent, addPlugin, addTemplate, addVitePlugin, addWebpackPlugin, defineNuxtModule, findPath, updateTemplates } from '@nuxt/kit'
|
||||||
import { dirname, join, relative, resolve } from 'pathe'
|
import { dirname, join, relative, resolve } from 'pathe'
|
||||||
import { genImport, genObjectFromRawEntries, genString } from 'knitwork'
|
import { genImport, genObjectFromRawEntries, genString } from 'knitwork'
|
||||||
import { joinURL } from 'ufo'
|
import { joinURL } from 'ufo'
|
||||||
import type { NuxtApp, NuxtPage } from 'nuxt/schema'
|
import type { Nuxt, NuxtApp, NuxtPage } from 'nuxt/schema'
|
||||||
import { createRoutesContext } from 'unplugin-vue-router'
|
import { createRoutesContext } from 'unplugin-vue-router'
|
||||||
import { resolveOptions } from 'unplugin-vue-router/options'
|
import { resolveOptions } from 'unplugin-vue-router/options'
|
||||||
import type { EditableTreeNode, Options as TypedRouterOptions } from 'unplugin-vue-router'
|
import type { EditableTreeNode, Options as TypedRouterOptions } from 'unplugin-vue-router'
|
||||||
@ -13,6 +13,7 @@ import { distDir } from '../dirs'
|
|||||||
import { normalizeRoutes, resolvePagesRoutes } from './utils'
|
import { normalizeRoutes, resolvePagesRoutes } from './utils'
|
||||||
import type { PageMetaPluginOptions } from './page-meta'
|
import type { PageMetaPluginOptions } from './page-meta'
|
||||||
import { PageMetaPlugin } from './page-meta'
|
import { PageMetaPlugin } from './page-meta'
|
||||||
|
import { RouteInjectionPlugin } from './route-injection'
|
||||||
|
|
||||||
const OPTIONAL_PARAM_RE = /^\/?:.*(\?|\(\.\*\)\*)$/
|
const OPTIONAL_PARAM_RE = /^\/?:.*(\?|\(\.\*\)\*)$/
|
||||||
|
|
||||||
@ -253,6 +254,11 @@ export default defineNuxtModule({
|
|||||||
// Add prefetching support for middleware & layouts
|
// Add prefetching support for middleware & layouts
|
||||||
addPlugin(resolve(runtimeDir, 'plugins/prefetch.client'))
|
addPlugin(resolve(runtimeDir, 'plugins/prefetch.client'))
|
||||||
|
|
||||||
|
// Add build plugin to ensure template $route is kept in sync with `<NuxtPage>`
|
||||||
|
if (nuxt.options.experimental.templateRouteInjection) {
|
||||||
|
addBuildPlugin(RouteInjectionPlugin(nuxt), { server: false })
|
||||||
|
}
|
||||||
|
|
||||||
// Add router plugin
|
// Add router plugin
|
||||||
addPlugin(resolve(runtimeDir, 'plugins/router'))
|
addPlugin(resolve(runtimeDir, 'plugins/router'))
|
||||||
|
|
||||||
@ -333,8 +339,8 @@ export default defineNuxtModule({
|
|||||||
|
|
||||||
addTemplate({
|
addTemplate({
|
||||||
filename: 'types/middleware.d.ts',
|
filename: 'types/middleware.d.ts',
|
||||||
getContents: ({ app }: { app: NuxtApp }) => {
|
getContents: ({ nuxt, app }: { nuxt: Nuxt, app: NuxtApp }) => {
|
||||||
const composablesFile = resolve(runtimeDir, 'composables')
|
const composablesFile = relative(join(nuxt.options.buildDir, 'types'), resolve(runtimeDir, 'composables'))
|
||||||
const namedMiddleware = app.middleware.filter(mw => !mw.global)
|
const namedMiddleware = app.middleware.filter(mw => !mw.global)
|
||||||
return [
|
return [
|
||||||
'import type { NavigationGuard } from \'vue-router\'',
|
'import type { NavigationGuard } from \'vue-router\'',
|
||||||
@ -350,8 +356,8 @@ export default defineNuxtModule({
|
|||||||
|
|
||||||
addTemplate({
|
addTemplate({
|
||||||
filename: 'types/layouts.d.ts',
|
filename: 'types/layouts.d.ts',
|
||||||
getContents: ({ app }: { app: NuxtApp }) => {
|
getContents: ({ nuxt, app }: { nuxt: Nuxt, app: NuxtApp }) => {
|
||||||
const composablesFile = resolve(runtimeDir, 'composables')
|
const composablesFile = relative(join(nuxt.options.buildDir, 'types'), resolve(runtimeDir, 'composables'))
|
||||||
return [
|
return [
|
||||||
'import { ComputedRef, MaybeRef } from \'vue\'',
|
'import { ComputedRef, MaybeRef } from \'vue\'',
|
||||||
`export type LayoutKey = ${Object.keys(app.layouts).map(name => genString(name)).join(' | ') || 'string'}`,
|
`export type LayoutKey = ${Object.keys(app.layouts).map(name => genString(name)).join(' | ') || 'string'}`,
|
||||||
|
39
packages/nuxt/src/pages/route-injection.ts
Normal file
39
packages/nuxt/src/pages/route-injection.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { createUnplugin } from 'unplugin'
|
||||||
|
import MagicString from 'magic-string'
|
||||||
|
import type { Nuxt } from '@nuxt/schema'
|
||||||
|
import { isVue } from '../core/utils'
|
||||||
|
|
||||||
|
const INJECTION_RE = /\b_ctx\.\$route\b/g
|
||||||
|
const INJECTION_SINGLE_RE = /\b_ctx\.\$route\b/
|
||||||
|
|
||||||
|
export const RouteInjectionPlugin = (nuxt: Nuxt) => createUnplugin(() => {
|
||||||
|
return {
|
||||||
|
name: 'nuxt:route-injection-plugin',
|
||||||
|
enforce: 'post',
|
||||||
|
transformInclude (id) {
|
||||||
|
return isVue(id, { type: ['template', 'script'] })
|
||||||
|
},
|
||||||
|
transform (code) {
|
||||||
|
if (!INJECTION_SINGLE_RE.test(code) || code.includes('_ctx._.provides[__nuxt_route_symbol')) { return }
|
||||||
|
|
||||||
|
let replaced = false
|
||||||
|
const s = new MagicString(code)
|
||||||
|
s.replace(INJECTION_RE, () => {
|
||||||
|
replaced = true
|
||||||
|
return '(_ctx._.provides[__nuxt_route_symbol] || _ctx.$route)'
|
||||||
|
})
|
||||||
|
if (replaced) {
|
||||||
|
s.prepend('import { PageRouteSymbol as __nuxt_route_symbol } from \'#app/components/injections\';\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.hasChanged()) {
|
||||||
|
return {
|
||||||
|
code: s.toString(),
|
||||||
|
map: nuxt.options.sourcemap.client || nuxt.options.sourcemap.server
|
||||||
|
? s.generateMap({ hires: true })
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
@ -52,7 +52,7 @@ const warnRuntimeUsage = (method: string) =>
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
export const definePageMeta = (meta: PageMeta): void => {
|
export const definePageMeta = (meta: PageMeta): void => {
|
||||||
if (process.dev) {
|
if (import.meta.dev) {
|
||||||
const component = getCurrentInstance()?.type
|
const component = getCurrentInstance()?.type
|
||||||
try {
|
try {
|
||||||
const isRouteComponent = component && useRoute().matched.some(p => Object.values(p.components || {}).includes(component))
|
const isRouteComponent = component && useRoute().matched.some(p => Object.values(p.components || {}).includes(component))
|
||||||
|
@ -5,7 +5,7 @@ import { devPagesDir } from '#build/nuxt.config.mjs'
|
|||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'NuxtPage',
|
name: 'NuxtPage',
|
||||||
setup (_, props) {
|
setup (_, props) {
|
||||||
if (process.dev) {
|
if (import.meta.dev) {
|
||||||
console.warn(`Create a Vue component in the \`${devPagesDir}/\` directory to enable \`<NuxtPage>\``)
|
console.warn(`Create a Vue component in the \`${devPagesDir}/\` directory to enable \`<NuxtPage>\``)
|
||||||
}
|
}
|
||||||
return () => props.slots.default?.()
|
return () => props.slots.default?.()
|
||||||
|
@ -51,24 +51,24 @@ export default defineComponent({
|
|||||||
return () => {
|
return () => {
|
||||||
return h(RouterView, { name: props.name, route: props.route, ...attrs }, {
|
return h(RouterView, { name: props.name, route: props.route, ...attrs }, {
|
||||||
default: (routeProps: RouterViewSlotProps) => {
|
default: (routeProps: RouterViewSlotProps) => {
|
||||||
const isRenderingNewRouteInOldFork = process.client && haveParentRoutesRendered(forkRoute, routeProps.route, routeProps.Component)
|
const isRenderingNewRouteInOldFork = import.meta.client && haveParentRoutesRendered(forkRoute, routeProps.route, routeProps.Component)
|
||||||
const hasSameChildren = process.client && forkRoute && forkRoute.matched.length === routeProps.route.matched.length
|
const hasSameChildren = import.meta.client && forkRoute && forkRoute.matched.length === routeProps.route.matched.length
|
||||||
|
|
||||||
if (!routeProps.Component) {
|
if (!routeProps.Component) {
|
||||||
// If we're rendering a `<NuxtPage>` child route on navigation to a route which lacks a child page
|
// If we're rendering a `<NuxtPage>` child route on navigation to a route which lacks a child page
|
||||||
// we'll render the old vnode until the new route finishes resolving
|
// we'll render the old vnode until the new route finishes resolving
|
||||||
if (process.client && vnode && !hasSameChildren) {
|
if (import.meta.client && vnode && !hasSameChildren) {
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return old vnode if we are rendering _new_ page suspense fork in _old_ layout suspense fork
|
// Return old vnode if we are rendering _new_ page suspense fork in _old_ layout suspense fork
|
||||||
if (process.client && vnode && _layoutMeta && !_layoutMeta.isCurrent(routeProps.route)) {
|
if (import.meta.client && vnode && _layoutMeta && !_layoutMeta.isCurrent(routeProps.route)) {
|
||||||
return vnode
|
return vnode
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.client && isRenderingNewRouteInOldFork && forkRoute && (!_layoutMeta || _layoutMeta?.isCurrent(forkRoute))) {
|
if (import.meta.client && isRenderingNewRouteInOldFork && forkRoute && (!_layoutMeta || _layoutMeta?.isCurrent(forkRoute))) {
|
||||||
// if leaving a route with an existing child route, render the old vnode
|
// if leaving a route with an existing child route, render the old vnode
|
||||||
if (hasSameChildren) {
|
if (hasSameChildren) {
|
||||||
return vnode
|
return vnode
|
||||||
|
@ -57,7 +57,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
|
|||||||
routerBase += '#'
|
routerBase += '#'
|
||||||
}
|
}
|
||||||
|
|
||||||
const history = routerOptions.history?.(routerBase) ?? (process.client
|
const history = routerOptions.history?.(routerBase) ?? (import.meta.client
|
||||||
? (routerOptions.hashMode ? createWebHashHistory(routerBase) : createWebHistory(routerBase))
|
? (routerOptions.hashMode ? createWebHashHistory(routerBase) : createWebHistory(routerBase))
|
||||||
: createMemoryHistory(routerBase)
|
: createMemoryHistory(routerBase)
|
||||||
)
|
)
|
||||||
@ -65,7 +65,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
|
|||||||
const routes = routerOptions.routes?.(_routes) ?? _routes
|
const routes = routerOptions.routes?.(_routes) ?? _routes
|
||||||
|
|
||||||
let startPosition: Parameters<RouterScrollBehavior>[2] | null
|
let startPosition: Parameters<RouterScrollBehavior>[2] | null
|
||||||
const initialURL = process.server
|
const initialURL = import.meta.server
|
||||||
? nuxtApp.ssrContext!.url
|
? nuxtApp.ssrContext!.url
|
||||||
: createCurrentLocation(routerBase, window.location, nuxtApp.payload.path)
|
: createCurrentLocation(routerBase, window.location, nuxtApp.payload.path)
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
|
|||||||
const error = useError()
|
const error = useError()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
await router.push(initialURL)
|
await router.push(initialURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
|
|||||||
}
|
}
|
||||||
nuxtApp._processingMiddleware = true
|
nuxtApp._processingMiddleware = true
|
||||||
|
|
||||||
if (process.client || !nuxtApp.ssrContext?.islandContext) {
|
if (import.meta.client || !nuxtApp.ssrContext?.islandContext) {
|
||||||
type MiddlewareDef = string | RouteMiddleware
|
type MiddlewareDef = string | RouteMiddleware
|
||||||
const middlewareEntries = new Set<MiddlewareDef>([...globalMiddleware, ...nuxtApp._middleware.global])
|
const middlewareEntries = new Set<MiddlewareDef>([...globalMiddleware, ...nuxtApp._middleware.global])
|
||||||
for (const component of to.matched) {
|
for (const component of to.matched) {
|
||||||
@ -161,14 +161,14 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
|
|||||||
const middleware = typeof entry === 'string' ? nuxtApp._middleware.named[entry] || await namedMiddleware[entry]?.().then((r: any) => r.default || r) : entry
|
const middleware = typeof entry === 'string' ? nuxtApp._middleware.named[entry] || await namedMiddleware[entry]?.().then((r: any) => r.default || r) : entry
|
||||||
|
|
||||||
if (!middleware) {
|
if (!middleware) {
|
||||||
if (process.dev) {
|
if (import.meta.dev) {
|
||||||
throw new Error(`Unknown route middleware: '${entry}'. Valid middleware: ${Object.keys(namedMiddleware).map(mw => `'${mw}'`).join(', ')}.`)
|
throw new Error(`Unknown route middleware: '${entry}'. Valid middleware: ${Object.keys(namedMiddleware).map(mw => `'${mw}'`).join(', ')}.`)
|
||||||
}
|
}
|
||||||
throw new Error(`Unknown route middleware: '${entry}'.`)
|
throw new Error(`Unknown route middleware: '${entry}'.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await nuxtApp.runWithContext(() => middleware(to, from))
|
const result = await nuxtApp.runWithContext(() => middleware(to, from))
|
||||||
if (process.server || (!nuxtApp.payload.serverRendered && nuxtApp.isHydrating)) {
|
if (import.meta.server || (!nuxtApp.payload.serverRendered && nuxtApp.isHydrating)) {
|
||||||
if (result === false || result instanceof Error) {
|
if (result === false || result instanceof Error) {
|
||||||
const error = result || createError({
|
const error = result || createError({
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
@ -191,20 +191,20 @@ const plugin: Plugin<{ router: Router }> = defineNuxtPlugin({
|
|||||||
router.afterEach(async (to, _from, failure) => {
|
router.afterEach(async (to, _from, failure) => {
|
||||||
delete nuxtApp._processingMiddleware
|
delete nuxtApp._processingMiddleware
|
||||||
|
|
||||||
if (process.client && !nuxtApp.isHydrating && error.value) {
|
if (import.meta.client && !nuxtApp.isHydrating && error.value) {
|
||||||
// Clear any existing errors
|
// Clear any existing errors
|
||||||
await nuxtApp.runWithContext(clearError)
|
await nuxtApp.runWithContext(clearError)
|
||||||
}
|
}
|
||||||
if (process.server && failure?.type === 4 /* ErrorTypes.NAVIGATION_ABORTED */) {
|
if (import.meta.server && failure?.type === 4 /* ErrorTypes.NAVIGATION_ABORTED */) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (to.matched.length === 0 && (!process.server || !nuxtApp.ssrContext?.islandContext)) {
|
if (to.matched.length === 0 && (!import.meta.server || !nuxtApp.ssrContext?.islandContext)) {
|
||||||
await nuxtApp.runWithContext(() => showError(createError({
|
await nuxtApp.runWithContext(() => showError(createError({
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
fatal: false,
|
fatal: false,
|
||||||
statusMessage: `Page not found: ${to.fullPath}`
|
statusMessage: `Page not found: ${to.fullPath}`
|
||||||
})))
|
})))
|
||||||
} else if (process.server && to.redirectedFrom && to.fullPath !== initialURL) {
|
} else if (import.meta.server && to.redirectedFrom && to.fullPath !== initialURL) {
|
||||||
await nuxtApp.runWithContext(() => navigateTo(to.fullPath || '/'))
|
await nuxtApp.runWithContext(() => navigateTo(to.fullPath || '/'))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -19,5 +19,5 @@ export const generateRouteKey = (routeProps: RouterViewSlotProps, override?: str
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const wrapInKeepAlive = (props: any, children: any) => {
|
export const wrapInKeepAlive = (props: any, children: any) => {
|
||||||
return { default: () => process.client && props ? h(KeepAlive, props === true ? {} : props, children) : children }
|
return { default: () => import.meta.client && props ? h(KeepAlive, props === true ? {} : props, children) : children }
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export default defineNuxtRouteMiddleware(async (to) => {
|
|||||||
if (result === true) {
|
if (result === true) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (process.server) {
|
if (import.meta.server) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
const error = createError({
|
const error = createError({
|
||||||
|
Binary file not shown.
@ -59,7 +59,7 @@ const ByeBye = defineAsyncComponent(() => import('./../some-glob.global.vue'))
|
|||||||
|
|
||||||
const NotDotClientComponent = defineAsyncComponent(() => import('./../some.island.vue'))
|
const NotDotClientComponent = defineAsyncComponent(() => import('./../some.island.vue'))
|
||||||
const SomeIsland = defineAsyncComponent(async () => {
|
const SomeIsland = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../some.island.vue'))
|
return (await import('./../some.island.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ const SomeIsland = defineAsyncComponent(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const NotToBeTreeShaken = defineAsyncComponent(async () => {
|
const NotToBeTreeShaken = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../HelloWorld.vue'))
|
return (await import('./../HelloWorld.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ const NotToBeTreeShaken = defineAsyncComponent(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { ObjectPattern } = defineAsyncComponent(async () => {
|
const { ObjectPattern } = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../HelloWorld.vue'))
|
return (await import('./../HelloWorld.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ const { ObjectPattern } = defineAsyncComponent(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { ObjectPattern: ObjectPatternDeclaration } = defineAsyncComponent(async () => {
|
const { ObjectPattern: ObjectPatternDeclaration } = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../HelloWorld.vue'))
|
return (await import('./../HelloWorld.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ const { ObjectPattern: ObjectPatternDeclaration } = defineAsyncComponent(async (
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { ObjectPattern: Halllo, ButShouldNotBeTreeShaken } = defineAsyncComponent(async () => {
|
const { ObjectPattern: Halllo, ButShouldNotBeTreeShaken } = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../HelloWorld.vue'))
|
return (await import('./../HelloWorld.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ const { ObjectPattern: Halllo, ButShouldNotBeTreeShaken } = defineAsyncComponent
|
|||||||
const isThis = {}
|
const isThis = {}
|
||||||
|
|
||||||
const { woooooo, What = isThis } = defineAsyncComponent(async () => {
|
const { woooooo, What = isThis } = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../HelloWorld.vue'))
|
return (await import('./../HelloWorld.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ const { woooooo, What = isThis } = defineAsyncComponent(async () => {
|
|||||||
console.log(woooooo)
|
console.log(woooooo)
|
||||||
|
|
||||||
const { Deep, assignment: { Pattern = ofComponent } } = defineAsyncComponent(async () => {
|
const { Deep, assignment: { Pattern = ofComponent } } = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../HelloWorld.vue'))
|
return (await import('./../HelloWorld.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ const { Deep, assignment: { Pattern = ofComponent } } = defineAsyncComponent(asy
|
|||||||
})
|
})
|
||||||
|
|
||||||
const [FromArray] = defineAsyncComponent(async () => {
|
const [FromArray] = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../HelloWorld.vue'))
|
return (await import('./../HelloWorld.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ const [FromArray] = defineAsyncComponent(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const [Please, { Dont, Doo }, That] = defineAsyncComponent(async () => {
|
const [Please, { Dont, Doo }, That] = defineAsyncComponent(async () => {
|
||||||
if (process.client) {
|
if (import.meta.client) {
|
||||||
return (await import('./../HelloWorld.vue'))
|
return (await import('./../HelloWorld.vue'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,21 +26,21 @@
|
|||||||
"prepack": "unbuild"
|
"prepack": "unbuild"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/telemetry": "2.3.2",
|
"@nuxt/telemetry": "2.4.1",
|
||||||
"@types/file-loader": "5.0.1",
|
"@types/file-loader": "5.0.1",
|
||||||
"@types/pug": "2.0.6",
|
"@types/pug": "2.0.6",
|
||||||
"@types/sass-loader": "8.0.5",
|
"@types/sass-loader": "8.0.5",
|
||||||
"@unhead/schema": "1.2.2",
|
"@unhead/schema": "1.3.3",
|
||||||
"@vitejs/plugin-vue": "4.2.3",
|
"@vitejs/plugin-vue": "4.2.3",
|
||||||
"@vitejs/plugin-vue-jsx": "3.0.1",
|
"@vitejs/plugin-vue-jsx": "3.0.1",
|
||||||
"@vue/compiler-core": "3.3.4",
|
"@vue/compiler-core": "3.3.4",
|
||||||
"esbuild-loader": "3.1.0",
|
"esbuild-loader": "4.0.0",
|
||||||
"h3": "1.7.1",
|
"h3": "1.8.0",
|
||||||
"ignore": "5.2.4",
|
"ignore": "5.2.4",
|
||||||
"nitropack": "2.5.2",
|
"nitropack": "2.5.2",
|
||||||
"unbuild": "latest",
|
"unbuild": "latest",
|
||||||
"unctx": "2.3.1",
|
"unctx": "2.3.1",
|
||||||
"vite": "4.4.8",
|
"vite": "4.4.9",
|
||||||
"vue": "3.3.4",
|
"vue": "3.3.4",
|
||||||
"vue-bundle-renderer": "2.0.0",
|
"vue-bundle-renderer": "2.0.0",
|
||||||
"vue-loader": "17.2.2",
|
"vue-loader": "17.2.2",
|
||||||
|
@ -34,6 +34,7 @@ export default defineUntypedSchema({
|
|||||||
/**
|
/**
|
||||||
* An array of custom directories that will be auto-imported.
|
* An array of custom directories that will be auto-imported.
|
||||||
* Note that this option will not override the default directories (~/composables, ~/utils).
|
* Note that this option will not override the default directories (~/composables, ~/utils).
|
||||||
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```js
|
* ```js
|
||||||
* imports: {
|
* imports: {
|
||||||
@ -57,9 +58,8 @@ export default defineUntypedSchema({
|
|||||||
* Manually disable nuxt telemetry.
|
* Manually disable nuxt telemetry.
|
||||||
*
|
*
|
||||||
* @see [Nuxt Telemetry](https://github.com/nuxt/telemetry) for more information.
|
* @see [Nuxt Telemetry](https://github.com/nuxt/telemetry) for more information.
|
||||||
*
|
|
||||||
* @type {boolean | Record<string, any>}
|
* @type {boolean | Record<string, any>}
|
||||||
*/
|
*/
|
||||||
telemetry: undefined,
|
telemetry: undefined,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user