diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 1c60dad82c..2e0d38e874 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -2,33 +2,18 @@ import { resolve } from 'path' import consola from 'consola' import { rollup, OutputOptions } from 'rollup' import Hookable from 'hookable' -import defu from 'defu' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' import chalk from 'chalk' import { copy, emptyDir, existsSync } from 'fs-extra' import { getRollupConfig } from './rollup/config' -import { tryImport, hl, prettyPath, renderTemplate, compileTemplateToJS } from './utils' +import { getTargetConfig } from './config' +import { hl, prettyPath, renderTemplate, compileTemplateToJS } from './utils' export async function build (baseConfig, target) { consola.info(`Generating bundle for ${hl(target.target)}`) - const _targetDefaults = tryImport(__dirname, `./targets/${target.target}`) || - tryImport(baseConfig.rootDir, target.target) - if (!_targetDefaults) { - throw new Error('Cannot resolve target: ' + target.target) - } - - const config: any = defu( - // Target specific config by user - target, - // Global user config - baseConfig, - // Target defaults - _targetDefaults, - // Generic defaults - { outDir: resolve(baseConfig.buildDir, `dist/${target.target}`), outName: 'index.js' } - ) + const config: any = getTargetConfig(baseConfig, target) const hooks = new Hookable() hooks.addHooks(config.hooks) diff --git a/packages/nitro/src/cli.ts b/packages/nitro/src/cli.ts index 11558f595c..24355d9da3 100644 --- a/packages/nitro/src/cli.ts +++ b/packages/nitro/src/cli.ts @@ -1,9 +1,8 @@ import { resolve } from 'path' -import consola from 'consola' import { build, compileHTMLTemplate, ensureDist } from './build' import { getBaseConfig } from './config' -async function _runCLI () { +export async function runCLI () { const rootDir = resolve(process.cwd(), process.argv[2] || '.') // Config @@ -23,10 +22,3 @@ async function _runCLI () { await build(baseConfig, target) } } - -export function runCLI () { - _runCLI().catch((err) => { - consola.error(err) - process.exit(1) - }) -} diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 33445067ce..11f9f28aca 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -1,8 +1,9 @@ import { resolve } from 'path' -import { tryImport } from './utils' +import defu from 'defu' +import { tryImport, LIB_DIR } from './utils' export function getBaseConfig (rootDir) { - const baseConfig = { + let baseConfig = { rootDir, buildDir: '', targets: [], @@ -14,7 +15,13 @@ export function getBaseConfig (rootDir) { logStartup: true } - Object.assign(baseConfig, tryImport(rootDir, './nuxt.config')!.serverless) + const nuxtConfig = tryImport(rootDir, './nuxt.config') + if (!nuxtConfig) { + throw new Error('`nuxt.config` file not found in: ' + rootDir) + } + if (nuxtConfig.serverless) { + baseConfig = defu(nuxtConfig.serverless, baseConfig) + } baseConfig.buildDir = resolve(baseConfig.rootDir, baseConfig.buildDir || '.nuxt') @@ -25,3 +32,24 @@ export function getBaseConfig (rootDir) { return baseConfig } + +export function getTargetConfig (baseConfig, target) { + const _targetDefaults = tryImport(LIB_DIR, `./targets/${target.target}`) || + tryImport(baseConfig.rootDir, target.target) + if (!_targetDefaults) { + throw new Error('Cannot resolve target: ' + target.target) + } + + // TODO: Merge hooks + + return defu( + // Target specific config by user + target, + // Global user config + baseConfig, + // Target defaults + _targetDefaults, + // Generic defaults + { outDir: resolve(baseConfig.buildDir, `dist/${target.target}`), outName: 'index.js' } + ) +} diff --git a/packages/nitro/src/nuxt-serverless.ts b/packages/nitro/src/nuxt-serverless.ts new file mode 100644 index 0000000000..c19e652658 --- /dev/null +++ b/packages/nitro/src/nuxt-serverless.ts @@ -0,0 +1,6 @@ + +require('../dist').runCLI().catch((error) => { + const consola = require('consola') + consola.error(error) + process.exit(1) +}) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 5782bab352..68415758bb 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -8,7 +8,7 @@ import alias from '@rollup/plugin-alias' import json from '@rollup/plugin-json' import replace from '@rollup/plugin-replace' import analyze from 'rollup-plugin-analyzer' -import ts from 'rollup-plugin-ts' +import { RUNTIME_DIR } from '../utils' import dynamicRequire from './dynamic-require' export type RollupConfig = InputOptions & { output: OutputOptions } @@ -83,22 +83,14 @@ export const getRollupConfig = (config) => { const renderer = config.renderer || (config.nuxt === 2 ? 'vue2' : 'vue3') options.plugins.push(alias({ entries: { - '~runtime': path.resolve(__dirname, '../runtime'), - '~renderer': require.resolve('../runtime/' + renderer), + '~runtime': RUNTIME_DIR, + '~renderer': require.resolve(path.resolve(RUNTIME_DIR, renderer)), '~build': config.buildDir, - '~mock': require.resolve('../runtime/mock'), + '~mock': require.resolve(path.resolve(RUNTIME_DIR, 'mock')), ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}) } })) - // https://github.com/wessberg/rollup-plugin-ts - options.plugins.push(ts({ - transpileOnly: true, - transpiler: 'babel', - include: ['**/*.ts'], - exclude: ['*.json', 'node_modules'] - })) - // https://github.com/rollup/plugins/tree/master/packages/node-resolve options.plugins.push(resolve({ extensions, diff --git a/packages/nitro/src/runtime/mock.js b/packages/nitro/src/runtime/mock.js deleted file mode 100644 index 70415e62eb..0000000000 --- a/packages/nitro/src/runtime/mock.js +++ /dev/null @@ -1,25 +0,0 @@ -function getProxy (name) { - const fn = function () { } - fn.prototype.name = name - - const props = {} - - return new Proxy(fn, { - get (_target, prop) { - if (prop === 'caller') { return null } - return (props[prop] = props[prop] || getProxy(`${name}.${prop.toString()}`)) - }, - apply (_target, _this, _args) { - console.debug(`${name}(...)`) - return getProxy(`${name}()`) - }, - construct (_target, _args, _newT) { - return getProxy(`[${name}]`) - }, - enumerate (_target) { - return [] - } - }) -} - -module.exports = getProxy('mock') diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts deleted file mode 100644 index 03519eaaa5..0000000000 --- a/packages/nitro/src/runtime/server.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { createRenderer } from 'vue-bundle-renderer' -import devalue from '@nuxt/devalue' - -// @ts-ignore -import { renderToString } from '~renderer' -// @ts-ignore -import server from '~build/dist/server/server' -// @ts-ignore -import clientManifest from '~build/dist/server/client.manifest.json' -// @ts-ignore -import htmlTemplate from '~build/views/document.template.js' - -const renderer = createRenderer(server, { - clientManifest, - renderToString -}) - -export async function render (url, ctx: any) { - const start = process.hrtime() - - const ssrContext: any = { - url, - runtimeConfig: { - public: {}, - private: {} - }, - ...ctx - } - const rendered = await renderer.renderToString(ssrContext) - - const state = `` - const _html = `
${rendered.html}
` - - const html = htmlTemplate({ - HTML_ATTRS: '', - HEAD_ATTRS: '', - BODY_ATTRS: '', - HEAD: rendered.renderResourceHints() + rendered.renderStyles() + (ssrContext.styles || ''), - APP: _html + state + rendered.renderScripts() - }) - - const end = process.hrtime(start) - const time = ((end[0] * 1e9) + end[1]) / 1e6 - - return { - html, - status: 200, - headers: { - 'Content-Type': 'text/html;charset=UTF-8', - // @ts-ignore - 'X-Nuxt-Coldstart': global._coldstart + 'ms', - 'X-Nuxt-ResponseTime': time + 'ms' - } - } -} diff --git a/packages/nitro/src/runtime/vue2.ts b/packages/nitro/src/runtime/vue2.ts deleted file mode 100644 index 7b55418b8e..0000000000 --- a/packages/nitro/src/runtime/vue2.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { createRenderer } from 'vue-server-renderer/build.prod.js' - -const _renderer = createRenderer({}) - -export function renderToString (component, context) { - return new Promise((resolve, reject) => { - _renderer.renderToString(component, context, (err, result) => { - if (err) { - return reject(err) - } - return resolve(result) - }) - }) -} diff --git a/packages/nitro/src/runtime/vue3.ts b/packages/nitro/src/runtime/vue3.ts deleted file mode 100644 index f3fd7daa59..0000000000 --- a/packages/nitro/src/runtime/vue3.ts +++ /dev/null @@ -1,2 +0,0 @@ -// @ts-ignore -export { renderToString } from '@vue/server-renderer' diff --git a/packages/nitro/src/targets/cloudflare/entry.ts b/packages/nitro/src/targets/cloudflare/entry.ts deleted file mode 100644 index 8143bfaa36..0000000000 --- a/packages/nitro/src/targets/cloudflare/entry.ts +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-ignore -import { render } from '~runtime/server' - -addEventListener('fetch', (event: any) => { - event.respondWith(handleEvent(event.request)) -}) - -async function handleEvent (request) { - try { - const url = new URL(request.url) - const { html, status, headers } = await render(url.pathname, { req: request }) - return new Response(html, { status, headers }) - } catch (error) { - return new Response('Internal Error: ' + error, { status: 500 }) - } -} diff --git a/packages/nitro/src/targets/cloudflare/index.ts b/packages/nitro/src/targets/cloudflare/index.ts deleted file mode 100644 index 0839345724..0000000000 --- a/packages/nitro/src/targets/cloudflare/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export default { - entry: require.resolve('./entry'), - node: false, - hooks: { - 'rollup:before' ({ rollupConfig }) { - rollupConfig.output.intro = - 'const global = {}; const exports = {}; const module = { exports }; const process = { env: {}, hrtime: () => [0,0]};' + - rollupConfig.output.intro - rollupConfig.output.format = 'iife' - } - } -} diff --git a/packages/nitro/src/targets/node/entry.ts b/packages/nitro/src/targets/node/entry.ts deleted file mode 100644 index b8d6bcf7d5..0000000000 --- a/packages/nitro/src/targets/node/entry.ts +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-ignore -import { render } from '~runtime/server' -// @ts-ignore -export { render } from '~runtime/server' - -async function cli () { - const url = process.argv[2] || '/' - - const debug = (label, ...args) => console.debug(`> ${label}:`, ...args) - - const { html, status, headers } = await render(url) - - debug('URL', url) - debug('Status', status) - for (const header in headers) { - debug(header, headers[header]) - } - - console.log('\n', html) -} - -if (require.main === module) { - cli().catch((err) => { - console.error(err) - process.exit(1) - }) -} diff --git a/packages/nitro/src/targets/node/index.ts b/packages/nitro/src/targets/node/index.ts deleted file mode 100644 index 4880495638..0000000000 --- a/packages/nitro/src/targets/node/index.ts +++ /dev/null @@ -1,11 +0,0 @@ - -import consola from 'consola' - -export default { - entry: require.resolve('./entry'), - hooks: { - 'done' ({ rollupConfig }) { - consola.info(`Usage: \`node ${rollupConfig.output.file} [route]\``) - } - } -} diff --git a/packages/nitro/src/targets/sw/entry.ts b/packages/nitro/src/targets/sw/entry.ts deleted file mode 100644 index e02d78428f..0000000000 --- a/packages/nitro/src/targets/sw/entry.ts +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-ignore -import { render } from '~runtime/server' - -addEventListener('fetch', (event: any) => { - const url = new URL(event.request.url) - - if (url.pathname.startsWith('/_nuxt') || url.pathname.includes('.') /* is file :} */) { - return - } - - event.respondWith(handleEvent(url, event.request)) -}) - -self.addEventListener('install', () => { - // @ts-ignore - self.skipWaiting() -}) - -self.addEventListener('activate', (event) => { - // @ts-ignore - event.waitUntil(self.clients.claim()) -}) - -async function handleEvent (url, request) { - try { - const { html, status, headers } = await render(url.pathname, { req: request }) - return new Response(html, { status, headers }) - } catch (error) { - return new Response('Internal Error: ' + error, { status: 500 }) - } -} diff --git a/packages/nitro/src/targets/sw/index.html b/packages/nitro/src/targets/sw/index.html deleted file mode 100644 index c61a952006..0000000000 --- a/packages/nitro/src/targets/sw/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - Loading... - - - diff --git a/packages/nitro/src/targets/sw/index.ts b/packages/nitro/src/targets/sw/index.ts deleted file mode 100644 index 6bb68d17fb..0000000000 --- a/packages/nitro/src/targets/sw/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { resolve } from 'path' -import consola from 'consola' - -export default { - entry: require.resolve('./entry'), - node: false, - copyAssets: '.', - outName: 'nuxt.sw.js', - templates: [ - { src: resolve(__dirname, 'index.html'), dst: 'index.html' }, - { src: resolve(__dirname, 'index.html'), dst: '200.html' } - ], - hooks: { - 'rollup:before' ({ rollupConfig }) { - rollupConfig.output.intro = - 'const global = {}; const exports = {}; const module = { exports }; const process = { env: {}, hrtime: () => [0,0]};' + - rollupConfig.output.intro - rollupConfig.output.format = 'iife' - }, - done ({ outDir }) { - consola.info(`Try with \`npx serve ${outDir}\``) - } - } -} diff --git a/packages/nitro/src/targets/vercel/entry.ts b/packages/nitro/src/targets/vercel/entry.ts deleted file mode 100644 index b92aba883b..0000000000 --- a/packages/nitro/src/targets/vercel/entry.ts +++ /dev/null @@ -1,17 +0,0 @@ -// @ts-ignore -import { render } from '~runtime/server' - -module.exports = async (req, res) => { - try { - const { html, status, headers } = await render(req.url, { req, res }) - for (const header in headers) { - res.setHeader(header, headers[header]) - } - res.status(status) - res.end(html) - } catch (error) { - console.error(error) - res.status(500) - res.end('Internal Error: ' + error) - } -} diff --git a/packages/nitro/src/targets/vercel/index.ts b/packages/nitro/src/targets/vercel/index.ts deleted file mode 100644 index 0fc011f944..0000000000 --- a/packages/nitro/src/targets/vercel/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import consola from 'consola' - -export default { - entry: require.resolve('./entry'), - dynamicImporter: false, - hooks: { - 'done' () { - consola.info('Run `vercel serverless` to serverless!') - } - } -} diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index 420fdfac67..af766bea24 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -1,4 +1,4 @@ -import { relative, dirname } from 'path' +import { relative, dirname, resolve } from 'path' import { readFile, writeFile, mkdirp } from 'fs-extra' import jiti from 'jiti' @@ -31,4 +31,8 @@ export async function compileTemplateToJS (src: string, dst: string) { await writeFile(dst, compiled) } -export const tryImport = (dir, path) => { try { return jiti(dir)(path) } catch (_err) { } } +export const jitiImport = (dir, path) => jiti(dir)(path) +export const tryImport = (dir, path) => { try { return jitiImport(dir, path) } catch (_err) { } } + +export const LIB_DIR = resolve(__dirname, '../lib') +export const RUNTIME_DIR = resolve(LIB_DIR, 'runtime')