From aece3518b541663c1731160e42e26e6ac7c79ce8 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Thu, 10 Feb 2022 18:29:59 +0100 Subject: [PATCH] feat(nuxt3): experimental nitropack support (#3160) --- package.json | 3 +- packages/nitro/README.md | 4 +- packages/nuxt3/package.json | 1 + .../src/core/{nitro.ts => nitro-legacy.ts} | 0 packages/nuxt3/src/core/nitro-nitropack.ts | 130 ++++++++++++++++++ packages/nuxt3/src/core/nuxt.ts | 2 +- packages/nuxt3/src/dirs.ts | 5 +- packages/schema/src/config/index.ts | 2 + packages/schema/src/config/nitro.ts | 11 ++ yarn.lock | 87 +++++++++++- 10 files changed, 237 insertions(+), 8 deletions(-) rename packages/nuxt3/src/core/{nitro.ts => nitro-legacy.ts} (100%) create mode 100644 packages/nuxt3/src/core/nitro-nitropack.ts create mode 100644 packages/schema/src/config/nitro.ts diff --git a/package.json b/package.json index 1336b3ac38..b31f57ba9e 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,9 @@ }, "resolutions": { "nuxt3": "workspace:./packages/nuxt3", - "@nuxt/ui": "npm:@nuxt/ui-edge@^0.0.0-27376194.a859489", + "@nuxt/ui": "npm:@nuxt/ui-edge@latest", "unbuild": "^0.6.9", + "nitropack-dev": "link:../nitropack", "jiti": "^1.12.15" }, "devDependencies": { diff --git a/packages/nitro/README.md b/packages/nitro/README.md index d5475eb07f..40e230e004 100644 --- a/packages/nitro/README.md +++ b/packages/nitro/README.md @@ -1,5 +1,3 @@ # Nitro -> The Server engine for Nuxt - -Learn more about this package: +**Notice:** This package is being deprecated. Read more: diff --git a/packages/nuxt3/package.json b/packages/nuxt3/package.json index 2658927c78..4711f675f7 100644 --- a/packages/nuxt3/package.json +++ b/packages/nuxt3/package.json @@ -42,6 +42,7 @@ "knitwork": "^0.1.0", "mlly": "^0.4.2", "murmurhash-es": "^0.1.1", + "nitropack": "npm:nitropack-edge@latest", "nuxi": "3.0.0", "ohmyfetch": "^0.4.15", "pathe": "^0.2.0", diff --git a/packages/nuxt3/src/core/nitro.ts b/packages/nuxt3/src/core/nitro-legacy.ts similarity index 100% rename from packages/nuxt3/src/core/nitro.ts rename to packages/nuxt3/src/core/nitro-legacy.ts diff --git a/packages/nuxt3/src/core/nitro-nitropack.ts b/packages/nuxt3/src/core/nitro-nitropack.ts new file mode 100644 index 0000000000..d756d680ce --- /dev/null +++ b/packages/nuxt3/src/core/nitro-nitropack.ts @@ -0,0 +1,130 @@ +import { resolve, join } from 'pathe' +import { createNitro, createDevServer, build, scanMiddleware, writeTypes, prepare, copyPublicAssets } from 'nitropack' +import type { NitroConfig, ServerMiddleware } from 'nitropack' +import type { Nuxt } from '@nuxt/schema' +import { resolvePath } from '@nuxt/kit' +import fsExtra from 'fs-extra' +import { ImportProtectionPlugin } from './plugins/import-protection' + +export async function initNitro (nuxt: Nuxt) { + // Create contexts + const nitroOptions = ((nuxt.options as any).nitro || {}) as NitroConfig + const nitro = await createNitro({ + ...nitroOptions, + rootDir: nuxt.options.rootDir, + srcDir: join(nuxt.options.srcDir, 'server'), + buildDir: nuxt.options.buildDir, + generateDir: join(nuxt.options.buildDir, 'dist'), + publicDir: nuxt.options.dir.public, + publicPath: nuxt.options.app.buildAssetsDir, + renderer: '#nitro/vue/render', + modulesDir: nuxt.options.modulesDir, + runtimeConfig: { + public: nuxt.options.publicRuntimeConfig, + private: nuxt.options.privateRuntimeConfig + }, + output: { + dir: nuxt.options.dev + ? join(nuxt.options.buildDir, 'nitro') + : resolve(nuxt.options.rootDir, '.output') + }, + dev: nuxt.options.dev, + preset: nuxt.options.dev ? 'dev' : undefined + }) + + const nitroDevServer = nuxt.server = createDevServer(nitro) + + nitro.vfs = nuxt.vfs = nitro.vfs || nuxt.vfs || {} + + // Connect hooks + const nitroHooks = [ + 'nitro:document' + ] + nuxt.hook('close', () => nitro.hooks.callHook('close')) + for (const hook of nitroHooks) { + nitro.hooks.hook(hook as any, (...args) => nuxt.callHook(hook as any, ...args)) + } + + // @ts-ignore + nuxt.hook('close', () => nitro.hooks.callHook('close')) + nitro.hooks.hook('nitro:document', template => nuxt.callHook('nitro:document', template)) + + // Register nuxt3 protection patterns + nitro.hooks.hook('nitro:rollup:before', (nitro) => { + nitro.options.rollupConfig.plugins.push(ImportProtectionPlugin.rollup({ + rootDir: nuxt.options.rootDir, + patterns: [ + ...['#app', /^#build(\/|$)/] + .map(p => [p, 'Vue app aliases are not allowed in server routes.']) as [RegExp | string, string][] + ] + })) + }) + + // Add typed route responses + nuxt.hook('prepare:types', (opts) => { + opts.references.push({ path: resolve(nuxt.options.buildDir, 'types/nitro.d.ts') }) + }) + + // Wait for all modules to be ready + nuxt.hook('modules:done', async () => { + // Extend nitro with modules + await nuxt.callHook('nitro:context', nitro) + + // Resolve middleware + const { middleware, legacyMiddleware } = await resolveMiddleware(nuxt) + nuxt.server.setLegacyMiddleware(legacyMiddleware) + nitro.options.middleware.push(...middleware) + }) + + // nuxt build/dev + nuxt.hook('build:done', async () => { + if (nuxt.options.dev) { + await build(nitro) + } else { + await prepare(nitro) + await copyPublicAssets(nitro) + await build(nitro) + } + }) + + nuxt.hook('builder:generateApp', async () => { + nitro.scannedMiddleware = await scanMiddleware(nitro.options.srcDir) + await writeTypes(nitro) + }) + + // nuxt dev + if (nuxt.options.dev) { + nitro.hooks.hook('nitro:compiled', () => { nitroDevServer.watch() }) + nuxt.hook('build:compile', ({ compiler }) => { + compiler.outputFileSystem = { ...fsExtra, join } as any + }) + nuxt.hook('server:devMiddleware', (m) => { nitroDevServer.setDevMiddleware(m) }) + } +} + +async function resolveMiddleware (nuxt: Nuxt) { + const middleware: ServerMiddleware[] = [] + const legacyMiddleware: ServerMiddleware[] = [] + + for (let m of nuxt.options.serverMiddleware) { + if (typeof m === 'string' || typeof m === 'function' /* legacy middleware */) { m = { handler: m } } + const route = m.path || m.route || '/' + const handle = m.handler || m.handle + if (typeof handle !== 'string' || typeof route !== 'string') { + legacyMiddleware.push(m) + } else { + delete m.handler + delete m.path + middleware.push({ + ...m, + handle: await resolvePath(handle), + route + }) + } + } + + return { + middleware, + legacyMiddleware + } +} diff --git a/packages/nuxt3/src/core/nuxt.ts b/packages/nuxt3/src/core/nuxt.ts index c1c98383c1..dc014e9e9f 100644 --- a/packages/nuxt3/src/core/nuxt.ts +++ b/packages/nuxt3/src/core/nuxt.ts @@ -9,7 +9,6 @@ import autoImportsModule from '../auto-imports/module' import { distDir, pkgDir } from '../dirs' import { version } from '../../package.json' import { ImportProtectionPlugin, vueAppPatterns } from './plugins/import-protection' -import { initNitro } from './nitro' import { addModuleTranspiles } from './modules' export function createNuxt (options: NuxtOptions): Nuxt { @@ -39,6 +38,7 @@ async function initNuxt (nuxt: Nuxt) { nuxt.hook('close', () => nuxtCtx.unset()) // Init nitro + const { initNitro } = await import(nuxt.options.experimentNitropack ? './nitro-nitropack' : './nitro-legacy') await initNitro(nuxt) // Add nuxt3 types diff --git a/packages/nuxt3/src/dirs.ts b/packages/nuxt3/src/dirs.ts index af0ffb33a2..9623521c6f 100644 --- a/packages/nuxt3/src/dirs.ts +++ b/packages/nuxt3/src/dirs.ts @@ -1,5 +1,8 @@ import { fileURLToPath } from 'url' import { dirname, resolve } from 'pathe' -export const distDir = dirname(fileURLToPath(import.meta.url)) +let _distDir = dirname(fileURLToPath(import.meta.url)) +if (_distDir.endsWith('chunks')) { _distDir = dirname(_distDir) } +export const distDir = _distDir export const pkgDir = resolve(distDir, '..') +export const runtimeDir = resolve(distDir, 'runtime') diff --git a/packages/schema/src/config/index.ts b/packages/schema/src/config/index.ts index a2dde046ff..d7879e6674 100644 --- a/packages/schema/src/config/index.ts +++ b/packages/schema/src/config/index.ts @@ -11,6 +11,7 @@ import server from './server' import cli from './cli' import generate from './generate' import typescript from './typescript' +import nitro from './nitro' /* TODO for top level normalizations: (nuxt2) @@ -35,6 +36,7 @@ export default { ..._app, ..._common, ..._internal, + ...nitro, build, messages, render, diff --git a/packages/schema/src/config/nitro.ts b/packages/schema/src/config/nitro.ts new file mode 100644 index 0000000000..87f4238945 --- /dev/null +++ b/packages/schema/src/config/nitro.ts @@ -0,0 +1,11 @@ +/** + * @version 3 + */ +export default { + experimentNitropack: process.env.EXPERIMENT_NITROPACK ? true : false, + + /** + * @typedef {Awaited>} + */ + nitro: {} +} diff --git a/yarn.lock b/yarn.lock index fd818f88ef..935e7cb8d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3186,7 +3186,7 @@ __metadata: languageName: node linkType: hard -"@nuxt/ui@npm:@nuxt/ui-edge@^0.0.0-27376194.a859489": +"@nuxt/ui@npm:@nuxt/ui-edge@latest": version: 0.0.0-27376194.a859489 resolution: "@nuxt/ui-edge@npm:0.0.0-27376194.a859489" dependencies: @@ -6810,6 +6810,21 @@ __metadata: languageName: node linkType: hard +"c12@npm:^0.1.2": + version: 0.1.2 + resolution: "c12@npm:0.1.2" + dependencies: + defu: ^5.0.1 + dotenv: ^14.3.2 + gittar: ^0.1.1 + jiti: ^1.12.14 + mlly: ^0.4.1 + pathe: ^0.2.0 + rc9: ^1.2.0 + checksum: 1977c1de00603a68b0ce0d825ec809afbf6443179dbf6cc2615cc050046dc8e43faa7aca30b538c7f177187fad23031fa8e263a427d9fc06e8d35fbdd9d5fe38 + languageName: node + linkType: hard + "cacache@npm:^12.0.2": version: 12.0.4 resolution: "cacache@npm:12.0.4" @@ -11456,7 +11471,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^13.1.1": +"globby@npm:^13.1.0, globby@npm:^13.1.1": version: 13.1.1 resolution: "globby@npm:13.1.1" dependencies: @@ -14450,6 +14465,73 @@ __metadata: languageName: node linkType: hard +"nitropack@npm:nitropack-edge@latest": + version: 0.0.0-27408562.5d3ca2f + resolution: "nitropack-edge@npm:0.0.0-27408562.5d3ca2f" + dependencies: + "@cloudflare/kv-asset-handler": ^0.2.0 + "@netlify/functions": ^0.11.0 + "@nuxt/devalue": ^2.0.0 + "@rollup/plugin-alias": ^3.1.9 + "@rollup/plugin-commonjs": ^21.0.1 + "@rollup/plugin-inject": ^4.0.4 + "@rollup/plugin-json": ^4.1.0 + "@rollup/plugin-node-resolve": ^13.1.3 + "@rollup/plugin-replace": ^3.0.1 + "@rollup/plugin-virtual": ^2.0.3 + "@rollup/plugin-wasm": ^5.1.2 + "@rollup/pluginutils": ^4.1.2 + "@types/jsdom": ^16.2.14 + "@vercel/nft": ^0.17.4 + archiver: ^5.3.0 + c12: ^0.1.2 + chalk: ^5.0.0 + chokidar: ^3.5.3 + connect: ^3.7.0 + consola: ^2.15.3 + defu: ^5.0.1 + destr: ^1.1.0 + dot-prop: ^7.1.1 + esbuild: ^0.14.14 + etag: ^1.8.1 + fs-extra: ^10.0.0 + globby: ^13.1.0 + gzip-size: ^7.0.0 + h3: ^0.3.9 + hasha: ^5.2.2 + hookable: ^5.1.1 + http-proxy: ^1.18.1 + is-primitive: ^3.0.1 + jiti: ^1.12.13 + listhen: ^0.2.6 + mime: ^3.0.0 + mlly: ^0.4.1 + mri: ^1.2.0 + node-fetch: ^3.2.0 + ohmyfetch: ^0.4.15 + ora: ^6.0.1 + p-debounce: ^4.0.0 + pathe: ^0.2.0 + pkg-types: ^0.3.2 + pretty-bytes: ^5.6.0 + rollup: ^2.66.1 + rollup-plugin-terser: ^7.0.2 + rollup-plugin-visualizer: ^5.5.4 + scule: ^0.2.1 + serve-placeholder: ^1.2.4 + serve-static: ^1.14.2 + std-env: ^3.0.1 + table: ^6.8.0 + ufo: ^0.7.9 + unenv: ^0.4.3 + unstorage: ^0.3.3 + bin: + nitro: ./dist/cli.mjs + nitropack: ./dist/cli.mjs + checksum: 525586f69228de053f7b7513acaf7fde635ca0b1c74325f907a07510c535791d061811e97601484fcd62792db84aa394c2c7693166cc4f63c0e11b3431ceb4d3 + languageName: node + linkType: hard + "no-case@npm:^2.2.0": version: 2.3.2 resolution: "no-case@npm:2.3.2" @@ -15129,6 +15211,7 @@ __metadata: knitwork: ^0.1.0 mlly: ^0.4.2 murmurhash-es: ^0.1.1 + nitropack: "npm:nitropack-edge@latest" nuxi: 3.0.0 ohmyfetch: ^0.4.15 pathe: ^0.2.0