From 7b5c755b3890e2a70e0ce5826fc35d77e2cd96b2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 02:40:06 -0700 Subject: [PATCH 01/55] chore(deps): update all non-major dependencies (main) (#20101) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- packages/kit/package.json | 2 +- packages/nuxt/package.json | 2 +- packages/schema/package.json | 2 +- packages/webpack/package.json | 2 +- pnpm-lock.yaml | 184 +++++++++++++++++----------------- 5 files changed, 96 insertions(+), 96 deletions(-) diff --git a/packages/kit/package.json b/packages/kit/package.json index 5d360d025e..4bd822f3e0 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -36,7 +36,7 @@ "scule": "^1.0.0", "semver": "^7.3.8", "unctx": "^2.1.2", - "unimport": "^3.0.5", + "unimport": "^3.0.6", "untyped": "^1.3.2" }, "devDependencies": { diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 680128ec2c..4262edf79b 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -96,7 +96,7 @@ "ufo": "^1.1.1", "unctx": "^2.1.2", "unenv": "^1.2.2", - "unimport": "^3.0.5", + "unimport": "^3.0.6", "unplugin": "^1.3.1", "untyped": "^1.3.2", "vue": "^3.2.47", diff --git a/packages/schema/package.json b/packages/schema/package.json index 57d56defd8..3ebebe54eb 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -42,7 +42,7 @@ "scule": "^1.0.0", "std-env": "^3.3.2", "ufo": "^1.1.1", - "unimport": "^3.0.5", + "unimport": "^3.0.6", "untyped": "^1.3.2" }, "engines": { diff --git a/packages/webpack/package.json b/packages/webpack/package.json index 2e3d419c1f..426888f4fc 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -52,7 +52,7 @@ "url-loader": "^4.1.1", "vue-bundle-renderer": "^1.0.3", "vue-loader": "^17.0.1", - "webpack": "^5.77.0", + "webpack": "^5.78.0", "webpack-bundle-analyzer": "^4.8.0", "webpack-dev-middleware": "^6.0.2", "webpack-hot-middleware": "^2.25.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eebdac33fc..1a63d5dcdd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -128,7 +128,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -137,7 +137,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -146,7 +146,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -167,7 +167,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../packages/nuxt @@ -176,7 +176,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -185,7 +185,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -194,7 +194,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -203,7 +203,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -212,7 +212,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -221,7 +221,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -230,7 +230,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -239,7 +239,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -248,7 +248,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -257,7 +257,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -272,7 +272,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -281,7 +281,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -290,7 +290,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -299,7 +299,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -308,7 +308,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -317,7 +317,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -326,7 +326,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -335,7 +335,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -344,7 +344,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -353,7 +353,7 @@ importers: devDependencies: '@nuxt/ui': specifier: ^0.3.3 - version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0) + version: 0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0) nuxt: specifier: workspace:* version: link:../../../packages/nuxt @@ -409,8 +409,8 @@ importers: specifier: ^2.1.2 version: 2.1.2 unimport: - specifier: ^3.0.5 - version: 3.0.5(rollup@3.20.2) + specifier: ^3.0.6 + version: 3.0.6(rollup@3.20.2) untyped: specifier: ^1.3.2 version: 1.3.2 @@ -627,8 +627,8 @@ importers: specifier: ^1.2.2 version: 1.2.2 unimport: - specifier: ^3.0.5 - version: 3.0.5(rollup@3.20.2) + specifier: ^3.0.6 + version: 3.0.6(rollup@3.20.2) unplugin: specifier: ^1.3.1 version: 1.3.1 @@ -694,8 +694,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 unimport: - specifier: ^3.0.5 - version: 3.0.5(rollup@3.20.2) + specifier: ^3.0.6 + version: 3.0.6(rollup@3.20.2) untyped: specifier: ^1.3.2 version: 1.3.2 @@ -893,7 +893,7 @@ importers: version: 7.21.4 '@nuxt/friendly-errors-webpack-plugin': specifier: ^2.5.2 - version: 2.5.2(webpack@5.77.0) + version: 2.5.2(webpack@5.78.0) '@nuxt/kit': specifier: workspace:* version: link:../kit @@ -902,16 +902,16 @@ importers: version: 10.4.14(postcss@8.4.21) css-loader: specifier: ^6.7.3 - version: 6.7.3(webpack@5.77.0) + version: 6.7.3(webpack@5.78.0) css-minimizer-webpack-plugin: specifier: ^5.0.0 - version: 5.0.0(webpack@5.77.0) + version: 5.0.0(webpack@5.78.0) cssnano: specifier: ^6.0.0 version: 6.0.0(postcss@8.4.21) esbuild-loader: specifier: ^3.0.1 - version: 3.0.1(webpack@5.77.0) + version: 3.0.1(webpack@5.78.0) escape-string-regexp: specifier: ^5.0.0 version: 5.0.0 @@ -920,10 +920,10 @@ importers: version: 3.0.3 file-loader: specifier: ^6.2.0 - version: 6.2.0(webpack@5.77.0) + version: 6.2.0(webpack@5.78.0) fork-ts-checker-webpack-plugin: specifier: ^8.0.0 - version: 8.0.0(typescript@5.0.3)(webpack@5.77.0) + version: 8.0.0(typescript@5.0.3)(webpack@5.78.0) fs-extra: specifier: ^11.1.1 version: 11.1.1 @@ -941,7 +941,7 @@ importers: version: 3.4.13 mini-css-extract-plugin: specifier: ^2.7.5 - version: 2.7.5(webpack@5.77.0) + version: 2.7.5(webpack@5.78.0) mlly: specifier: ^1.2.0 version: 1.2.0 @@ -962,16 +962,16 @@ importers: version: 15.1.0(postcss@8.4.21) postcss-loader: specifier: ^7.2.4 - version: 7.2.4(@types/node@18.15.11)(postcss@8.4.21)(ts-node@10.9.1)(typescript@5.0.3)(webpack@5.77.0) + version: 7.2.4(@types/node@18.15.11)(postcss@8.4.21)(ts-node@10.9.1)(typescript@5.0.3)(webpack@5.78.0) postcss-url: specifier: ^10.1.3 version: 10.1.3(postcss@8.4.21) style-resources-loader: specifier: ^1.5.0 - version: 1.5.0(webpack@5.77.0) + version: 1.5.0(webpack@5.78.0) time-fix-plugin: specifier: ^2.0.7 - version: 2.0.7(webpack@5.77.0) + version: 2.0.7(webpack@5.78.0) ufo: specifier: ^1.1.1 version: 1.1.1 @@ -980,22 +980,22 @@ importers: version: 1.3.1 url-loader: specifier: ^4.1.1 - version: 4.1.1(file-loader@6.2.0)(webpack@5.77.0) + version: 4.1.1(file-loader@6.2.0)(webpack@5.78.0) vue-bundle-renderer: specifier: ^1.0.3 version: 1.0.3 vue-loader: specifier: ^17.0.1 - version: 17.0.1(vue@3.2.47)(webpack@5.77.0) + version: 17.0.1(vue@3.2.47)(webpack@5.78.0) webpack: - specifier: ^5.77.0 - version: 5.77.0 + specifier: ^5.78.0 + version: 5.78.0 webpack-bundle-analyzer: specifier: ^4.8.0 version: 4.8.0 webpack-dev-middleware: specifier: ^6.0.2 - version: 6.0.2(webpack@5.77.0) + version: 6.0.2(webpack@5.78.0) webpack-hot-middleware: specifier: ^2.25.3 version: 2.25.3 @@ -1004,7 +1004,7 @@ importers: version: 0.5.0 webpackbar: specifier: ^5.0.2 - version: 5.0.2(webpack@5.77.0) + version: 5.0.2(webpack@5.78.0) devDependencies: '@nuxt/schema': specifier: workspace:* @@ -1998,7 +1998,7 @@ packages: resolution: {integrity: sha512-YBI/6o2EBz02tdEJRBK8xkt3zvOFOWlLBf7WKYGBsSYSRtjjgrqPe2skp6VLLmKx5WbHHDNcW+6oACaurxGzeA==} dev: false - /@nuxt/friendly-errors-webpack-plugin@2.5.2(webpack@5.77.0): + /@nuxt/friendly-errors-webpack-plugin@2.5.2(webpack@5.78.0): resolution: {integrity: sha512-LLc+90lnxVbpKkMqk5z1EWpXoODhc6gRkqqXJCInJwF5xabHAE7biFvbULfvTRmtaTzAaP8IV4HQDLUgeAUTTw==} engines: {node: '>=8.0.0', npm: '>=5.0.0'} peerDependencies: @@ -2008,7 +2008,7 @@ packages: consola: 2.15.3 error-stack-parser: 2.1.4 string-width: 4.2.3 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /@nuxt/telemetry@2.1.10: @@ -2041,14 +2041,14 @@ packages: resolution: {integrity: sha512-PjVETP7+iZXAs5Q8O4ivl4t6qjWZMZqwiTVogUXHoHGZZcw7GZW3u3tzfYfE1HbzyYJfr236IXqQ02MeR8Fz2w==} dev: false - /@nuxt/ui@0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.77.0): + /@nuxt/ui@0.3.3(nuxt@packages+nuxt)(rollup@3.20.2)(vite@3.2.5)(vue@3.2.47)(webpack@5.78.0): resolution: {integrity: sha512-KkPAJ+7snNj3lbvzgc6UD5exVsLGExJPP1WwPIdMfXBAUUytXV5CTftpySxcAclN8j+B/GIbcjagBOpJkr7KGQ==} dependencies: '@iconify-json/carbon': 1.1.16 '@nuxt/kit': link:packages/kit '@nuxtjs/color-mode': 3.2.0 '@unocss/core': 0.45.30 - '@unocss/nuxt': 0.45.30(rollup@3.20.2)(vite@3.2.5)(webpack@5.77.0) + '@unocss/nuxt': 0.45.30(rollup@3.20.2)(vite@3.2.5)(webpack@5.78.0) '@unocss/preset-attributify': 0.45.30 '@unocss/preset-icons': 0.45.30 '@unocss/preset-mini': 0.45.30 @@ -2475,7 +2475,7 @@ packages: dependencies: '@types/node': 18.15.11 tapable: 2.2.1 - webpack: 5.77.0 + webpack: 5.78.0 transitivePeerDependencies: - '@swc/core' - esbuild @@ -2488,7 +2488,7 @@ packages: dependencies: '@types/connect': 3.4.35 tapable: 2.2.1 - webpack: 5.77.0 + webpack: 5.78.0 transitivePeerDependencies: - '@swc/core' - esbuild @@ -2751,7 +2751,7 @@ packages: sirv: 2.0.2 dev: true - /@unocss/nuxt@0.45.30(rollup@3.20.2)(vite@3.2.5)(webpack@5.77.0): + /@unocss/nuxt@0.45.30(rollup@3.20.2)(vite@3.2.5)(webpack@5.78.0): resolution: {integrity: sha512-m2CEbLLoqE/WacdEGEDXR9R3FbTbSTPV5gPL0Myv0jrHRSRt1MkULZ/IfPgA/A/QiOzcSIUTVXW1dSlOFh5ngQ==} dependencies: '@nuxt/kit': link:packages/kit @@ -2765,7 +2765,7 @@ packages: '@unocss/preset-wind': 0.45.30 '@unocss/reset': 0.45.30 '@unocss/vite': 0.45.30(rollup@3.20.2)(vite@3.2.5) - '@unocss/webpack': 0.45.30(rollup@3.20.2)(webpack@5.77.0) + '@unocss/webpack': 0.45.30(rollup@3.20.2)(webpack@5.78.0) unocss: 0.45.30(@unocss/webpack@0.45.30)(rollup@3.20.2)(vite@3.2.5) transitivePeerDependencies: - rollup @@ -2885,7 +2885,7 @@ packages: - rollup dev: true - /@unocss/webpack@0.45.30(rollup@3.20.2)(webpack@5.77.0): + /@unocss/webpack@0.45.30(rollup@3.20.2)(webpack@5.78.0): resolution: {integrity: sha512-ke3B+YHmd2O6fxSUoHn24lfiQl1gsc8EQp5n4cqsy92IVw+lmGrVj6V3EyIN5aykrxgEqiZc9NLhPoADWoai7g==} peerDependencies: webpack: ^4 || ^5 @@ -2896,7 +2896,7 @@ packages: '@unocss/core': 0.45.30 magic-string: 0.30.0 unplugin: 0.10.2 - webpack: 5.77.0 + webpack: 5.78.0 webpack-sources: 3.2.3 transitivePeerDependencies: - rollup @@ -4101,7 +4101,7 @@ packages: postcss: 8.4.21 dev: false - /css-loader@6.7.3(webpack@5.77.0): + /css-loader@6.7.3(webpack@5.78.0): resolution: {integrity: sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==} engines: {node: '>= 12.13.0'} peerDependencies: @@ -4115,10 +4115,10 @@ packages: postcss-modules-values: 4.0.0(postcss@8.4.21) postcss-value-parser: 4.2.0 semver: 7.3.8 - webpack: 5.77.0 + webpack: 5.78.0 dev: false - /css-minimizer-webpack-plugin@5.0.0(webpack@5.77.0): + /css-minimizer-webpack-plugin@5.0.0(webpack@5.78.0): resolution: {integrity: sha512-1wZ/PYvg+ZKwi5FX6YrvbB31jMAdurS+CmRQLwWCVSlfzJC85l/a6RVICqUHFa+jXyhilfnCyjafzJGbmz5tcA==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -4149,7 +4149,7 @@ packages: schema-utils: 4.0.0 serialize-javascript: 6.0.1 source-map: 0.6.1 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /css-select@1.2.0: @@ -4790,7 +4790,7 @@ packages: dev: true optional: true - /esbuild-loader@3.0.1(webpack@5.77.0): + /esbuild-loader@3.0.1(webpack@5.78.0): resolution: {integrity: sha512-aZfGybqTeuyCd4AsVvWOOfkhIuN+wfZFjMyh3gyQEU1Uvsl8L6vye9HqP93iRa0iTA+6Jclap514PJIC3cLnMA==} peerDependencies: webpack: ^4.40.0 || ^5.0.0 @@ -4798,7 +4798,7 @@ packages: esbuild: 0.17.15 get-tsconfig: 4.4.0 loader-utils: 2.0.4 - webpack: 5.77.0 + webpack: 5.78.0 webpack-sources: 1.4.3 dev: false @@ -5442,7 +5442,7 @@ packages: dependencies: flat-cache: 3.0.4 - /file-loader@6.2.0(webpack@5.77.0): + /file-loader@6.2.0(webpack@5.78.0): resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -5450,7 +5450,7 @@ packages: dependencies: loader-utils: 2.0.4 schema-utils: 3.1.1 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /file-uri-to-path@1.0.0: @@ -5516,7 +5516,7 @@ packages: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} dev: true - /fork-ts-checker-webpack-plugin@8.0.0(typescript@5.0.3)(webpack@5.77.0): + /fork-ts-checker-webpack-plugin@8.0.0(typescript@5.0.3)(webpack@5.78.0): resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} engines: {node: '>=12.13.0', yarn: '>=1.0.0'} peerDependencies: @@ -5536,7 +5536,7 @@ packages: semver: 7.3.8 tapable: 2.2.1 typescript: 5.0.3 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /form-data@2.3.3: @@ -6764,14 +6764,14 @@ packages: engines: {node: '>=4'} dev: true - /mini-css-extract-plugin@2.7.5(webpack@5.77.0): + /mini-css-extract-plugin@2.7.5(webpack@5.78.0): resolution: {integrity: sha512-9HaR++0mlgom81s95vvNjxkg52n2b5s//3ZTI1EtzFb98awsLSivs2LMsVqnQ3ay0PVhqWcGNyDaTE961FOcjQ==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^5.0.0 dependencies: schema-utils: 4.0.0 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /minimatch@3.0.8: @@ -6967,7 +6967,7 @@ packages: std-env: 3.3.2 ufo: 1.1.1 unenv: 1.2.2 - unimport: 3.0.5(rollup@3.20.2) + unimport: 3.0.6(rollup@3.20.2) unstorage: 1.4.1 transitivePeerDependencies: - '@azure/app-configuration' @@ -7479,7 +7479,7 @@ packages: resolve: 1.22.1 dev: false - /postcss-loader@7.2.4(@types/node@18.15.11)(postcss@8.4.21)(ts-node@10.9.1)(typescript@5.0.3)(webpack@5.77.0): + /postcss-loader@7.2.4(@types/node@18.15.11)(postcss@8.4.21)(ts-node@10.9.1)(typescript@5.0.3)(webpack@5.78.0): resolution: {integrity: sha512-F88rpxxNspo5hatIc+orYwZDtHFaVFOSIVAx+fBfJC1GmhWbVmPWtmg2gXKE1OxJbneOSGn8PWdIwsZFcruS+w==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -7500,7 +7500,7 @@ packages: semver: 7.3.8 ts-node: 10.9.1(@types/node@18.15.11)(typescript@5.0.3) typescript: 5.0.3 - webpack: 5.77.0 + webpack: 5.78.0 transitivePeerDependencies: - '@types/node' dev: false @@ -8464,7 +8464,7 @@ packages: dependencies: acorn: 8.8.2 - /style-resources-loader@1.5.0(webpack@5.77.0): + /style-resources-loader@1.5.0(webpack@5.78.0): resolution: {integrity: sha512-fIfyvQ+uvXaCBGGAgfh+9v46ARQB1AWdaop2RpQw0PBVuROsTBqGvx8dj0kxwjGOAyq3vepe4AOK3M6+Q/q2jw==} engines: {node: '>=8.9'} peerDependencies: @@ -8474,7 +8474,7 @@ packages: loader-utils: 2.0.4 schema-utils: 2.7.1 tslib: 2.5.0 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /stylehacks@6.0.0(postcss@8.4.21): @@ -8568,7 +8568,7 @@ packages: mkdirp: 1.0.4 yallist: 4.0.0 - /terser-webpack-plugin@5.3.7(webpack@5.77.0): + /terser-webpack-plugin@5.3.7(webpack@5.78.0): resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -8589,7 +8589,7 @@ packages: schema-utils: 3.1.1 serialize-javascript: 6.0.1 terser: 5.16.6 - webpack: 5.77.0 + webpack: 5.78.0 /terser@5.16.6: resolution: {integrity: sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==} @@ -8608,12 +8608,12 @@ packages: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} dev: false - /time-fix-plugin@2.0.7(webpack@5.77.0): + /time-fix-plugin@2.0.7(webpack@5.78.0): resolution: {integrity: sha512-uVFet1LQToeUX0rTcSiYVYVoGuBpc8gP/2jnlUzuHMHe+gux6XLsNzxLUweabMwiUj5ejhoIMsUI55nVSEa/Vw==} peerDependencies: webpack: '>=4.0.0' dependencies: - webpack: 5.77.0 + webpack: 5.78.0 dev: false /tiny-glob@0.2.9: @@ -8918,8 +8918,8 @@ packages: hookable: 5.5.3 dev: false - /unimport@3.0.5(rollup@3.20.2): - resolution: {integrity: sha512-enRW0sVcTBxUZY6R2iumWMUsPbGC5GW9jM89VtF0pFUz9vDPrvEmOAklbSE/a4fqhjW/7dMWBvfLw/IDlBaPdQ==} + /unimport@3.0.6(rollup@3.20.2): + resolution: {integrity: sha512-GYxGJ1Bri1oqx8VFDjdgooGzeK7jBk3bvhXmamTIpu3nONOcUMGwZbX7X0L5RA7OWMXpR4vzpSQP7pXUzJg1/Q==} dependencies: '@rollup/pluginutils': 5.0.2(rollup@3.20.2) escape-string-regexp: 5.0.0 @@ -8965,7 +8965,7 @@ packages: '@unocss/transformer-directives': 0.45.30 '@unocss/transformer-variant-group': 0.45.30 '@unocss/vite': 0.45.30(rollup@3.20.2)(vite@3.2.5) - '@unocss/webpack': 0.45.30(rollup@3.20.2)(webpack@5.77.0) + '@unocss/webpack': 0.45.30(rollup@3.20.2)(webpack@5.78.0) transitivePeerDependencies: - rollup - supports-color @@ -9063,7 +9063,7 @@ packages: dependencies: punycode: 2.3.0 - /url-loader@4.1.1(file-loader@6.2.0)(webpack@5.77.0): + /url-loader@4.1.1(file-loader@6.2.0)(webpack@5.78.0): resolution: {integrity: sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -9073,11 +9073,11 @@ packages: file-loader: optional: true dependencies: - file-loader: 6.2.0(webpack@5.77.0) + file-loader: 6.2.0(webpack@5.78.0) loader-utils: 2.0.4 mime-types: 2.1.35 schema-utils: 3.1.1 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /util-deprecate@1.0.2: @@ -9402,7 +9402,7 @@ packages: - supports-color dev: true - /vue-loader@17.0.1(vue@3.2.47)(webpack@5.77.0): + /vue-loader@17.0.1(vue@3.2.47)(webpack@5.78.0): resolution: {integrity: sha512-/OOyugJnImKCkAKrAvdsWMuwoCqGxWT5USLsjohzWbMgOwpA5wQmzQiLMzZd7DjhIfunzAGIApTOgIylz/kwcg==} peerDependencies: '@vue/compiler-sfc': '*' @@ -9418,7 +9418,7 @@ packages: hash-sum: 2.0.0 loader-utils: 2.0.4 vue: 3.2.47 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /vue-router@4.1.6(vue@3.2.47): @@ -9496,7 +9496,7 @@ packages: - utf-8-validate dev: false - /webpack-dev-middleware@6.0.2(webpack@5.77.0): + /webpack-dev-middleware@6.0.2(webpack@5.78.0): resolution: {integrity: sha512-iOddiJzPcQC6lwOIu60vscbGWth8PCRcWRCwoQcTQf9RMoOWBHg5EyzpGdtSmGMrSPd5vHEfFXmVErQEmkRngQ==} engines: {node: '>= 14.15.0'} peerDependencies: @@ -9510,7 +9510,7 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.0.0 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /webpack-hot-middleware@2.25.3: @@ -9539,8 +9539,8 @@ packages: /webpack-virtual-modules@0.5.0: resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} - /webpack@5.77.0: - resolution: {integrity: sha512-sbGNjBr5Ya5ss91yzjeJTLKyfiwo5C628AFjEa6WSXcZa4E+F57om3Cc8xLb1Jh0b243AWuSYRf3dn7HVeFQ9Q==} + /webpack@5.78.0: + resolution: {integrity: sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -9570,7 +9570,7 @@ packages: neo-async: 2.6.2 schema-utils: 3.1.1 tapable: 2.2.1 - terser-webpack-plugin: 5.3.7(webpack@5.77.0) + terser-webpack-plugin: 5.3.7(webpack@5.78.0) watchpack: 2.4.0 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -9578,7 +9578,7 @@ packages: - esbuild - uglify-js - /webpackbar@5.0.2(webpack@5.77.0): + /webpackbar@5.0.2(webpack@5.78.0): resolution: {integrity: sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==} engines: {node: '>=12'} peerDependencies: @@ -9588,7 +9588,7 @@ packages: consola: 2.15.3 pretty-time: 1.1.0 std-env: 3.3.2 - webpack: 5.77.0 + webpack: 5.78.0 dev: false /whatwg-url@5.0.0: From 3fc9a75070367a4bdd90e3a7fc7f38185b71da19 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Thu, 6 Apr 2023 13:51:32 +0200 Subject: [PATCH 02/55] feat(nuxt): support vue runtime compiler (#4762) --- package.json | 2 +- packages/nuxt/src/core/nitro.ts | 57 +++++++++++++-- packages/schema/src/config/app.ts | 2 +- packages/schema/src/config/experimental.ts | 6 ++ test/fixtures/runtime-compiler/.gitignore | 8 +++ .../components/Helloworld.vue | 5 ++ .../runtime-compiler/components/Name.ts | 15 ++++ .../components/ShowTemplate.vue | 35 ++++++++++ test/fixtures/runtime-compiler/nuxt.config.ts | 8 +++ test/fixtures/runtime-compiler/package.json | 10 +++ .../fixtures/runtime-compiler/pages/index.vue | 66 ++++++++++++++++++ .../runtime-compiler/public/favicon.ico | Bin 0 -> 15406 bytes .../server/api/full-component.get.ts | 18 +++++ .../server/api/template.get.ts | 7 ++ test/fixtures/runtime-compiler/tsconfig.json | 4 ++ test/runtime-compiler.test.ts | 59 ++++++++++++++++ 16 files changed, 295 insertions(+), 7 deletions(-) create mode 100644 test/fixtures/runtime-compiler/.gitignore create mode 100644 test/fixtures/runtime-compiler/components/Helloworld.vue create mode 100644 test/fixtures/runtime-compiler/components/Name.ts create mode 100644 test/fixtures/runtime-compiler/components/ShowTemplate.vue create mode 100644 test/fixtures/runtime-compiler/nuxt.config.ts create mode 100644 test/fixtures/runtime-compiler/package.json create mode 100644 test/fixtures/runtime-compiler/pages/index.vue create mode 100644 test/fixtures/runtime-compiler/public/favicon.ico create mode 100644 test/fixtures/runtime-compiler/server/api/full-component.get.ts create mode 100644 test/fixtures/runtime-compiler/server/api/template.get.ts create mode 100644 test/fixtures/runtime-compiler/tsconfig.json create mode 100644 test/runtime-compiler.test.ts diff --git a/package.json b/package.json index f9e8d6da7b..89b96c211c 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "play": "pnpm nuxi dev playground", "play:build": "pnpm nuxi build playground", "play:preview": "pnpm nuxi preview playground", - "test:fixtures": "pnpm nuxi prepare test/fixtures/basic && JITI_ESM_RESOLVE=1 vitest run --dir test", + "test:fixtures": "pnpm nuxi prepare test/fixtures/basic && nuxi prepare test/fixtures/runtime-compiler && JITI_ESM_RESOLVE=1 vitest run --dir test", "test:fixtures:dev": "TEST_ENV=dev pnpm test:fixtures", "test:fixtures:webpack": "TEST_BUILDER=webpack pnpm test:fixtures", "test:types": "pnpm nuxi prepare test/fixtures/basic && cd test/fixtures/basic && npx vue-tsc --noEmit", diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index c0114b2ea7..684ff3758e 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -126,6 +126,18 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { 'nuxt/dist', 'nuxt3/dist', distDir + ], + traceInclude: [ + // force include files used in generated code from the runtime-compiler + ...(nuxt.options.experimental.runtimeVueCompiler && !nuxt.options.experimental.externalVue) + ? [ + ...nuxt.options.modulesDir.reduce((targets, path) => { + const serverRendererPath = resolve(path, 'vue/server-renderer/index.js') + if (existsSync(serverRendererPath)) { targets.push(serverRendererPath) } + return targets + }, []) + ] + : [] ] }, alias: { @@ -137,11 +149,15 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { vue: await resolvePath(`vue/dist/vue.cjs${nuxt.options.dev ? '' : '.prod'}.js`) }, // Vue 3 mocks - 'estree-walker': 'unenv/runtime/mock/proxy', - '@babel/parser': 'unenv/runtime/mock/proxy', - '@vue/compiler-core': 'unenv/runtime/mock/proxy', - '@vue/compiler-dom': 'unenv/runtime/mock/proxy', - '@vue/compiler-ssr': 'unenv/runtime/mock/proxy', + ...nuxt.options.experimental.runtimeVueCompiler || nuxt.options.experimental.externalVue + ? {} + : { + 'estree-walker': 'unenv/runtime/mock/proxy', + '@babel/parser': 'unenv/runtime/mock/proxy', + '@vue/compiler-core': 'unenv/runtime/mock/proxy', + '@vue/compiler-dom': 'unenv/runtime/mock/proxy', + '@vue/compiler-ssr': 'unenv/runtime/mock/proxy' + }, '@vue/devtools-api': 'vue-devtools-stub', // Paths @@ -231,6 +247,37 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { nuxt.callHook('prerender:routes', { routes }) }) + // Enable runtime compiler client side + if (nuxt.options.experimental.runtimeVueCompiler) { + nuxt.hook('vite:extendConfig', (config, { isClient }) => { + if (isClient) { + if (Array.isArray(config.resolve!.alias)) { + config.resolve!.alias.push({ + find: 'vue', + replacement: 'vue/dist/vue.esm-bundler' + }) + } else { + config.resolve!.alias = { + ...config.resolve!.alias, + vue: 'vue/dist/vue.esm-bundler' + } + } + } + }) + nuxt.hook('webpack:config', (configuration) => { + const clientConfig = configuration.find(config => config.name === 'client') + if (!clientConfig!.resolve) { clientConfig!.resolve!.alias = {} } + if (Array.isArray(clientConfig!.resolve!.alias)) { + clientConfig!.resolve!.alias.push({ + name: 'vue', + alias: 'vue/dist/vue.esm-bundler' + }) + } else { + clientConfig!.resolve!.alias!.vue = 'vue/dist/vue.esm-bundler' + } + }) + } + // Setup handlers const devMiddlewareHandler = dynamicEventHandler() nitro.options.devHandlers.unshift({ handler: devMiddlewareHandler }) diff --git a/packages/schema/src/config/app.ts b/packages/schema/src/config/app.ts index d3c3aede68..c9a42f37db 100644 --- a/packages/schema/src/config/app.ts +++ b/packages/schema/src/config/app.ts @@ -12,7 +12,7 @@ export default defineUntypedSchema({ * @see [documentation](https://vuejs.org/api/application.html#app-config-compileroptions) * @type {typeof import('@vue/compiler-core').CompilerOptions} */ - compilerOptions: {} + compilerOptions: {}, }, /** diff --git a/packages/schema/src/config/experimental.ts b/packages/schema/src/config/experimental.ts index 2469dd2680..0817b672a1 100644 --- a/packages/schema/src/config/experimental.ts +++ b/packages/schema/src/config/experimental.ts @@ -21,6 +21,12 @@ export default defineUntypedSchema({ */ externalVue: true, + // TODO: move to `vue.runtimeCompiler` in v3.5 + /** + * Include Vue compiler in runtime bundle. + */ + runtimeVueCompiler: false, + /** * Tree shakes contents of client-only components from server bundle. * @see https://github.com/nuxt/framework/pull/5750 diff --git a/test/fixtures/runtime-compiler/.gitignore b/test/fixtures/runtime-compiler/.gitignore new file mode 100644 index 0000000000..438cb0860d --- /dev/null +++ b/test/fixtures/runtime-compiler/.gitignore @@ -0,0 +1,8 @@ +node_modules +*.log* +.nuxt +.nitro +.cache +.output +.env +dist diff --git a/test/fixtures/runtime-compiler/components/Helloworld.vue b/test/fixtures/runtime-compiler/components/Helloworld.vue new file mode 100644 index 0000000000..f25b73707c --- /dev/null +++ b/test/fixtures/runtime-compiler/components/Helloworld.vue @@ -0,0 +1,5 @@ + diff --git a/test/fixtures/runtime-compiler/components/Name.ts b/test/fixtures/runtime-compiler/components/Name.ts new file mode 100644 index 0000000000..54b23cd97e --- /dev/null +++ b/test/fixtures/runtime-compiler/components/Name.ts @@ -0,0 +1,15 @@ +export default defineNuxtComponent({ + props: ['template', 'name'], + + /** + * most of the time, vue compiler need at least a VNode, use h() to render the component + */ + render () { + return h({ + props: ['name'], + template: this.template + }, { + name: this.name + }) + } +}) diff --git a/test/fixtures/runtime-compiler/components/ShowTemplate.vue b/test/fixtures/runtime-compiler/components/ShowTemplate.vue new file mode 100644 index 0000000000..02456fa6ae --- /dev/null +++ b/test/fixtures/runtime-compiler/components/ShowTemplate.vue @@ -0,0 +1,35 @@ + + + diff --git a/test/fixtures/runtime-compiler/nuxt.config.ts b/test/fixtures/runtime-compiler/nuxt.config.ts new file mode 100644 index 0000000000..604986a3fc --- /dev/null +++ b/test/fixtures/runtime-compiler/nuxt.config.ts @@ -0,0 +1,8 @@ +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + experimental: { + runtimeVueCompiler: true, + externalVue: false + }, + builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite' +}) diff --git a/test/fixtures/runtime-compiler/package.json b/test/fixtures/runtime-compiler/package.json new file mode 100644 index 0000000000..cf133dcd9b --- /dev/null +++ b/test/fixtures/runtime-compiler/package.json @@ -0,0 +1,10 @@ +{ + "private": true, + "name": "fixture-runtime-compiler", + "scripts": { + "build": "nuxi build" + }, + "dependencies": { + "nuxt": "workspace:*" + } +} diff --git a/test/fixtures/runtime-compiler/pages/index.vue b/test/fixtures/runtime-compiler/pages/index.vue new file mode 100644 index 0000000000..42fd3135f7 --- /dev/null +++ b/test/fixtures/runtime-compiler/pages/index.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/test/fixtures/runtime-compiler/public/favicon.ico b/test/fixtures/runtime-compiler/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..d44088fe25f6dd6b3a0c9b0914c07b2cbfb063f1 GIT binary patch literal 15406 zcmeHOd2Ccg7=IprEB@iXupna9D0pFl8gJv7h^UF8hG@KEOiVQT2aUvkj7G#55rL(& z6vPTGN0D;NU9J{HjsQiVv`|X7`}TZq-?g9LH|v}3JGR|@-R^c}C)v!KneX_`_vX!f zGxMz=TqRs1j2Izc?h`(^RuCo%g5dL|$`v;V!a}T@FyX)Uae~l%qaaiu4YD9dsva}f z6!iPP?DdaQf(v|*%a8GRkv|H-s<9w0 zoyhpLp1&cua4g8j77fU+^&DY5(Jdb_S_9=#AA&Wv4aiHjNgQ9o_>K4_h_0UodiWeG zhn78@6@Pfu3(S6cxE*sNB`eYn!Rm2Y@e_vF_RpC8Lv;`0yL=hMnp?Bx9q9e$yL~X< z0PzMqeuGRe^14n6IaJa-SYm%T|*bU*;lN~rBO|Rn` zyaklD6>LrEPnMT9?NSR{>rxAz#@2pQj#zsqB-L17J3gtMJ0QH`83#_2C)ZpTPg~^E zx@pRYZg|_$#tY~d#I}9P=}dYrxgP4%pH$=MuiVV#l24YN}?;VDk* zMK|&2!INAC^Ow@*E%GPQQ>1YU^R4vY30AGNtsJy|)9)gIcKs3bqtcVK{~M-HTyi(V zt%uGIUVqnKt|Dn@Al8oOGDCHfcpE*a9ou;u`Ly!kUwGN8{gpFK79H{C85WsFtc$m^ z@lkb?rQNGulTSW8m&>OI@_U0d6)SGkq*p+q$XQ2;NDJZnVEOprVZITWatpzRmpVF9xlFXI!Fh9g!rDX@-o+%x-#ZD z?6oq=NSi;)G`XFvlHT|P=T?TAIy1q0YxQC?;(9(Krf}nA&;m!nkb2melG?Ei=xjaTxU!W;XKeOFXYJvY z&p9xO)fN0c+s>n&+YHn6Nwy2jrw2#Pj|mEarnZ;=PJ| zcwSC14|ZMImetOkT&?+_bsutICwa>0)g}qgm9y(WTyhu0{`?ry?{Fv%CZG3Hnfjxi z-^#I=56YV_`Js~8q;?B7}3X$#*c%c2b{yDL$fXS*rY$c^9u`^S%_|Yw z755>jJAQHT1c>8zOMbmBo&r5^3@9!khI6S{TfCSt`#TU9-45~Hl^~(t7+U_AyG_}e z?DUQ7vWix<oO6L(%Z0jgK-0@8>jS+m&rs9s^gz7%18MQ~WQQjK31UzaBZ2^`per zEsA+yF(()UA^Lr@OQ{cponlTXZiZq|%s3A0M>EcO!})uV2qW3u#7_9jscZqS7Wfy? CQ%)8D literal 0 HcmV?d00001 diff --git a/test/fixtures/runtime-compiler/server/api/full-component.get.ts b/test/fixtures/runtime-compiler/server/api/full-component.get.ts new file mode 100644 index 0000000000..26baa9d6c7 --- /dev/null +++ b/test/fixtures/runtime-compiler/server/api/full-component.get.ts @@ -0,0 +1,18 @@ +/** + * sometimes, CMS wants to give full control on components. This might not be a good practice. + * SO MAKE SURE TO SANITIZE ALL YOUR STRINGS + */ +export default defineEventHandler(() => { + return { + props: ['lastname', 'firstname'], + // don't forget to sanitize + setup: ` + const fullName = computed(() => props.lastname + ' ' + props.firstname); + + const count = ref(0); + + return {fullName, count} + `, + template: '
my name is {{ fullName }}, count: {{count}}. I am defined by Interactive in the setup of App.vue. My full component definition is retrieved from the api
' + } +}) diff --git a/test/fixtures/runtime-compiler/server/api/template.get.ts b/test/fixtures/runtime-compiler/server/api/template.get.ts new file mode 100644 index 0000000000..500bb1ff85 --- /dev/null +++ b/test/fixtures/runtime-compiler/server/api/template.get.ts @@ -0,0 +1,7 @@ +/** + * mock the behavior of nuxt retrieving data from an api + */ + +export default defineEventHandler(() => { + return '
Hello my name is : {{name}}, i am defined by ShowTemplate.vue and my template is retrieved from the API
' +}) diff --git a/test/fixtures/runtime-compiler/tsconfig.json b/test/fixtures/runtime-compiler/tsconfig.json new file mode 100644 index 0000000000..a746f2a70c --- /dev/null +++ b/test/fixtures/runtime-compiler/tsconfig.json @@ -0,0 +1,4 @@ +{ + // https://nuxt.com/docs/guide/concepts/typescript + "extends": "./.nuxt/tsconfig.json" +} diff --git a/test/runtime-compiler.test.ts b/test/runtime-compiler.test.ts new file mode 100644 index 0000000000..b125a47d25 --- /dev/null +++ b/test/runtime-compiler.test.ts @@ -0,0 +1,59 @@ +import { fileURLToPath } from 'node:url' +import { isWindows } from 'std-env' +import { describe, it, expect } from 'vitest' +import { setup, $fetch } from '@nuxt/test-utils' +import { expectNoClientErrors, renderPage } from './utils' +const isWebpack = process.env.TEST_BUILDER === 'webpack' + +await setup({ + rootDir: fileURLToPath(new URL('./fixtures/runtime-compiler', import.meta.url)), + dev: process.env.TEST_ENV === 'dev', + server: true, + browser: true, + setupTimeout: (isWindows ? 240 : 120) * 1000, + nuxtConfig: { + builder: isWebpack ? 'webpack' : 'vite' + } +}) + +describe('test basic config', () => { + it('expect render page without any error or logs', async () => { + await expectNoClientErrors('/') + }) + + it('test HelloWorld.vue', async () => { + const html = await $fetch('/') + const { page } = await renderPage('/') + + expect(html).toContain('
hello, Helloworld.vue here !
') + expect(await page.locator('body').innerHTML()).toContain('
hello, Helloworld.vue here !
') + }) + + it('test Name.ts', async () => { + const html = await $fetch('/') + const { page } = await renderPage('/') + + expect(html).toContain('
I am the Name.ts component
') + expect(await page.locator('body').innerHTML()).toContain('
I am the Name.ts component
') + }) + + it('test ShowTemplate.ts', async () => { + const html = await $fetch('/') + const { page } = await renderPage('/') + + expect(html).toContain('
Hello my name is : John, i am defined by ShowTemplate.vue and my template is retrieved from the API
') + expect(await page.locator('body').innerHTML()).toContain('
Hello my name is : John, i am defined by ShowTemplate.vue and my template is retrieved from the API
') + }) + + it('test Interactive component.ts', async () => { + const html = await $fetch('/') + const { page } = await renderPage('/') + + expect(html).toContain('I am defined by Interactive in the setup of App.vue. My full component definition is retrieved from the api') + expect(await page.locator('#interactive').innerHTML()).toContain('I am defined by Interactive in the setup of App.vue. My full component definition is retrieved from the api') + const button = page.locator('#inc-interactive-count') + await button.click() + const count = page.locator('#interactive-count') + expect(await count.innerHTML()).toBe('1') + }) +}) From 72ba53efbc2384f802d654fffd92eaf36a81b507 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Thu, 6 Apr 2023 14:07:22 +0200 Subject: [PATCH 03/55] feat(test-utils): allow mounting single component for testing (#5723) --- .../nuxt/src/app/components/nuxt-root.vue | 5 ++++ .../app/components/test-component-wrapper.ts | 19 +++++++++++++++ packages/nuxt/src/core/templates.ts | 5 ++++ packages/test-utils/build.config.ts | 1 + packages/test-utils/experimental.d.ts | 1 + packages/test-utils/package.json | 7 +++++- packages/test-utils/src/experimental.ts | 23 +++++++++++++++++++ packages/test-utils/src/server.ts | 5 +++- pnpm-lock.yaml | 3 +++ test/basic.test.ts | 11 +++++++++ vitest.config.ts | 1 + 11 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 packages/nuxt/src/app/components/test-component-wrapper.ts create mode 100644 packages/test-utils/experimental.d.ts create mode 100644 packages/test-utils/src/experimental.ts diff --git a/packages/nuxt/src/app/components/nuxt-root.vue b/packages/nuxt/src/app/components/nuxt-root.vue index 4983519062..698899bce4 100644 --- a/packages/nuxt/src/app/components/nuxt-root.vue +++ b/packages/nuxt/src/app/components/nuxt-root.vue @@ -2,6 +2,7 @@ + @@ -21,6 +22,10 @@ const IslandRenderer = process.server const nuxtApp = useNuxtApp() const onResolve = nuxtApp.deferHydration() +const url = process.server ? nuxtApp.ssrContext.url : window.location.pathname +const SingleRenderer = process.dev && process.server && url.startsWith('/__nuxt_component_test__/') && defineAsyncComponent(() => import('#build/test-component-wrapper.mjs') + .then(r => r.default(process.server ? url : window.location.href))) + // Inject default route (outside of pages) as active route provide('_route', useRoute()) diff --git a/packages/nuxt/src/app/components/test-component-wrapper.ts b/packages/nuxt/src/app/components/test-component-wrapper.ts new file mode 100644 index 0000000000..676b821e8b --- /dev/null +++ b/packages/nuxt/src/app/components/test-component-wrapper.ts @@ -0,0 +1,19 @@ +import { parseURL } from 'ufo' +import { defineComponent, h } from 'vue' +import { parseQuery } from 'vue-router' + +export default (url:string) => defineComponent({ + name: 'NuxtTestComponentWrapper', + + async setup (props, { attrs }) { + const query = parseQuery(parseURL(url).search) + const urlProps = query.props ? JSON.parse(query.props as string) : {} + const comp = await import(/* @vite-ignore */ query.path as string).then(r => r.default) + return () => [ + h('div', 'Component Test Wrapper for ' + query.path), + h('div', { id: 'nuxt-component-root' }, [ + h(comp, { ...attrs, ...props, ...urlProps }) + ]) + ] + } +}) diff --git a/packages/nuxt/src/core/templates.ts b/packages/nuxt/src/core/templates.ts index 33c031cd08..0f75b2bc29 100644 --- a/packages/nuxt/src/core/templates.ts +++ b/packages/nuxt/src/core/templates.ts @@ -40,6 +40,11 @@ export const errorComponentTemplate: NuxtTemplate = { filename: 'error-component.mjs', getContents: ctx => genExport(ctx.app.errorComponent!, ['default']) } +// TODO: Use an alias +export const testComponentWrapperTemplate = { + filename: 'test-component-wrapper.mjs', + getContents: (ctx: TemplateContext) => genExport(resolve(ctx.nuxt.options.appDir, 'components/test-component-wrapper'), ['default']) +} export const cssTemplate: NuxtTemplate = { filename: 'css.mjs', diff --git a/packages/test-utils/build.config.ts b/packages/test-utils/build.config.ts index 4b6640762b..e0f61579a1 100644 --- a/packages/test-utils/build.config.ts +++ b/packages/test-utils/build.config.ts @@ -4,6 +4,7 @@ export default defineBuildConfig({ declaration: true, entries: [ 'src/index', + 'src/experimental', { input: 'src/runtime/', outDir: 'dist/runtime', format: 'esm' } ], externals: [ diff --git a/packages/test-utils/experimental.d.ts b/packages/test-utils/experimental.d.ts new file mode 100644 index 0000000000..c9d24adffa --- /dev/null +++ b/packages/test-utils/experimental.d.ts @@ -0,0 +1 @@ +export * from './dist/experimental' diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 603989324e..d0ce8c87e4 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -9,6 +9,10 @@ ".": { "types": "./dist/index.d.ts", "import": "./dist/index.mjs" + }, + "./experimental": { + "types": "./dist/experimental.d.ts", + "import": "./dist/experimental.mjs" } }, "files": [ @@ -26,7 +30,8 @@ "get-port-please": "^3.0.1", "jiti": "^1.18.2", "ofetch": "^1.0.1", - "pathe": "^1.1.0" + "pathe": "^1.1.0", + "ufo": "^1.1.1" }, "devDependencies": { "playwright": "^1.32.2", diff --git a/packages/test-utils/src/experimental.ts b/packages/test-utils/src/experimental.ts new file mode 100644 index 0000000000..7d24def0a5 --- /dev/null +++ b/packages/test-utils/src/experimental.ts @@ -0,0 +1,23 @@ +import { fetch as _fetch, $fetch as _$fetch } from 'ofetch' +import * as _kit from '@nuxt/kit' +import { resolve } from 'pathe' +import { stringifyQuery } from 'ufo' +import { useTestContext } from './context' +import { $fetch } from './server' + +/** + * This is a function to render a component directly with the Nuxt server. + */ +export function $fetchComponent (filepath: string, props?: Record) { + return $fetch(componentTestUrl(filepath, props)) +} + +export function componentTestUrl (filepath: string, props?: Record) { + const ctx = useTestContext() + filepath = resolve(ctx.options.rootDir, filepath) + const path = stringifyQuery({ + path: filepath, + props: JSON.stringify(props) + }) + return `/__nuxt_component_test__/?${path}` +} diff --git a/packages/test-utils/src/server.ts b/packages/test-utils/src/server.ts index 56261dd898..77b580e2ae 100644 --- a/packages/test-utils/src/server.ts +++ b/packages/test-utils/src/server.ts @@ -1,9 +1,9 @@ -import { resolve } from 'node:path' import { execa } from 'execa' import { getRandomPort, waitForPort } from 'get-port-please' import type { FetchOptions } from 'ofetch' import { fetch as _fetch, $fetch as _$fetch } from 'ofetch' import * as _kit from '@nuxt/kit' +import { resolve } from 'pathe' import { useTestContext } from './context' // @ts-ignore type cast @@ -75,5 +75,8 @@ export function url (path: string) { if (!ctx.url) { throw new Error('url is not available (is server option enabled?)') } + if (path.startsWith(ctx.url)) { + return path + } return ctx.url + path } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1a63d5dcdd..cdfee34c88 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -754,6 +754,9 @@ importers: pathe: specifier: ^1.1.0 version: 1.1.0 + ufo: + specifier: ^1.1.1 + version: 1.1.1 vue: specifier: ^3.2.47 version: 3.2.47 diff --git a/test/basic.test.ts b/test/basic.test.ts index 9e34bb3120..35f764b437 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -7,6 +7,7 @@ import { setup, fetch, $fetch, startServer, isDev, createPage, url } from '@nuxt import type { NuxtIslandResponse } from '../packages/nuxt/src/core/runtime/nitro/renderer' import { expectNoClientErrors, expectWithPolling, renderPage, withLogs } from './utils' +import { $fetchComponent } from '@nuxt/test-utils/experimental' const isWebpack = process.env.TEST_BUILDER === 'webpack' @@ -1277,3 +1278,13 @@ describe.skipIf(isWindows)('useAsyncData', () => { await expectNoClientErrors('/useAsyncData/promise-all') }) }) + +describe.runIf(isDev())('component testing', () => { + it('should work', async () => { + const comp1 = await $fetchComponent('components/SugarCounter.vue', { multiplier: 2 }) + expect(comp1).toContain('12 x 2 = 24') + + const comp2 = await $fetchComponent('components/SugarCounter.vue', { multiplier: 4 }) + expect(comp2).toContain('12 x 4 = 48') + }) +}) diff --git a/vitest.config.ts b/vitest.config.ts index 6a054ad90c..048dfb643b 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -7,6 +7,7 @@ export default defineConfig({ resolve: { alias: { '#app': resolve('./packages/nuxt/dist/app/index'), + '@nuxt/test-utils/experimental': resolve('./packages/test-utils/src/experimental.ts'), '@nuxt/test-utils': resolve('./packages/test-utils/src/index.ts') } }, From f1baa0355b56b291dab8a34d5291433e29fa1e74 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 6 Apr 2023 13:12:20 +0100 Subject: [PATCH 04/55] style: lint --- test/basic.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/basic.test.ts b/test/basic.test.ts index 35f764b437..d0c2a0d821 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -4,10 +4,10 @@ import { joinURL, withQuery } from 'ufo' import { isCI, isWindows } from 'std-env' import { normalize } from 'pathe' import { setup, fetch, $fetch, startServer, isDev, createPage, url } from '@nuxt/test-utils' +import { $fetchComponent } from '@nuxt/test-utils/experimental' import type { NuxtIslandResponse } from '../packages/nuxt/src/core/runtime/nitro/renderer' import { expectNoClientErrors, expectWithPolling, renderPage, withLogs } from './utils' -import { $fetchComponent } from '@nuxt/test-utils/experimental' const isWebpack = process.env.TEST_BUILDER === 'webpack' From 13b8536225c82ce8d68d63e312d648fa281c6bfe Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 6 Apr 2023 13:14:17 +0100 Subject: [PATCH 05/55] ci: stub project before linting --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc7bb96e26..9773ce8f5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,6 +104,9 @@ jobs: - name: Install dependencies run: pnpm install + - name: Build (stub) + run: pnpm build:stub + - name: Lint run: pnpm lint From 857e9cb3daded16186700321264a872ae60f7ad6 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 6 Apr 2023 13:15:28 +0100 Subject: [PATCH 06/55] ci: lint before stubbing --- .github/workflows/autofix.yml | 6 +++--- .github/workflows/ci.yml | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index 3c47e98c69..e57571f5ea 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -27,12 +27,12 @@ jobs: if: ${{ contains(github.ref_name, 'renovate') }} run: pnpm dedupe - - name: Build (stub) - run: pnpm build:stub - - name: Lint (code) run: pnpm lint:fix + - name: Build (stub) + run: pnpm build:stub + - name: Test (unit) run: pnpm test:unit -u diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9773ce8f5d..bc7bb96e26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,9 +104,6 @@ jobs: - name: Install dependencies run: pnpm install - - name: Build (stub) - run: pnpm build:stub - - name: Lint run: pnpm lint From b8cdef69cd7f2faa0fcdb62b52953fb72fdf86f4 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 6 Apr 2023 13:31:46 +0100 Subject: [PATCH 07/55] chore: exclude new subpath from lint reordering --- .eslintrc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.eslintrc b/.eslintrc index 9fc115a2f7..5cebc9ab20 100644 --- a/.eslintrc +++ b/.eslintrc @@ -28,6 +28,10 @@ "error", { "pathGroups": [ + { + "pattern": "@nuxt/test-utils/experimental", + "group": "external" + }, { "pattern": "@nuxt/test-utils", "group": "external" From 4d75540655476e4ee1b70d315c02e8458d4b6083 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 6 Apr 2023 13:33:07 +0100 Subject: [PATCH 08/55] fix(nuxt): add `@types/node` as a peerDependency (#20025) --- docs/2.guide/1.concepts/8.typescript.md | 2 +- docs/3.api/5.commands/typecheck.md | 2 +- packages/nuxt/package.json | 3 +++ pnpm-lock.yaml | 3 +++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/2.guide/1.concepts/8.typescript.md b/docs/2.guide/1.concepts/8.typescript.md index ffb934e1e7..a8723bc9c4 100644 --- a/docs/2.guide/1.concepts/8.typescript.md +++ b/docs/2.guide/1.concepts/8.typescript.md @@ -8,7 +8,7 @@ Nuxt 3 is fully typed and provides helpful shortcuts to ensure you have access t ## Type-checking -By default, Nuxt doesn't check types when you run `nuxi dev` or `nuxi build`, for performance reasons. However, you can enable type-checking at build or development time by installing `@types/node`, `vue-tsc` and `typescript` as devDependencies and either enabling [the `typescript.typeCheck` option in your `nuxt.config` file](/docs/api/configuration/nuxt-config#typescript) or [manually checking your types with nuxi](/docs/api/commands/typecheck). +By default, Nuxt doesn't check types when you run `nuxi dev` or `nuxi build`, for performance reasons. However, you can enable type-checking at build or development time by installing `vue-tsc` and `typescript` as devDependencies and either enabling [the `typescript.typeCheck` option in your `nuxt.config` file](/docs/api/configuration/nuxt-config#typescript) or [manually checking your types with nuxi](/docs/api/commands/typecheck). ```bash yarn nuxi typecheck diff --git a/docs/3.api/5.commands/typecheck.md b/docs/3.api/5.commands/typecheck.md index eef39ed27c..7f3c6cd7a7 100644 --- a/docs/3.api/5.commands/typecheck.md +++ b/docs/3.api/5.commands/typecheck.md @@ -18,5 +18,5 @@ Option | Default | Description This command sets `process.env.NODE_ENV` to `production`. To override, define `NODE_ENV` in a `.env` file or as a command-line argument. ::alert -You can also enable type-checking at build or development time by installing `@types/node`, `typescript` and `vue-tsc` as devDependencies and enabling [the `typescript.typeCheck` option in your `nuxt.config` file](/docs/api/configuration/nuxt-config#typescript). +You can also enable type-checking at build or development time by installing `typescript` and `vue-tsc` as devDependencies and enabling [the `typescript.typeCheck` option in your `nuxt.config` file](/docs/api/configuration/nuxt-config#typescript). :: diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 4262edf79b..f8a4b8027f 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -109,6 +109,9 @@ "@types/hash-sum": "^1.0.0", "unbuild": "latest" }, + "peerDependencies": { + "@types/node": "^14.18.0 || ^16.10.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, "engines": { "node": "^14.18.0 || ^16.10.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cdfee34c88..71620d547a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -536,6 +536,9 @@ importers: '@nuxt/vite-builder': specifier: workspace:* version: link:../vite + '@types/node': + specifier: ^14.18.0 || ^16.10.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + version: 18.15.11 '@unhead/ssr': specifier: ^1.1.25 version: 1.1.25 From 41bfd55230828cd9ea2d5ec1fe71ea6e03e12d43 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 6 Apr 2023 13:33:54 +0100 Subject: [PATCH 09/55] fix(nuxt): test all custom app config keys for `any` (#20105) --- packages/nuxt/src/core/templates.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/nuxt/src/core/templates.ts b/packages/nuxt/src/core/templates.ts index 0f75b2bc29..55e73f7669 100644 --- a/packages/nuxt/src/core/templates.ts +++ b/packages/nuxt/src/core/templates.ts @@ -224,14 +224,14 @@ type IsAny = 0 extends 1 & T ? true : false type MergedAppConfig, Custom extends Record> = { [K in keyof Resolved]: K extends keyof Custom - ? Custom[K] extends Record - ? IsAny extends true - ? Resolved[K] - : Resolved[K] extends Record + ? IsAny extends true + ? Resolved[K] + : Custom[K] extends Record + ? Resolved[K] extends Record ? MergedAppConfig : Exclude : Exclude - : Resolved[K] + : Resolved[K] } declare module 'nuxt/schema' { From b329ed7813d808b0411d233064264aff603a33ec Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 6 Apr 2023 13:55:12 +0100 Subject: [PATCH 10/55] ci: stub project before linting --- .github/workflows/autofix.yml | 6 +++--- .github/workflows/ci.yml | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml index e57571f5ea..3c47e98c69 100644 --- a/.github/workflows/autofix.yml +++ b/.github/workflows/autofix.yml @@ -27,12 +27,12 @@ jobs: if: ${{ contains(github.ref_name, 'renovate') }} run: pnpm dedupe - - name: Lint (code) - run: pnpm lint:fix - - name: Build (stub) run: pnpm build:stub + - name: Lint (code) + run: pnpm lint:fix + - name: Test (unit) run: pnpm test:unit -u diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bc7bb96e26..9773ce8f5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,6 +104,9 @@ jobs: - name: Install dependencies run: pnpm install + - name: Build (stub) + run: pnpm build:stub + - name: Lint run: pnpm lint From a02f69943f57d39a55c924818a6e43b2e2fc4eaa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Apr 2023 15:03:08 -0700 Subject: [PATCH 11/55] chore(deps): update dependency memfs to ^3.5.0 (main) (#20116) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- packages/webpack/package.json | 2 +- pnpm-lock.yaml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/webpack/package.json b/packages/webpack/package.json index 426888f4fc..da355257a9 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -35,7 +35,7 @@ "hash-sum": "^2.0.0", "lodash-es": "^4.17.21", "magic-string": "^0.30.0", - "memfs": "^3.4.13", + "memfs": "^3.5.0", "mini-css-extract-plugin": "^2.7.5", "mlly": "^1.2.0", "ohash": "^1.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 71620d547a..bafd147a20 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -943,8 +943,8 @@ importers: specifier: ^0.30.0 version: 0.30.0 memfs: - specifier: ^3.4.13 - version: 3.4.13 + specifier: ^3.5.0 + version: 3.5.0 mini-css-extract-plugin: specifier: ^2.7.5 version: 2.7.5(webpack@5.78.0) @@ -5535,7 +5535,7 @@ packages: cosmiconfig: 7.1.0 deepmerge: 4.3.0 fs-extra: 10.1.0 - memfs: 3.4.13 + memfs: 3.5.0 minimatch: 3.1.2 node-abort-controller: 3.1.1 schema-utils: 3.1.1 @@ -6702,8 +6702,8 @@ packages: engines: {node: '>= 0.6'} dev: true - /memfs@3.4.13: - resolution: {integrity: sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg==} + /memfs@3.5.0: + resolution: {integrity: sha512-yK6o8xVJlQerz57kvPROwTMgx5WtGwC2ZxDtOUsnGl49rHjYkfQoPNZPCKH73VdLE1BwBu/+Fx/NL8NYMUw2aA==} engines: {node: '>= 4.0.0'} dependencies: fs-monkey: 1.0.3 @@ -9512,7 +9512,7 @@ packages: optional: true dependencies: colorette: 2.0.19 - memfs: 3.4.13 + memfs: 3.5.0 mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.0.0 From b068f79fee9e71ab322658d08ee60a685ac48dec Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Fri, 7 Apr 2023 10:31:04 +0200 Subject: [PATCH 12/55] fix(nuxt): add key to `.client` component placeholders (#20093) --- packages/nuxt/src/app/components/client-only.mjs | 6 +++--- test/basic.test.ts | 4 ++++ .../basic/components/client/SetupScript.client.vue | 8 +++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/nuxt/src/app/components/client-only.mjs b/packages/nuxt/src/app/components/client-only.mjs index 5bc55149a5..10df63239d 100644 --- a/packages/nuxt/src/app/components/client-only.mjs +++ b/packages/nuxt/src/app/components/client-only.mjs @@ -1,4 +1,4 @@ -import { ref, onMounted, defineComponent, createElementBlock, h, createElementVNode } from 'vue' +import { mergeProps, ref, onMounted, defineComponent, createElementBlock, h, createElementVNode } from 'vue' export default defineComponent({ name: 'ClientOnly', @@ -37,7 +37,7 @@ export function createClientOnly (component) { ? createElementVNode(res.type, res.props, res.children, res.patchFlag, res.dynamicProps, res.shapeFlag) : h(res) } else { - return h('div', ctx.$attrs ?? ctx._.attrs) + return h('div', mergeProps(ctx.$attrs ?? ctx._.attrs, { key: 'placeholder-key' })) } } } else if (clone.template) { @@ -63,7 +63,7 @@ export function createClientOnly (component) { ? createElementVNode(res.type, res.props, res.children, res.patchFlag, res.dynamicProps, res.shapeFlag) : h(res) } else { - return h('div', ctx.attrs) + return h('div', mergeProps(ctx.attrs, { key: 'placeholder-key' })) } } }) diff --git a/test/basic.test.ts b/test/basic.test.ts index d0c2a0d821..15ae710a0e 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -229,6 +229,7 @@ describe('pages', () => { '.client-only-script-setup', '.no-state' ] + // ensure directives are correctly applied await Promise.all(hiddenSelectors.map(selector => page.locator(selector).isHidden())) .then(results => results.forEach(isHidden => expect(isHidden).toBeTruthy())) @@ -240,6 +241,9 @@ describe('pages', () => { await Promise.all(visibleSelectors.map(selector => page.locator(selector).innerHTML())) .then(results => results.forEach(innerHTML => expect(innerHTML).not.toBe(''))) + // issue #20061 + expect(await page.$eval('.client-only-script-setup', e => getComputedStyle(e).backgroundColor)).toBe('rgb(255, 0, 0)') + // ensure multi-root-node is correctly rendered expect(await page.locator('.multi-root-node-count').innerHTML()).toContain('0') expect(await page.locator('.multi-root-node-button').innerHTML()).toContain('add 1 to count') diff --git a/test/fixtures/basic/components/client/SetupScript.client.vue b/test/fixtures/basic/components/client/SetupScript.client.vue index becd6eb01e..3844c38b8b 100644 --- a/test/fixtures/basic/components/client/SetupScript.client.vue +++ b/test/fixtures/basic/components/client/SetupScript.client.vue @@ -7,7 +7,7 @@ defineExpose({ add }) + + From 4f0b3c7223d919c28da57e917b453f07d0873c81 Mon Sep 17 00:00:00 2001 From: cany748 <123sasha2@mail.ru> Date: Fri, 7 Apr 2023 15:45:44 +0700 Subject: [PATCH 13/55] fix(nuxt): add `undefined` type for `useCookie` return value --- packages/nuxt/src/app/composables/cookie.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nuxt/src/app/composables/cookie.ts b/packages/nuxt/src/app/composables/cookie.ts index 10454caec8..b92a8903bf 100644 --- a/packages/nuxt/src/app/composables/cookie.ts +++ b/packages/nuxt/src/app/composables/cookie.ts @@ -27,7 +27,7 @@ const CookieDefaults: CookieOptions = { encode: val => encodeURIComponent(typeof val === 'string' ? val : JSON.stringify(val)) } -export function useCookie (name: string, _opts?: CookieOptions): CookieRef { +export function useCookie (name: string, _opts?: CookieOptions): CookieRef { const opts = { ...CookieDefaults, ..._opts } const cookies = readRawCookies(opts) || {} From d4f718d8cd913bcddb3645884d7f27f1104baeee Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 7 Apr 2023 11:05:09 +0100 Subject: [PATCH 14/55] refactor(schema): clean up `experimental` options (#20112) --- packages/schema/src/config/experimental.ts | 26 ++-------------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/packages/schema/src/config/experimental.ts b/packages/schema/src/config/experimental.ts index 0817b672a1..617f943c25 100644 --- a/packages/schema/src/config/experimental.ts +++ b/packages/schema/src/config/experimental.ts @@ -15,6 +15,8 @@ export default defineUntypedSchema({ */ reactivityTransform: false, + // TODO: Remove in v3.5 when nitro has support for mocking traced dependencies + // https://github.com/unjs/nitro/issues/1118 /** * Externalize `vue`, `@vue/*` and `vue-router` when building. * @see https://github.com/nuxt/nuxt/issues/13632 @@ -73,30 +75,6 @@ export default defineUntypedSchema({ */ restoreState: false, - /** - * Use vite-node for on-demand server chunk loading - * - * @deprecated use `vite.devBundler: 'vite-node'` - */ - viteNode: { - $resolve: (val) => { - val = process.env.EXPERIMENTAL_VITE_NODE ? true : val - if (val === true) { - console.warn('`vite-node` is now enabled by default. You can safely remove `experimental.viteNode` from your config.') - } else if (val === false) { - console.warn('`vite-node` is now enabled by default. To disable it, set `vite.devBundler` to `legacy` instead.') - } - return val ?? true - } - }, - - /** - * Split server bundle into multiple chunks and dynamically import them. - * - * @see https://github.com/nuxt/nuxt/issues/14525 - */ - viteServerDynamicImports: true, - /** * Inline styles when rendering HTML (currently vite only). * From 9e503be0f2a24f4df72a3ccab2db4d3e63511f57 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Fri, 7 Apr 2023 12:34:35 +0200 Subject: [PATCH 15/55] feat(nuxt): experimental option for rich json payloads (#19205) Co-authored-by: Daniel Roe --- docs/3.api/1.composables/use-nuxt-app.md | 22 +++++- packages/nuxt/package.json | 1 + .../nuxt/src/app/composables/asyncData.ts | 2 +- packages/nuxt/src/app/composables/index.ts | 2 +- packages/nuxt/src/app/composables/payload.ts | 78 ++++++++++++++++++- packages/nuxt/src/app/entry.ts | 5 +- packages/nuxt/src/app/nuxt.ts | 29 ++++--- .../src/app/plugins/revive-payload.client.ts | 23 ++++++ .../src/app/plugins/revive-payload.server.ts | 21 +++++ packages/nuxt/src/core/nitro.ts | 1 + packages/nuxt/src/core/nuxt.ts | 7 ++ .../nuxt/src/core/runtime/nitro/renderer.ts | 48 ++++++++++-- packages/nuxt/src/core/templates.ts | 1 + packages/nuxt/src/imports/presets.ts | 4 +- packages/schema/src/config/build.ts | 2 + packages/schema/src/config/experimental.ts | 4 + pnpm-lock.yaml | 7 ++ test/basic.test.ts | 58 +++++++++++--- test/bundle.test.ts | 5 +- test/fixtures/basic/nuxt.config.ts | 7 ++ test/fixtures/basic/pages/json-payload.vue | 26 +++++++ .../plugins/custom-type-assertion.client.ts | 7 ++ .../basic/plugins/custom-type-registration.ts | 7 ++ test/utils.ts | 29 +++++++ 24 files changed, 355 insertions(+), 41 deletions(-) create mode 100644 packages/nuxt/src/app/plugins/revive-payload.client.ts create mode 100644 packages/nuxt/src/app/plugins/revive-payload.server.ts create mode 100644 test/fixtures/basic/pages/json-payload.vue create mode 100644 test/fixtures/basic/plugins/custom-type-assertion.client.ts create mode 100644 test/fixtures/basic/plugins/custom-type-registration.ts diff --git a/docs/3.api/1.composables/use-nuxt-app.md b/docs/3.api/1.composables/use-nuxt-app.md index e986656d06..d962cca4d0 100644 --- a/docs/3.api/1.composables/use-nuxt-app.md +++ b/docs/3.api/1.composables/use-nuxt-app.md @@ -84,9 +84,7 @@ await nuxtApp.callHook('my-plugin:init') ### `payload` -`payload` exposes data and state variables from server side to client side and makes them available in the `window.__NUXT__` object that is accessible from the browser. - -`payload` exposes the following keys on the client side after they are stringified and passed from the server side: +`payload` exposes data and state variables from server side to client side. The following keys will be available on the client after they have been passed from the server side: - **serverRendered** (boolean) - Indicates if response is server-side-rendered. - **data** (object) - When you fetch the data from an API endpoint using either `useFetch` or `useAsyncData`, resulting payload can be accessed from the `payload.data`. This data is cached and helps you prevent fetching the same data in case an identical request is made more than once. @@ -115,6 +113,24 @@ export default defineNuxtPlugin((nuxtApp) => { }) ``` +::alert +Normally `payload` must contain only plain JavaScript objects. But by setting `experimental.renderJsonPayloads`, it is possible to use more advanced types, such as `ref`, `reactive`, `shallowRef`, `shallowReactive` and `NuxtError`. + +You can also add your own types. In future you will be able to add your own types easily with [object-syntax plugins](https://github.com/nuxt/nuxt/issues/14628). For now, you must add your plugin which calls both `definePayloadReducer` and `definePayloadReviver` via a custom module: + +```ts +export default defineNuxtConfig({ + modules: [ + function (_options, nuxt) { + // TODO: support directly via object syntax plugins: https://github.com/nuxt/nuxt/issues/14628 + nuxt.hook('modules:done', () => { + nuxt.options.plugins.unshift('~/plugins/custom-type-plugin') + }) + }, + ] +}) +:: + ### `isHydrating` Use `nuxtApp.isHydrating` (boolean) to check if the Nuxt app is hydrating on the client side. diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index f8a4b8027f..7b00c02c43 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -74,6 +74,7 @@ "cookie-es": "^0.5.0", "defu": "^6.1.2", "destr": "^1.2.2", + "devalue": "^4.3.0", "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "fs-extra": "^11.1.1", diff --git a/packages/nuxt/src/app/composables/asyncData.ts b/packages/nuxt/src/app/composables/asyncData.ts index f9e33480cb..d2791772d5 100644 --- a/packages/nuxt/src/app/composables/asyncData.ts +++ b/packages/nuxt/src/app/composables/asyncData.ts @@ -118,7 +118,7 @@ export function useAsyncData< nuxt._asyncData[key] = { data: ref(getCachedData() ?? options.default?.() ?? null), pending: ref(!hasCachedData()), - error: ref(nuxt.payload._errors[key] ? createError(nuxt.payload._errors[key]) : null) + error: toRef(nuxt.payload._errors, key) } } // TODO: Else, somehow check for conflicting keys with different defaults or fetcher diff --git a/packages/nuxt/src/app/composables/index.ts b/packages/nuxt/src/app/composables/index.ts index 845894679e..e40cb76ce6 100644 --- a/packages/nuxt/src/app/composables/index.ts +++ b/packages/nuxt/src/app/composables/index.ts @@ -28,6 +28,6 @@ export { onNuxtReady } from './ready' export { abortNavigation, addRouteMiddleware, defineNuxtRouteMiddleware, onBeforeRouteLeave, onBeforeRouteUpdate, setPageLayout, navigateTo, useRoute, useRouter } from './router' export type { AddRouteMiddlewareOptions, RouteMiddleware } from './router' export { preloadComponents, prefetchComponents, preloadRouteComponents } from './preload' -export { isPrerendered, loadPayload, preloadPayload } from './payload' +export { isPrerendered, loadPayload, preloadPayload, definePayloadReducer, definePayloadReviver } from './payload' export type { ReloadNuxtAppOptions } from './chunk' export { reloadNuxtApp } from './chunk' diff --git a/packages/nuxt/src/app/composables/payload.ts b/packages/nuxt/src/app/composables/payload.ts index 3ceef7a0eb..f7f8249c32 100644 --- a/packages/nuxt/src/app/composables/payload.ts +++ b/packages/nuxt/src/app/composables/payload.ts @@ -1,7 +1,12 @@ import { joinURL, hasProtocol } from 'ufo' +import { parse } from 'devalue' import { useHead } from '@unhead/vue' +import { getCurrentInstance } from 'vue' import { useNuxtApp, useRuntimeConfig } from '../nuxt' +// @ts-expect-error virtual import +import { renderJsonPayloads } from '#build/nuxt.config.mjs' + interface LoadPayloadOptions { fresh?: boolean hash?: string @@ -36,6 +41,7 @@ export function preloadPayload (url: string, opts: LoadPayloadOptions = {}) { // --- Internal --- +const extension = renderJsonPayloads ? 'json' : 'js' function _getPayloadURL (url: string, opts: LoadPayloadOptions = {}) { const u = new URL(url, 'http://localhost') if (u.search) { @@ -45,15 +51,19 @@ function _getPayloadURL (url: string, opts: LoadPayloadOptions = {}) { throw new Error('Payload URL must not include hostname: ' + url) } const hash = opts.hash || (opts.fresh ? Date.now() : '') - return joinURL(useRuntimeConfig().app.baseURL, u.pathname, hash ? `_payload.${hash}.js` : '_payload.js') + return joinURL(useRuntimeConfig().app.baseURL, u.pathname, hash ? `_payload.${hash}.${extension}` : `_payload.${extension}`) } async function _importPayload (payloadURL: string) { if (process.server) { return null } - const res = await import(/* webpackIgnore: true */ /* @vite-ignore */ payloadURL).catch((err) => { + try { + return renderJsonPayloads + ? parsePayload(await fetch(payloadURL).then(res => res.text())) + : await import(/* webpackIgnore: true */ /* @vite-ignore */ payloadURL).then(r => r.default || r) + } catch (err) { console.warn('[nuxt] Cannot load payload ', payloadURL, err) - }) - return res?.default || null + } + return null } export function isPrerendered () { @@ -61,3 +71,63 @@ export function isPrerendered () { const nuxtApp = useNuxtApp() return !!nuxtApp.payload.prerenderedAt } + +let payloadCache: any = null +export async function getNuxtClientPayload () { + if (process.server) { + return + } + if (payloadCache) { + return payloadCache + } + + const el = document.getElementById('__NUXT_DATA__') + if (!el) { + return {} + } + + const inlineData = parsePayload(el.textContent || '') + + const externalData = el.dataset.src ? await _importPayload(el.dataset.src) : undefined + + payloadCache = { + ...inlineData, + ...externalData, + ...window.__NUXT__ + } + + return payloadCache +} + +export function parsePayload (payload: string) { + return parse(payload, useNuxtApp()._payloadRevivers) +} + +/** + * This is an experimental function for configuring passing rich data from server -> client. + */ +export function definePayloadReducer ( + name: string, + reduce: (data: any) => any +) { + if (process.server) { + useNuxtApp().ssrContext!._payloadReducers[name] = reduce + } +} + +/** + * This is an experimental function for configuring passing rich data from server -> client. + * + * This function _must_ be called in a Nuxt plugin that is `unshift`ed to the beginning of the Nuxt plugins array. + */ +export function definePayloadReviver ( + name: string, + revive: (data: string) => any | undefined +) { + if (process.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.') + } + if (process.client) { + useNuxtApp()._payloadRevivers[name] = revive + } +} diff --git a/packages/nuxt/src/app/entry.ts b/packages/nuxt/src/app/entry.ts index 4424ae4a4d..9d09fd7ddf 100644 --- a/packages/nuxt/src/app/entry.ts +++ b/packages/nuxt/src/app/entry.ts @@ -52,7 +52,10 @@ if (process.client) { } entry = async function initApp () { - const isSSR = Boolean(window.__NUXT__?.serverRendered) + const isSSR = Boolean( + window.__NUXT__?.serverRendered || + document.getElementById('__NUXT_DATA__')?.dataset.ssr === 'true' + ) const vueApp = isSSR ? createSSRApp(RootComponent) : createApp(RootComponent) const nuxt = createNuxtApp({ vueApp }) diff --git a/packages/nuxt/src/app/nuxt.ts b/packages/nuxt/src/app/nuxt.ts index 05d89f8269..62779112d1 100644 --- a/packages/nuxt/src/app/nuxt.ts +++ b/packages/nuxt/src/app/nuxt.ts @@ -1,5 +1,5 @@ /* eslint-disable no-use-before-define */ -import { getCurrentInstance, reactive } from 'vue' +import { getCurrentInstance, shallowReactive, reactive } from 'vue' import type { App, onErrorCaptured, VNode, Ref } from 'vue' import type { RouteLocationNormalizedLoaded } from 'vue-router' import type { Hookable, HookCallback } from 'hookable' @@ -12,6 +12,7 @@ import type { RuntimeConfig, AppConfigInput, AppConfig } from 'nuxt/schema' // eslint-disable-next-line import/no-restricted-paths import type { NuxtIslandContext } from '../core/runtime/nitro/renderer' import type { RouteMiddleware } from '../../app' +import type { NuxtError } from '../app/composables/error' const nuxtAppCtx = /* #__PURE__ */ getContext('nuxt-app') @@ -58,6 +59,8 @@ export interface NuxtSSRContext extends SSRContext { teleports?: Record renderMeta?: () => Promise | NuxtMeta islandContext?: NuxtIslandContext + /** @internal */ + _payloadReducers: Record any> } interface _NuxtApp { @@ -99,6 +102,9 @@ interface _NuxtApp { /** @internal */ _islandPromises?: Record> + /** @internal */ + _payloadRevivers: Record any> + // Nuxt injections $config: RuntimeConfig @@ -111,7 +117,6 @@ interface _NuxtApp { prerenderedAt?: number data: Record state: Record - rendered?: Function error?: Error | { url: string statusCode: number @@ -120,6 +125,7 @@ interface _NuxtApp { description: string data?: any } | null + _errors: Record [key: string]: any } static: { @@ -152,11 +158,11 @@ export function createNuxtApp (options: CreateOptions) { get nuxt () { return __NUXT_VERSION__ }, get vue () { return nuxtApp.vueApp.version } }, - payload: reactive({ - data: {}, - state: {}, - _errors: {}, - ...(process.client ? window.__NUXT__ : { serverRendered: true }) + payload: shallowReactive({ + data: shallowReactive({}), + state: shallowReactive({}), + _errors: shallowReactive({}), + ...(process.client ? window.__NUXT__ ?? {} : { serverRendered: true }) }), static: { data: {} @@ -182,6 +188,7 @@ export function createNuxtApp (options: CreateOptions) { }, _asyncDataPromises: {}, _asyncData: {}, + _payloadRevivers: {}, ...options } as any as NuxtApp @@ -217,7 +224,11 @@ export function createNuxtApp (options: CreateOptions) { if (nuxtApp.ssrContext) { nuxtApp.ssrContext.nuxt = nuxtApp } - // Expose to server renderer to create window.__NUXT__ + // Expose payload types + if (nuxtApp.ssrContext) { + nuxtApp.ssrContext._payloadReducers = {} + } + // Expose to server renderer to create payload nuxtApp.ssrContext = nuxtApp.ssrContext || {} as any if (nuxtApp.ssrContext!.payload) { Object.assign(nuxtApp.payload, nuxtApp.ssrContext!.payload) @@ -225,7 +236,7 @@ export function createNuxtApp (options: CreateOptions) { nuxtApp.ssrContext!.payload = nuxtApp.payload // Expose client runtime-config to the payload - nuxtApp.payload.config = { + nuxtApp.ssrContext!.config = { public: options.ssrContext!.runtimeConfig.public, app: options.ssrContext!.runtimeConfig.app } diff --git a/packages/nuxt/src/app/plugins/revive-payload.client.ts b/packages/nuxt/src/app/plugins/revive-payload.client.ts new file mode 100644 index 0000000000..53c2f73fe5 --- /dev/null +++ b/packages/nuxt/src/app/plugins/revive-payload.client.ts @@ -0,0 +1,23 @@ +import { reactive, ref, shallowRef, shallowReactive } from 'vue' +import { definePayloadReviver, getNuxtClientPayload } from '#app/composables/payload' +import { createError } from '#app/composables/error' +import { callWithNuxt, defineNuxtPlugin } from '#app/nuxt' + +const revivers = { + NuxtError: (data: any) => createError(data), + EmptyShallowRef: (data: any) => shallowRef(JSON.parse(data)), + EmptyRef: (data: any) => ref(JSON.parse(data)), + ShallowRef: (data: any) => shallowRef(data), + ShallowReactive: (data: any) => shallowReactive(data), + Ref: (data: any) => ref(data), + Reactive: (data: any) => reactive(data) +} + +export default defineNuxtPlugin(async (nuxtApp) => { + for (const reviver in revivers) { + definePayloadReviver(reviver, revivers[reviver as keyof typeof revivers]) + } + Object.assign(nuxtApp.payload, await callWithNuxt(nuxtApp, getNuxtClientPayload, [])) + // For backwards compatibility - TODO: remove later + window.__NUXT__ = nuxtApp.payload +}) diff --git a/packages/nuxt/src/app/plugins/revive-payload.server.ts b/packages/nuxt/src/app/plugins/revive-payload.server.ts new file mode 100644 index 0000000000..5573d8ab04 --- /dev/null +++ b/packages/nuxt/src/app/plugins/revive-payload.server.ts @@ -0,0 +1,21 @@ +import { isShallow, isRef, isReactive, toRaw } from 'vue' +import { definePayloadReducer } from '#app/composables/payload' +import { isNuxtError } from '#app/composables/error' +import { defineNuxtPlugin } from '#app/nuxt' +/* Defining a plugin that will be used by the Nuxt framework. */ + +const reducers = { + NuxtError: (data: any) => isNuxtError(data) && data.toJSON(), + EmptyShallowRef: (data: any) => isRef(data) && isShallow(data) && !data.value && JSON.stringify(data.value), + EmptyRef: (data: any) => isRef(data) && !data.value && JSON.stringify(data.value), + ShallowRef: (data: any) => isRef(data) && isShallow(data) && data.value, + ShallowReactive: (data: any) => isReactive(data) && isShallow(data) && toRaw(data), + Ref: (data: any) => isRef(data) && data.value, + Reactive: (data: any) => isReactive(data) && toRaw(data) +} + +export default defineNuxtPlugin(() => { + for (const reducer in reducers) { + definePayloadReducer(reducer, reducers[reducer as keyof typeof reducers]) + } +}) diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index 684ff3758e..9b2526e078 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -172,6 +172,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { 'process.env.NUXT_NO_SCRIPTS': !!nuxt.options.experimental.noScripts && !nuxt.options.dev, 'process.env.NUXT_INLINE_STYLES': !!nuxt.options.experimental.inlineSSRStyles, 'process.env.NUXT_PAYLOAD_EXTRACTION': !!nuxt.options.experimental.payloadExtraction, + 'process.env.NUXT_JSON_PAYLOADS': !!nuxt.options.experimental.renderJsonPayloads, 'process.env.NUXT_COMPONENT_ISLANDS': !!nuxt.options.experimental.componentIslands, 'process.dev': nuxt.options.dev, __VUE_PROD_DEVTOOLS__: false diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index f820fd1f1a..6d533a1a8e 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -281,6 +281,13 @@ async function initNuxt (nuxt: Nuxt) { addPlugin(resolve(nuxt.options.appDir, 'plugins/restore-state.client')) } + if (nuxt.options.experimental.renderJsonPayloads) { + nuxt.hook('modules:done', () => { + nuxt.options.plugins.unshift(resolve(nuxt.options.appDir, 'plugins/revive-payload.client')) + nuxt.options.plugins.unshift(resolve(nuxt.options.appDir, 'plugins/revive-payload.server')) + }) + } + // Track components used to render for webpack if (nuxt.options.builder === '@nuxt/webpack-builder') { addPlugin(resolve(nuxt.options.appDir, 'plugins/preload.server')) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index 9336bdfa5a..cfab7c4924 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -4,6 +4,7 @@ import type { Manifest } from 'vite' import type { H3Event } from 'h3' import { appendHeader, getQuery, writeEarlyHints, readBody, createError } from 'h3' import devalue from '@nuxt/devalue' +import { stringify, uneval } from 'devalue' import destr from 'destr' import { joinURL, withoutTrailingSlash } from 'ufo' import { renderToString as _renderToString } from 'vue/server-renderer' @@ -121,6 +122,7 @@ const getSPARenderer = lazyCachedFunction(async () => { const renderToString = (ssrContext: NuxtSSRContext) => { const config = useRuntimeConfig() ssrContext!.payload = { + _errors: {}, serverRendered: false, config: { public: config.public, @@ -160,7 +162,7 @@ async function getIslandContext (event: H3Event): Promise { const PAYLOAD_CACHE = (process.env.NUXT_PAYLOAD_EXTRACTION && process.env.prerender) ? new Map() : null // TODO: Use LRU cache const ISLAND_CACHE = (process.env.NUXT_COMPONENT_ISLANDS && process.env.prerender) ? new Map() : null // TODO: Use LRU cache -const PAYLOAD_URL_RE = /\/_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]*)$`) const PRERENDER_NO_SSR_ROUTES = new Set(['/index.html', '/200.html', '/404.html']) @@ -219,12 +221,13 @@ export default defineRenderHandler(async (event) => { error: !!ssrError, nuxt: undefined!, /* NuxtApp */ payload: (ssrError ? { error: ssrError } : {}) as NuxtSSRContext['payload'], + _payloadReducers: {}, islandContext } // Whether we are prerendering route const _PAYLOAD_EXTRACTION = process.env.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !ssrContext.noSSR - const payloadURL = _PAYLOAD_EXTRACTION ? joinURL(useRuntimeConfig().app.baseURL, url, '_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) { ssrContext.payload.prerenderedAt = Date.now() } @@ -260,7 +263,7 @@ export default defineRenderHandler(async (event) => { if (_PAYLOAD_EXTRACTION) { // Hint nitro to prerender payload for this route - appendHeader(event, 'x-nitro-prerender', joinURL(url, '_payload.js')) + appendHeader(event, 'x-nitro-prerender', joinURL(url, process.env.NUXT_JSON_PAYLOADS ? '_payload.json' : '_payload.js')) // Use same ssr context to generate payload for this route PAYLOAD_CACHE!.set(withoutTrailingSlash(url), renderPayloadResponse(ssrContext)) } @@ -279,7 +282,9 @@ export default defineRenderHandler(async (event) => { htmlAttrs: normalizeChunks([renderedMeta.htmlAttrs]), head: normalizeChunks([ renderedMeta.headTags, - _PAYLOAD_EXTRACTION ? `` : null, + process.env.NUXT_JSON_PAYLOADS + ? _PAYLOAD_EXTRACTION ? `` : null + : _PAYLOAD_EXTRACTION ? `` : null, _rendered.renderResourceHints(), _rendered.renderStyles(), inlinedStyles, @@ -295,8 +300,12 @@ export default defineRenderHandler(async (event) => { process.env.NUXT_NO_SCRIPTS ? undefined : (_PAYLOAD_EXTRACTION - ? `` - : `` + ? process.env.NUXT_JSON_PAYLOADS + ? renderPayloadJsonScript({ id: '__NUXT_DATA__', ssrContext, data: splitPayload(ssrContext).initial, src: payloadURL }) + : renderPayloadScript({ ssrContext, data: splitPayload(ssrContext).initial, src: payloadURL }) + : process.env.NUXT_JSON_PAYLOADS + ? renderPayloadJsonScript({ id: '__NUXT_DATA__', ssrContext, data: ssrContext.payload }) + : renderPayloadScript({ ssrContext, data: ssrContext.payload }) ), _rendered.renderScripts(), // Note: bodyScripts may contain tags other than ` + + `` +} + +function renderPayloadScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }) { + opts.data.config = opts.ssrContext.config + const _PAYLOAD_EXTRACTION = process.env.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !opts.ssrContext.noSSR + if (_PAYLOAD_EXTRACTION) { + return `` + } + return `` +} + function splitPayload (ssrContext: NuxtSSRContext) { const { data, prerenderedAt, ...initial } = ssrContext.payload return { diff --git a/packages/nuxt/src/core/templates.ts b/packages/nuxt/src/core/templates.ts index 55e73f7669..e77d7094e3 100644 --- a/packages/nuxt/src/core/templates.ts +++ b/packages/nuxt/src/core/templates.ts @@ -296,6 +296,7 @@ export const nuxtConfigTemplate = { getContents: (ctx: TemplateContext) => { return [ ...Object.entries(ctx.nuxt.options.app).map(([k, v]) => `export const ${camelCase('app-' + k)} = ${JSON.stringify(v)}`), + `export const renderJsonPayloads = ${!!ctx.nuxt.options.experimental.renderJsonPayloads}`, `export const devPagesDir = ${ctx.nuxt.options.dev ? JSON.stringify(ctx.nuxt.options.dir.pages) : 'null'}` ].join('\n\n') } diff --git a/packages/nuxt/src/imports/presets.ts b/packages/nuxt/src/imports/presets.ts index 5479c26a14..c8fb0c7368 100644 --- a/packages/nuxt/src/imports/presets.ts +++ b/packages/nuxt/src/imports/presets.ts @@ -55,7 +55,9 @@ const appPreset = defineUnimportPreset({ 'prefetchComponents', 'loadPayload', 'preloadPayload', - 'isPrerendered' + 'isPrerendered', + 'definePayloadReducer', + 'definePayloadReviver' ] }) diff --git a/packages/schema/src/config/build.ts b/packages/schema/src/config/build.ts index 8d68e361bf..e4f74a60da 100644 --- a/packages/schema/src/config/build.ts +++ b/packages/schema/src/config/build.ts @@ -170,6 +170,7 @@ export default defineUntypedSchema({ $resolve: async (val, get) => defu(val || {}, await get('dev') ? {} : { vue: ['onBeforeMount', 'onMounted', 'onBeforeUpdate', 'onRenderTracked', 'onRenderTriggered', 'onActivated', 'onDeactivated', 'onBeforeUnmount'], + '#app': ['definePayloadReviver'] } ) }, @@ -177,6 +178,7 @@ export default defineUntypedSchema({ $resolve: async (val, get) => defu(val || {}, await get('dev') ? {} : { vue: ['onServerPrefetch', 'onRenderTracked', 'onRenderTriggered'], + '#app': ['definePayloadReducer'] } ) } diff --git a/packages/schema/src/config/experimental.ts b/packages/schema/src/config/experimental.ts index 617f943c25..858f8d54e1 100644 --- a/packages/schema/src/config/experimental.ts +++ b/packages/schema/src/config/experimental.ts @@ -98,6 +98,10 @@ export default defineUntypedSchema({ */ noScripts: false, + // TODO: enable by default in v3.5 + /** Render JSON payloads with support for revivifying complex types. */ + renderJsonPayloads: false, + /** * Disable vue server renderer endpoint within nitro. */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bafd147a20..d64cd22397 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -563,6 +563,9 @@ importers: destr: specifier: ^1.2.2 version: 1.2.2 + devalue: + specifier: ^4.3.0 + version: 4.3.0 escape-string-regexp: specifier: ^5.0.0 version: 5.0.0 @@ -4419,6 +4422,10 @@ packages: resolution: {integrity: sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==} engines: {node: '>=8'} + /devalue@4.3.0: + resolution: {integrity: sha512-n94yQo4LI3w7erwf84mhRUkUJfhLoCZiLyoOZ/QFsDbcWNZePrLwbQpvZBUG2TNxwV3VjCKPxkiiQA6pe3TrTA==} + dev: false + /diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} diff --git a/test/basic.test.ts b/test/basic.test.ts index 15ae710a0e..ed58421013 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -7,7 +7,7 @@ import { setup, fetch, $fetch, startServer, isDev, createPage, url } from '@nuxt import { $fetchComponent } from '@nuxt/test-utils/experimental' import type { NuxtIslandResponse } from '../packages/nuxt/src/core/runtime/nitro/renderer' -import { expectNoClientErrors, expectWithPolling, renderPage, withLogs } from './utils' +import { expectNoClientErrors, expectWithPolling, parseData, parsePayload, renderPage, withLogs } from './utils' const isWebpack = process.env.TEST_BUILDER === 'webpack' @@ -43,7 +43,9 @@ describe('server api', () => { describe('route rules', () => { it('should enable spa mode', async () => { - expect(await $fetch('/route-rules/spa')).toContain('serverRendered:false') + const { script, attrs } = parseData(await $fetch('/route-rules/spa')) + expect(script.serverRendered).toEqual(false) + expect(attrs['data-ssr']).toEqual('false') }) }) @@ -324,6 +326,23 @@ describe('pages', () => { }) }) +describe('rich payloads', () => { + it('correctly serializes and revivifies complex types', async () => { + const html = await $fetch('/json-payload') + for (const test of [ + 'Date: true', + 'Recursive objects: true', + 'Shallow reactive: true', + 'Shallow ref: true', + 'Reactive: true', + 'Ref: true', + 'Error: true' + ]) { + expect(html).toContain(test) + } + }) +}) + describe('nuxt links', () => { it('handles trailing slashes', async () => { const html = await $fetch('/nuxt-link/trailing-slash') @@ -467,7 +486,8 @@ describe('legacy async data', () => { it('should work with defineNuxtComponent', async () => { const html = await $fetch('/legacy/async-data') expect(html).toContain('
Hello API
') - expect(html).toContain('{hello:"Hello API"}') + const { script } = parseData(html) + expect(script.data['options:asyncdata:/legacy/async-data'].hello).toEqual('Hello API') }) }) @@ -1205,10 +1225,28 @@ describe.runIf(isDev() && !isWebpack)('vite plugins', () => { describe.skipIf(isDev() || isWindows)('payload rendering', () => { it('renders a payload', async () => { - const payload = await $fetch('/random/a/_payload.js', { responseType: 'text' }) - expect(payload).toMatch( - /export default \{data:\{hey:\{[^}]*\},rand_a:\[[^\]]*\],".*":\{html:".*server-only component.*",head:\{link:\[\],style:\[\]\}\}\},prerenderedAt:\d*\}/ - ) + const payload = await $fetch('/random/a/_payload.json', { responseType: 'text' }) + const data = parsePayload(payload) + expect(typeof data.prerenderedAt).toEqual('number') + + const [_key, serverData] = Object.entries(data.data).find(([key]) => key.startsWith('ServerOnlyComponent'))! + expect(serverData).toMatchInlineSnapshot(` + { + "head": { + "link": [], + "style": [], + }, + "html": "
server-only component
", + } + `) + + expect(data.data).toMatchObject({ + hey: { + baz: 'qux', + foo: 'bar' + }, + rand_a: expect.arrayContaining([expect.anything()]) + }) }) it('does not fetch a prefetched payload', async () => { @@ -1222,10 +1260,8 @@ describe.skipIf(isDev() || isWindows)('payload rendering', () => { await page.goto(url('/random/a')) await page.waitForLoadState('networkidle') - const importSuffix = isDev() && !isWebpack ? '?import' : '' - // We are manually prefetching other payloads - expect(requests).toContain('/random/c/_payload.js') + expect(requests).toContain('/random/c/_payload.json') // We are not triggering API requests in the payload expect(requests).not.toContain(expect.stringContaining('/api/random')) @@ -1240,7 +1276,7 @@ describe.skipIf(isDev() || isWindows)('payload rendering', () => { expect(requests).not.toContain(expect.stringContaining('/__nuxt_island')) // We are fetching a payload we did not prefetch - expect(requests).toContain('/random/b/_payload.js' + importSuffix) + expect(requests).toContain('/random/b/_payload.json') // We are not refetching payloads we've already prefetched // expect(requests.filter(p => p.includes('_payload')).length).toBe(1) diff --git a/test/bundle.test.ts b/test/bundle.test.ts index e29efc0ab7..9098877aaa 100644 --- a/test/bundle.test.ts +++ b/test/bundle.test.ts @@ -40,10 +40,10 @@ describe.skipIf(isWindows || process.env.ECOSYSTEM_CI)('minimal nuxt application it('default server bundle size', async () => { stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir) - expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"91k"') + expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"92k"') const modules = await analyzeSizes('node_modules/**/*', serverDir) - expect(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2632k"') + expect(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2648k"') const packages = modules.files .filter(m => m.endsWith('package.json')) @@ -66,6 +66,7 @@ describe.skipIf(isWindows || process.env.ECOSYSTEM_CI)('minimal nuxt application "cookie-es", "defu", "destr", + "devalue", "estree-walker", "h3", "hookable", diff --git a/test/fixtures/basic/nuxt.config.ts b/test/fixtures/basic/nuxt.config.ts index c6a7ab5b31..6a11e29bba 100644 --- a/test/fixtures/basic/nuxt.config.ts +++ b/test/fixtures/basic/nuxt.config.ts @@ -108,6 +108,12 @@ export default defineNuxtConfig({ addVitePlugin(plugin.vite()) addWebpackPlugin(plugin.webpack()) }, + function (_options, nuxt) { + // TODO: support directly via object syntax plugins: https://github.com/nuxt/nuxt/issues/14628 + nuxt.hook('modules:done', () => { + nuxt.options.plugins.unshift('~/plugins/custom-type-registration') + }) + }, function (_options, nuxt) { const routesToDuplicate = ['/async-parent', '/fixed-keyed-child-parent', '/keyed-child-parent', '/with-layout', '/with-layout2'] const stripLayout = (page: NuxtPage): NuxtPage => ({ @@ -184,6 +190,7 @@ export default defineNuxtConfig({ } }, experimental: { + renderJsonPayloads: true, respectNoSSRHeader: true, clientFallback: true, restoreState: true, diff --git a/test/fixtures/basic/pages/json-payload.vue b/test/fixtures/basic/pages/json-payload.vue new file mode 100644 index 0000000000..97a7fc8dd0 --- /dev/null +++ b/test/fixtures/basic/pages/json-payload.vue @@ -0,0 +1,26 @@ + + + diff --git a/test/fixtures/basic/plugins/custom-type-assertion.client.ts b/test/fixtures/basic/plugins/custom-type-assertion.client.ts new file mode 100644 index 0000000000..a7294f6159 --- /dev/null +++ b/test/fixtures/basic/plugins/custom-type-assertion.client.ts @@ -0,0 +1,7 @@ +export default defineNuxtPlugin((nuxtApp) => { + if (nuxtApp.payload.blinkable !== '') { + throw createError({ + message: 'Custom type in Nuxt payload was not revived correctly' + }) + } +}) diff --git a/test/fixtures/basic/plugins/custom-type-registration.ts b/test/fixtures/basic/plugins/custom-type-registration.ts new file mode 100644 index 0000000000..b7ef9b110f --- /dev/null +++ b/test/fixtures/basic/plugins/custom-type-registration.ts @@ -0,0 +1,7 @@ +export default defineNuxtPlugin((nuxtApp) => { + definePayloadReducer('BlinkingText', data => data === '' && '_') + definePayloadReviver('BlinkingText', () => '') + if (process.server) { + nuxtApp.payload.blinkable = '' + } +}) diff --git a/test/utils.ts b/test/utils.ts index 33b43d3863..5d2be09ba8 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,5 +1,8 @@ import { expect } from 'vitest' import type { Page } from 'playwright' +import { parse } from 'devalue' +import { shallowReactive, shallowRef, reactive, ref } from 'vue' +import { createError } from 'h3' import { createPage, getBrowser, url, useTestContext } from '@nuxt/test-utils' export async function renderPage (path = '/') { @@ -89,3 +92,29 @@ export async function withLogs (callback: (page: Page, logs: string[]) => Promis await page.close() } } + +const revivers = { + NuxtError: (data: any) => createError(data), + EmptyShallowRef: (data: any) => shallowRef(JSON.parse(data)), + EmptyRef: (data: any) => ref(JSON.parse(data)), + ShallowRef: (data: any) => shallowRef(data), + ShallowReactive: (data: any) => shallowReactive(data), + Ref: (data: any) => ref(data), + Reactive: (data: any) => reactive(data), + // test fixture reviver only + BlinkingText: () => '' +} +export function parsePayload (payload: string) { + return parse(payload || '', revivers) +} +export function parseData (html: string) { + const { script, attrs } = html.match(/ diff --git a/test/fixtures/basic/pages/legacy/async-data.vue b/test/fixtures/basic/pages/legacy/async-data.vue index 3ca56e0798..8b36739185 100644 --- a/test/fixtures/basic/pages/legacy/async-data.vue +++ b/test/fixtures/basic/pages/legacy/async-data.vue @@ -6,7 +6,12 @@ From f951a15232a297e43544df5078cce04bbc204f6e Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 11 Apr 2023 11:07:39 +0100 Subject: [PATCH 37/55] chore: upgrade to consola v3 (#20194) --- packages/kit/package.json | 2 +- packages/nuxi/package.json | 2 +- packages/nuxi/src/cli.ts | 10 +++++----- packages/test-utils/package.json | 2 +- pnpm-lock.yaml | 16 ++++++++-------- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/kit/package.json b/packages/kit/package.json index 66397bfa8b..8994d9d6c5 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -22,7 +22,7 @@ "dependencies": { "@nuxt/schema": "workspace:../schema", "c12": "^1.2.0", - "consola": "^3.0.0-3", + "consola": "^3.0.1", "defu": "^6.1.2", "globby": "^13.1.3", "hash-sum": "^2.0.0", diff --git a/packages/nuxi/package.json b/packages/nuxi/package.json index 559e3721ee..1da97dc25d 100644 --- a/packages/nuxi/package.json +++ b/packages/nuxi/package.json @@ -29,7 +29,7 @@ "clear": "^0.1.0", "clipboardy": "^3.0.0", "colorette": "^2.0.19", - "consola": "^3.0.0-3", + "consola": "^3.0.1", "deep-object-diff": "^1.1.9", "destr": "^1.2.2", "execa": "^7.1.1", diff --git a/packages/nuxi/src/cli.ts b/packages/nuxi/src/cli.ts index ea56732bcb..0118ade73d 100755 --- a/packages/nuxi/src/cli.ts +++ b/packages/nuxi/src/cli.ts @@ -1,6 +1,6 @@ import mri from 'mri' import { red } from 'colorette' -import type { Consola } from 'consola' +import type { ConsolaReporter } from 'consola' import { consola } from 'consola' import { checkEngines } from './utils/engines' import type { Command, NuxtCommand } from './commands' @@ -45,8 +45,7 @@ consola.wrapAll() // Filter out unwanted logs // TODO: Use better API from consola for intercepting logs -// TODO: export type from Consola -const wrapReporter = (reporter: Consola['_reporters'][0]) => { +const wrapReporter = (reporter: ConsolaReporter) => ({ log (logObj, ctx) { if (!logObj.args || !logObj.args.length) { return } const msg = logObj.args[0] @@ -62,8 +61,9 @@ const wrapReporter = (reporter: Consola['_reporters'][0]) => consola.error('[unhandledRejection]', err)) process.on('uncaughtException', err => consola.error('[uncaughtException]', err)) diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index ba62cb2284..ed7e555c4f 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -24,7 +24,7 @@ "dependencies": { "@nuxt/kit": "workspace:../kit", "@nuxt/schema": "workspace:../schema", - "consola": "^3.0.0-3", + "consola": "^3.0.1", "defu": "^6.1.2", "execa": "^7.1.1", "get-port-please": "^3.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0fe492507b..b61298d565 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -367,8 +367,8 @@ importers: specifier: ^1.2.0 version: 1.2.0 consola: - specifier: ^3.0.0-3 - version: 3.0.0-3 + specifier: ^3.0.1 + version: 3.0.1 defu: specifier: ^6.1.2 version: 6.1.2 @@ -465,8 +465,8 @@ importers: specifier: ^2.0.19 version: 2.0.19 consola: - specifier: ^3.0.0-3 - version: 3.0.0-3 + specifier: ^3.0.1 + version: 3.0.1 deep-object-diff: specifier: ^1.1.9 version: 1.1.9 @@ -755,8 +755,8 @@ importers: specifier: workspace:* version: link:../schema consola: - specifier: ^3.0.0-3 - version: 3.0.0-3 + specifier: ^3.0.1 + version: 3.0.1 defu: specifier: ^6.1.2 version: 6.1.2 @@ -3800,8 +3800,8 @@ packages: /consola@2.15.3: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} - /consola@3.0.0-3: - resolution: {integrity: sha512-3vhBx7Qw5LlF1/QnaeoQSSA5fOohGr9xtHkQ1RFbNlr6kOTwtVz0FvUPx6CdobrDDSP19cj0uWwPtf+/+VBKQA==} + /consola@3.0.1: + resolution: {integrity: sha512-08E7bC2N6gaFdzPU/qtBi4ulVvJitYnfrDdxEiwElC3jSNICbOvkcE+8N56EfIrBoxp37O9Qnn5ZZPElov83UQ==} /console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} From 42850928794e1f05216e7c9502cf7f64d54f9d54 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 11 Apr 2023 12:58:43 +0100 Subject: [PATCH 38/55] feat(nuxt): support object-syntax plugins (#20003) --- .../2.directory-structure/1.plugins.md | 25 ++ docs/3.api/1.composables/use-nuxt-app.md | 22 +- packages/nuxt/src/app/nuxt.ts | 104 +++++- .../src/app/plugins/chunk-reload.client.ts | 29 +- .../plugins/cross-origin-prefetch.client.ts | 57 ++-- packages/nuxt/src/app/plugins/debug.ts | 8 +- .../nuxt/src/app/plugins/payload.client.ts | 41 +-- .../nuxt/src/app/plugins/preload.server.ts | 19 +- .../src/app/plugins/restore-state.client.ts | 26 +- .../src/app/plugins/revive-payload.client.ts | 16 +- .../src/app/plugins/revive-payload.server.ts | 9 +- packages/nuxt/src/app/plugins/router.ts | 316 +++++++++--------- packages/nuxt/src/components/templates.ts | 11 +- packages/nuxt/src/core/nuxt.ts | 6 +- .../nuxt/src/head/runtime/plugins/unhead.ts | 57 ++-- .../runtime/plugins/vueuse-head-polyfill.ts | 9 +- packages/nuxt/src/imports/presets.ts | 1 + .../pages/runtime/plugins/prefetch.client.ts | 60 ++-- .../nuxt/src/pages/runtime/plugins/router.ts | 278 +++++++-------- packages/schema/src/config/build.ts | 1 + test/bundle.test.ts | 4 +- test/fixtures/basic/nuxt.config.ts | 6 - .../basic/plugins/custom-type-registration.ts | 2 +- 23 files changed, 621 insertions(+), 486 deletions(-) diff --git a/docs/2.guide/2.directory-structure/1.plugins.md b/docs/2.guide/2.directory-structure/1.plugins.md index e5147b23d1..091b3e68a4 100644 --- a/docs/2.guide/2.directory-structure/1.plugins.md +++ b/docs/2.guide/2.directory-structure/1.plugins.md @@ -40,6 +40,31 @@ export default defineNuxtPlugin(nuxtApp => { }) ``` +### Object Syntax Plugins + +It is also possible to define a plugin using an object syntax, for more advanced use cases. For example: + +```ts +export default defineNuxtPlugin({ + name: 'my-plugin', + enforce: 'pre', // or 'post' + async setup (nuxtApp) { + // this is the equivalent of a normal functional plugin + }, + hooks: { + // You can directly register Nuxt app hooks here + 'app:created'() { + const nuxtApp = useNuxtApp() + // + } + } +}) +``` + +::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. +:: + ## Plugin Registration Order You can control the order in which plugins are registered by prefixing a number to the file names. diff --git a/docs/3.api/1.composables/use-nuxt-app.md b/docs/3.api/1.composables/use-nuxt-app.md index d962cca4d0..70d4777d43 100644 --- a/docs/3.api/1.composables/use-nuxt-app.md +++ b/docs/3.api/1.composables/use-nuxt-app.md @@ -116,19 +116,19 @@ export default defineNuxtPlugin((nuxtApp) => { ::alert Normally `payload` must contain only plain JavaScript objects. But by setting `experimental.renderJsonPayloads`, it is possible to use more advanced types, such as `ref`, `reactive`, `shallowRef`, `shallowReactive` and `NuxtError`. -You can also add your own types. In future you will be able to add your own types easily with [object-syntax plugins](https://github.com/nuxt/nuxt/issues/14628). For now, you must add your plugin which calls both `definePayloadReducer` and `definePayloadReviver` via a custom module: +You can also add your own types, with a special plugin helper: -```ts -export default defineNuxtConfig({ - modules: [ - function (_options, nuxt) { - // TODO: support directly via object syntax plugins: https://github.com/nuxt/nuxt/issues/14628 - nuxt.hook('modules:done', () => { - nuxt.options.plugins.unshift('~/plugins/custom-type-plugin') - }) - }, - ] +```ts [plugins/custom-payload.ts] + /** + * This kind of plugin runs very early in the Nuxt lifecycle, before we revive the payload. + * You will not have access to the router or other Nuxt-injected properties. + */ +export default definePayloadPlugin((nuxtApp) => { + definePayloadReducer('BlinkingText', data => data === '' && '_') + definePayloadReviver('BlinkingText', () => '') }) +``` + :: ### `isHydrating` diff --git a/packages/nuxt/src/app/nuxt.ts b/packages/nuxt/src/app/nuxt.ts index 41812dd231..1fa4c2ab88 100644 --- a/packages/nuxt/src/app/nuxt.ts +++ b/packages/nuxt/src/app/nuxt.ts @@ -139,9 +139,31 @@ interface _NuxtApp { export interface NuxtApp extends _NuxtApp {} export const NuxtPluginIndicator = '__nuxt_plugin' + +export interface PluginMeta { + name?: string + enforce?: 'pre' | 'default' | 'post' + /** + * This allows more granular control over plugin order and should only be used by advanced users. + * It overrides the value of `enforce` and is used to sort plugins. + */ + order?: number +} + +export interface ResolvedPluginMeta { + name?: string + order: number +} + export interface Plugin = Record> { (nuxt: _NuxtApp): Promise | Promise<{ provide?: Injections }> | void | { provide?: Injections } [NuxtPluginIndicator]?: true + meta?: ResolvedPluginMeta +} + +export interface ObjectPluginInput = Record> extends PluginMeta { + hooks?: Partial + setup?: Plugin } export interface CreateOptions { @@ -306,25 +328,30 @@ export function normalizePlugins (_plugins: Plugin[]) { const legacyInjectPlugins: Plugin[] = [] const invalidPlugins: Plugin[] = [] - const plugins = _plugins.map((plugin) => { + const plugins: Plugin[] = [] + + for (const plugin of _plugins) { if (typeof plugin !== 'function') { - invalidPlugins.push(plugin) - return null + if (process.dev) { invalidPlugins.push(plugin) } + continue } + + // TODO: Skip invalid plugins in next releases + let _plugin = plugin if (plugin.length > 1) { - legacyInjectPlugins.push(plugin) // Allow usage without wrapper but warn - // TODO: Skip invalid in next releases - // @ts-ignore - return (nuxtApp: NuxtApp) => plugin(nuxtApp, nuxtApp.provide) - // return null + if (process.dev) { legacyInjectPlugins.push(plugin) } + // @ts-expect-error deliberate invalid second argument + _plugin = (nuxtApp: NuxtApp) => plugin(nuxtApp, nuxtApp.provide) } - if (!isNuxtPlugin(plugin)) { - unwrappedPlugins.push(plugin) - // Allow usage without wrapper but warn - } - return plugin - }).filter(Boolean) + + // Allow usage without wrapper but warn + if (process.dev && !isNuxtPlugin(_plugin)) { unwrappedPlugins.push(_plugin) } + + plugins.push(_plugin) + } + + plugins.sort((a, b) => (a.meta?.order || orderMap.default) - (b.meta?.order || orderMap.default)) if (process.dev && legacyInjectPlugins.length) { console.warn('[warn] [nuxt] You are using a plugin with legacy Nuxt 2 format (context, inject) which is likely to be broken. In the future they will be ignored:', legacyInjectPlugins.map(p => p.name || p).join(',')) @@ -336,12 +363,53 @@ export function normalizePlugins (_plugins: Plugin[]) { console.warn('[warn] [nuxt] You are using a plugin that has not been wrapped in `defineNuxtPlugin`. It is advised to wrap your plugins as in the future this may enable enhancements:', unwrappedPlugins.map(p => p.name || p).join(',')) } - return plugins as Plugin[] + return plugins } -export function defineNuxtPlugin> (plugin: Plugin) { - plugin[NuxtPluginIndicator] = true - return plugin +// -50: pre-all (nuxt) +// -40: custom payload revivers (user) +// -30: payload reviving (nuxt) +// -20: pre (user) <-- pre mapped to this +// -10: default (nuxt) +// 0: default (user) <-- default behavior +// +10: post (nuxt) +// +20: post (user) <-- post mapped to this +// +30: post-all (nuxt) + +const orderMap: Record, number> = { + pre: -20, + default: 0, + post: 20 +} + +export function definePayloadPlugin> (plugin: Plugin | ObjectPluginInput) { + return defineNuxtPlugin(plugin, { order: -40 }) +} + +export function defineNuxtPlugin> (plugin: Plugin | ObjectPluginInput, meta?: PluginMeta): Plugin { + if (typeof plugin === 'function') { return defineNuxtPlugin({ setup: plugin }, meta) } + + const wrapper: Plugin = (nuxtApp) => { + if (plugin.hooks) { + nuxtApp.hooks.addHooks(plugin.hooks) + } + if (plugin.setup) { + return plugin.setup(nuxtApp) + } + } + + wrapper.meta = { + name: meta?.name || plugin.name || plugin.setup?.name, + order: + meta?.order || + plugin.order || + orderMap[plugin.enforce || 'default'] || + orderMap.default + } + + wrapper[NuxtPluginIndicator] = true + + return wrapper } export function isNuxtPlugin (plugin: unknown) { diff --git a/packages/nuxt/src/app/plugins/chunk-reload.client.ts b/packages/nuxt/src/app/plugins/chunk-reload.client.ts index 55a1211e3f..d90677688e 100644 --- a/packages/nuxt/src/app/plugins/chunk-reload.client.ts +++ b/packages/nuxt/src/app/plugins/chunk-reload.client.ts @@ -3,20 +3,23 @@ import { defineNuxtPlugin, useRuntimeConfig } from '#app/nuxt' import { useRouter } from '#app/composables/router' import { reloadNuxtApp } from '#app/composables/chunk' -export default defineNuxtPlugin((nuxtApp) => { - const router = useRouter() - const config = useRuntimeConfig() +export default defineNuxtPlugin({ + name: 'nuxt:chunk-reload', + setup (nuxtApp) { + const router = useRouter() + const config = useRuntimeConfig() - const chunkErrors = new Set() + const chunkErrors = new Set() - router.beforeEach(() => { chunkErrors.clear() }) - nuxtApp.hook('app:chunkError', ({ error }) => { chunkErrors.add(error) }) + router.beforeEach(() => { chunkErrors.clear() }) + nuxtApp.hook('app:chunkError', ({ error }) => { chunkErrors.add(error) }) - router.onError((error, to) => { - if (chunkErrors.has(error)) { - const isHash = 'href' in to && (to.href as string).startsWith('#') - const path = isHash ? config.app.baseURL + (to as any).href : joinURL(config.app.baseURL, to.fullPath) - reloadNuxtApp({ path, persistState: true }) - } - }) + router.onError((error, to) => { + if (chunkErrors.has(error)) { + const isHash = 'href' in to && (to.href as string).startsWith('#') + const path = isHash ? config.app.baseURL + (to as any).href : joinURL(config.app.baseURL, to.fullPath) + reloadNuxtApp({ path, persistState: true }) + } + }) + } }) diff --git a/packages/nuxt/src/app/plugins/cross-origin-prefetch.client.ts b/packages/nuxt/src/app/plugins/cross-origin-prefetch.client.ts index 08e58dd695..191f69133b 100644 --- a/packages/nuxt/src/app/plugins/cross-origin-prefetch.client.ts +++ b/packages/nuxt/src/app/plugins/cross-origin-prefetch.client.ts @@ -3,33 +3,36 @@ import { parseURL } from 'ufo' import { useHead } from '@unhead/vue' import { defineNuxtPlugin } from '#app/nuxt' -export default defineNuxtPlugin((nuxtApp) => { - const externalURLs = ref(new Set()) - function generateRules () { - return { - type: 'speculationrules', - key: 'speculationrules', - innerHTML: JSON.stringify({ - prefetch: [ - { - source: 'list', - urls: [...externalURLs.value], - requires: ['anonymous-client-ip-when-cross-origin'] - } - ] - }) +export default defineNuxtPlugin({ + name: 'nuxt:cross-origin-prefetch', + setup (nuxtApp) { + const externalURLs = ref(new Set()) + function generateRules () { + return { + type: 'speculationrules', + key: 'speculationrules', + innerHTML: JSON.stringify({ + prefetch: [ + { + source: 'list', + urls: [...externalURLs.value], + requires: ['anonymous-client-ip-when-cross-origin'] + } + ] + }) + } } + const head = useHead({ + script: [generateRules()] + }) + nuxtApp.hook('link:prefetch', (url) => { + const { protocol } = parseURL(url) + if (protocol && ['http:', 'https:'].includes(protocol)) { + externalURLs.value.add(url) + head?.patch({ + script: [generateRules()] + }) + } + }) } - const head = useHead({ - script: [generateRules()] - }) - nuxtApp.hook('link:prefetch', (url) => { - const { protocol } = parseURL(url) - if (protocol && ['http:', 'https:'].includes(protocol)) { - externalURLs.value.add(url) - head?.patch({ - script: [generateRules()] - }) - } - }) }) diff --git a/packages/nuxt/src/app/plugins/debug.ts b/packages/nuxt/src/app/plugins/debug.ts index f2909d069e..5479a84d45 100644 --- a/packages/nuxt/src/app/plugins/debug.ts +++ b/packages/nuxt/src/app/plugins/debug.ts @@ -1,6 +1,10 @@ import { createDebugger } from 'hookable' import { defineNuxtPlugin } from '#app/nuxt' -export default defineNuxtPlugin((nuxtApp) => { - createDebugger(nuxtApp.hooks, { tag: 'nuxt-app' }) +export default defineNuxtPlugin({ + name: 'nuxt:debug', + enforce: 'pre', + setup (nuxtApp) { + createDebugger(nuxtApp.hooks, { tag: 'nuxt-app' }) + } }) diff --git a/packages/nuxt/src/app/plugins/payload.client.ts b/packages/nuxt/src/app/plugins/payload.client.ts index 55d6417c31..d080ea944d 100644 --- a/packages/nuxt/src/app/plugins/payload.client.ts +++ b/packages/nuxt/src/app/plugins/payload.client.ts @@ -3,25 +3,28 @@ import { defineNuxtPlugin } from '#app/nuxt' import { isPrerendered, loadPayload } from '#app/composables/payload' import { useRouter } from '#app/composables/router' -export default defineNuxtPlugin((nuxtApp) => { - // Only enable behavior if initial page is prerendered - // TODO: Support hybrid and dev - if (!isPrerendered()) { - return - } - - // Load payload into cache - nuxtApp.hooks.hook('link:prefetch', async (url) => { - if (!parseURL(url).protocol) { - await loadPayload(url) +export default defineNuxtPlugin({ + name: 'nuxt:payload', + setup (nuxtApp) { + // Only enable behavior if initial page is prerendered + // TODO: Support hybrid and dev + if (!isPrerendered()) { + return } - }) - // Load payload after middleware & once final route is resolved - useRouter().beforeResolve(async (to, from) => { - if (to.path === from.path) { return } - const payload = await loadPayload(to.path) - if (!payload) { return } - Object.assign(nuxtApp.static.data, payload.data) - }) + // Load payload into cache + nuxtApp.hooks.hook('link:prefetch', async (url) => { + if (!parseURL(url).protocol) { + await loadPayload(url) + } + }) + + // Load payload after middleware & once final route is resolved + useRouter().beforeResolve(async (to, from) => { + if (to.path === from.path) { return } + const payload = await loadPayload(to.path) + if (!payload) { return } + Object.assign(nuxtApp.static.data, payload.data) + }) + } }) diff --git a/packages/nuxt/src/app/plugins/preload.server.ts b/packages/nuxt/src/app/plugins/preload.server.ts index 9f6b25d62d..ec9501988b 100644 --- a/packages/nuxt/src/app/plugins/preload.server.ts +++ b/packages/nuxt/src/app/plugins/preload.server.ts @@ -1,11 +1,14 @@ import { defineNuxtPlugin } from '#app/nuxt' -export default defineNuxtPlugin((nuxtApp) => { - nuxtApp.vueApp.mixin({ - beforeCreate () { - const { _registeredComponents } = this.$nuxt.ssrContext - const { __moduleIdentifier } = this.$options - _registeredComponents.add(__moduleIdentifier) - } - }) +export default defineNuxtPlugin({ + name: 'nuxt:webpack-preload', + setup (nuxtApp) { + nuxtApp.vueApp.mixin({ + beforeCreate () { + const { _registeredComponents } = this.$nuxt.ssrContext + const { __moduleIdentifier } = this.$options + _registeredComponents.add(__moduleIdentifier) + } + }) + } }) diff --git a/packages/nuxt/src/app/plugins/restore-state.client.ts b/packages/nuxt/src/app/plugins/restore-state.client.ts index 6533650ce9..e6786e8cea 100644 --- a/packages/nuxt/src/app/plugins/restore-state.client.ts +++ b/packages/nuxt/src/app/plugins/restore-state.client.ts @@ -1,13 +1,17 @@ -import { defineNuxtPlugin } from '#app/nuxt' +import { defineNuxtPlugin, useNuxtApp } from '#app/nuxt' -export default defineNuxtPlugin((nuxtApp) => { - nuxtApp.hook('app:mounted', () => { - try { - const state = sessionStorage.getItem('nuxt:reload:state') - if (state) { - sessionStorage.removeItem('nuxt:reload:state') - Object.assign(nuxtApp.payload.state, JSON.parse(state)?.state) - } - } catch {} - }) +export default defineNuxtPlugin({ + name: 'nuxt:restore-state', + hooks: { + 'app:mounted' () { + const nuxtApp = useNuxtApp() + try { + const state = sessionStorage.getItem('nuxt:reload:state') + if (state) { + sessionStorage.removeItem('nuxt:reload:state') + Object.assign(nuxtApp.payload.state, JSON.parse(state)?.state) + } + } catch {} + } + } }) diff --git a/packages/nuxt/src/app/plugins/revive-payload.client.ts b/packages/nuxt/src/app/plugins/revive-payload.client.ts index e7fa0eaa4c..ae58308cc2 100644 --- a/packages/nuxt/src/app/plugins/revive-payload.client.ts +++ b/packages/nuxt/src/app/plugins/revive-payload.client.ts @@ -13,11 +13,15 @@ const revivers = { Reactive: (data: any) => reactive(data) } -export default defineNuxtPlugin(async (nuxtApp) => { - for (const reviver in revivers) { - definePayloadReviver(reviver, revivers[reviver as keyof typeof revivers]) +export default defineNuxtPlugin({ + name: 'nuxt:revive-payload:client', + order: -30, + async setup (nuxtApp) { + for (const reviver in revivers) { + definePayloadReviver(reviver, revivers[reviver as keyof typeof revivers]) + } + Object.assign(nuxtApp.payload, await callWithNuxt(nuxtApp, getNuxtClientPayload, [])) + // For backwards compatibility - TODO: remove later + window.__NUXT__ = nuxtApp.payload } - Object.assign(nuxtApp.payload, await callWithNuxt(nuxtApp, getNuxtClientPayload, [])) - // For backwards compatibility - TODO: remove later - window.__NUXT__ = nuxtApp.payload }) diff --git a/packages/nuxt/src/app/plugins/revive-payload.server.ts b/packages/nuxt/src/app/plugins/revive-payload.server.ts index d04c4ac4b0..b8e54569f6 100644 --- a/packages/nuxt/src/app/plugins/revive-payload.server.ts +++ b/packages/nuxt/src/app/plugins/revive-payload.server.ts @@ -14,8 +14,11 @@ const reducers = { Reactive: (data: any) => isReactive(data) && toRaw(data) } -export default defineNuxtPlugin(() => { - for (const reducer in reducers) { - definePayloadReducer(reducer, reducers[reducer as keyof typeof reducers]) +export default defineNuxtPlugin({ + name: 'nuxt:revive-payload:server', + setup () { + for (const reducer in reducers) { + definePayloadReducer(reducer, reducers[reducer as keyof typeof reducers]) + } } }) diff --git a/packages/nuxt/src/app/plugins/router.ts b/packages/nuxt/src/app/plugins/router.ts index 8b61b0f245..0863c5d5d7 100644 --- a/packages/nuxt/src/app/plugins/router.ts +++ b/packages/nuxt/src/app/plugins/router.ts @@ -96,176 +96,180 @@ interface Router { removeRoute: (name: string) => void } -export default defineNuxtPlugin<{ route: Route, router: Router }>((nuxtApp) => { - const initialURL = process.client - ? withoutBase(window.location.pathname, useRuntimeConfig().app.baseURL) + window.location.search + window.location.hash - : nuxtApp.ssrContext!.url +export default defineNuxtPlugin<{ route: Route, router: Router }>({ + name: 'nuxt:router', + enforce: 'pre', + setup (nuxtApp) { + const initialURL = process.client + ? withoutBase(window.location.pathname, useRuntimeConfig().app.baseURL) + window.location.search + window.location.hash + : nuxtApp.ssrContext!.url - const routes: Route[] = [] + const routes: Route[] = [] - const hooks: { [key in keyof RouterHooks]: RouterHooks[key][] } = { - 'navigate:before': [], - 'resolve:before': [], - 'navigate:after': [], - error: [] - } + const hooks: { [key in keyof RouterHooks]: RouterHooks[key][] } = { + 'navigate:before': [], + 'resolve:before': [], + 'navigate:after': [], + error: [] + } - const registerHook = (hook: T, guard: RouterHooks[T]) => { - hooks[hook].push(guard) - return () => hooks[hook].splice(hooks[hook].indexOf(guard), 1) - } - const baseURL = useRuntimeConfig().app.baseURL + const registerHook = (hook: T, guard: RouterHooks[T]) => { + hooks[hook].push(guard) + return () => hooks[hook].splice(hooks[hook].indexOf(guard), 1) + } + const baseURL = useRuntimeConfig().app.baseURL - const route: Route = reactive(getRouteFromPath(initialURL)) - async function handleNavigation (url: string | Partial, replace?: boolean): Promise { - try { - // Resolve route - const to = getRouteFromPath(url) + const route: Route = reactive(getRouteFromPath(initialURL)) + async function handleNavigation (url: string | Partial, replace?: boolean): Promise { + try { + // Resolve route + const to = getRouteFromPath(url) - // Run beforeEach hooks - for (const middleware of hooks['navigate:before']) { - const result = await middleware(to, route) - // Cancel navigation - if (result === false || result instanceof Error) { return } - // Redirect - if (result) { return handleNavigation(result, true) } - } - - for (const handler of hooks['resolve:before']) { - await handler(to, route) - } - // Perform navigation - Object.assign(route, to) - if (process.client) { - window.history[replace ? 'replaceState' : 'pushState']({}, '', joinURL(baseURL, to.fullPath)) - if (!nuxtApp.isHydrating) { - // Clear any existing errors - await callWithNuxt(nuxtApp, clearError) + // Run beforeEach hooks + for (const middleware of hooks['navigate:before']) { + const result = await middleware(to, route) + // Cancel navigation + if (result === false || result instanceof Error) { return } + // Redirect + if (result) { return handleNavigation(result, true) } } - } - // Run afterEach hooks - for (const middleware of hooks['navigate:after']) { - await middleware(to, route) - } - } catch (err) { - if (process.dev && !hooks.error.length) { - 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) { - await handler(err) - } - } - } - const router: Router = { - currentRoute: route, - isReady: () => Promise.resolve(), - // These options provide a similar API to vue-router but have no effect - options: {}, - install: () => Promise.resolve(), - // Navigation - push: (url: string) => handleNavigation(url, false), - replace: (url: string) => handleNavigation(url, true), - back: () => window.history.go(-1), - go: (delta: number) => window.history.go(delta), - forward: () => window.history.go(1), - // Guards - beforeResolve: (guard: RouterHooks['resolve:before']) => registerHook('resolve:before', guard), - beforeEach: (guard: RouterHooks['navigate:before']) => registerHook('navigate:before', guard), - afterEach: (guard: RouterHooks['navigate:after']) => registerHook('navigate:after', guard), - onError: (handler: RouterHooks['error']) => registerHook('error', handler), - // Routes - resolve: getRouteFromPath, - addRoute: (parentName: string, route: Route) => { routes.push(route) }, - getRoutes: () => routes, - hasRoute: (name: string) => routes.some(route => route.name === name), - removeRoute: (name: string) => { - const index = routes.findIndex(route => route.name === name) - if (index !== -1) { - routes.splice(index, 1) - } - } - } - - nuxtApp.vueApp.component('RouterLink', { - functional: true, - props: { - to: String, - custom: Boolean, - replace: Boolean, - // Not implemented - activeClass: String, - exactActiveClass: String, - ariaCurrentValue: String - }, - setup: (props, { slots }) => { - const navigate = () => handleNavigation(props.to, props.replace) - return () => { - const route = router.resolve(props.to) - return props.custom - ? slots.default?.({ href: props.to, navigate, route }) - : h('a', { href: props.to, onClick: (e: MouseEvent) => { e.preventDefault(); return navigate() } }, slots) - } - } - }) - - if (process.client) { - window.addEventListener('popstate', (event) => { - const location = (event.target as Window).location - router.replace(location.href.replace(location.origin, '')) - }) - } - - nuxtApp._route = route - - // Handle middleware - nuxtApp._middleware = nuxtApp._middleware || { - global: [], - named: {} - } - - const initialLayout = useState('_layout') - nuxtApp.hooks.hookOnce('app:created', async () => { - router.beforeEach(async (to, from) => { - to.meta = reactive(to.meta || {}) - if (nuxtApp.isHydrating && initialLayout.value && !isReadonly(to.meta.layout)) { - to.meta.layout = initialLayout.value - } - nuxtApp._processingMiddleware = true - - const middlewareEntries = new Set([...globalMiddleware, ...nuxtApp._middleware.global]) - - for (const middleware of middlewareEntries) { - const result = await callWithNuxt(nuxtApp, middleware, [to, from]) - if (process.server) { - if (result === false || result instanceof Error) { - const error = result || createError({ - statusCode: 404, - statusMessage: `Page Not Found: ${initialURL}` - }) - return callWithNuxt(nuxtApp, showError, [error]) + for (const handler of hooks['resolve:before']) { + await handler(to, route) + } + // Perform navigation + Object.assign(route, to) + if (process.client) { + window.history[replace ? 'replaceState' : 'pushState']({}, '', joinURL(baseURL, to.fullPath)) + if (!nuxtApp.isHydrating) { + // Clear any existing errors + await callWithNuxt(nuxtApp, clearError) } } - if (result || result === false) { return result } + // Run afterEach hooks + for (const middleware of hooks['navigate:after']) { + await middleware(to, route) + } + } catch (err) { + if (process.dev && !hooks.error.length) { + 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) { + await handler(err) + } + } + } + + const router: Router = { + currentRoute: route, + isReady: () => Promise.resolve(), + // These options provide a similar API to vue-router but have no effect + options: {}, + install: () => Promise.resolve(), + // Navigation + push: (url: string) => handleNavigation(url, false), + replace: (url: string) => handleNavigation(url, true), + back: () => window.history.go(-1), + go: (delta: number) => window.history.go(delta), + forward: () => window.history.go(1), + // Guards + beforeResolve: (guard: RouterHooks['resolve:before']) => registerHook('resolve:before', guard), + beforeEach: (guard: RouterHooks['navigate:before']) => registerHook('navigate:before', guard), + afterEach: (guard: RouterHooks['navigate:after']) => registerHook('navigate:after', guard), + onError: (handler: RouterHooks['error']) => registerHook('error', handler), + // Routes + resolve: getRouteFromPath, + addRoute: (parentName: string, route: Route) => { routes.push(route) }, + getRoutes: () => routes, + hasRoute: (name: string) => routes.some(route => route.name === name), + removeRoute: (name: string) => { + const index = routes.findIndex(route => route.name === name) + if (index !== -1) { + routes.splice(index, 1) + } + } + } + + nuxtApp.vueApp.component('RouterLink', { + functional: true, + props: { + to: String, + custom: Boolean, + replace: Boolean, + // Not implemented + activeClass: String, + exactActiveClass: String, + ariaCurrentValue: String + }, + setup: (props, { slots }) => { + const navigate = () => handleNavigation(props.to, props.replace) + return () => { + const route = router.resolve(props.to) + return props.custom + ? slots.default?.({ href: props.to, navigate, route }) + : h('a', { href: props.to, onClick: (e: MouseEvent) => { e.preventDefault(); return navigate() } }, slots) + } } }) - router.afterEach(() => { - delete nuxtApp._processingMiddleware + if (process.client) { + window.addEventListener('popstate', (event) => { + const location = (event.target as Window).location + router.replace(location.href.replace(location.origin, '')) + }) + } + + nuxtApp._route = route + + // Handle middleware + nuxtApp._middleware = nuxtApp._middleware || { + global: [], + named: {} + } + + const initialLayout = useState('_layout') + nuxtApp.hooks.hookOnce('app:created', async () => { + router.beforeEach(async (to, from) => { + to.meta = reactive(to.meta || {}) + if (nuxtApp.isHydrating && initialLayout.value && !isReadonly(to.meta.layout)) { + to.meta.layout = initialLayout.value + } + nuxtApp._processingMiddleware = true + + const middlewareEntries = new Set([...globalMiddleware, ...nuxtApp._middleware.global]) + + for (const middleware of middlewareEntries) { + const result = await callWithNuxt(nuxtApp, middleware, [to, from]) + if (process.server) { + if (result === false || result instanceof Error) { + const error = result || createError({ + statusCode: 404, + statusMessage: `Page Not Found: ${initialURL}` + }) + return callWithNuxt(nuxtApp, showError, [error]) + } + } + if (result || result === false) { return result } + } + }) + + router.afterEach(() => { + delete nuxtApp._processingMiddleware + }) + + await router.replace(initialURL) + if (!isEqual(route.fullPath, initialURL)) { + const event = await callWithNuxt(nuxtApp, useRequestEvent) + const options = { redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302 } + await callWithNuxt(nuxtApp, navigateTo, [route.fullPath, options]) + } }) - await router.replace(initialURL) - if (!isEqual(route.fullPath, initialURL)) { - const event = await callWithNuxt(nuxtApp, useRequestEvent) - const options = { redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302 } - await callWithNuxt(nuxtApp, navigateTo, [route.fullPath, options]) - } - }) - - return { - provide: { - route, - router + return { + provide: { + route, + router + } } } }) diff --git a/packages/nuxt/src/components/templates.ts b/packages/nuxt/src/components/templates.ts index 3d1705cf72..19dd42eb24 100644 --- a/packages/nuxt/src/components/templates.ts +++ b/packages/nuxt/src/components/templates.ts @@ -40,10 +40,13 @@ const components = ${genObjectFromRawEntries(globalComponents.map((c) => { return [c.pascalName, `defineAsyncComponent(${genDynamicImport(c.filePath, { comment })}.then(c => ${exp}))`] }))} -export default defineNuxtPlugin(nuxtApp => { - for (const name in components) { - nuxtApp.vueApp.component(name, components[name]) - nuxtApp.vueApp.component('Lazy' + name, components[name]) +export default defineNuxtPlugin({ + name: 'nuxt:global-components', + setup (nuxtApp) { + for (const name in components) { + nuxtApp.vueApp.component(name, components[name]) + nuxtApp.vueApp.component('Lazy' + name, components[name]) + } } }) ` diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index 6659fab06f..638fd6a29b 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -292,9 +292,9 @@ async function initNuxt (nuxt: Nuxt) { // Add experimental support for custom types in JSON payload if (nuxt.options.experimental.renderJsonPayloads) { - nuxt.hook('modules:done', () => { - nuxt.options.plugins.unshift(resolve(nuxt.options.appDir, 'plugins/revive-payload.client')) - nuxt.options.plugins.unshift(resolve(nuxt.options.appDir, 'plugins/revive-payload.server')) + nuxt.hooks.hook('modules:done', () => { + addPlugin(resolve(nuxt.options.appDir, 'plugins/revive-payload.client')) + addPlugin(resolve(nuxt.options.appDir, 'plugins/revive-payload.server')) }) } diff --git a/packages/nuxt/src/head/runtime/plugins/unhead.ts b/packages/nuxt/src/head/runtime/plugins/unhead.ts index 527be0586f..3fd5e0c330 100644 --- a/packages/nuxt/src/head/runtime/plugins/unhead.ts +++ b/packages/nuxt/src/head/runtime/plugins/unhead.ts @@ -4,37 +4,40 @@ import { defineNuxtPlugin } from '#app/nuxt' // @ts-expect-error untyped import { appHead } from '#build/nuxt.config.mjs' -export default defineNuxtPlugin((nuxtApp) => { - const createHead = process.server ? createServerHead : createClientHead - const head = createHead() - head.push(appHead) +export default defineNuxtPlugin({ + name: 'nuxt:head', + setup (nuxtApp) { + const createHead = process.server ? createServerHead : createClientHead + const head = createHead() + head.push(appHead) - nuxtApp.vueApp.use(head) + nuxtApp.vueApp.use(head) - if (process.client) { - // pause dom updates until page is ready and between page transitions - let pauseDOMUpdates = true - const unpauseDom = () => { - pauseDOMUpdates = false - // trigger the debounced DOM update - head.hooks.callHook('entries:updated', head) + if (process.client) { + // pause dom updates until page is ready and between page transitions + let pauseDOMUpdates = true + const unpauseDom = () => { + pauseDOMUpdates = false + // trigger the debounced DOM update + head.hooks.callHook('entries:updated', head) + } + head.hooks.hook('dom:beforeRender', (context) => { context.shouldRender = !pauseDOMUpdates }) + nuxtApp.hooks.hook('page:start', () => { pauseDOMUpdates = true }) + // wait for new page before unpausing dom updates (triggered after suspense resolved) + nuxtApp.hooks.hook('page:finish', unpauseDom) + // unpause the DOM once the mount suspense is resolved + nuxtApp.hooks.hook('app:suspense:resolve', unpauseDom) } - head.hooks.hook('dom:beforeRender', (context) => { context.shouldRender = !pauseDOMUpdates }) - nuxtApp.hooks.hook('page:start', () => { pauseDOMUpdates = true }) - // wait for new page before unpausing dom updates (triggered after suspense resolved) - nuxtApp.hooks.hook('page:finish', unpauseDom) - // unpause the DOM once the mount suspense is resolved - nuxtApp.hooks.hook('app:suspense:resolve', unpauseDom) - } - if (process.server) { - nuxtApp.ssrContext!.renderMeta = async () => { - const meta = await renderSSRHead(head) - return { - ...meta, - bodyScriptsPrepend: meta.bodyTagsOpen, - // resolves naming difference with NuxtMeta and Unhead - bodyScripts: meta.bodyTags + if (process.server) { + nuxtApp.ssrContext!.renderMeta = async () => { + const meta = await renderSSRHead(head) + return { + ...meta, + bodyScriptsPrepend: meta.bodyTagsOpen, + // resolves naming difference with NuxtMeta and Unhead + bodyScripts: meta.bodyTags + } } } } diff --git a/packages/nuxt/src/head/runtime/plugins/vueuse-head-polyfill.ts b/packages/nuxt/src/head/runtime/plugins/vueuse-head-polyfill.ts index 57d1a15bc4..d3dfb3be67 100644 --- a/packages/nuxt/src/head/runtime/plugins/vueuse-head-polyfill.ts +++ b/packages/nuxt/src/head/runtime/plugins/vueuse-head-polyfill.ts @@ -2,7 +2,10 @@ import { polyfillAsVueUseHead } from '@unhead/vue/polyfill' import { defineNuxtPlugin } from '#app/nuxt' -export default defineNuxtPlugin((nuxtApp) => { - // avoid breaking ecosystem dependencies using low-level @vueuse/head APIs - polyfillAsVueUseHead(nuxtApp.vueApp._context.provides.usehead) +export default defineNuxtPlugin({ + name: 'nuxt:vueuse-head-polyfill', + setup (nuxtApp) { + // avoid breaking ecosystem dependencies using low-level @vueuse/head APIs + polyfillAsVueUseHead(nuxtApp.vueApp._context.provides.usehead) + } }) diff --git a/packages/nuxt/src/imports/presets.ts b/packages/nuxt/src/imports/presets.ts index c8fb0c7368..89518467eb 100644 --- a/packages/nuxt/src/imports/presets.ts +++ b/packages/nuxt/src/imports/presets.ts @@ -23,6 +23,7 @@ const appPreset = defineUnimportPreset({ 'defineNuxtComponent', 'useNuxtApp', 'defineNuxtPlugin', + 'definePayloadPlugin', 'reloadNuxtApp', 'useRuntimeConfig', 'useState', diff --git a/packages/nuxt/src/pages/runtime/plugins/prefetch.client.ts b/packages/nuxt/src/pages/runtime/plugins/prefetch.client.ts index b258812103..d946f14ea8 100644 --- a/packages/nuxt/src/pages/runtime/plugins/prefetch.client.ts +++ b/packages/nuxt/src/pages/runtime/plugins/prefetch.client.ts @@ -1,41 +1,43 @@ import { hasProtocol } from 'ufo' -import { defineNuxtPlugin, useNuxtApp } from '#app/nuxt' +import { defineNuxtPlugin } from '#app/nuxt' import { useRouter } from '#app/composables/router' // @ts-ignore import layouts from '#build/layouts' // @ts-ignore import { namedMiddleware } from '#build/middleware' -export default defineNuxtPlugin(() => { - const nuxtApp = useNuxtApp() - const router = useRouter() +export default defineNuxtPlugin({ + name: 'nuxt:prefetch', + setup (nuxtApp) { + const router = useRouter() + + // Force layout prefetch on route changes + nuxtApp.hooks.hook('app:mounted', () => { + router.beforeEach(async (to) => { + const layout = to?.meta?.layout + if (layout && typeof layouts[layout] === 'function') { + await layouts[layout]() + } + }) + }) + // Prefetch layouts & middleware + nuxtApp.hooks.hook('link:prefetch', (url) => { + if (hasProtocol(url)) { return } + const route = router.resolve(url) + if (!route) { return } + const layout = route?.meta?.layout + let middleware = Array.isArray(route?.meta?.middleware) ? route?.meta?.middleware : [route?.meta?.middleware] + middleware = middleware.filter(m => typeof m === 'string') + + for (const name of middleware) { + if (typeof namedMiddleware[name] === 'function') { + namedMiddleware[name]() + } + } - // Force layout prefetch on route changes - nuxtApp.hooks.hook('app:mounted', () => { - router.beforeEach(async (to) => { - const layout = to?.meta?.layout if (layout && typeof layouts[layout] === 'function') { - await layouts[layout]() + layouts[layout]() } }) - }) - // Prefetch layouts & middleware - nuxtApp.hooks.hook('link:prefetch', (url) => { - if (hasProtocol(url)) { return } - const route = router.resolve(url) - if (!route) { return } - const layout = route?.meta?.layout - let middleware = Array.isArray(route?.meta?.middleware) ? route?.meta?.middleware : [route?.meta?.middleware] - middleware = middleware.filter(m => typeof m === 'string') - - for (const name of middleware) { - if (typeof namedMiddleware[name] === 'function') { - namedMiddleware[name]() - } - } - - if (layout && typeof layouts[layout] === 'function') { - layouts[layout]() - } - }) + } }) diff --git a/packages/nuxt/src/pages/runtime/plugins/router.ts b/packages/nuxt/src/pages/runtime/plugins/router.ts index c76405d4d2..5e48553154 100644 --- a/packages/nuxt/src/pages/runtime/plugins/router.ts +++ b/packages/nuxt/src/pages/runtime/plugins/router.ts @@ -45,157 +45,161 @@ function createCurrentLocation ( return path + search + hash } -export default defineNuxtPlugin(async (nuxtApp) => { - let routerBase = useRuntimeConfig().app.baseURL - if (routerOptions.hashMode && !routerBase.includes('#')) { - // allow the user to provide a `#` in the middle: `/base/#/app` - routerBase += '#' - } - - const history = routerOptions.history?.(routerBase) ?? (process.client - ? (routerOptions.hashMode ? createWebHashHistory(routerBase) : createWebHistory(routerBase)) - : createMemoryHistory(routerBase) - ) - - const routes = routerOptions.routes?.(_routes) ?? _routes - - const initialURL = process.server ? nuxtApp.ssrContext!.url : createCurrentLocation(routerBase, window.location) - const router = createRouter({ - ...routerOptions, - history, - routes - }) - nuxtApp.vueApp.use(router) - - const previousRoute = shallowRef(router.currentRoute.value) - router.afterEach((_to, from) => { - previousRoute.value = from - }) - - Object.defineProperty(nuxtApp.vueApp.config.globalProperties, 'previousRoute', { - get: () => previousRoute.value - }) - - // Allows suspending the route object until page navigation completes - const _route = shallowRef(router.resolve(initialURL) as RouteLocation) - const syncCurrentRoute = () => { _route.value = router.currentRoute.value } - nuxtApp.hook('page:finish', syncCurrentRoute) - router.afterEach((to, from) => { - // We won't trigger suspense if the component is reused between routes - // so we need to update the route manually - if (to.matched[0]?.components?.default === from.matched[0]?.components?.default) { - syncCurrentRoute() - } - }) - - // https://github.com/vuejs/router/blob/main/packages/router/src/router.ts#L1225-L1233 - const route = {} as RouteLocation - for (const key in _route.value) { - (route as any)[key] = computed(() => _route.value[key as keyof RouteLocation]) - } - - nuxtApp._route = reactive(route) - - nuxtApp._middleware = nuxtApp._middleware || { - global: [], - named: {} - } - - const error = useError() - - try { - if (process.server) { - await router.push(initialURL) +export default defineNuxtPlugin({ + name: 'nuxt:router', + enforce: 'pre', + async setup (nuxtApp) { + let routerBase = useRuntimeConfig().app.baseURL + if (routerOptions.hashMode && !routerBase.includes('#')) { + // allow the user to provide a `#` in the middle: `/base/#/app` + routerBase += '#' } - await router.isReady() - } catch (error: any) { - // We'll catch 404s here - await callWithNuxt(nuxtApp, showError, [error]) - } + const history = routerOptions.history?.(routerBase) ?? (process.client + ? (routerOptions.hashMode ? createWebHashHistory(routerBase) : createWebHistory(routerBase)) + : createMemoryHistory(routerBase) + ) - const initialLayout = useState('_layout') - router.beforeEach(async (to, from) => { - to.meta = reactive(to.meta) - if (nuxtApp.isHydrating && initialLayout.value && !isReadonly(to.meta.layout)) { - to.meta.layout = initialLayout.value as Exclude - } - nuxtApp._processingMiddleware = true + const routes = routerOptions.routes?.(_routes) ?? _routes - type MiddlewareDef = string | RouteMiddleware - const middlewareEntries = new Set([...globalMiddleware, ...nuxtApp._middleware.global]) - for (const component of to.matched) { - const componentMiddleware = component.meta.middleware as MiddlewareDef | MiddlewareDef[] - if (!componentMiddleware) { continue } - if (Array.isArray(componentMiddleware)) { - for (const entry of componentMiddleware) { - middlewareEntries.add(entry) - } - } else { - middlewareEntries.add(componentMiddleware) + const initialURL = process.server ? nuxtApp.ssrContext!.url : createCurrentLocation(routerBase, window.location) + const router = createRouter({ + ...routerOptions, + history, + routes + }) + nuxtApp.vueApp.use(router) + + const previousRoute = shallowRef(router.currentRoute.value) + router.afterEach((_to, from) => { + previousRoute.value = from + }) + + Object.defineProperty(nuxtApp.vueApp.config.globalProperties, 'previousRoute', { + get: () => previousRoute.value + }) + + // Allows suspending the route object until page navigation completes + const _route = shallowRef(router.resolve(initialURL) as RouteLocation) + const syncCurrentRoute = () => { _route.value = router.currentRoute.value } + nuxtApp.hook('page:finish', syncCurrentRoute) + router.afterEach((to, from) => { + // We won't trigger suspense if the component is reused between routes + // so we need to update the route manually + if (to.matched[0]?.components?.default === from.matched[0]?.components?.default) { + syncCurrentRoute() } + }) + + // https://github.com/vuejs/router/blob/main/packages/router/src/router.ts#L1225-L1233 + const route = {} as RouteLocation + for (const key in _route.value) { + (route as any)[key] = computed(() => _route.value[key as keyof RouteLocation]) } - for (const entry of middlewareEntries) { - const middleware = typeof entry === 'string' ? nuxtApp._middleware.named[entry] || await namedMiddleware[entry]?.().then((r: any) => r.default || r) : entry + nuxtApp._route = reactive(route) - if (!middleware) { - if (process.dev) { - throw new Error(`Unknown route middleware: '${entry}'. Valid middleware: ${Object.keys(namedMiddleware).map(mw => `'${mw}'`).join(', ')}.`) - } - throw new Error(`Unknown route middleware: '${entry}'.`) - } - - const result = await callWithNuxt(nuxtApp, middleware, [to, from]) - if (process.server || (!nuxtApp.payload.serverRendered && nuxtApp.isHydrating)) { - if (result === false || result instanceof Error) { - const error = result || createError({ - statusCode: 404, - statusMessage: `Page Not Found: ${initialURL}` - }) - await callWithNuxt(nuxtApp, showError, [error]) - return false - } - } - if (result || result === false) { return result } + nuxtApp._middleware = nuxtApp._middleware || { + global: [], + named: {} } - }) - router.afterEach(async (to) => { - delete nuxtApp._processingMiddleware + const error = useError() - if (process.client && !nuxtApp.isHydrating && error.value) { - // Clear any existing errors - await callWithNuxt(nuxtApp, clearError) - } - if (to.matched.length === 0) { - await callWithNuxt(nuxtApp, showError, [createError({ - statusCode: 404, - fatal: false, - statusMessage: `Page not found: ${to.fullPath}` - })]) - } else if (process.server) { - const currentURL = to.fullPath || '/' - if (!isEqual(currentURL, initialURL, { trailingSlash: true })) { - const event = await callWithNuxt(nuxtApp, useRequestEvent) - const options = { redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302 } - await callWithNuxt(nuxtApp, navigateTo, [currentURL, options]) - } - } - }) - - nuxtApp.hooks.hookOnce('app:created', async () => { try { - await router.replace({ - ...router.resolve(initialURL), - name: undefined, // #4920, #$4982 - force: true - }) + if (process.server) { + await router.push(initialURL) + } + + await router.isReady() } catch (error: any) { - // We'll catch middleware errors or deliberate exceptions here + // We'll catch 404s here await callWithNuxt(nuxtApp, showError, [error]) } - }) - return { provide: { router } } + const initialLayout = useState('_layout') + router.beforeEach(async (to, from) => { + to.meta = reactive(to.meta) + if (nuxtApp.isHydrating && initialLayout.value && !isReadonly(to.meta.layout)) { + to.meta.layout = initialLayout.value as Exclude + } + nuxtApp._processingMiddleware = true + + type MiddlewareDef = string | RouteMiddleware + const middlewareEntries = new Set([...globalMiddleware, ...nuxtApp._middleware.global]) + for (const component of to.matched) { + const componentMiddleware = component.meta.middleware as MiddlewareDef | MiddlewareDef[] + if (!componentMiddleware) { continue } + if (Array.isArray(componentMiddleware)) { + for (const entry of componentMiddleware) { + middlewareEntries.add(entry) + } + } else { + middlewareEntries.add(componentMiddleware) + } + } + + for (const entry of middlewareEntries) { + const middleware = typeof entry === 'string' ? nuxtApp._middleware.named[entry] || await namedMiddleware[entry]?.().then((r: any) => r.default || r) : entry + + if (!middleware) { + if (process.dev) { + throw new Error(`Unknown route middleware: '${entry}'. Valid middleware: ${Object.keys(namedMiddleware).map(mw => `'${mw}'`).join(', ')}.`) + } + throw new Error(`Unknown route middleware: '${entry}'.`) + } + + const result = await callWithNuxt(nuxtApp, middleware, [to, from]) + if (process.server || (!nuxtApp.payload.serverRendered && nuxtApp.isHydrating)) { + if (result === false || result instanceof Error) { + const error = result || createError({ + statusCode: 404, + statusMessage: `Page Not Found: ${initialURL}` + }) + await callWithNuxt(nuxtApp, showError, [error]) + return false + } + } + if (result || result === false) { return result } + } + }) + + router.afterEach(async (to) => { + delete nuxtApp._processingMiddleware + + if (process.client && !nuxtApp.isHydrating && error.value) { + // Clear any existing errors + await callWithNuxt(nuxtApp, clearError) + } + if (to.matched.length === 0) { + await callWithNuxt(nuxtApp, showError, [createError({ + statusCode: 404, + fatal: false, + statusMessage: `Page not found: ${to.fullPath}` + })]) + } else if (process.server) { + const currentURL = to.fullPath || '/' + if (!isEqual(currentURL, initialURL, { trailingSlash: true })) { + const event = await callWithNuxt(nuxtApp, useRequestEvent) + const options = { redirectCode: event.node.res.statusCode !== 200 ? event.node.res.statusCode || 302 : 302 } + await callWithNuxt(nuxtApp, navigateTo, [currentURL, options]) + } + } + }) + + nuxtApp.hooks.hookOnce('app:created', async () => { + try { + await router.replace({ + ...router.resolve(initialURL), + name: undefined, // #4920, #$4982 + force: true + }) + } catch (error: any) { + // We'll catch middleware errors or deliberate exceptions here + await callWithNuxt(nuxtApp, showError, [error]) + } + }) + + return { provide: { router } } + } }) as Plugin<{ router: Router }> diff --git a/packages/schema/src/config/build.ts b/packages/schema/src/config/build.ts index 076146b50a..c905fae4ce 100644 --- a/packages/schema/src/config/build.ts +++ b/packages/schema/src/config/build.ts @@ -195,6 +195,7 @@ export default defineUntypedSchema({ asyncFunctions: ['defineNuxtPlugin', 'defineNuxtRouteMiddleware'], objectDefinitions: { defineNuxtComponent: ['asyncData', 'setup'], + defineNuxtPlugin: ['setup'], definePageMeta: ['middleware', 'validate'] } } diff --git a/test/bundle.test.ts b/test/bundle.test.ts index a6603d6629..cf9cd47f5e 100644 --- a/test/bundle.test.ts +++ b/test/bundle.test.ts @@ -26,7 +26,7 @@ describe.skipIf(isWindows || process.env.ECOSYSTEM_CI)('minimal nuxt application it('default client bundle size', async () => { stats.client = await analyzeSizes('**/*.js', publicDir) - expect(roundToKilobytes(stats.client.totalBytes)).toMatchInlineSnapshot('"104k"') + expect(roundToKilobytes(stats.client.totalBytes)).toMatchInlineSnapshot('"105k"') expect(stats.client.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(` [ "_nuxt/_plugin-vue_export-helper.js", @@ -40,7 +40,7 @@ describe.skipIf(isWindows || process.env.ECOSYSTEM_CI)('minimal nuxt application it('default server bundle size', async () => { stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir) - expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"91k"') + expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"92k"') const modules = await analyzeSizes('node_modules/**/*', serverDir) expect(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2650k"') diff --git a/test/fixtures/basic/nuxt.config.ts b/test/fixtures/basic/nuxt.config.ts index a1e40b709d..e625264c02 100644 --- a/test/fixtures/basic/nuxt.config.ts +++ b/test/fixtures/basic/nuxt.config.ts @@ -108,12 +108,6 @@ export default defineNuxtConfig({ addVitePlugin(plugin.vite()) addWebpackPlugin(plugin.webpack()) }, - function (_options, nuxt) { - // TODO: support directly via object syntax plugins: https://github.com/nuxt/nuxt/issues/14628 - nuxt.hook('modules:done', () => { - nuxt.options.plugins.unshift('~/plugins/custom-type-registration') - }) - }, function (_options, nuxt) { const routesToDuplicate = ['/async-parent', '/fixed-keyed-child-parent', '/keyed-child-parent', '/with-layout', '/with-layout2'] const stripLayout = (page: NuxtPage): NuxtPage => ({ diff --git a/test/fixtures/basic/plugins/custom-type-registration.ts b/test/fixtures/basic/plugins/custom-type-registration.ts index b7ef9b110f..ec37ab6ce9 100644 --- a/test/fixtures/basic/plugins/custom-type-registration.ts +++ b/test/fixtures/basic/plugins/custom-type-registration.ts @@ -1,4 +1,4 @@ -export default defineNuxtPlugin((nuxtApp) => { +export default definePayloadPlugin((nuxtApp) => { definePayloadReducer('BlinkingText', data => data === '' && '_') definePayloadReviver('BlinkingText', () => '') if (process.server) { From 5a0a5f405fc475e82b07edc74c57deac4940b280 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 04:59:08 -0700 Subject: [PATCH 39/55] chore(deps): update all non-major dependencies (main) (#20188) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 6 +-- packages/kit/package.json | 2 +- packages/nuxi/package.json | 2 +- packages/test-utils/package.json | 2 +- pnpm-lock.yaml | 90 ++++++++++++++++---------------- 5 files changed, 51 insertions(+), 51 deletions(-) diff --git a/package.json b/package.json index 43eada0aac..6d9d85e820 100644 --- a/package.json +++ b/package.json @@ -53,12 +53,12 @@ "@types/node": "^18.15.11", "@types/rimraf": "^3.0.2", "@types/semver": "^7.3.13", - "@unocss/reset": "^0.51.2", + "@unocss/reset": "^0.51.3", "case-police": "^0.5.14", "changelogen": "^0.5.2", "crawler": "^1.4.0", "eslint": "^8.38.0", - "eslint-plugin-jsdoc": "^40.2.1", + "eslint-plugin-jsdoc": "^40.3.0", "execa": "^7.1.1", "expect-type": "^0.15.0", "globby": "^13.1.3", @@ -69,7 +69,7 @@ "ofetch": "^1.0.1", "pathe": "^1.1.0", "rimraf": "^5.0.0", - "semver": "^7.3.8", + "semver": "^7.4.0", "std-env": "^3.3.2", "typescript": "^5.0.4", "ufo": "^1.1.1", diff --git a/packages/kit/package.json b/packages/kit/package.json index 8994d9d6c5..7361800d1e 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -34,7 +34,7 @@ "pathe": "^1.1.0", "pkg-types": "^1.0.2", "scule": "^1.0.0", - "semver": "^7.3.8", + "semver": "^7.4.0", "unctx": "^2.2.0", "unimport": "^3.0.6", "untyped": "^1.3.2" diff --git a/packages/nuxi/package.json b/packages/nuxi/package.json index 1da97dc25d..169efa6a82 100644 --- a/packages/nuxi/package.json +++ b/packages/nuxi/package.json @@ -44,7 +44,7 @@ "perfect-debounce": "^0.1.3", "pkg-types": "^1.0.2", "scule": "^1.0.0", - "semver": "^7.3.8", + "semver": "^7.4.0", "unbuild": "latest" }, "optionalDependencies": { diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index ed7e555c4f..980530d579 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -34,7 +34,7 @@ "ufo": "^1.1.1" }, "devDependencies": { - "playwright": "^1.32.2", + "playwright": "^1.32.3", "unbuild": "latest", "vitest": "^0.30.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b61298d565..eb233ea267 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,8 +52,8 @@ importers: specifier: ^7.3.13 version: 7.3.13 '@unocss/reset': - specifier: ^0.51.2 - version: 0.51.2 + specifier: ^0.51.3 + version: 0.51.3 case-police: specifier: ^0.5.14 version: 0.5.14 @@ -67,8 +67,8 @@ importers: specifier: ^8.38.0 version: 8.38.0 eslint-plugin-jsdoc: - specifier: ^40.2.1 - version: 40.2.1(eslint@8.38.0) + specifier: ^40.3.0 + version: 40.3.0(eslint@8.38.0) execa: specifier: ^7.1.1 version: 7.1.1 @@ -100,8 +100,8 @@ importers: specifier: ^5.0.0 version: 5.0.0 semver: - specifier: ^7.3.8 - version: 7.3.8 + specifier: ^7.4.0 + version: 7.4.0 std-env: specifier: ^3.3.2 version: 3.3.2 @@ -119,7 +119,7 @@ importers: version: 4.2.1(@types/node@18.15.11) vitest: specifier: ^0.30.0 - version: 0.30.0(playwright@1.32.2) + version: 0.30.0(playwright@1.32.3) vue-tsc: specifier: ^1.2.0 version: 1.2.0(typescript@5.0.4) @@ -161,7 +161,7 @@ importers: version: link:../../../packages/nuxt vitest: specifier: latest - version: 0.30.0(playwright@1.32.2) + version: 0.30.0(playwright@1.32.3) examples/app-config: devDependencies: @@ -403,8 +403,8 @@ importers: specifier: ^1.0.0 version: 1.0.0 semver: - specifier: ^7.3.8 - version: 7.3.8 + specifier: ^7.4.0 + version: 7.4.0 unctx: specifier: ^2.2.0 version: 2.2.0 @@ -510,8 +510,8 @@ importers: specifier: ^1.0.0 version: 1.0.0 semver: - specifier: ^7.3.8 - version: 7.3.8 + specifier: ^7.4.0 + version: 7.4.0 unbuild: specifier: ^1.2.0 version: 1.2.0 @@ -783,14 +783,14 @@ importers: version: 3.2.47 devDependencies: playwright: - specifier: ^1.32.2 - version: 1.32.2 + specifier: ^1.32.3 + version: 1.32.3 unbuild: specifier: ^1.2.0 version: 1.2.0 vitest: specifier: ^0.30.0 - version: 0.30.0(playwright@1.32.2) + version: 0.30.0(playwright@1.32.3) packages/vite: dependencies: @@ -1737,7 +1737,7 @@ packages: nopt: 5.0.0 npmlog: 5.0.1 rimraf: 3.0.2 - semver: 7.3.8 + semver: 7.4.0 tar: 6.1.13 transitivePeerDependencies: - encoding @@ -2332,7 +2332,7 @@ packages: ignore: 5.2.4 natural-compare-lite: 1.4.0 regexpp: 3.2.0 - semver: 7.3.8 + semver: 7.4.0 tsutils: 3.21.0(typescript@5.0.4) typescript: 5.0.4 transitivePeerDependencies: @@ -2406,7 +2406,7 @@ packages: debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 - semver: 7.3.8 + semver: 7.4.0 tsutils: 3.21.0(typescript@5.0.4) typescript: 5.0.4 transitivePeerDependencies: @@ -2427,7 +2427,7 @@ packages: eslint: 8.38.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0(eslint@8.38.0) - semver: 7.3.8 + semver: 7.4.0 transitivePeerDependencies: - supports-color - typescript @@ -2614,8 +2614,8 @@ packages: resolution: {integrity: sha512-m6+M3E2cTPhX+2aKocRfDqQt7ebEtjJHH8sVYpX8xJoN0vOqjSNmUYc6AIkwUYljx4QbEC3thcQSbqel82RbXQ==} dev: true - /@unocss/reset@0.51.2: - resolution: {integrity: sha512-HWn3qSdYT+VE1IiMgsXz5bE9pQF5SXWr7EIjFj2seb+YQkaf266vaUNUM5ln/uD6mWWwuo3TZSrA5+Vz4darkw==} + /@unocss/reset@0.51.3: + resolution: {integrity: sha512-hdm9pKj7ih6MLOSjGJisvh0TMnPmyGDMXQDcgGZJATgVuTJtBmXE74nsIgBVRCfjwqDDqmzG2TB0PlpiTFM9mg==} dev: true /@unocss/scope@0.45.30: @@ -3477,7 +3477,7 @@ packages: /builtins@5.0.1: resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} dependencies: - semver: 7.3.8 + semver: 7.4.0 dev: true /bundle-name@3.0.0: @@ -3596,7 +3596,7 @@ packages: pathe: 1.1.0 pkg-types: 1.0.2 scule: 1.0.0 - semver: 7.3.8 + semver: 7.4.0 yaml: 2.2.1 transitivePeerDependencies: - supports-color @@ -3793,7 +3793,7 @@ packages: js-string-escape: 1.0.1 lodash: 4.17.21 md5-hex: 3.0.1 - semver: 7.3.8 + semver: 7.4.0 well-known-symbols: 2.0.0 dev: true @@ -3917,7 +3917,7 @@ packages: postcss-modules-scope: 3.0.0(postcss@8.4.21) postcss-modules-values: 4.0.0(postcss@8.4.21) postcss-value-parser: 4.2.0 - semver: 7.3.8 + semver: 7.4.0 webpack: 5.78.0 dev: false @@ -4874,8 +4874,8 @@ packages: - supports-color dev: true - /eslint-plugin-jsdoc@40.2.1(eslint@8.38.0): - resolution: {integrity: sha512-d7PsUMNqrbCROSAeJd2dhTS/DapYEJ7vo27g12u4nh/bLQHHcqXNbXwhANf/D5/gUDNwinU3ZmmM4f2alQ1ncA==} + /eslint-plugin-jsdoc@40.3.0(eslint@8.38.0): + resolution: {integrity: sha512-EhCqpzRkxoT2DUB4AnrU0ggBYvTh3bWrLZzQTupq6vSVE6XzNwJVKsOHa41GCoevnsWMBNmoDVjXWGqckjuG1g==} engines: {node: ^14 || ^16 || ^17 || ^18 || ^19} peerDependencies: eslint: ^7.0.0 || ^8.0.0 @@ -4886,7 +4886,7 @@ packages: escape-string-regexp: 4.0.0 eslint: 8.38.0 esquery: 1.5.0 - semver: 7.3.8 + semver: 7.4.0 spdx-expression-parse: 3.0.1 transitivePeerDependencies: - supports-color @@ -4906,7 +4906,7 @@ packages: is-core-module: 2.11.0 minimatch: 3.1.2 resolve: 1.22.1 - semver: 7.3.8 + semver: 7.4.0 dev: true /eslint-plugin-node@11.1.0(eslint@8.38.0): @@ -4952,7 +4952,7 @@ packages: read-pkg-up: 7.0.1 regexp-tree: 0.1.24 safe-regex: 2.1.1 - semver: 7.3.8 + semver: 7.4.0 strip-indent: 3.0.0 dev: true @@ -4967,7 +4967,7 @@ packages: natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.0.11 - semver: 7.3.8 + semver: 7.4.0 vue-eslint-parser: 9.1.0(eslint@8.38.0) xml-name-validator: 4.0.0 transitivePeerDependencies: @@ -5318,7 +5318,7 @@ packages: minimatch: 3.1.2 node-abort-controller: 3.1.1 schema-utils: 3.1.1 - semver: 7.3.8 + semver: 7.4.0 tapable: 2.2.1 typescript: 5.0.4 webpack: 5.78.0 @@ -6766,7 +6766,7 @@ packages: rollup: 3.20.2 rollup-plugin-visualizer: 5.9.0(rollup@3.20.2) scule: 1.0.0 - semver: 7.3.8 + semver: 7.4.0 serve-placeholder: 2.0.1 serve-static: 1.15.0 source-map-support: 0.5.21 @@ -7182,19 +7182,19 @@ packages: mlly: 1.2.0 pathe: 1.1.0 - /playwright-core@1.32.2: - resolution: {integrity: sha512-zD7aonO+07kOTthsrCR3YCVnDcqSHIJpdFUtZEMOb6//1Rc7/6mZDRdw+nlzcQiQltOOsiqI3rrSyn/SlyjnJQ==} + /playwright-core@1.32.3: + resolution: {integrity: sha512-SB+cdrnu74ZIn5Ogh/8278ngEh9NEEV0vR4sJFmK04h2iZpybfbqBY0bX6+BLYWVdV12JLLI+JEFtSnYgR+mWg==} engines: {node: '>=14'} hasBin: true dev: true - /playwright@1.32.2: - resolution: {integrity: sha512-jHVnXJke0PXpuPszKtk9y1zZSlzO5+2a+aockT/AND0oeXx46FiJEFrafthurglLygVZA+1gEbtUM1C7qtTV+Q==} + /playwright@1.32.3: + resolution: {integrity: sha512-h/ylpgoj6l/EjkfUDyx8cdOlfzC96itPpPe8BXacFkqpw/YsuxkpPyVbzEq4jw+bAJh5FLgh31Ljg2cR6HV3uw==} engines: {node: '>=14'} hasBin: true requiresBuild: true dependencies: - playwright-core: 1.32.2 + playwright-core: 1.32.3 dev: true /pluralize@8.0.0: @@ -7308,7 +7308,7 @@ packages: cosmiconfig-typescript-loader: 4.3.0(@types/node@18.15.11)(cosmiconfig@8.1.3)(ts-node@10.9.1)(typescript@5.0.4) klona: 2.0.6 postcss: 8.4.21 - semver: 7.3.8 + semver: 7.4.0 ts-node: 10.9.1(@types/node@18.15.11)(typescript@5.0.4) typescript: 5.0.4 webpack: 5.78.0 @@ -7991,8 +7991,8 @@ packages: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true - /semver@7.3.8: - resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + /semver@7.4.0: + resolution: {integrity: sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==} engines: {node: '>=10'} hasBin: true dependencies: @@ -9075,7 +9075,7 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vitest@0.30.0(playwright@1.32.2): + /vitest@0.30.0(playwright@1.32.3): resolution: {integrity: sha512-2WW4WeTHtrLFeoiuotWvEW6khozx1NvMGYoGsNz2btdddEbqvEdPJIouIdoiC5i61Rl1ctZvm9cn2R9TcPQlzw==} engines: {node: '>=v14.18.0'} hasBin: true @@ -9124,7 +9124,7 @@ packages: magic-string: 0.30.0 pathe: 1.1.0 picocolors: 1.0.0 - playwright: 1.32.2 + playwright: 1.32.3 source-map: 0.6.1 std-env: 3.3.2 strip-literal: 1.0.1 @@ -9152,7 +9152,7 @@ packages: engines: {vscode: ^1.52.0} dependencies: minimatch: 3.1.2 - semver: 7.3.8 + semver: 7.4.0 vscode-languageserver-protocol: 3.16.0 dev: false @@ -9220,7 +9220,7 @@ packages: espree: 9.5.1 esquery: 1.5.0 lodash: 4.17.21 - semver: 7.3.8 + semver: 7.4.0 transitivePeerDependencies: - supports-color dev: true From bc910f68374f540994b2da4528f08a4186c00930 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 05:38:53 -0700 Subject: [PATCH 40/55] chore(deps): update all non-major dependencies (main) (#20196) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- package.json | 2 +- packages/nuxt/package.json | 4 +- packages/test-utils/package.json | 2 +- packages/vite/package.json | 2 +- pnpm-lock.yaml | 109 ++++++++++++++++--------------- 5 files changed, 60 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index 6d9d85e820..5e7074c30f 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "ufo": "^1.1.1", "unbuild": "^1.2.0", "vite": "^4.2.1", - "vitest": "^0.30.0", + "vitest": "^0.30.1", "vue-tsc": "^1.2.0" }, "packageManager": "pnpm@8.2.0", diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index e5ff4d874f..b0076f0cec 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -59,7 +59,7 @@ "@nuxt/devalue": "^2.0.0", "@nuxt/kit": "workspace:../kit", "@nuxt/schema": "workspace:../schema", - "@nuxt/telemetry": "^2.1.10", + "@nuxt/telemetry": "^2.2.0", "@nuxt/ui-templates": "^1.1.1", "@nuxt/vite-builder": "workspace:../vite", "@unhead/ssr": "^1.1.25", @@ -95,7 +95,7 @@ "strip-literal": "^1.0.1", "ufo": "^1.1.1", "unctx": "^2.2.0", - "unenv": "^1.3.0", + "unenv": "^1.3.1", "unimport": "^3.0.6", "unplugin": "^1.3.1", "untyped": "^1.3.2", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 980530d579..4d22530b44 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -36,7 +36,7 @@ "devDependencies": { "playwright": "^1.32.3", "unbuild": "latest", - "vitest": "^0.30.0" + "vitest": "^0.30.1" }, "peerDependencies": { "vue": "^3.2.47" diff --git a/packages/vite/package.json b/packages/vite/package.json index 63ad91ad63..0a78daa9e8 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -55,7 +55,7 @@ "ufo": "^1.1.1", "unplugin": "^1.3.1", "vite": "~4.2.1", - "vite-node": "^0.30.0", + "vite-node": "^0.30.1", "vite-plugin-checker": "^0.5.6", "vue-bundle-renderer": "^1.0.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eb233ea267..9b216e8e9b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -118,8 +118,8 @@ importers: specifier: ^4.2.1 version: 4.2.1(@types/node@18.15.11) vitest: - specifier: ^0.30.0 - version: 0.30.0(playwright@1.32.3) + specifier: ^0.30.1 + version: 0.30.1(playwright@1.32.3) vue-tsc: specifier: ^1.2.0 version: 1.2.0(typescript@5.0.4) @@ -161,7 +161,7 @@ importers: version: link:../../../packages/nuxt vitest: specifier: latest - version: 0.30.0(playwright@1.32.3) + version: 0.30.1(playwright@1.32.3) examples/app-config: devDependencies: @@ -528,8 +528,8 @@ importers: specifier: workspace:* version: link:../schema '@nuxt/telemetry': - specifier: ^2.1.10 - version: 2.1.10 + specifier: ^2.2.0 + version: 2.2.0 '@nuxt/ui-templates': specifier: ^1.1.1 version: 1.1.1 @@ -639,8 +639,8 @@ importers: specifier: ^2.2.0 version: 2.2.0 unenv: - specifier: ^1.3.0 - version: 1.3.0 + specifier: ^1.3.1 + version: 1.3.1 unimport: specifier: ^3.0.6 version: 3.0.6(rollup@3.20.2) @@ -789,8 +789,8 @@ importers: specifier: ^1.2.0 version: 1.2.0 vitest: - specifier: ^0.30.0 - version: 0.30.0(playwright@1.32.3) + specifier: ^0.30.1 + version: 0.30.1(playwright@1.32.3) packages/vite: dependencies: @@ -891,8 +891,8 @@ importers: specifier: ^4.2.1 version: 4.2.1(@types/node@18.15.11) vite-node: - specifier: ^0.30.0 - version: 0.30.0(@types/node@18.15.11) + specifier: ^0.30.1 + version: 0.30.1(@types/node@18.15.11) vite-plugin-checker: specifier: ^0.5.6 version: 0.5.6(eslint@8.38.0)(typescript@5.0.4)(vite@4.2.1)(vue-tsc@1.2.0) @@ -1784,29 +1784,29 @@ packages: webpack: 5.78.0 dev: false - /@nuxt/telemetry@2.1.10: - resolution: {integrity: sha512-FOsfC0i6Ix66M/ZlWV/095JIdfnRR9CRbFvBSpojt2CpbwU1pGMbRiicwYg2f1Wf27LXQRNpNn1OczruBfEWag==} + /@nuxt/telemetry@2.2.0: + resolution: {integrity: sha512-Z2UmPkBy5WjxvHKuUcl1X6vKWnIyWSP+9UGde1F+MzzZxYgAQybFud1uL2B3KCowxZdoqT1hd2WklV7EtyCwrQ==} hasBin: true dependencies: '@nuxt/kit': link:packages/kit chalk: 5.2.0 ci-info: 3.8.0 - consola: 2.15.3 + consola: 3.0.1 create-require: 1.1.1 defu: 6.1.2 destr: 1.2.2 dotenv: 16.0.3 fs-extra: 10.1.0 git-url-parse: 13.1.0 - inquirer: 9.1.4 + inquirer: 9.1.5 is-docker: 3.0.0 jiti: 1.18.2 mri: 1.2.0 - nanoid: 4.0.1 + nanoid: 4.0.2 node-fetch: 3.3.1 ofetch: 1.0.1 parse-git-config: 3.0.0 - rc9: 2.0.1 + rc9: 2.1.0 std-env: 3.3.2 dev: false @@ -2727,39 +2727,39 @@ packages: vite: 4.2.1(@types/node@18.15.11) vue: 3.2.47 - /@vitest/expect@0.30.0: - resolution: {integrity: sha512-b/jLWBqi6WQHfezWm8VjgXdIyfejAurtxqdyCdDqoToCim5W/nDxKjFAADitEHPz80oz+IP+c+wmkGKBucSpiw==} + /@vitest/expect@0.30.1: + resolution: {integrity: sha512-c3kbEtN8XXJSeN81iDGq29bUzSjQhjES2WR3aColsS4lPGbivwLtas4DNUe0jD9gg/FYGIteqOenfU95EFituw==} dependencies: - '@vitest/spy': 0.30.0 - '@vitest/utils': 0.30.0 + '@vitest/spy': 0.30.1 + '@vitest/utils': 0.30.1 chai: 4.3.7 dev: true - /@vitest/runner@0.30.0: - resolution: {integrity: sha512-Xh4xkdRcymdeRNrSwjhgarCTSgnQu2J59wsFI6i4UhKrL5whzo5+vWyq7iWK1ht3fppPeNAtvkbqUDf+OJSCbQ==} + /@vitest/runner@0.30.1: + resolution: {integrity: sha512-W62kT/8i0TF1UBCNMRtRMOBWJKRnNyv9RrjIgdUryEe0wNpGZvvwPDLuzYdxvgSckzjp54DSpv1xUbv4BQ0qVA==} dependencies: - '@vitest/utils': 0.30.0 + '@vitest/utils': 0.30.1 concordance: 5.0.4 p-limit: 4.0.0 pathe: 1.1.0 dev: true - /@vitest/snapshot@0.30.0: - resolution: {integrity: sha512-e4eSGCy36Bw3/Tkir9qYJDlFsUz3NALFPNJSxzlY8CFl901TV9iZdKgpqXpyG1sAhLO0tPHThBAMHRi8hRA8cg==} + /@vitest/snapshot@0.30.1: + resolution: {integrity: sha512-fJZqKrE99zo27uoZA/azgWyWbFvM1rw2APS05yB0JaLwUIg9aUtvvnBf4q7JWhEcAHmSwbrxKFgyBUga6tq9Tw==} dependencies: magic-string: 0.30.0 pathe: 1.1.0 pretty-format: 27.5.1 dev: true - /@vitest/spy@0.30.0: - resolution: {integrity: sha512-olTWyG5gVWdfhCrdgxWQb2K3JYtj1/ZwInFFOb4GZ2HFI91PUWHWHhLRPORxwRwVvoXD1MS1162vPJZuHlKJkg==} + /@vitest/spy@0.30.1: + resolution: {integrity: sha512-YfJeIf37GvTZe04ZKxzJfnNNuNSmTEGnla2OdL60C8od16f3zOfv9q9K0nNii0NfjDJRt/CVN/POuY5/zTS+BA==} dependencies: tinyspy: 2.1.0 dev: true - /@vitest/utils@0.30.0: - resolution: {integrity: sha512-qFZgoOKQ+rJV9xG4BBxgOSilnLQ2gkfG4I+z1wBuuQ3AD33zQrnB88kMFfzsot1E1AbF3dNK1e4CU7q3ojahRA==} + /@vitest/utils@0.30.1: + resolution: {integrity: sha512-/c8Xv2zUVc+rnNt84QF0Y0zkfxnaGhp87K2dYJMLtLOIckPzuxLVzAtFCicGFdB4NeBHNzTRr1tNn7rCtQcWFA==} dependencies: concordance: 5.0.4 loupe: 2.3.6 @@ -3504,7 +3504,7 @@ packages: mlly: 1.2.0 pathe: 1.1.0 pkg-types: 1.0.2 - rc9: 2.0.1 + rc9: 2.1.0 transitivePeerDependencies: - supports-color @@ -5836,9 +5836,9 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} dev: true - /inquirer@9.1.4: - resolution: {integrity: sha512-9hiJxE5gkK/cM2d1mTEnuurGTAoHebbkX0BYl3h7iEg7FYfuNIom+nDfBCSWtvSnoSrWCeBxqqBZu26xdlJlXA==} - engines: {node: '>=12.0.0'} + /inquirer@9.1.5: + resolution: {integrity: sha512-3ygAIh8gcZavV9bj6MTdYddG2zPSYswP808fKS46NOwlF0zZljVpnLCHODDqItWJDbDpLb3aouAxGaJbkxoppA==} + engines: {node: '>=14.18.0'} dependencies: ansi-escapes: 6.0.0 chalk: 5.2.0 @@ -5847,7 +5847,7 @@ packages: external-editor: 3.1.0 figures: 5.0.0 lodash: 4.17.21 - mute-stream: 0.0.8 + mute-stream: 1.0.0 ora: 6.1.2 run-async: 2.4.1 rxjs: 7.8.0 @@ -6687,8 +6687,9 @@ packages: /muggle-string@0.2.2: resolution: {integrity: sha512-YVE1mIJ4VpUMqZObFndk9CJu6DBJR/GB13p3tXuNbwD4XExaI5EOuRl6BHeIDxIqXZVxSfAC+y6U1Z/IxCfKUg==} - /mute-stream@0.0.8: - resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + /mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} dev: false /nanoid@3.3.4: @@ -6696,8 +6697,8 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - /nanoid@4.0.1: - resolution: {integrity: sha512-udKGtCCUafD3nQtJg9wBhRP3KMbPglUsgV5JVsXhvyBs/oefqb4sqMEhKBBgqZncYowu58p1prsZQBYvAj/Gww==} + /nanoid@4.0.2: + resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==} engines: {node: ^14 || ^16 || >=18} hasBin: true dev: false @@ -6772,7 +6773,7 @@ packages: source-map-support: 0.5.21 std-env: 3.3.2 ufo: 1.1.1 - unenv: 1.3.0 + unenv: 1.3.1 unimport: 3.0.6(rollup@3.20.2) unstorage: 1.4.1 transitivePeerDependencies: @@ -7669,8 +7670,8 @@ packages: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} - /rc9@2.0.1: - resolution: {integrity: sha512-9EfjLgNmzP9255YX8bGnILQcmdtOXKtUlFTu8bOZPJVtaUDZ2imswcUdpK51tMjTRQyB7r5RebNijrzuyGXcVA==} + /rc9@2.1.0: + resolution: {integrity: sha512-ROO9bv8PPqngWKoiUZU3JDQ4sugpdRs9DfwHnzDSxK25XtQn6BEHL6EOd/OtKuDT2qodrtNR+0WkPT6l0jxH5Q==} dependencies: defu: 6.1.2 destr: 1.2.2 @@ -8722,8 +8723,8 @@ packages: busboy: 1.6.0 dev: true - /unenv@1.3.0: - resolution: {integrity: sha512-NTAVceoRPD5brWx6ej+zVCP6aw1LXsx6VjmpaJKE3nZqrycZ6nB1MrKOVZ65hcSVlzCb8QdZAEY162awdD5juA==} + /unenv@1.3.1: + resolution: {integrity: sha512-4hTMiJf1TgQNnOsZxaI6XpCpVvOUNYLW3NxEkjdzXf+Dukys4b01AShapcXzKzvgoyoWByP3MLbg/CkzcKx+GA==} dependencies: defu: 6.1.2 mime: 3.0.0 @@ -8935,8 +8936,8 @@ packages: extsprintf: 1.3.0 dev: true - /vite-node@0.30.0(@types/node@18.15.11): - resolution: {integrity: sha512-23X5Ggylx0kU/bMf8MCcEEl55d/gsTtU81mMZjm7Z0FSpgKZexUqmX3mJtgglP9SySQQs9ydYg/GEahi/cKHaA==} + /vite-node@0.30.1(@types/node@18.15.11): + resolution: {integrity: sha512-vTikpU/J7e6LU/8iM3dzBo8ZhEiKZEKRznEMm+mJh95XhWaPrJQraT/QsT2NWmuEf+zgAoMe64PKT7hfZ1Njmg==} engines: {node: '>=v14.18.0'} hasBin: true dependencies: @@ -9075,8 +9076,8 @@ packages: optionalDependencies: fsevents: 2.3.2 - /vitest@0.30.0(playwright@1.32.3): - resolution: {integrity: sha512-2WW4WeTHtrLFeoiuotWvEW6khozx1NvMGYoGsNz2btdddEbqvEdPJIouIdoiC5i61Rl1ctZvm9cn2R9TcPQlzw==} + /vitest@0.30.1(playwright@1.32.3): + resolution: {integrity: sha512-y35WTrSTlTxfMLttgQk4rHcaDkbHQwDP++SNwPb+7H8yb13Q3cu2EixrtHzF27iZ8v0XCciSsLg00RkPAzB/aA==} engines: {node: '>=v14.18.0'} hasBin: true peerDependencies: @@ -9109,11 +9110,11 @@ packages: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 '@types/node': 18.15.11 - '@vitest/expect': 0.30.0 - '@vitest/runner': 0.30.0 - '@vitest/snapshot': 0.30.0 - '@vitest/spy': 0.30.0 - '@vitest/utils': 0.30.0 + '@vitest/expect': 0.30.1 + '@vitest/runner': 0.30.1 + '@vitest/snapshot': 0.30.1 + '@vitest/spy': 0.30.1 + '@vitest/utils': 0.30.1 acorn: 8.8.2 acorn-walk: 8.2.0 cac: 6.7.14 @@ -9131,7 +9132,7 @@ packages: tinybench: 2.4.0 tinypool: 0.4.0 vite: 4.2.1(@types/node@18.15.11) - vite-node: 0.30.0(@types/node@18.15.11) + vite-node: 0.30.1(@types/node@18.15.11) why-is-node-running: 2.2.2 transitivePeerDependencies: - less From 1f70cb7219ef8f7f921d92c2a2a8f1a529d1b954 Mon Sep 17 00:00:00 2001 From: Jeremy Graziani Date: Tue, 11 Apr 2023 14:41:22 +0200 Subject: [PATCH 41/55] docs: fix typo in `@pinia/nuxt` module name (#20199) --- docs/7.migration/2.configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/7.migration/2.configuration.md b/docs/7.migration/2.configuration.md index 84c8634e32..d56d218211 100644 --- a/docs/7.migration/2.configuration.md +++ b/docs/7.migration/2.configuration.md @@ -136,7 +136,7 @@ Nuxt no longer provides a Vuex integration. Instead, the official Vue recommenda A simple way to provide global state management with pinia would be: -Install the [@nuxt/pinia](https://nuxt.com/modules/pinia) module: +Install the [@pinia/nuxt](https://nuxt.com/modules/pinia) module: ```bash yarn add pinia @pinia/nuxt From 0443a283d9cbd7686f9f114e3e76eae837a85ac8 Mon Sep 17 00:00:00 2001 From: Nolan <824015+ncphillips@users.noreply.github.com> Date: Tue, 11 Apr 2023 09:41:44 -0300 Subject: [PATCH 42/55] docs: add import to server-side cookies example (#20197) --- docs/1.getting-started/6.data-fetching.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/1.getting-started/6.data-fetching.md b/docs/1.getting-started/6.data-fetching.md index 089f61b40a..f001320633 100644 --- a/docs/1.getting-started/6.data-fetching.md +++ b/docs/1.getting-started/6.data-fetching.md @@ -263,6 +263,8 @@ Be very careful before proxying headers to an external API and just include head If you want to pass on/proxy cookies in the other direction, from an internal request back to the client, you will need to handle this yourself. ```ts [composables/fetch.ts] +import { appendHeader, H3Event } from 'h3' + export const fetchWithCookie = async (event: H3Event, url: string) => { const res = await $fetch.raw(url) const cookies = (res.headers.get('set-cookie') || '').split(',') From 89ab2e522d90a31f49155fc11e7321c2bb879c71 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 11 Apr 2023 13:46:49 +0100 Subject: [PATCH 43/55] fix(nuxi, vite): suppress sourcemap + native fetch warnings (#20198) --- packages/nuxi/src/cli.ts | 5 +++++ packages/vite/src/utils/logger.ts | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/packages/nuxi/src/cli.ts b/packages/nuxi/src/cli.ts index 0118ade73d..5084564dbc 100755 --- a/packages/nuxi/src/cli.ts +++ b/packages/nuxi/src/cli.ts @@ -54,6 +54,11 @@ const wrapReporter = (reporter: ConsolaReporter) => ({ if (msg.startsWith('[Vue Router warn]: No match found for location with path')) { return } + // Suppress warning about native Node.js fetch + if (msg.includes('ExperimentalWarning: The Fetch API is an experimental feature')) { + return + } + // TODO: resolve upstream in Vite // Hide sourcemap warnings related to node_modules if (msg.startsWith('Sourcemap') && msg.includes('node_modules')) { return diff --git a/packages/vite/src/utils/logger.ts b/packages/vite/src/utils/logger.ts index cf7d2452bb..7b25658b2a 100644 --- a/packages/vite/src/utils/logger.ts +++ b/packages/vite/src/utils/logger.ts @@ -27,6 +27,12 @@ export function createViteLogger (config: vite.InlineConfig): vite.Logger { const clearScreen = canClearScreen ? clear : () => {} function output (type: vite.LogType, msg: string, options: vite.LogErrorOptions = {}) { + if (typeof msg === 'string' && !process.env.DEBUG) { + // TODO: resolve upstream in Vite + // Hide sourcemap warnings related to node_modules + if (msg.startsWith('Sourcemap') && msg.includes('node_modules')) { return } + } + const sameAsLast = lastType === type && lastMsg === msg if (sameAsLast) { duplicateCount += 1 From 4da289d150d07cd2a9e129dde9678a0d088b7547 Mon Sep 17 00:00:00 2001 From: Harlan Wilton Date: Tue, 11 Apr 2023 20:55:25 +0700 Subject: [PATCH 44/55] fix(schema): allow `ignorePrefix` to be changed (#20202) --- packages/schema/src/config/common.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/schema/src/config/common.ts b/packages/schema/src/config/common.ts index cfd29dc9a4..bce40ea5ad 100644 --- a/packages/schema/src/config/common.ts +++ b/packages/schema/src/config/common.ts @@ -331,7 +331,9 @@ export default defineUntypedSchema({ * Any file in `pages/`, `layouts/`, `middleware/` or `store/` will be ignored during * building if its filename starts with the prefix specified by `ignorePrefix`. */ - ignorePrefix: '-', + ignorePrefix: { + $resolve: (val) => val ?? '-', + }, /** * More customizable than `ignorePrefix`: all files matching glob patterns specified From 4fc3e780be00443830566e0b7ca363e14d43574d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 06:55:49 -0700 Subject: [PATCH 45/55] chore(deps): update devdependency @unocss/reset to ^0.51.4 (main) (#20200) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 5e7074c30f..beaae878f5 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@types/node": "^18.15.11", "@types/rimraf": "^3.0.2", "@types/semver": "^7.3.13", - "@unocss/reset": "^0.51.3", + "@unocss/reset": "^0.51.4", "case-police": "^0.5.14", "changelogen": "^0.5.2", "crawler": "^1.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9b216e8e9b..bae91f0667 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,8 +52,8 @@ importers: specifier: ^7.3.13 version: 7.3.13 '@unocss/reset': - specifier: ^0.51.3 - version: 0.51.3 + specifier: ^0.51.4 + version: 0.51.4 case-police: specifier: ^0.5.14 version: 0.5.14 @@ -2614,8 +2614,8 @@ packages: resolution: {integrity: sha512-m6+M3E2cTPhX+2aKocRfDqQt7ebEtjJHH8sVYpX8xJoN0vOqjSNmUYc6AIkwUYljx4QbEC3thcQSbqel82RbXQ==} dev: true - /@unocss/reset@0.51.3: - resolution: {integrity: sha512-hdm9pKj7ih6MLOSjGJisvh0TMnPmyGDMXQDcgGZJATgVuTJtBmXE74nsIgBVRCfjwqDDqmzG2TB0PlpiTFM9mg==} + /@unocss/reset@0.51.4: + resolution: {integrity: sha512-3FnajZSOrQ4qSbpkY1IGRIFYw8I9E98SBXvjMnHqSl8k4YPbBP29W3YrgSVBMOnPNRL67hRcTaMF3nmbnBuWtQ==} dev: true /@unocss/scope@0.45.30: From 90d9cbbe88ec7c430aeab024940b6911625abcbe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 07:14:46 -0700 Subject: [PATCH 46/55] chore(deps): update devdependency nitropack to ^2.3.3 (main) (#20203) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- packages/nuxt/package.json | 2 +- packages/schema/package.json | 2 +- pnpm-lock.yaml | 43 +++++++++++++++++++++++------------- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index b0076f0cec..3384e9e84a 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -83,7 +83,7 @@ "local-pkg": "^0.4.3", "magic-string": "^0.30.0", "mlly": "^1.2.0", - "nitropack": "^2.3.2", + "nitropack": "^2.3.3", "nuxi": "workspace:../nuxi", "nypm": "^0.1.0", "ofetch": "^1.0.1", diff --git a/packages/schema/package.json b/packages/schema/package.json index f9bef6b958..3944656fbb 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -26,7 +26,7 @@ "@unhead/schema": "^1.1.25", "@vitejs/plugin-vue": "^4.1.0", "@vitejs/plugin-vue-jsx": "^3.0.1", - "nitropack": "^2.3.2", + "nitropack": "^2.3.3", "unbuild": "latest", "unctx": "^2.2.0", "vite": "~4.2.1" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bae91f0667..bd01f8b0c3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -603,8 +603,8 @@ importers: specifier: ^1.2.0 version: 1.2.0 nitropack: - specifier: ^2.3.2 - version: 2.3.2 + specifier: ^2.3.3 + version: 2.3.3 nuxi: specifier: workspace:* version: link:../nuxi @@ -734,8 +734,8 @@ importers: specifier: ^3.0.1 version: 3.0.1(vite@4.2.1)(vue@3.2.47) nitropack: - specifier: ^2.3.2 - version: 2.3.2 + specifier: ^2.3.3 + version: 2.3.3 unbuild: specifier: ^1.2.0 version: 1.2.0 @@ -1926,6 +1926,19 @@ packages: dependencies: rollup: 3.20.2 slash: 4.0.0 + dev: true + + /@rollup/plugin-alias@5.0.0(rollup@3.20.2): + resolution: {integrity: sha512-l9hY5chSCjuFRPsnRm16twWBiSApl2uYFLsepQYwtBuAxNMQ/1dJqADld40P0Jkqm65GRTLy/AC6hnpVebtLsA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + rollup: 3.20.2 + slash: 4.0.0 /@rollup/plugin-commonjs@24.0.1(rollup@3.20.2): resolution: {integrity: sha512-15LsiWRZk4eOGqvrJyu3z3DaBu5BhXIMeWnijSRvd8irrrg9SHpQ1pH+BUK4H6Z9wL9yOxZJMTLU+Au86XHxow==} @@ -1970,8 +1983,8 @@ packages: '@rollup/pluginutils': 5.0.2(rollup@3.20.2) rollup: 3.20.2 - /@rollup/plugin-node-resolve@15.0.1(rollup@3.20.2): - resolution: {integrity: sha512-ReY88T7JhJjeRVbfCyNj+NXAG3IIsVMsX9b5/9jC98dRP8/yxlZdz7mHZbHk5zHr24wZZICS5AcXsFZAXYUQEg==} + /@rollup/plugin-node-resolve@15.0.2(rollup@3.20.2): + resolution: {integrity: sha512-Y35fRGUjC3FaurG722uhUuG8YHOJRJQbI6/CkbRkdPotSpDj9NtIN85z1zrcyDcCQIW4qp5mgG72U+gJ0TAFEg==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^2.78.0||^3.0.0 @@ -2000,8 +2013,8 @@ packages: magic-string: 0.30.0 rollup: 3.20.2 - /@rollup/plugin-terser@0.4.0(rollup@3.20.2): - resolution: {integrity: sha512-Ipcf3LPNerey1q9ZMjiaWHlNPEHNU/B5/uh9zXLltfEQ1lVSLLeZSgAtTPWGyw8Ip1guOeq+mDtdOlEj/wNxQw==} + /@rollup/plugin-terser@0.4.1(rollup@3.20.2): + resolution: {integrity: sha512-aKS32sw5a7hy+fEXVy+5T95aDIwjpGHCTv833HXVtyKMDoVS7pBr5K3L9hEQoNqbJFjfANPrNpIXlTQ7is00eA==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^2.x || ^3.x @@ -6713,20 +6726,20 @@ packages: /neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - /nitropack@2.3.2: - resolution: {integrity: sha512-bps3OvC3JocB3Hl6/FUaQpbLw1Xsr6KXV3hTDnh54N0B0uAGWN9aF1LVHKBpWSS5JJvjwd+ZewOUFsPRM2NJ9Q==} + /nitropack@2.3.3: + resolution: {integrity: sha512-1g/4zdwWo+tWSvno57rhRXeGk6jNbG5W1yRNtOywInT1nyoEG1ksOwQ3W3JHGB2E1GNjZwAVi611UVOVL+JgYw==} engines: {node: ^14.16.0 || ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0} hasBin: true dependencies: '@cloudflare/kv-asset-handler': 0.3.0 '@netlify/functions': 1.4.0 - '@rollup/plugin-alias': 4.0.3(rollup@3.20.2) + '@rollup/plugin-alias': 5.0.0(rollup@3.20.2) '@rollup/plugin-commonjs': 24.0.1(rollup@3.20.2) '@rollup/plugin-inject': 5.0.3(rollup@3.20.2) '@rollup/plugin-json': 6.0.0(rollup@3.20.2) - '@rollup/plugin-node-resolve': 15.0.1(rollup@3.20.2) + '@rollup/plugin-node-resolve': 15.0.2(rollup@3.20.2) '@rollup/plugin-replace': 5.0.2(rollup@3.20.2) - '@rollup/plugin-terser': 0.4.0(rollup@3.20.2) + '@rollup/plugin-terser': 0.4.1(rollup@3.20.2) '@rollup/plugin-wasm': 6.1.2(rollup@3.20.2) '@rollup/pluginutils': 5.0.2(rollup@3.20.2) '@vercel/nft': 0.22.6 @@ -6734,7 +6747,7 @@ packages: c12: 1.2.0 chalk: 5.2.0 chokidar: 3.5.3 - consola: 2.15.3 + consola: 3.0.1 cookie-es: 0.5.0 defu: 6.1.2 destr: 1.2.2 @@ -8670,7 +8683,7 @@ packages: '@rollup/plugin-alias': 4.0.3(rollup@3.20.2) '@rollup/plugin-commonjs': 24.0.1(rollup@3.20.2) '@rollup/plugin-json': 6.0.0(rollup@3.20.2) - '@rollup/plugin-node-resolve': 15.0.1(rollup@3.20.2) + '@rollup/plugin-node-resolve': 15.0.2(rollup@3.20.2) '@rollup/plugin-replace': 5.0.2(rollup@3.20.2) '@rollup/pluginutils': 5.0.2(rollup@3.20.2) chalk: 5.2.0 From 163913a7443455397e6fb215be2c813b72b0db63 Mon Sep 17 00:00:00 2001 From: Julien Huang Date: Tue, 11 Apr 2023 16:17:44 +0200 Subject: [PATCH 47/55] feat(nuxt): add `experimentalNoScripts` route rule (#19805) --- docs/2.guide/1.concepts/3.rendering.md | 1 + packages/nuxt/src/core/runtime/nitro/renderer.ts | 8 +++++--- packages/nuxt/types.d.ts | 2 ++ packages/schema/src/config/experimental.ts | 1 + test/basic.test.ts | 5 +++++ test/fixtures/basic/nuxt.config.ts | 3 ++- test/fixtures/basic/pages/index.vue | 3 +++ test/fixtures/basic/pages/no-scripts.vue | 12 ++++++++++++ 8 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/basic/pages/no-scripts.vue diff --git a/docs/2.guide/1.concepts/3.rendering.md b/docs/2.guide/1.concepts/3.rendering.md index cc8503fb10..af31e52a73 100644 --- a/docs/2.guide/1.concepts/3.rendering.md +++ b/docs/2.guide/1.concepts/3.rendering.md @@ -100,6 +100,7 @@ Nuxt 3 includes route rules and hybrid rendering support. Using route rules you - `swr` - Add cache headers to the server response and cache it in the server or reverse proxy for a configurable TTL. The `node-server` preset of Nitro is able to cache the full response. For Netlify and Vercel, the response is also added to the CDN layer. - `static` - The behavior is the same as `swr` except that there is no TTL; the response is cached until the next deployment. On Netlify and Vercel, it enables full incremental static generation. - `prerender` - Prerenders routes at build time and includes them in your build as static assets +- `experimentalNoScripts` - Disables rendering of Nuxt scripts and JS resource hints for sections of your site. **Examples:** diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index 78ed13c2e3..86dd6acf1d 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -276,6 +276,8 @@ export default defineRenderHandler(async (event) => { ? await renderInlineStyles(ssrContext.modules ?? ssrContext._registeredComponents ?? []) : '' + const NO_SCRIPTS = process.env.NUXT_NO_SCRIPTS || routeOptions.experimentalNoScripts + // Create render context const htmlContext: NuxtRenderHTMLContext = { island: Boolean(islandContext), @@ -285,7 +287,7 @@ export default defineRenderHandler(async (event) => { process.env.NUXT_JSON_PAYLOADS ? _PAYLOAD_EXTRACTION ? `` : null : _PAYLOAD_EXTRACTION ? `` : null, - _rendered.renderResourceHints(), + NO_SCRIPTS ? null : _rendered.renderResourceHints(), _rendered.renderStyles(), inlinedStyles, ssrContext.styles @@ -297,7 +299,7 @@ export default defineRenderHandler(async (event) => { ]), body: [_rendered.html], bodyAppend: normalizeChunks([ - process.env.NUXT_NO_SCRIPTS + NO_SCRIPTS ? undefined : (_PAYLOAD_EXTRACTION ? process.env.NUXT_JSON_PAYLOADS @@ -307,7 +309,7 @@ export default defineRenderHandler(async (event) => { ? renderPayloadJsonScript({ id: '__NUXT_DATA__', ssrContext, data: ssrContext.payload }) : renderPayloadScript({ ssrContext, data: ssrContext.payload }) ), - _rendered.renderScripts(), + routeOptions.experimentalNoScripts ? undefined : _rendered.renderScripts(), // Note: bodyScripts may contain tags other than From 811bf28068363530b5719bd9cae06cf5fbd6b6ff Mon Sep 17 00:00:00 2001 From: Sacha Stafyniak Date: Tue, 11 Apr 2023 14:19:45 +0000 Subject: [PATCH 48/55] feat(nuxt): add chokidar watcher debug timing (#20176) --- packages/nuxt/src/core/builder.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/nuxt/src/core/builder.ts b/packages/nuxt/src/core/builder.ts index 6c8647c393..76707abc9d 100644 --- a/packages/nuxt/src/core/builder.ts +++ b/packages/nuxt/src/core/builder.ts @@ -44,6 +44,10 @@ export async function build (nuxt: Nuxt) { } function watch (nuxt: Nuxt) { + if (nuxt.options.debug) { + console.time('[nuxt] builder:chokidar:watch') + } + const watcher = chokidar.watch(nuxt.options._layers.map(i => i.config.srcDir as string).filter(Boolean), { ...nuxt.options.watchers.chokidar, cwd: nuxt.options.srcDir, @@ -55,6 +59,10 @@ function watch (nuxt: Nuxt) { ] }) + if (nuxt.options.debug) { + watcher.on('ready', () => console.timeEnd('[nuxt] builder:chokidar:watch')) + } + watcher.on('all', (event, path) => nuxt.callHook('builder:watch', event, normalize(path))) nuxt.hook('close', () => watcher.close()) return watcher From d265abbad779d9559995f21c2423ca384adea858 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 11 Apr 2023 16:05:25 +0100 Subject: [PATCH 49/55] test: update bundle size snapshot --- test/bundle.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bundle.test.ts b/test/bundle.test.ts index cf9cd47f5e..cd30d6c2ba 100644 --- a/test/bundle.test.ts +++ b/test/bundle.test.ts @@ -40,7 +40,7 @@ describe.skipIf(isWindows || process.env.ECOSYSTEM_CI)('minimal nuxt application it('default server bundle size', async () => { stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir) - expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"92k"') + expect(roundToKilobytes(stats.server.totalBytes)).toMatchInlineSnapshot('"93k"') const modules = await analyzeSizes('node_modules/**/*', serverDir) expect(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"2650k"') From 25e3a9046cc1b3dd9c1bf2c188a627b0a9446ad2 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 11 Apr 2023 17:17:01 +0100 Subject: [PATCH 50/55] v3.4.0 (#20170) --- packages/kit/package.json | 2 +- packages/nuxi/package.json | 2 +- packages/nuxt/package.json | 2 +- packages/schema/package.json | 2 +- packages/test-utils/package.json | 2 +- packages/vite/package.json | 2 +- packages/webpack/package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/kit/package.json b/packages/kit/package.json index 7361800d1e..b51e21b8d8 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -1,6 +1,6 @@ { "name": "@nuxt/kit", - "version": "3.3.3", + "version": "3.4.0", "repository": "nuxt/nuxt", "license": "MIT", "type": "module", diff --git a/packages/nuxi/package.json b/packages/nuxi/package.json index 169efa6a82..33570588c6 100644 --- a/packages/nuxi/package.json +++ b/packages/nuxi/package.json @@ -1,6 +1,6 @@ { "name": "nuxi", - "version": "3.3.3", + "version": "3.4.0", "repository": "nuxt/nuxt", "license": "MIT", "type": "module", diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index 3384e9e84a..bbbf783036 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -1,6 +1,6 @@ { "name": "nuxt", - "version": "3.3.3", + "version": "3.4.0", "repository": "nuxt/nuxt", "license": "MIT", "type": "module", diff --git a/packages/schema/package.json b/packages/schema/package.json index 3944656fbb..8f5683edca 100644 --- a/packages/schema/package.json +++ b/packages/schema/package.json @@ -1,6 +1,6 @@ { "name": "@nuxt/schema", - "version": "3.3.3", + "version": "3.4.0", "repository": "nuxt/nuxt", "license": "MIT", "type": "module", diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 4d22530b44..55380a69fa 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@nuxt/test-utils", - "version": "3.3.3", + "version": "3.4.0", "repository": "nuxt/nuxt", "license": "MIT", "type": "module", diff --git a/packages/vite/package.json b/packages/vite/package.json index 0a78daa9e8..fabc46103c 100644 --- a/packages/vite/package.json +++ b/packages/vite/package.json @@ -1,6 +1,6 @@ { "name": "@nuxt/vite-builder", - "version": "3.3.3", + "version": "3.4.0", "repository": "nuxt/nuxt", "license": "MIT", "type": "module", diff --git a/packages/webpack/package.json b/packages/webpack/package.json index da355257a9..bcc316d702 100644 --- a/packages/webpack/package.json +++ b/packages/webpack/package.json @@ -1,6 +1,6 @@ { "name": "@nuxt/webpack-builder", - "version": "3.3.3", + "version": "3.4.0", "repository": "nuxt/nuxt", "license": "MIT", "type": "module", From da21afd5491ecdfa078c206f659d09ddced6accf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 18:47:28 +0100 Subject: [PATCH 51/55] chore(deps): update devdependency eslint-plugin-jsdoc to v41 (main) (#20207) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- pnpm-lock.yaml | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index beaae878f5..5ed56a8b8e 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "changelogen": "^0.5.2", "crawler": "^1.4.0", "eslint": "^8.38.0", - "eslint-plugin-jsdoc": "^40.3.0", + "eslint-plugin-jsdoc": "^41.1.0", "execa": "^7.1.1", "expect-type": "^0.15.0", "globby": "^13.1.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bd01f8b0c3..b4cbe82717 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,8 +67,8 @@ importers: specifier: ^8.38.0 version: 8.38.0 eslint-plugin-jsdoc: - specifier: ^40.3.0 - version: 40.3.0(eslint@8.38.0) + specifier: ^41.1.0 + version: 41.1.0(eslint@8.38.0) execa: specifier: ^7.1.1 version: 7.1.1 @@ -3263,6 +3263,11 @@ packages: tar-stream: 2.2.0 zip-stream: 4.1.0 + /are-docs-informative@0.0.1: + resolution: {integrity: sha512-iBN6NxFQTEH0au0K8EOz6BoXXs9Pz6bGOPOgQpstabUHlX7fFx72TXB/wy7hSGZ8QcMI+XalPeM3p8IG5ncGIA==} + engines: {node: '>=18'} + dev: true + /are-we-there-yet@2.0.0: resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} engines: {node: '>=10'} @@ -4887,13 +4892,14 @@ packages: - supports-color dev: true - /eslint-plugin-jsdoc@40.3.0(eslint@8.38.0): - resolution: {integrity: sha512-EhCqpzRkxoT2DUB4AnrU0ggBYvTh3bWrLZzQTupq6vSVE6XzNwJVKsOHa41GCoevnsWMBNmoDVjXWGqckjuG1g==} + /eslint-plugin-jsdoc@41.1.0(eslint@8.38.0): + resolution: {integrity: sha512-7nE0soOQfVhRNeV0pXTUz9IhdpBiAFNbRgs1W7TcPIOx+c4Qvy3vgI4848O9UmHrbrVUaYwpVHZvaXDeP0SBeg==} engines: {node: ^14 || ^16 || ^17 || ^18 || ^19} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: '@es-joy/jsdoccomment': 0.37.0 + are-docs-informative: 0.0.1 comment-parser: 1.3.1 debug: 4.3.4 escape-string-regexp: 4.0.0 From 8f67d871b8516ebea7ee4ba4287893bda8d50d1e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 11 Apr 2023 18:47:45 +0100 Subject: [PATCH 52/55] chore(deps): update dependency globby to ^13.1.4 (main) (#20206) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- packages/kit/package.json | 2 +- packages/nuxt/package.json | 2 +- pnpm-lock.yaml | 24 ++++++++++++------------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 5ed56a8b8e..5b9deaaa37 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "eslint-plugin-jsdoc": "^41.1.0", "execa": "^7.1.1", "expect-type": "^0.15.0", - "globby": "^13.1.3", + "globby": "^13.1.4", "jiti": "^1.18.2", "markdownlint-cli": "^0.33.0", "nuxi": "workspace:*", diff --git a/packages/kit/package.json b/packages/kit/package.json index b51e21b8d8..3a106a4f13 100644 --- a/packages/kit/package.json +++ b/packages/kit/package.json @@ -24,7 +24,7 @@ "c12": "^1.2.0", "consola": "^3.0.1", "defu": "^6.1.2", - "globby": "^13.1.3", + "globby": "^13.1.4", "hash-sum": "^2.0.0", "ignore": "^5.2.4", "jiti": "^1.18.2", diff --git a/packages/nuxt/package.json b/packages/nuxt/package.json index bbbf783036..c04ee9ad63 100644 --- a/packages/nuxt/package.json +++ b/packages/nuxt/package.json @@ -74,7 +74,7 @@ "escape-string-regexp": "^5.0.0", "estree-walker": "^3.0.3", "fs-extra": "^11.1.1", - "globby": "^13.1.3", + "globby": "^13.1.4", "h3": "^1.6.4", "hash-sum": "^2.0.0", "hookable": "^5.5.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b4cbe82717..6f1f9ecdb6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,8 +76,8 @@ importers: specifier: ^0.15.0 version: 0.15.0 globby: - specifier: ^13.1.3 - version: 13.1.3 + specifier: ^13.1.4 + version: 13.1.4 jiti: specifier: ^1.18.2 version: 1.18.2 @@ -373,8 +373,8 @@ importers: specifier: ^6.1.2 version: 6.1.2 globby: - specifier: ^13.1.3 - version: 13.1.3 + specifier: ^13.1.4 + version: 13.1.4 hash-sum: specifier: ^2.0.0 version: 2.0.0 @@ -576,8 +576,8 @@ importers: specifier: ^11.1.1 version: 11.1.1 globby: - specifier: ^13.1.3 - version: 13.1.3 + specifier: ^13.1.4 + version: 13.1.4 h3: specifier: ^1.6.4 version: 1.6.4 @@ -4799,7 +4799,7 @@ packages: eslint: 8.38.0 eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.54.1)(eslint-import-resolver-typescript@3.5.3)(eslint@8.38.0) get-tsconfig: 4.4.0 - globby: 13.1.3 + globby: 13.1.4 is-core-module: 2.11.0 is-glob: 4.0.3 synckit: 0.8.5 @@ -5608,8 +5608,8 @@ packages: slash: 3.0.0 dev: true - /globby@13.1.3: - resolution: {integrity: sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==} + /globby@13.1.4: + resolution: {integrity: sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: dir-glob: 3.0.1 @@ -6670,7 +6670,7 @@ packages: defu: 6.1.2 esbuild: 0.17.16 fs-extra: 11.1.1 - globby: 13.1.3 + globby: 13.1.4 jiti: 1.18.2 mlly: 1.2.0 mri: 1.2.0 @@ -6762,7 +6762,7 @@ packages: escape-string-regexp: 5.0.0 etag: 1.8.1 fs-extra: 11.1.1 - globby: 13.1.3 + globby: 13.1.4 gzip-size: 7.0.0 h3: 1.6.4 hookable: 5.5.3 @@ -8696,7 +8696,7 @@ packages: consola: 2.15.3 defu: 6.1.2 esbuild: 0.17.16 - globby: 13.1.3 + globby: 13.1.4 hookable: 5.5.3 jiti: 1.18.2 magic-string: 0.30.0 From fe2800540c9a3c9d921707e17e74b4ea4747853f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 11 Apr 2023 23:33:21 +0100 Subject: [PATCH 53/55] fix(nuxt): set config on `ssrContext` in spa renderer (#20216) --- packages/nuxt/src/core/runtime/nitro/renderer.ts | 8 ++++---- test/basic.test.ts | 1 + .../basic/plugins/custom-type-assertion.client.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index 86dd6acf1d..3427b90b08 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -124,13 +124,13 @@ const getSPARenderer = lazyCachedFunction(async () => { ssrContext!.payload = { _errors: {}, serverRendered: false, - config: { - public: config.public, - app: config.app - }, data: {}, state: {} } + ssrContext.config = { + public: config.public, + app: config.app + } ssrContext!.renderMeta = ssrContext!.renderMeta ?? getStaticRenderedHead return Promise.resolve(result) } diff --git a/test/basic.test.ts b/test/basic.test.ts index 6394819149..18d3577205 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -46,6 +46,7 @@ describe('route rules', () => { const { script, attrs } = parseData(await $fetch('/route-rules/spa')) expect(script.serverRendered).toEqual(false) expect(attrs['data-ssr']).toEqual('false') + await expectNoClientErrors('/route-rules/spa') }) it('test noScript routeRules', async () => { diff --git a/test/fixtures/basic/plugins/custom-type-assertion.client.ts b/test/fixtures/basic/plugins/custom-type-assertion.client.ts index a7294f6159..b5f985d505 100644 --- a/test/fixtures/basic/plugins/custom-type-assertion.client.ts +++ b/test/fixtures/basic/plugins/custom-type-assertion.client.ts @@ -1,5 +1,5 @@ export default defineNuxtPlugin((nuxtApp) => { - if (nuxtApp.payload.blinkable !== '') { + if (nuxtApp.payload.serverRendered && nuxtApp.payload.blinkable !== '') { throw createError({ message: 'Custom type in Nuxt payload was not revived correctly' }) From 67ca0815ac6e36a2580ecefbd4efd029d3d1a270 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 11 Apr 2023 23:57:12 +0100 Subject: [PATCH 54/55] test: add js payload test suite (#20217) --- .github/workflows/ci.yml | 2 ++ package.json | 1 + test/basic.test.ts | 8 +++++--- test/fixtures/basic/nuxt.config.ts | 2 +- .../basic/plugins/custom-type-assertion.client.ts | 2 +- test/utils.ts | 11 +++++++++++ 6 files changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9773ce8f5d..5ae9165693 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,6 +121,7 @@ jobs: os: [ubuntu-latest, windows-latest] env: ['dev', 'built'] builder: ['vite', 'webpack'] + payload: ['json', 'js'] node: [16] exclude: - env: 'dev' @@ -180,6 +181,7 @@ jobs: env: TEST_ENV: ${{ matrix.env }} TEST_BUILDER: ${{ matrix.builder }} + TEST_PAYLOAD: ${{ matrix.payload }} build-release: if: | diff --git a/package.json b/package.json index 5b9deaaa37..2d71daaa12 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "play:build": "nuxi build playground", "play:preview": "nuxi preview playground", "test:fixtures": "nuxi prepare test/fixtures/basic && nuxi prepare test/fixtures/runtime-compiler && vitest run --dir test", + "text:fixtures:payload": "TEST_PAYLOAD=js pnpm test:fixtures", "test:fixtures:dev": "TEST_ENV=dev pnpm test:fixtures", "test:fixtures:webpack": "TEST_BUILDER=webpack pnpm test:fixtures", "test:types": "nuxi prepare test/fixtures/basic && cd test/fixtures/basic && npx vue-tsc --noEmit", diff --git a/test/basic.test.ts b/test/basic.test.ts index 18d3577205..4fe77b8731 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -7,7 +7,7 @@ import { $fetch, createPage, fetch, isDev, setup, startServer, url } from '@nuxt import { $fetchComponent } from '@nuxt/test-utils/experimental' import type { NuxtIslandResponse } from '../packages/nuxt/src/core/runtime/nitro/renderer' -import { expectNoClientErrors, expectWithPolling, parseData, parsePayload, renderPage, withLogs } from './utils' +import { expectNoClientErrors, expectWithPolling, isRenderingJson, parseData, parsePayload, renderPage, withLogs } from './utils' const isWebpack = process.env.TEST_BUILDER === 'webpack' @@ -45,7 +45,9 @@ describe('route rules', () => { it('should enable spa mode', async () => { const { script, attrs } = parseData(await $fetch('/route-rules/spa')) expect(script.serverRendered).toEqual(false) - expect(attrs['data-ssr']).toEqual('false') + if (isRenderingJson) { + expect(attrs['data-ssr']).toEqual('false') + } await expectNoClientErrors('/route-rules/spa') }) @@ -1229,7 +1231,7 @@ describe.runIf(isDev() && !isWebpack)('vite plugins', () => { }) }) -describe.skipIf(isDev() || isWindows)('payload rendering', () => { +describe.skipIf(isDev() || isWindows || !isRenderingJson)('payload rendering', () => { it('renders a payload', async () => { const payload = await $fetch('/random/a/_payload.json', { responseType: 'text' }) const data = parsePayload(payload) diff --git a/test/fixtures/basic/nuxt.config.ts b/test/fixtures/basic/nuxt.config.ts index cda5773b94..532255b0e4 100644 --- a/test/fixtures/basic/nuxt.config.ts +++ b/test/fixtures/basic/nuxt.config.ts @@ -186,7 +186,7 @@ export default defineNuxtConfig({ }, experimental: { polyfillVueUseHead: true, - renderJsonPayloads: true, + renderJsonPayloads: process.env.TEST_PAYLOAD !== 'js', respectNoSSRHeader: true, clientFallback: true, restoreState: true, diff --git a/test/fixtures/basic/plugins/custom-type-assertion.client.ts b/test/fixtures/basic/plugins/custom-type-assertion.client.ts index b5f985d505..1aeb11c650 100644 --- a/test/fixtures/basic/plugins/custom-type-assertion.client.ts +++ b/test/fixtures/basic/plugins/custom-type-assertion.client.ts @@ -1,5 +1,5 @@ export default defineNuxtPlugin((nuxtApp) => { - if (nuxtApp.payload.serverRendered && nuxtApp.payload.blinkable !== '') { + if (nuxtApp.payload.serverRendered && nuxtApp.payload.blinkable !== '' && document.querySelector('#__NUXT_DATA__')) { throw createError({ message: 'Custom type in Nuxt payload was not revived correctly' }) diff --git a/test/utils.ts b/test/utils.ts index 3d12ad112d..cddfe671f4 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,3 +1,4 @@ +import { Script, createContext } from 'node:vm' import { expect } from 'vitest' import type { Page } from 'playwright' import { parse } from 'devalue' @@ -5,6 +6,8 @@ import { reactive, ref, shallowReactive, shallowRef } from 'vue' import { createError } from 'h3' import { createPage, getBrowser, url, useTestContext } from '@nuxt/test-utils' +export const isRenderingJson = process.env.TEST_PAYLOAD !== 'js' + export async function renderPage (path = '/') { const ctx = useTestContext() if (!ctx.options.browser) { @@ -108,6 +111,14 @@ export function parsePayload (payload: string) { return parse(payload || '', revivers) } export function parseData (html: string) { + if (!isRenderingJson) { + const { script } = html.match(/