From 4908a963ca3927f83b696aced93f490c33f496c9 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 00:17:44 +0100 Subject: [PATCH 001/227] initial commit --- packages/nitro/src/nuxt-deploy.ts | 89 ++++++++++++++ packages/nitro/src/rollup.config.ts | 109 ++++++++++++++++++ packages/nitro/src/runtime/mock.ts | 25 ++++ packages/nitro/src/runtime/server.ts | 39 +++++++ packages/nitro/src/runtime/vue2.ts | 12 ++ packages/nitro/src/runtime/vue3.ts | 2 + packages/nitro/src/targets/cli/entry.ts | 8 ++ packages/nitro/src/targets/cli/index.ts | 11 ++ .../nitro/src/targets/cloudflare/entry.ts | 17 +++ .../nitro/src/targets/cloudflare/index.ts | 10 ++ packages/nitro/src/targets/vercel/entry.ts | 18 +++ packages/nitro/src/targets/vercel/index.ts | 10 ++ packages/nitro/src/utils.ts | 11 ++ 13 files changed, 361 insertions(+) create mode 100644 packages/nitro/src/nuxt-deploy.ts create mode 100644 packages/nitro/src/rollup.config.ts create mode 100644 packages/nitro/src/runtime/mock.ts create mode 100644 packages/nitro/src/runtime/server.ts create mode 100644 packages/nitro/src/runtime/vue2.ts create mode 100644 packages/nitro/src/runtime/vue3.ts create mode 100644 packages/nitro/src/targets/cli/entry.ts create mode 100644 packages/nitro/src/targets/cli/index.ts create mode 100644 packages/nitro/src/targets/cloudflare/entry.ts create mode 100644 packages/nitro/src/targets/cloudflare/index.ts create mode 100644 packages/nitro/src/targets/vercel/entry.ts create mode 100644 packages/nitro/src/targets/vercel/index.ts create mode 100644 packages/nitro/src/utils.ts diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts new file mode 100644 index 0000000000..292c52c13f --- /dev/null +++ b/packages/nitro/src/nuxt-deploy.ts @@ -0,0 +1,89 @@ +import { resolve } from 'path' +import { rollup, OutputOptions } from 'rollup' +import consola from 'consola' +import Hookable from 'hookable' +import defu from 'defu' +import { readFile, writeFile, existsSync } from 'fs-extra' +import prettyBytes from 'pretty-bytes' +import gzipSize from 'gzip-size' +import chalk from 'chalk' +import { getRollupConfig } from './rollup.config' +import { tryImport, hl, prettyPath } from './utils' + +async function main () { + const rootDir = resolve(process.cwd(), process.argv[2] || '.') + + // Config + const config = { + rootDir, + buildDir: '', + targets: [], + target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, + minify: process.argv.includes('--minify') ? true : null, + analyze: process.argv.includes('--analyze') ? true : null, + logStartup: true + } + Object.assign(config, tryImport(rootDir, './nuxt.config')!.deploy) + config.buildDir = resolve(config.rootDir, config.buildDir || '.nuxt') + + // Ensure dist exists + if (!existsSync(resolve(config.buildDir, 'dist/server'))) { + return consola.error('Please use `nuxt build` first to build project!') + } else { + consola.success('Using existing nuxt build from', prettyPath(config.buildDir)) + } + + // Compile html template + const htmlTemplateFile = resolve(config.buildDir, 'views/app.template.html') // TODO: nuxt3: document.template.html + const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') + const htmlTemplateContents = await readFile(htmlTemplateFile, 'utf-8') + // eslint-disable-next-line no-template-curly-in-string + const htmlTemplateCompiled = `export default (params) => \`${htmlTemplateContents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` + await writeFile(htmlTemplateFileJS, htmlTemplateCompiled) + consola.info('Generated', (prettyPath(htmlTemplateFileJS))) + + // Bundle for each target + for (let target of config.targets) { + if (typeof target === 'string') { + target = { target } + } + + if (config.target && target.target !== config.target) { + continue + } + + console.log('\n') + consola.info(`Generating bundle for ${hl(target.target)}`) + + const ctx: any = defu( + target, + config, + tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target) + ) + + const hooks = new Hookable() + hooks.addHooks(ctx.hooks) + + await hooks.callHook('rollup:prepare', ctx) + ctx.rollupConfig = getRollupConfig(ctx) + await hooks.callHook('rollup:config', ctx) + + await hooks.callHook('rollup:before', ctx) + const build = await rollup(ctx.rollupConfig) + await hooks.callHook('rollup:built', ctx, build) + + const { output } = await build.write(ctx.rollupConfig.output as OutputOptions) + const size = prettyBytes(output[0].code.length) + const zSize = prettyBytes(await gzipSize(output[0].code)) + consola.success('Generated', prettyPath((ctx.rollupConfig.output as any).file), + chalk.gray(`(Size: ${size} Gzip: ${zSize})`) + ) + + await hooks.callHook('rollup:done', ctx) + } +} + +main().catch((err) => { + consola.error(err) + process.exit(1) +}) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts new file mode 100644 index 0000000000..32931f0d63 --- /dev/null +++ b/packages/nitro/src/rollup.config.ts @@ -0,0 +1,109 @@ +import Module from 'module' +import path from 'path' +import { InputOptions, OutputOptions } from 'rollup' +import { terser } from 'rollup-plugin-terser' +import commonjs from '@rollup/plugin-commonjs' +import resolve from '@rollup/plugin-node-resolve' +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 esbuild from 'rollup-plugin-esbuild' + +export type RollupConfig = InputOptions & { output: OutputOptions } + +export const getRollupConfig = (config) => { + const mocks = [ + '@babel/parser', + '@vue/compiler-core', + '@vue/compiler-dom', + '@vue/compiler-ssr' + ] + + const extensions = ['.ts', '.mjs', '.js', '.json', '.node'] + + const external = [] + + if (config.node === false) { + mocks.push(...Module.builtinModules) + } else { + external.push(...Module.builtinModules) + } + + const options: RollupConfig = { + input: config.entry, + + output: { + file: path.resolve(config.buildDir, 'dist/server', `index.${config.target}.js`), + format: 'cjs', + intro: '', + outro: '', + preferConst: true + }, + + external, + + plugins: [ + replace({ + values: { + 'process.env.NODE_ENV': '"production"' + } + }), + + alias({ + entries: { + '~runtime': path.resolve(__dirname, 'runtime'), + '~build': config.buildDir, + '~mock': require.resolve('./runtime/mock'), + ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}) + } + }), + + // https://github.com/rollup/plugins/tree/master/packages/node-resolve + resolve({ + extensions, + preferBuiltins: true, + mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) + }), + + // https://github.com/rollup/plugins/tree/master/packages/commonjs + commonjs({ + extensions: extensions.filter(ext => ext !== '.json'), + dynamicRequireTargets: ['*.js'] + }), + + // https://github.com/egoist/rollup-plugin-esbuild + esbuild({ + target: 'node12', + include: /\.[jt]s?$/, + tsconfig: false, + sourceMap: false, + loaders: { + '.json': 'json', + '.js': 'jsx', + '.ts': 'ts' + } + }), + + // https://github.com/rollup/plugins/tree/master/packages/json + json() + ] + } + + if (config.logStartup) { + options.output.intro += 'global._startTime = process.hrtime();' + // eslint-disable-next-line no-template-curly-in-string + options.output.outro += 'global._endTime = process.hrtime(global._startTime); global._coldstart = ((_endTime[0] * 1e9) + _endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms`);' + } + + if (config.analyze) { + // https://github.com/doesdev/rollup-plugin-analyzer + options.plugins.push(analyze()) + } + + if (config.minify) { + options.plugins.push(terser()) + } + + return options +} diff --git a/packages/nitro/src/runtime/mock.ts b/packages/nitro/src/runtime/mock.ts new file mode 100644 index 0000000000..5b30aba73a --- /dev/null +++ b/packages/nitro/src/runtime/mock.ts @@ -0,0 +1,25 @@ +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 [] + } + }) +} + +export default getProxy('mock') diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts new file mode 100644 index 0000000000..26006d6549 --- /dev/null +++ b/packages/nitro/src/runtime/server.ts @@ -0,0 +1,39 @@ +import { createRenderer } from 'vue-bundle-renderer' +import devalue from '@nuxt/devalue' + +// @ts-ignore +import { renderToString } from './vue2' +// @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) { + const ssrContext = { + url, + runtimeConfig: { + public: {}, + private: {} + }, + _registeredComponents: [] + } + const rendered = await renderer.renderToString(ssrContext) + + const state = `` + const html = `
${rendered.html}
` + + return htmlTemplate({ + HTML_ATTRS: '', + HEAD_ATTRS: '', + BODY_ATTRS: '', + HEAD: rendered.renderResourceHints() + rendered.renderStyles(), + APP: html + state + rendered.renderScripts() + }) +} diff --git a/packages/nitro/src/runtime/vue2.ts b/packages/nitro/src/runtime/vue2.ts new file mode 100644 index 0000000000..e1c7593799 --- /dev/null +++ b/packages/nitro/src/runtime/vue2.ts @@ -0,0 +1,12 @@ +const _renderToString = require('vue-server-renderer/basic.js') + +export function renderToString (component, context) { + return new Promise((resolve, reject) => { + _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 new file mode 100644 index 0000000000..f3fd7daa59 --- /dev/null +++ b/packages/nitro/src/runtime/vue3.ts @@ -0,0 +1,2 @@ +// @ts-ignore +export { renderToString } from '@vue/server-renderer' diff --git a/packages/nitro/src/targets/cli/entry.ts b/packages/nitro/src/targets/cli/entry.ts new file mode 100644 index 0000000000..e82677f019 --- /dev/null +++ b/packages/nitro/src/targets/cli/entry.ts @@ -0,0 +1,8 @@ +import { render } from '~runtime/server' + +render(process.argv[2] || '/') + .then(html => console.log(html)) + .catch((err) => { + console.error(err) + process.exit(1) + }) diff --git a/packages/nitro/src/targets/cli/index.ts b/packages/nitro/src/targets/cli/index.ts new file mode 100644 index 0000000000..c1e4b06ec0 --- /dev/null +++ b/packages/nitro/src/targets/cli/index.ts @@ -0,0 +1,11 @@ +import { relative } from 'path' +import consola from 'consola' + +export default { + entry: require.resolve('./entry'), + hooks: { + 'rollup:done' ({ rollupConfig }) { + consola.info(`Usage: \`node ${relative(process.cwd(), rollupConfig.output.file)} [route]\``) + } + } +} diff --git a/packages/nitro/src/targets/cloudflare/entry.ts b/packages/nitro/src/targets/cloudflare/entry.ts new file mode 100644 index 0000000000..0aa0b0c613 --- /dev/null +++ b/packages/nitro/src/targets/cloudflare/entry.ts @@ -0,0 +1,17 @@ +import { render } from '~runtime/server' + +addEventListener('fetch', (event) => { + // @ts-ignore + event.respondWith(handleRequest(event.request)) +}) + +async function handleRequest (_request) { + // @ts-ignore + const html = await render() + return new Response(html, { + status: 200, + headers: { + 'content-type': 'text/html;charset=UTF-8' + } + }) +} diff --git a/packages/nitro/src/targets/cloudflare/index.ts b/packages/nitro/src/targets/cloudflare/index.ts new file mode 100644 index 0000000000..f8df33757c --- /dev/null +++ b/packages/nitro/src/targets/cloudflare/index.ts @@ -0,0 +1,10 @@ +export default { + entry: require.resolve('./entry'), + node: false, + hooks: { + 'rollup:config' ({ rollupConfig }) { + rollupConfig.output.intro += 'const global = {}; const exports = {}; const module = { exports }; const require = function() {};' + rollupConfig.output.format = 'iife' + } + } +} diff --git a/packages/nitro/src/targets/vercel/entry.ts b/packages/nitro/src/targets/vercel/entry.ts new file mode 100644 index 0000000000..7937bbfe27 --- /dev/null +++ b/packages/nitro/src/targets/vercel/entry.ts @@ -0,0 +1,18 @@ +// @ts-ignore +import { render } from '~runtime/server' + +module.exports = (req, res) => { + const start = process.hrtime() + render(req.url).then((html) => { + const end = process.hrtime(start) + const time = ((end[0] * 1e9) + end[1]) / 1e6 + // @ts-ignore + res.setHeader('X-Nuxt-Coldstart', global._coldstart + 'ms') + res.setHeader('X-Nuxt-Responsetime', time + 'ms') + + res.end(html) + }).catch((err) => { + console.error(err) + res.end('Error: ' + err) + }) +} diff --git a/packages/nitro/src/targets/vercel/index.ts b/packages/nitro/src/targets/vercel/index.ts new file mode 100644 index 0000000000..fe643f31e0 --- /dev/null +++ b/packages/nitro/src/targets/vercel/index.ts @@ -0,0 +1,10 @@ +import consola from 'consola' + +export default { + entry: require.resolve('./entry'), + hooks: { + 'rollup:done' (_ctx) { + consola.info('Run `vercel deploy` to deploy!') + } + } +} diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts new file mode 100644 index 0000000000..510d3fb00e --- /dev/null +++ b/packages/nitro/src/utils.ts @@ -0,0 +1,11 @@ +import { relative } from 'path' +import jiti from 'jiti' + +export const hl = str => '`' + str + '`' + +export const prettyPath = (p, highlight = true) => { + p = relative(process.cwd(), p) + return highlight ? hl(p) : p +} + +export const tryImport = (dir, path) => { try { return jiti(dir)(path) } catch (_err) { } } From ef4e5443aa874af840fed851b1b1f4a1cf18f80e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 01:11:33 +0100 Subject: [PATCH 002/227] fix: don't set _registeredComponents --- packages/nitro/src/runtime/server.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts index 26006d6549..fe7a518bb3 100644 --- a/packages/nitro/src/runtime/server.ts +++ b/packages/nitro/src/runtime/server.ts @@ -21,8 +21,7 @@ export async function render (url) { runtimeConfig: { public: {}, private: {} - }, - _registeredComponents: [] + } } const rendered = await renderer.renderToString(ssrContext) From a9a262f258ec5acaeb1c2914b398d9a596f97cd1 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 01:13:35 +0100 Subject: [PATCH 003/227] fix: ensure builds are relative to buildDir --- packages/nitro/src/nuxt-deploy.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index 292c52c13f..f69ae9c320 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -33,6 +33,9 @@ async function main () { consola.success('Using existing nuxt build from', prettyPath(config.buildDir)) } + // Ensure relative operations are relative to build dir (fixes rollup dynamic imports) + process.chdir(config.buildDir) + // Compile html template const htmlTemplateFile = resolve(config.buildDir, 'views/app.template.html') // TODO: nuxt3: document.template.html const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') @@ -78,7 +81,6 @@ async function main () { consola.success('Generated', prettyPath((ctx.rollupConfig.output as any).file), chalk.gray(`(Size: ${size} Gzip: ${zSize})`) ) - await hooks.callHook('rollup:done', ctx) } } From aea527fd879380975640bc91e406892af96bfe46 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 01:31:43 +0100 Subject: [PATCH 004/227] fix typescript support --- packages/nitro/src/rollup.config.ts | 93 +++++++++++++--------------- packages/nitro/src/runtime/server.ts | 2 +- 2 files changed, 45 insertions(+), 50 deletions(-) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 32931f0d63..8ffaf46c8e 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -8,13 +8,14 @@ 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 esbuild from 'rollup-plugin-esbuild' +import ts from 'rollup-plugin-ts' export type RollupConfig = InputOptions & { output: OutputOptions } export const getRollupConfig = (config) => { const mocks = [ '@babel/parser', + 'encoding', '@vue/compiler-core', '@vue/compiler-dom', '@vue/compiler-ssr' @@ -32,7 +33,6 @@ export const getRollupConfig = (config) => { const options: RollupConfig = { input: config.entry, - output: { file: path.resolve(config.buildDir, 'dist/server', `index.${config.target}.js`), format: 'cjs', @@ -40,56 +40,51 @@ export const getRollupConfig = (config) => { outro: '', preferConst: true }, - external, - - plugins: [ - replace({ - values: { - 'process.env.NODE_ENV': '"production"' - } - }), - - alias({ - entries: { - '~runtime': path.resolve(__dirname, 'runtime'), - '~build': config.buildDir, - '~mock': require.resolve('./runtime/mock'), - ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}) - } - }), - - // https://github.com/rollup/plugins/tree/master/packages/node-resolve - resolve({ - extensions, - preferBuiltins: true, - mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) - }), - - // https://github.com/rollup/plugins/tree/master/packages/commonjs - commonjs({ - extensions: extensions.filter(ext => ext !== '.json'), - dynamicRequireTargets: ['*.js'] - }), - - // https://github.com/egoist/rollup-plugin-esbuild - esbuild({ - target: 'node12', - include: /\.[jt]s?$/, - tsconfig: false, - sourceMap: false, - loaders: { - '.json': 'json', - '.js': 'jsx', - '.ts': 'ts' - } - }), - - // https://github.com/rollup/plugins/tree/master/packages/json - json() - ] + plugins: [] } + // https://github.com/rollup/plugins/tree/master/packages/replace + options.plugins.push(replace({ + values: { + 'process.env.NODE_ENV': '"production"' + } + })) + + // https://github.com/rollup/plugins/tree/master/packages/alias + options.plugins.push(alias({ + entries: { + '~runtime': path.resolve(__dirname, 'runtime'), + '~build': config.buildDir, + '~mock': require.resolve('./runtime/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, + preferBuiltins: true, + mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) + })) + + // https://github.com/rollup/plugins/tree/master/packages/commonjs + options.plugins.push(commonjs({ + extensions: extensions.filter(ext => ext !== '.json'), + dynamicRequireTargets: ['*.js'] + })) + + // https://github.com/rollup/plugins/tree/master/packages/json + options.plugins.push(json()) + if (config.logStartup) { options.output.intro += 'global._startTime = process.hrtime();' // eslint-disable-next-line no-template-curly-in-string diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts index fe7a518bb3..84fdaf0aab 100644 --- a/packages/nitro/src/runtime/server.ts +++ b/packages/nitro/src/runtime/server.ts @@ -16,7 +16,7 @@ const renderer = createRenderer(server, { }) export async function render (url) { - const ssrContext = { + const ssrContext: any = { url, runtimeConfig: { public: {}, From 9e5bb2a580ad33ef05fe966ebed470d0f2e83220 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 01:37:57 +0100 Subject: [PATCH 005/227] fix _renderToString import for vue2 --- packages/nitro/src/runtime/vue2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/runtime/vue2.ts b/packages/nitro/src/runtime/vue2.ts index e1c7593799..b15946b340 100644 --- a/packages/nitro/src/runtime/vue2.ts +++ b/packages/nitro/src/runtime/vue2.ts @@ -1,4 +1,4 @@ -const _renderToString = require('vue-server-renderer/basic.js') +import _renderToString from 'vue-server-renderer/basic.js' export function renderToString (component, context) { return new Promise((resolve, reject) => { From 9b7016059b0fce6722bda803284f52a753731f22 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 01:54:31 +0100 Subject: [PATCH 006/227] fix vue2 import --- packages/nitro/src/runtime/vue2.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/runtime/vue2.ts b/packages/nitro/src/runtime/vue2.ts index b15946b340..7b55418b8e 100644 --- a/packages/nitro/src/runtime/vue2.ts +++ b/packages/nitro/src/runtime/vue2.ts @@ -1,8 +1,10 @@ -import _renderToString from 'vue-server-renderer/basic.js' +import { createRenderer } from 'vue-server-renderer/build.prod.js' + +const _renderer = createRenderer({}) export function renderToString (component, context) { return new Promise((resolve, reject) => { - _renderToString(component, context, (err, result) => { + _renderer.renderToString(component, context, (err, result) => { if (err) { return reject(err) } From 82399259db2f3dd7e169bcaf358ebec01ca2a453 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 01:54:45 +0100 Subject: [PATCH 007/227] tree-shake extra deps for vue-server-renderer --- packages/nitro/src/rollup.config.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 8ffaf46c8e..334f52df4e 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -14,8 +14,17 @@ export type RollupConfig = InputOptions & { output: OutputOptions } export const getRollupConfig = (config) => { const mocks = [ - '@babel/parser', + // @nuxt/devalue + 'consola', + // vue2 'encoding', + 'he', + 'resolve', + 'source-map', + 'lodash.template', + 'serialize-javascript', + // vue3 + '@babel/parser', '@vue/compiler-core', '@vue/compiler-dom', '@vue/compiler-ssr' From 87df0ac9868feb111213c1192c9a6108bbfa0b40 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 02:41:55 +0100 Subject: [PATCH 008/227] ignore alias import for now --- packages/nitro/src/targets/cli/entry.ts | 1 + packages/nitro/src/targets/cloudflare/entry.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/nitro/src/targets/cli/entry.ts b/packages/nitro/src/targets/cli/entry.ts index e82677f019..ad058ad4bf 100644 --- a/packages/nitro/src/targets/cli/entry.ts +++ b/packages/nitro/src/targets/cli/entry.ts @@ -1,3 +1,4 @@ +// @ts-ignore import { render } from '~runtime/server' render(process.argv[2] || '/') diff --git a/packages/nitro/src/targets/cloudflare/entry.ts b/packages/nitro/src/targets/cloudflare/entry.ts index 0aa0b0c613..b27f83034c 100644 --- a/packages/nitro/src/targets/cloudflare/entry.ts +++ b/packages/nitro/src/targets/cloudflare/entry.ts @@ -1,3 +1,4 @@ +// @ts-ignore import { render } from '~runtime/server' addEventListener('fetch', (event) => { From 54bb617474089c19e92a51b19aac9fbcbb0ca6d6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 13:12:39 +0100 Subject: [PATCH 009/227] fix resolution when linking --- packages/nitro/src/rollup.config.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 334f52df4e..450fbaffe0 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -82,6 +82,11 @@ export const getRollupConfig = (config) => { options.plugins.push(resolve({ extensions, preferBuiltins: true, + rootDir: config.rootDir, + // https://www.npmjs.com/package/resolve + customResolveOptions: { + basedir: config.rootDir + }, mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) })) From 0c4225238a54e6e1f94bac7b1c0a6b304af66ff7 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 13:50:40 +0100 Subject: [PATCH 010/227] configurable nuxt version --- packages/nitro/src/nuxt-deploy.ts | 3 ++- packages/nitro/src/rollup.config.ts | 1 + packages/nitro/src/runtime/server.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index f69ae9c320..dd0633295f 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -18,6 +18,7 @@ async function main () { rootDir, buildDir: '', targets: [], + nuxt: 2, target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, minify: process.argv.includes('--minify') ? true : null, analyze: process.argv.includes('--analyze') ? true : null, @@ -37,7 +38,7 @@ async function main () { process.chdir(config.buildDir) // Compile html template - const htmlTemplateFile = resolve(config.buildDir, 'views/app.template.html') // TODO: nuxt3: document.template.html + const htmlTemplateFile = resolve(config.buildDir, `views/${{ 2: 'app', 3: 'template' }[config.nuxt]}.template.html`) const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') const htmlTemplateContents = await readFile(htmlTemplateFile, 'utf-8') // eslint-disable-next-line no-template-curly-in-string diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 450fbaffe0..8e93be3620 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -64,6 +64,7 @@ export const getRollupConfig = (config) => { options.plugins.push(alias({ entries: { '~runtime': path.resolve(__dirname, 'runtime'), + '~rendertostring': config.nuxt === 2 ? require.resolve('./runtime/vue2') : require.resolve('./runtime/vue3'), '~build': config.buildDir, '~mock': require.resolve('./runtime/mock'), ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}) diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts index 84fdaf0aab..f83c1b73a4 100644 --- a/packages/nitro/src/runtime/server.ts +++ b/packages/nitro/src/runtime/server.ts @@ -2,7 +2,7 @@ import { createRenderer } from 'vue-bundle-renderer' import devalue from '@nuxt/devalue' // @ts-ignore -import { renderToString } from './vue2' +import { renderToString } from '~rendertostring' // @ts-ignore import server from '~build/dist/server/server' // @ts-ignore From ef072d972c21a0c346af0f35ee0db7ca625af809 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 13:51:57 +0100 Subject: [PATCH 011/227] fix typo --- packages/nitro/src/nuxt-deploy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index dd0633295f..8148e7f959 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -38,7 +38,7 @@ async function main () { process.chdir(config.buildDir) // Compile html template - const htmlTemplateFile = resolve(config.buildDir, `views/${{ 2: 'app', 3: 'template' }[config.nuxt]}.template.html`) + const htmlTemplateFile = resolve(config.buildDir, `views/${{ 2: 'app', 3: 'document' }[config.nuxt]}.template.html`) const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') const htmlTemplateContents = await readFile(htmlTemplateFile, 'utf-8') // eslint-disable-next-line no-template-curly-in-string From e17b0c57870a76fc483a618211a14f587cf78c8e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 14:11:26 +0100 Subject: [PATCH 012/227] preserve webpack dynamic requires --- packages/nitro/src/rollup.config.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 8e93be3620..b9b4645f6a 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -60,6 +60,16 @@ export const getRollupConfig = (config) => { } })) + // Preserve dynamic require + // https://github.com/rollup/plugins/tree/master/packages/replace + options.output.intro += 'const requireDynamic = require;' + options.plugins.push(replace({ + values: { + 'require("./"': 'requireDynamic("./"' + }, + delimiters: ['', ''] + })) + // https://github.com/rollup/plugins/tree/master/packages/alias options.plugins.push(alias({ entries: { @@ -93,8 +103,7 @@ export const getRollupConfig = (config) => { // https://github.com/rollup/plugins/tree/master/packages/commonjs options.plugins.push(commonjs({ - extensions: extensions.filter(ext => ext !== '.json'), - dynamicRequireTargets: ['*.js'] + extensions: extensions.filter(ext => ext !== '.json') })) // https://github.com/rollup/plugins/tree/master/packages/json From b03eef0cebc53fa3167653718e2ed6c67238e0d5 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 14:12:33 +0100 Subject: [PATCH 013/227] make requireDynamic pattern more exact --- packages/nitro/src/rollup.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index b9b4645f6a..e9358bd021 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -65,7 +65,7 @@ export const getRollupConfig = (config) => { options.output.intro += 'const requireDynamic = require;' options.plugins.push(replace({ values: { - 'require("./"': 'requireDynamic("./"' + 'require("./" +': 'requireDynamic("./" +' }, delimiters: ['', ''] })) From 9959411f60e82b62c18aeb25c5d335fc8da2a086 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 14:40:56 +0100 Subject: [PATCH 014/227] export targets to individual dir --- packages/nitro/src/rollup.config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index e9358bd021..33649243cf 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -43,7 +43,7 @@ export const getRollupConfig = (config) => { const options: RollupConfig = { input: config.entry, output: { - file: path.resolve(config.buildDir, 'dist/server', `index.${config.target}.js`), + file: path.resolve(config.buildDir, `dist/${config.target}`, 'index.js'), format: 'cjs', intro: '', outro: '', @@ -65,7 +65,7 @@ export const getRollupConfig = (config) => { options.output.intro += 'const requireDynamic = require;' options.plugins.push(replace({ values: { - 'require("./" +': 'requireDynamic("./" +' + 'require("./" +': 'requireDynamic("../server/" +' }, delimiters: ['', ''] })) From ad4fc18ab8b1fa516c9d9d433a01366c358b2b6c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 15:42:27 +0100 Subject: [PATCH 015/227] feat: dynamic chunk importer --- packages/nitro/src/dynamic.ts | 44 +++++++++++++++++++++++++++++ packages/nitro/src/nuxt-deploy.ts | 12 +++++++- packages/nitro/src/rollup.config.ts | 28 +++++++++--------- packages/nitro/src/utils.ts | 4 ++- 4 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 packages/nitro/src/dynamic.ts diff --git a/packages/nitro/src/dynamic.ts b/packages/nitro/src/dynamic.ts new file mode 100644 index 0000000000..2209ce7519 --- /dev/null +++ b/packages/nitro/src/dynamic.ts @@ -0,0 +1,44 @@ +import { join } from 'path' +import globby from 'globby' + +export async function createDynamicImporter (cwd: string) { + const assets = await globby('**/*.js', { cwd, absolute: false }) + const chunkInfo = {} + for (const asset of assets) { + const { id, ids, modules } = require(join(cwd, asset)) + if ((id || ids) && modules) { + chunkInfo[asset] = { id, ids, modules: Object.keys(modules) } + } + } + + return (syncImport, asyncImport) => genRequireDynamic(chunkInfo, syncImport, asyncImport) +} + +export function genRequireDynamic (chunkInfo, syncImport, asyncImport) { + return `\nconst _dynamic_chunks = ${JSON.stringify(chunkInfo, null, 2)}; +function requireDynamic (chunkId) { + const chunk = _dynamic_chunks[chunkId] + + if (!chunk) { + return ${syncImport} + } + + const promise = ${asyncImport} + + if (Array.isArray(chunk.modules)) { + const modules = {} + for (const id of chunk.modules) { + modules[id] = function (module, _exports, _require) { + module.exports = promise.then(chunk => { + const asyncModule = { exports: {}, require: _require } + chunk.modules[id](asyncModule, asyncModule.exports, asyncModule.require) + return asyncModule.exports + }) + } + } + chunk.modules = modules + } + + return chunk +};` +} diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index 8148e7f959..bb4ee92788 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -9,6 +9,7 @@ import gzipSize from 'gzip-size' import chalk from 'chalk' import { getRollupConfig } from './rollup.config' import { tryImport, hl, prettyPath } from './utils' +import { createDynamicImporter } from './dynamic' async function main () { const rootDir = resolve(process.cwd(), process.argv[2] || '.') @@ -19,6 +20,9 @@ async function main () { buildDir: '', targets: [], nuxt: 2, + dynamicImporter: undefined, + importSync: "require('../server/' + chunkId)", + importAsync: "Promise.resolve(require('../server/' + chunkId))", target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, minify: process.argv.includes('--minify') ? true : null, analyze: process.argv.includes('--analyze') ? true : null, @@ -44,7 +48,13 @@ async function main () { // eslint-disable-next-line no-template-curly-in-string const htmlTemplateCompiled = `export default (params) => \`${htmlTemplateContents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` await writeFile(htmlTemplateFileJS, htmlTemplateCompiled) - consola.info('Generated', (prettyPath(htmlTemplateFileJS))) + consola.info('Generated', prettyPath(htmlTemplateFileJS)) + + // Collect dynamic chunks + if (!config.dynamicImporter) { + consola.info('Collecting dynamic chunks...') + config.dynamicImporter = await createDynamicImporter(resolve(config.buildDir, 'dist/server')) + } // Bundle for each target for (let target of config.targets) { diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 33649243cf..ede9cdc4fb 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -53,6 +53,12 @@ export const getRollupConfig = (config) => { plugins: [] } + if (config.logStartup) { + options.output.intro += 'global._startTime = process.hrtime();' + // eslint-disable-next-line no-template-curly-in-string + options.output.outro += 'global._endTime = process.hrtime(global._startTime); global._coldstart = ((_endTime[0] * 1e9) + _endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms`);' + } + // https://github.com/rollup/plugins/tree/master/packages/replace options.plugins.push(replace({ values: { @@ -60,15 +66,13 @@ export const getRollupConfig = (config) => { } })) - // Preserve dynamic require - // https://github.com/rollup/plugins/tree/master/packages/replace - options.output.intro += 'const requireDynamic = require;' - options.plugins.push(replace({ - values: { - 'require("./" +': 'requireDynamic("../server/" +' - }, - delimiters: ['', ''] - })) + // Dynamic Importer + if (config.dynamicImporter) { + options.output.intro += config.dynamicImporter(config.importSync, config.importAsync) + } else { + options.output.intro += 'const requireDynamic = require;' + } + options.plugins.push(replace({ values: { 'require("./" +': 'requireDynamic(' }, delimiters: ['', ''] })) // https://github.com/rollup/plugins/tree/master/packages/alias options.plugins.push(alias({ @@ -109,12 +113,6 @@ export const getRollupConfig = (config) => { // https://github.com/rollup/plugins/tree/master/packages/json options.plugins.push(json()) - if (config.logStartup) { - options.output.intro += 'global._startTime = process.hrtime();' - // eslint-disable-next-line no-template-curly-in-string - options.output.outro += 'global._endTime = process.hrtime(global._startTime); global._coldstart = ((_endTime[0] * 1e9) + _endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms`);' - } - if (config.analyze) { // https://github.com/doesdev/rollup-plugin-analyzer options.plugins.push(analyze()) diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index 510d3fb00e..9994a57d4b 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -1,10 +1,12 @@ import { relative } from 'path' import jiti from 'jiti' +const pwd = process.cwd() + export const hl = str => '`' + str + '`' export const prettyPath = (p, highlight = true) => { - p = relative(process.cwd(), p) + p = relative(pwd, p) return highlight ? hl(p) : p } From ee27e3b5fe9eeeabc50157a0cefff67ae81777bc Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 2 Nov 2020 15:54:18 +0100 Subject: [PATCH 016/227] allow disabling async importer --- packages/nitro/src/nuxt-deploy.ts | 10 ++++------ packages/nitro/src/rollup.config.ts | 2 +- packages/nitro/src/targets/vercel/index.ts | 1 + 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index bb4ee92788..ec1807ae5a 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -20,7 +20,6 @@ async function main () { buildDir: '', targets: [], nuxt: 2, - dynamicImporter: undefined, importSync: "require('../server/' + chunkId)", importAsync: "Promise.resolve(require('../server/' + chunkId))", target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, @@ -51,10 +50,8 @@ async function main () { consola.info('Generated', prettyPath(htmlTemplateFileJS)) // Collect dynamic chunks - if (!config.dynamicImporter) { - consola.info('Collecting dynamic chunks...') - config.dynamicImporter = await createDynamicImporter(resolve(config.buildDir, 'dist/server')) - } + consola.info('Collecting dynamic chunks...') + const dynamicImporter = await createDynamicImporter(resolve(config.buildDir, 'dist/server')) // Bundle for each target for (let target of config.targets) { @@ -72,7 +69,8 @@ async function main () { const ctx: any = defu( target, config, - tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target) + tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target), + { dynamicImporter } ) const hooks = new Hookable() diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index ede9cdc4fb..61fd29f24c 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -70,7 +70,7 @@ export const getRollupConfig = (config) => { if (config.dynamicImporter) { options.output.intro += config.dynamicImporter(config.importSync, config.importAsync) } else { - options.output.intro += 'const requireDynamic = require;' + options.output.intro += `const requireDynamic = (chunkId) => ${config.importSync}` } options.plugins.push(replace({ values: { 'require("./" +': 'requireDynamic(' }, delimiters: ['', ''] })) diff --git a/packages/nitro/src/targets/vercel/index.ts b/packages/nitro/src/targets/vercel/index.ts index fe643f31e0..ff115845d6 100644 --- a/packages/nitro/src/targets/vercel/index.ts +++ b/packages/nitro/src/targets/vercel/index.ts @@ -2,6 +2,7 @@ import consola from 'consola' export default { entry: require.resolve('./entry'), + dynamicImporter: false, hooks: { 'rollup:done' (_ctx) { consola.info('Run `vercel deploy` to deploy!') From ec8468635be2aa86d896689217213afc17189aa6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 18:09:39 +0100 Subject: [PATCH 017/227] fix timing script --- packages/nitro/src/rollup.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 61fd29f24c..c5e3fac88b 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -56,7 +56,7 @@ export const getRollupConfig = (config) => { if (config.logStartup) { options.output.intro += 'global._startTime = process.hrtime();' // eslint-disable-next-line no-template-curly-in-string - options.output.outro += 'global._endTime = process.hrtime(global._startTime); global._coldstart = ((_endTime[0] * 1e9) + _endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms`);' + options.output.outro += 'global._endTime = process.hrtime(global._startTime); global._coldstart = ((global._endTime[0] * 1e9) + global._endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms`);' } // https://github.com/rollup/plugins/tree/master/packages/replace From cbae59a88ba756c7b609544439d20a0e2026d9c9 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 20:55:36 +0100 Subject: [PATCH 018/227] feat: dynamic-require rollup plugin --- packages/nitro/src/dynamic-require.ts | 46 +++++++++++++++++++++++++++ packages/nitro/src/dynamic.ts | 44 ------------------------- packages/nitro/src/nuxt-deploy.ts | 10 +----- packages/nitro/src/rollup.config.ts | 17 ++++++---- 4 files changed, 57 insertions(+), 60 deletions(-) create mode 100644 packages/nitro/src/dynamic-require.ts delete mode 100644 packages/nitro/src/dynamic.ts diff --git a/packages/nitro/src/dynamic-require.ts b/packages/nitro/src/dynamic-require.ts new file mode 100644 index 0000000000..c2d4894cfd --- /dev/null +++ b/packages/nitro/src/dynamic-require.ts @@ -0,0 +1,46 @@ +import { resolve } from 'path' +import globby, { GlobbyOptions } from 'globby' + +const PLUGIN_NAME = 'dynamic-require' +const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js` +const DYNAMIC_REQUIRE_RE = /require\("\.\/" \+/g + +function CJSTemplate ({ imports }) { + return `${imports.map(i => `import ${i.name} from '${i.import}'`).join('\n')} +const dynamicChunks = { + ${imports.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} +}; + +export default function dynamicRequire(id) { + return dynamicChunks[id]; +};` +} + +interface Options { + dir: string, + globbyOptions: GlobbyOptions +} + +export default function dynamicRequire ({ dir, globbyOptions }: Options) { + return { + name: PLUGIN_NAME, + transform (code, _id) { + return code.replace(DYNAMIC_REQUIRE_RE, `require('${HELPER_DYNAMIC}')(`) + }, + resolveId (id) { + return id === HELPER_DYNAMIC ? id : null + }, + async load (id) { + if (id === HELPER_DYNAMIC) { + const files = await globby('**/*.js', { cwd: dir, absolute: false, ...globbyOptions }) + const imports = files.map(id => ({ + id, + import: resolve(dir, id), + name: id.replace(/[\\/.]/g, '_') + })) + return CJSTemplate({ imports }) + } + return null + } + } +} diff --git a/packages/nitro/src/dynamic.ts b/packages/nitro/src/dynamic.ts deleted file mode 100644 index 2209ce7519..0000000000 --- a/packages/nitro/src/dynamic.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { join } from 'path' -import globby from 'globby' - -export async function createDynamicImporter (cwd: string) { - const assets = await globby('**/*.js', { cwd, absolute: false }) - const chunkInfo = {} - for (const asset of assets) { - const { id, ids, modules } = require(join(cwd, asset)) - if ((id || ids) && modules) { - chunkInfo[asset] = { id, ids, modules: Object.keys(modules) } - } - } - - return (syncImport, asyncImport) => genRequireDynamic(chunkInfo, syncImport, asyncImport) -} - -export function genRequireDynamic (chunkInfo, syncImport, asyncImport) { - return `\nconst _dynamic_chunks = ${JSON.stringify(chunkInfo, null, 2)}; -function requireDynamic (chunkId) { - const chunk = _dynamic_chunks[chunkId] - - if (!chunk) { - return ${syncImport} - } - - const promise = ${asyncImport} - - if (Array.isArray(chunk.modules)) { - const modules = {} - for (const id of chunk.modules) { - modules[id] = function (module, _exports, _require) { - module.exports = promise.then(chunk => { - const asyncModule = { exports: {}, require: _require } - chunk.modules[id](asyncModule, asyncModule.exports, asyncModule.require) - return asyncModule.exports - }) - } - } - chunk.modules = modules - } - - return chunk -};` -} diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index ec1807ae5a..748493c938 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -9,7 +9,6 @@ import gzipSize from 'gzip-size' import chalk from 'chalk' import { getRollupConfig } from './rollup.config' import { tryImport, hl, prettyPath } from './utils' -import { createDynamicImporter } from './dynamic' async function main () { const rootDir = resolve(process.cwd(), process.argv[2] || '.') @@ -20,8 +19,6 @@ async function main () { buildDir: '', targets: [], nuxt: 2, - importSync: "require('../server/' + chunkId)", - importAsync: "Promise.resolve(require('../server/' + chunkId))", target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, minify: process.argv.includes('--minify') ? true : null, analyze: process.argv.includes('--analyze') ? true : null, @@ -49,10 +46,6 @@ async function main () { await writeFile(htmlTemplateFileJS, htmlTemplateCompiled) consola.info('Generated', prettyPath(htmlTemplateFileJS)) - // Collect dynamic chunks - consola.info('Collecting dynamic chunks...') - const dynamicImporter = await createDynamicImporter(resolve(config.buildDir, 'dist/server')) - // Bundle for each target for (let target of config.targets) { if (typeof target === 'string') { @@ -69,8 +62,7 @@ async function main () { const ctx: any = defu( target, config, - tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target), - { dynamicImporter } + tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target) ) const hooks = new Hookable() diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index c5e3fac88b..687214a11e 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -9,6 +9,7 @@ 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 dynamicRequire from './dynamic-require' export type RollupConfig = InputOptions & { output: OutputOptions } @@ -66,13 +67,15 @@ export const getRollupConfig = (config) => { } })) - // Dynamic Importer - if (config.dynamicImporter) { - options.output.intro += config.dynamicImporter(config.importSync, config.importAsync) - } else { - options.output.intro += `const requireDynamic = (chunkId) => ${config.importSync}` - } - options.plugins.push(replace({ values: { 'require("./" +': 'requireDynamic(' }, delimiters: ['', ''] })) + // Dynamic Require Support + options.plugins.push(dynamicRequire({ + dir: path.resolve(config.buildDir, 'dist/server'), + globbyOptions: { + ignore: [ + 'server.js' + ] + } + })) // https://github.com/rollup/plugins/tree/master/packages/alias options.plugins.push(alias({ From d441d79c6ca3eb3c0f64bba1217375e6505401c0 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 21:26:27 +0100 Subject: [PATCH 019/227] refactor: move common logic to server --- packages/nitro/src/runtime/server.ts | 21 ++++++++++++++--- packages/nitro/src/targets/cli/entry.ts | 26 +++++++++++++++++----- packages/nitro/src/targets/vercel/entry.ts | 25 ++++++++++----------- 3 files changed, 50 insertions(+), 22 deletions(-) diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts index f83c1b73a4..512b24d3fc 100644 --- a/packages/nitro/src/runtime/server.ts +++ b/packages/nitro/src/runtime/server.ts @@ -16,6 +16,8 @@ const renderer = createRenderer(server, { }) export async function render (url) { + const start = process.hrtime() + const ssrContext: any = { url, runtimeConfig: { @@ -26,13 +28,26 @@ export async function render (url) { const rendered = await renderer.renderToString(ssrContext) const state = `` - const html = `
${rendered.html}
` + const _html = `
${rendered.html}
` - return htmlTemplate({ + const html = htmlTemplate({ HTML_ATTRS: '', HEAD_ATTRS: '', BODY_ATTRS: '', HEAD: rendered.renderResourceHints() + rendered.renderStyles(), - APP: html + state + rendered.renderScripts() + 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', + 'X-Nuxt-Coldstart': global._coldstart + 'ms', + 'X-Nuxt-ResponseTime': time + 'ms' + } + } } diff --git a/packages/nitro/src/targets/cli/entry.ts b/packages/nitro/src/targets/cli/entry.ts index ad058ad4bf..607ca89587 100644 --- a/packages/nitro/src/targets/cli/entry.ts +++ b/packages/nitro/src/targets/cli/entry.ts @@ -1,9 +1,23 @@ // @ts-ignore import { render } from '~runtime/server' -render(process.argv[2] || '/') - .then(html => console.log(html)) - .catch((err) => { - console.error(err) - process.exit(1) - }) +const debug = (label, ...args) => console.debug(`> ${label}:`, ...args) + +async function main () { + const url = process.argv[2] || '/' + debug('URL', url) + + const { html, status, headers } = await render(url) + + debug('Status', status) + for (const header in headers) { + debug(header, headers[header]) + } + + console.log('\n', html) +} + +main().catch((err) => { + console.error(err) + process.exit(1) +}) diff --git a/packages/nitro/src/targets/vercel/entry.ts b/packages/nitro/src/targets/vercel/entry.ts index 7937bbfe27..51f712c47b 100644 --- a/packages/nitro/src/targets/vercel/entry.ts +++ b/packages/nitro/src/targets/vercel/entry.ts @@ -1,18 +1,17 @@ // @ts-ignore import { render } from '~runtime/server' -module.exports = (req, res) => { - const start = process.hrtime() - render(req.url).then((html) => { - const end = process.hrtime(start) - const time = ((end[0] * 1e9) + end[1]) / 1e6 - // @ts-ignore - res.setHeader('X-Nuxt-Coldstart', global._coldstart + 'ms') - res.setHeader('X-Nuxt-Responsetime', time + 'ms') - +module.exports = async (req, res) => { + try { + const { html, status, headers } = await render(req.url, { req, res }) + for (const header in headers) { + res.setHeadeer(header, headers[header]) + } + res.status(status) res.end(html) - }).catch((err) => { - console.error(err) - res.end('Error: ' + err) - }) + } catch (error) { + console.error(error) + res.status(500) + res.end('Internal Error: ' + error) + } } From 69b810a58e9194f52b208f2d86f7fcb12a5556ae Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 21:28:46 +0100 Subject: [PATCH 020/227] fix typo --- packages/nitro/src/targets/vercel/entry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/vercel/entry.ts b/packages/nitro/src/targets/vercel/entry.ts index 51f712c47b..b92aba883b 100644 --- a/packages/nitro/src/targets/vercel/entry.ts +++ b/packages/nitro/src/targets/vercel/entry.ts @@ -5,7 +5,7 @@ module.exports = async (req, res) => { try { const { html, status, headers } = await render(req.url, { req, res }) for (const header in headers) { - res.setHeadeer(header, headers[header]) + res.setHeader(header, headers[header]) } res.status(status) res.end(html) From e6fa415e5a4a97dadd9ff7aa3339952c9f25dbe0 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 21:51:11 +0100 Subject: [PATCH 021/227] feat: working cloudflare with vue2 and async chunks --- packages/nitro/src/nuxt-deploy.ts | 21 ++++++++---------- packages/nitro/src/rollup.config.ts | 3 ++- packages/nitro/src/runtime/server.ts | 7 +++--- packages/nitro/src/runtime/vue2.basic.ts | 13 +++++++++++ packages/nitro/src/targets/cli/index.ts | 2 +- .../nitro/src/targets/cloudflare/entry.ts | 22 +++++++++---------- .../nitro/src/targets/cloudflare/index.ts | 11 ++++++++-- packages/nitro/src/targets/vercel/index.ts | 2 +- 8 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 packages/nitro/src/runtime/vue2.basic.ts diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index 748493c938..63cc99e815 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -56,33 +56,30 @@ async function main () { continue } - console.log('\n') consola.info(`Generating bundle for ${hl(target.target)}`) - const ctx: any = defu( + const _config: any = defu( target, config, tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target) ) const hooks = new Hookable() - hooks.addHooks(ctx.hooks) + hooks.addHooks(_config.hooks) - await hooks.callHook('rollup:prepare', ctx) - ctx.rollupConfig = getRollupConfig(ctx) - await hooks.callHook('rollup:config', ctx) + await hooks.callHook('config', _config) - await hooks.callHook('rollup:before', ctx) - const build = await rollup(ctx.rollupConfig) - await hooks.callHook('rollup:built', ctx, build) + _config.rollupConfig = getRollupConfig(_config) + await hooks.callHook('rollup:before', _config) + const build = await rollup(_config.rollupConfig) - const { output } = await build.write(ctx.rollupConfig.output as OutputOptions) + const { output } = await build.write(_config.rollupConfig.output as OutputOptions) const size = prettyBytes(output[0].code.length) const zSize = prettyBytes(await gzipSize(output[0].code)) - consola.success('Generated', prettyPath((ctx.rollupConfig.output as any).file), + consola.success('Generated', prettyPath((_config.rollupConfig.output as any).file), chalk.gray(`(Size: ${size} Gzip: ${zSize})`) ) - await hooks.callHook('rollup:done', ctx) + await hooks.callHook('done', _config) } } diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 687214a11e..5c0292e1b5 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -78,10 +78,11 @@ export const getRollupConfig = (config) => { })) // https://github.com/rollup/plugins/tree/master/packages/alias + const renderer = config.renderer || (config.nuxt === 2 ? 'vue2' : 'vue3') options.plugins.push(alias({ entries: { '~runtime': path.resolve(__dirname, 'runtime'), - '~rendertostring': config.nuxt === 2 ? require.resolve('./runtime/vue2') : require.resolve('./runtime/vue3'), + '~renderer': require.resolve('./runtime/' + renderer), '~build': config.buildDir, '~mock': require.resolve('./runtime/mock'), ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}) diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts index 512b24d3fc..ddc15dbfe5 100644 --- a/packages/nitro/src/runtime/server.ts +++ b/packages/nitro/src/runtime/server.ts @@ -2,7 +2,7 @@ import { createRenderer } from 'vue-bundle-renderer' import devalue from '@nuxt/devalue' // @ts-ignore -import { renderToString } from '~rendertostring' +import { renderToString } from '~renderer' // @ts-ignore import server from '~build/dist/server/server' // @ts-ignore @@ -15,7 +15,7 @@ const renderer = createRenderer(server, { renderToString }) -export async function render (url) { +export async function render (url, ctx: any) { const start = process.hrtime() const ssrContext: any = { @@ -23,7 +23,8 @@ export async function render (url) { runtimeConfig: { public: {}, private: {} - } + }, + ...ctx } const rendered = await renderer.renderToString(ssrContext) diff --git a/packages/nitro/src/runtime/vue2.basic.ts b/packages/nitro/src/runtime/vue2.basic.ts new file mode 100644 index 0000000000..4c4bb8eabd --- /dev/null +++ b/packages/nitro/src/runtime/vue2.basic.ts @@ -0,0 +1,13 @@ + +import _renderToString from 'vue-server-renderer/basic.js' + +export function renderToString (component, context) { + return new Promise((resolve, reject) => { + _renderToString(component, context, (err, result) => { + if (err) { + return reject(err) + } + return resolve(result) + }) + }) +} diff --git a/packages/nitro/src/targets/cli/index.ts b/packages/nitro/src/targets/cli/index.ts index c1e4b06ec0..a1ecef69d7 100644 --- a/packages/nitro/src/targets/cli/index.ts +++ b/packages/nitro/src/targets/cli/index.ts @@ -4,7 +4,7 @@ import consola from 'consola' export default { entry: require.resolve('./entry'), hooks: { - 'rollup:done' ({ rollupConfig }) { + 'done' ({ rollupConfig }) { consola.info(`Usage: \`node ${relative(process.cwd(), rollupConfig.output.file)} [route]\``) } } diff --git a/packages/nitro/src/targets/cloudflare/entry.ts b/packages/nitro/src/targets/cloudflare/entry.ts index b27f83034c..8143bfaa36 100644 --- a/packages/nitro/src/targets/cloudflare/entry.ts +++ b/packages/nitro/src/targets/cloudflare/entry.ts @@ -1,18 +1,16 @@ // @ts-ignore import { render } from '~runtime/server' -addEventListener('fetch', (event) => { - // @ts-ignore - event.respondWith(handleRequest(event.request)) +addEventListener('fetch', (event: any) => { + event.respondWith(handleEvent(event.request)) }) -async function handleRequest (_request) { - // @ts-ignore - const html = await render() - return new Response(html, { - status: 200, - headers: { - 'content-type': 'text/html;charset=UTF-8' - } - }) +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 index f8df33757c..c6d384669b 100644 --- a/packages/nitro/src/targets/cloudflare/index.ts +++ b/packages/nitro/src/targets/cloudflare/index.ts @@ -2,8 +2,15 @@ export default { entry: require.resolve('./entry'), node: false, hooks: { - 'rollup:config' ({ rollupConfig }) { - rollupConfig.output.intro += 'const global = {}; const exports = {}; const module = { exports }; const require = function() {};' + config (config) { + if (config.nuxt === 2) { + config.renderer = 'vue2.basic' + } + }, + '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/vercel/index.ts b/packages/nitro/src/targets/vercel/index.ts index ff115845d6..74824ee1fd 100644 --- a/packages/nitro/src/targets/vercel/index.ts +++ b/packages/nitro/src/targets/vercel/index.ts @@ -4,7 +4,7 @@ export default { entry: require.resolve('./entry'), dynamicImporter: false, hooks: { - 'rollup:done' (_ctx) { + 'done' () { consola.info('Run `vercel deploy` to deploy!') } } From 2dbaae6b7d55ff352ac131ffc08220e2c16d2e44 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 23:14:32 +0100 Subject: [PATCH 022/227] feat: ssr with service worker --- packages/nitro/src/nuxt-deploy.ts | 40 +++++++++++++++++++----- packages/nitro/src/rollup.config.ts | 2 +- packages/nitro/src/targets/cli/index.ts | 4 +-- packages/nitro/src/targets/sw/entry.ts | 21 +++++++++++++ packages/nitro/src/targets/sw/index.html | 20 ++++++++++++ packages/nitro/src/targets/sw/index.ts | 29 +++++++++++++++++ packages/nitro/src/utils.ts | 25 +++++++++++++-- 7 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 packages/nitro/src/targets/sw/entry.ts create mode 100644 packages/nitro/src/targets/sw/index.html create mode 100644 packages/nitro/src/targets/sw/index.ts diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index 63cc99e815..e304939d06 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -3,12 +3,12 @@ import { rollup, OutputOptions } from 'rollup' import consola from 'consola' import Hookable from 'hookable' import defu from 'defu' -import { readFile, writeFile, existsSync } from 'fs-extra' +import { existsSync, copy, emptyDir } from 'fs-extra' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' import chalk from 'chalk' import { getRollupConfig } from './rollup.config' -import { tryImport, hl, prettyPath } from './utils' +import { tryImport, hl, prettyPath, compileTemplateToJS, renderTemplate } from './utils' async function main () { const rootDir = resolve(process.cwd(), process.argv[2] || '.') @@ -18,15 +18,23 @@ async function main () { rootDir, buildDir: '', targets: [], + templates: [], nuxt: 2, target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, minify: process.argv.includes('--minify') ? true : null, analyze: process.argv.includes('--analyze') ? true : null, logStartup: true } + Object.assign(config, tryImport(rootDir, './nuxt.config')!.deploy) + config.buildDir = resolve(config.rootDir, config.buildDir || '.nuxt') + config.targets = config.targets.map(t => typeof t === 'string' ? { target: t } : t) + if (config.target && !config.targets.find(t => t.target === config.target)) { + config.targets.push({ target: config.target }) + } + // Ensure dist exists if (!existsSync(resolve(config.buildDir, 'dist/server'))) { return consola.error('Please use `nuxt build` first to build project!') @@ -40,10 +48,7 @@ async function main () { // Compile html template const htmlTemplateFile = resolve(config.buildDir, `views/${{ 2: 'app', 3: 'document' }[config.nuxt]}.template.html`) const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') - const htmlTemplateContents = await readFile(htmlTemplateFile, 'utf-8') - // eslint-disable-next-line no-template-curly-in-string - const htmlTemplateCompiled = `export default (params) => \`${htmlTemplateContents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` - await writeFile(htmlTemplateFileJS, htmlTemplateCompiled) + await compileTemplateToJS(htmlTemplateFile, htmlTemplateFileJS) consola.info('Generated', prettyPath(htmlTemplateFileJS)) // Bundle for each target @@ -59,9 +64,14 @@ async function main () { consola.info(`Generating bundle for ${hl(target.target)}`) const _config: any = defu( + // Target specific config by user target, + // Global user config config, - tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target) + // Target defaults + tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target), + // Generic defaults + { outDir: resolve(config.buildDir, `dist/${config.target}`), outName: 'index.js' } ) const hooks = new Hookable() @@ -69,6 +79,8 @@ async function main () { await hooks.callHook('config', _config) + emptyDir(_config.outDir) + _config.rollupConfig = getRollupConfig(_config) await hooks.callHook('rollup:before', _config) const build = await rollup(_config.rollupConfig) @@ -79,6 +91,20 @@ async function main () { consola.success('Generated', prettyPath((_config.rollupConfig.output as any).file), chalk.gray(`(Size: ${size} Gzip: ${zSize})`) ) + + for (const tmpl of _config.templates) { + const dstPath = resolve(_config.outDir, tmpl.dst) + await renderTemplate(tmpl.src, dstPath, { config: _config }) + consola.info('Compiled', prettyPath(dstPath)) + } + + if (_config.copyAssets) { + const publicDir = typeof _config.copyAssets === 'string' ? _config.copyAssets : 'public' + const dst = resolve(_config.outDir, publicDir, '_nuxt') + await copy(resolve(_config.buildDir, 'dist/client'), dst) + consola.info('Copied public assets to', prettyPath(dst)) + } + await hooks.callHook('done', _config) } } diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 5c0292e1b5..d7e0ce6f0b 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -44,7 +44,7 @@ export const getRollupConfig = (config) => { const options: RollupConfig = { input: config.entry, output: { - file: path.resolve(config.buildDir, `dist/${config.target}`, 'index.js'), + file: path.resolve(config.outDir, config.outName), format: 'cjs', intro: '', outro: '', diff --git a/packages/nitro/src/targets/cli/index.ts b/packages/nitro/src/targets/cli/index.ts index a1ecef69d7..4880495638 100644 --- a/packages/nitro/src/targets/cli/index.ts +++ b/packages/nitro/src/targets/cli/index.ts @@ -1,11 +1,11 @@ -import { relative } from 'path' + import consola from 'consola' export default { entry: require.resolve('./entry'), hooks: { 'done' ({ rollupConfig }) { - consola.info(`Usage: \`node ${relative(process.cwd(), rollupConfig.output.file)} [route]\``) + 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 new file mode 100644 index 0000000000..ffa520a9ea --- /dev/null +++ b/packages/nitro/src/targets/sw/entry.ts @@ -0,0 +1,21 @@ +// @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)) +}) + +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 new file mode 100644 index 0000000000..1ee2757492 --- /dev/null +++ b/packages/nitro/src/targets/sw/index.html @@ -0,0 +1,20 @@ + + + + Loading... + + + + diff --git a/packages/nitro/src/targets/sw/index.ts b/packages/nitro/src/targets/sw/index.ts new file mode 100644 index 0000000000..c98c22a0b8 --- /dev/null +++ b/packages/nitro/src/targets/sw/index.ts @@ -0,0 +1,29 @@ +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: { + config (config) { + if (config.nuxt === 2) { + config.renderer = 'vue2.basic' + } + }, + '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/utils.ts b/packages/nitro/src/utils.ts index 9994a57d4b..420fdfac67 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -1,13 +1,34 @@ -import { relative } from 'path' +import { relative, dirname } from 'path' +import { readFile, writeFile, mkdirp } from 'fs-extra' import jiti from 'jiti' const pwd = process.cwd() export const hl = str => '`' + str + '`' -export const prettyPath = (p, highlight = true) => { +export function prettyPath (p, highlight = true) { p = relative(pwd, p) return highlight ? hl(p) : p } +export async function loadTemplate (src) { + const contents = await readFile(src, 'utf-8') + return params => contents.replace(/{{ (\w+) }}/g, `${params.$1}`) +} + +export async function renderTemplate (src, dst: string, params: any) { + const tmpl = await loadTemplate(src) + const rendered = tmpl(params) + await mkdirp(dirname(dst)) + await writeFile(dst, rendered) +} + +export async function compileTemplateToJS (src: string, dst: string) { + const contents = await readFile(src, 'utf-8') + // eslint-disable-next-line no-template-curly-in-string + const compiled = `export default (params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` + await mkdirp(dirname(dst)) + await writeFile(dst, compiled) +} + export const tryImport = (dir, path) => { try { return jiti(dir)(path) } catch (_err) { } } From ae0fd1b108b5ac3856c521aa47d818c3a4bd3ae3 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 23:20:19 +0100 Subject: [PATCH 023/227] refactor: rename cli to node and export render --- .../nitro/src/targets/{cli => node}/entry.ts | 20 +++++++++++-------- .../nitro/src/targets/{cli => node}/index.ts | 0 2 files changed, 12 insertions(+), 8 deletions(-) rename packages/nitro/src/targets/{cli => node}/entry.ts (53%) rename packages/nitro/src/targets/{cli => node}/index.ts (100%) diff --git a/packages/nitro/src/targets/cli/entry.ts b/packages/nitro/src/targets/node/entry.ts similarity index 53% rename from packages/nitro/src/targets/cli/entry.ts rename to packages/nitro/src/targets/node/entry.ts index 607ca89587..b8d6bcf7d5 100644 --- a/packages/nitro/src/targets/cli/entry.ts +++ b/packages/nitro/src/targets/node/entry.ts @@ -1,14 +1,16 @@ // @ts-ignore import { render } from '~runtime/server' +// @ts-ignore +export { render } from '~runtime/server' -const debug = (label, ...args) => console.debug(`> ${label}:`, ...args) - -async function main () { +async function cli () { const url = process.argv[2] || '/' - debug('URL', url) + + 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]) @@ -17,7 +19,9 @@ async function main () { console.log('\n', html) } -main().catch((err) => { - console.error(err) - process.exit(1) -}) +if (require.main === module) { + cli().catch((err) => { + console.error(err) + process.exit(1) + }) +} diff --git a/packages/nitro/src/targets/cli/index.ts b/packages/nitro/src/targets/node/index.ts similarity index 100% rename from packages/nitro/src/targets/cli/index.ts rename to packages/nitro/src/targets/node/index.ts From 1a6a4cb248db50b388883f94255799283b997c82 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 23:25:37 +0100 Subject: [PATCH 024/227] fix: add critical css --- packages/nitro/src/runtime/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts index ddc15dbfe5..af2bc1e51c 100644 --- a/packages/nitro/src/runtime/server.ts +++ b/packages/nitro/src/runtime/server.ts @@ -35,7 +35,7 @@ export async function render (url, ctx: any) { HTML_ATTRS: '', HEAD_ATTRS: '', BODY_ATTRS: '', - HEAD: rendered.renderResourceHints() + rendered.renderStyles(), + HEAD: rendered.renderResourceHints() + rendered.renderStyles() + (ssrContext.styles || ''), APP: _html + state + rendered.renderScripts() }) From 55819d52e0f7cf2af498e5254deee72e17584ff7 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 23:27:38 +0100 Subject: [PATCH 025/227] reload sw page after loading --- packages/nitro/src/targets/sw/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/nitro/src/targets/sw/index.html b/packages/nitro/src/targets/sw/index.html index 1ee2757492..bea8875fee 100644 --- a/packages/nitro/src/targets/sw/index.html +++ b/packages/nitro/src/targets/sw/index.html @@ -10,8 +10,10 @@ window.addEventListener('load', () => { navigator.serviceWorker.register('/nuxt.sw.js').then((registration) => { console.log('ServiceWorker registration successful with scope:', registration.scope) + window.location.reload() }).catch(error => { console.error('ServiceWorker registration failed:', error) + document.write(error) }) }) From a8db45a8bac20dedb7ee62a9a5004a3a705f49da Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 3 Nov 2020 23:38:46 +0100 Subject: [PATCH 026/227] fix payload for nuxt2 --- packages/nitro/src/runtime/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts index af2bc1e51c..81eff98744 100644 --- a/packages/nitro/src/runtime/server.ts +++ b/packages/nitro/src/runtime/server.ts @@ -28,7 +28,7 @@ export async function render (url, ctx: any) { } const rendered = await renderer.renderToString(ssrContext) - const state = `` + const state = `` const _html = `
${rendered.html}
` const html = htmlTemplate({ From c43cf33c95f79b3efae620cda42cedaa5fd8eba5 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 00:13:45 +0100 Subject: [PATCH 027/227] fast claim all clients --- packages/nitro/src/targets/sw/entry.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/nitro/src/targets/sw/entry.ts b/packages/nitro/src/targets/sw/entry.ts index ffa520a9ea..e02d78428f 100644 --- a/packages/nitro/src/targets/sw/entry.ts +++ b/packages/nitro/src/targets/sw/entry.ts @@ -11,6 +11,16 @@ addEventListener('fetch', (event: any) => { 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 }) From dd7f32324f8671c00f87ab0a6bf08485957ebf65 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 00:43:16 +0100 Subject: [PATCH 028/227] preload service-worker --- packages/nitro/src/targets/sw/index.html | 29 ++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/targets/sw/index.html b/packages/nitro/src/targets/sw/index.html index bea8875fee..98a9602e50 100644 --- a/packages/nitro/src/targets/sw/index.html +++ b/packages/nitro/src/targets/sw/index.html @@ -1,16 +1,41 @@ - Loading... - + + + From 10fddd223edf6fd55ce2a51dbcf5704c26656ac1 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 00:52:23 +0100 Subject: [PATCH 030/227] always show loading --- packages/nitro/src/targets/sw/index.html | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/nitro/src/targets/sw/index.html b/packages/nitro/src/targets/sw/index.html index d34d5ee904..75d0d3b272 100644 --- a/packages/nitro/src/targets/sw/index.html +++ b/packages/nitro/src/targets/sw/index.html @@ -1,6 +1,5 @@ - @@ -9,24 +8,16 @@ if (!('serviceWorker' in navigator)) { throw new Error('Browser not supported!') } - - let timeout - const stopTimer = () => { if (timeout) { clearTimeout(timeout); timeout = undefined } } - const startTimer = () => { stopTimer(); timeout = setTimeout(() => { document.write('Loading...') }, 3000) } - - startTimer() navigator.serviceWorker.register('/nuxt.sw.js').then((registration) => { - stopTimer() console.log('ServiceWorker registration successful with scope:', registration.scope) window.location.reload(false) }).catch(error => { - stopTimer() console.error('ServiceWorker registration failed:', error) document.write(error) }) - - - + + Loading... + From 885f0aba66e527b96957faf4e2dcb4a57a552a02 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 01:24:40 +0100 Subject: [PATCH 031/227] fast replace instead of reload --- packages/nitro/src/targets/sw/index.html | 35 +++++++++++++++++------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/nitro/src/targets/sw/index.html b/packages/nitro/src/targets/sw/index.html index 75d0d3b272..9aef25e111 100644 --- a/packages/nitro/src/targets/sw/index.html +++ b/packages/nitro/src/targets/sw/index.html @@ -1,23 +1,38 @@ + + - + Loading... + From fab1326cd80e6b91c98a06896bcce9effb675db4 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 01:28:45 +0100 Subject: [PATCH 032/227] automatically reddirect to secure origin --- packages/nitro/src/targets/sw/index.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/nitro/src/targets/sw/index.html b/packages/nitro/src/targets/sw/index.html index 9aef25e111..cc58ba2b1f 100644 --- a/packages/nitro/src/targets/sw/index.html +++ b/packages/nitro/src/targets/sw/index.html @@ -6,6 +6,10 @@ From bec1c8edfa661f6b75e005a6858b554ed1ba41d5 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 02:15:42 +0100 Subject: [PATCH 034/227] fix: host ~> hostname --- packages/nitro/src/targets/sw/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/sw/index.html b/packages/nitro/src/targets/sw/index.html index 50a4d70c4c..c61a952006 100644 --- a/packages/nitro/src/targets/sw/index.html +++ b/packages/nitro/src/targets/sw/index.html @@ -27,7 +27,7 @@ }) } - if (location.host !== 'localhost' && location.protocol === 'http:') { + if (location.hostname !== 'localhost' && location.protocol === 'http:') { location.replace(location.href.replace('http://', 'https://')) } else { register() From 040af4ea4ed5f09211da6a977dcda65e87179848 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 03:06:23 +0100 Subject: [PATCH 035/227] feat: mock stream --- packages/nitro/src/rollup.config.ts | 1 + packages/nitro/src/runtime/{mock.ts => mock.js} | 2 +- packages/nitro/src/runtime/vue2.basic.ts | 13 ------------- packages/nitro/src/targets/cloudflare/index.ts | 5 ----- packages/nitro/src/targets/sw/index.ts | 5 ----- 5 files changed, 2 insertions(+), 24 deletions(-) rename packages/nitro/src/runtime/{mock.ts => mock.js} (94%) delete mode 100644 packages/nitro/src/runtime/vue2.basic.ts diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index d7e0ce6f0b..4d7ccbc02b 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -19,6 +19,7 @@ export const getRollupConfig = (config) => { 'consola', // vue2 'encoding', + 'stream', 'he', 'resolve', 'source-map', diff --git a/packages/nitro/src/runtime/mock.ts b/packages/nitro/src/runtime/mock.js similarity index 94% rename from packages/nitro/src/runtime/mock.ts rename to packages/nitro/src/runtime/mock.js index 5b30aba73a..70415e62eb 100644 --- a/packages/nitro/src/runtime/mock.ts +++ b/packages/nitro/src/runtime/mock.js @@ -22,4 +22,4 @@ function getProxy (name) { }) } -export default getProxy('mock') +module.exports = getProxy('mock') diff --git a/packages/nitro/src/runtime/vue2.basic.ts b/packages/nitro/src/runtime/vue2.basic.ts deleted file mode 100644 index 4c4bb8eabd..0000000000 --- a/packages/nitro/src/runtime/vue2.basic.ts +++ /dev/null @@ -1,13 +0,0 @@ - -import _renderToString from 'vue-server-renderer/basic.js' - -export function renderToString (component, context) { - return new Promise((resolve, reject) => { - _renderToString(component, context, (err, result) => { - if (err) { - return reject(err) - } - return resolve(result) - }) - }) -} diff --git a/packages/nitro/src/targets/cloudflare/index.ts b/packages/nitro/src/targets/cloudflare/index.ts index c6d384669b..0839345724 100644 --- a/packages/nitro/src/targets/cloudflare/index.ts +++ b/packages/nitro/src/targets/cloudflare/index.ts @@ -2,11 +2,6 @@ export default { entry: require.resolve('./entry'), node: false, hooks: { - config (config) { - if (config.nuxt === 2) { - config.renderer = 'vue2.basic' - } - }, 'rollup:before' ({ rollupConfig }) { rollupConfig.output.intro = 'const global = {}; const exports = {}; const module = { exports }; const process = { env: {}, hrtime: () => [0,0]};' + diff --git a/packages/nitro/src/targets/sw/index.ts b/packages/nitro/src/targets/sw/index.ts index c98c22a0b8..6bb68d17fb 100644 --- a/packages/nitro/src/targets/sw/index.ts +++ b/packages/nitro/src/targets/sw/index.ts @@ -11,11 +11,6 @@ export default { { src: resolve(__dirname, 'index.html'), dst: '200.html' } ], hooks: { - config (config) { - if (config.nuxt === 2) { - config.renderer = 'vue2.basic' - } - }, 'rollup:before' ({ rollupConfig }) { rollupConfig.output.intro = 'const global = {}; const exports = {}; const module = { exports }; const process = { env: {}, hrtime: () => [0,0]};' + From bda5805b2d8676cb3c1d47381534e955017557b6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 03:14:39 +0100 Subject: [PATCH 036/227] perf: short circuit window type to recuce bundle size --- packages/nitro/src/rollup.config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup.config.ts index 4d7ccbc02b..27fa87e2b4 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup.config.ts @@ -64,7 +64,8 @@ export const getRollupConfig = (config) => { // https://github.com/rollup/plugins/tree/master/packages/replace options.plugins.push(replace({ values: { - 'process.env.NODE_ENV': '"production"' + 'process.env.NODE_ENV': '"production"', + 'typeof window': '"undefined"' } })) From 904f813ae9df59399e4be45aaf9a0facb12d00f9 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 03:22:58 +0100 Subject: [PATCH 037/227] fix outDir default --- packages/nitro/src/nuxt-deploy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/nuxt-deploy.ts index e304939d06..07d6190b4c 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/nuxt-deploy.ts @@ -71,7 +71,7 @@ async function main () { // Target defaults tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target), // Generic defaults - { outDir: resolve(config.buildDir, `dist/${config.target}`), outName: 'index.js' } + { outDir: resolve(config.buildDir, `dist/${target.target}`), outName: 'index.js' } ) const hooks = new Hookable() From 93f265d5e01a9c2700997822f9d982c8fea6c6c3 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 12:33:19 +0100 Subject: [PATCH 038/227] refactor: rename to serverless and improve struct --- packages/nitro/src/{nuxt-deploy.ts => cli.ts} | 24 ++++++++++++------- packages/nitro/src/index.ts | 1 + .../{rollup.config.ts => rollup/config.ts} | 6 ++--- .../nitro/src/{ => rollup}/dynamic-require.ts | 0 packages/nitro/src/targets/vercel/index.ts | 2 +- 5 files changed, 21 insertions(+), 12 deletions(-) rename packages/nitro/src/{nuxt-deploy.ts => cli.ts} (87%) create mode 100644 packages/nitro/src/index.ts rename packages/nitro/src/{rollup.config.ts => rollup/config.ts} (95%) rename packages/nitro/src/{ => rollup}/dynamic-require.ts (100%) diff --git a/packages/nitro/src/nuxt-deploy.ts b/packages/nitro/src/cli.ts similarity index 87% rename from packages/nitro/src/nuxt-deploy.ts rename to packages/nitro/src/cli.ts index 07d6190b4c..b048857b45 100644 --- a/packages/nitro/src/nuxt-deploy.ts +++ b/packages/nitro/src/cli.ts @@ -7,10 +7,10 @@ import { existsSync, copy, emptyDir } from 'fs-extra' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' import chalk from 'chalk' -import { getRollupConfig } from './rollup.config' +import { getRollupConfig } from './rollup/config' import { tryImport, hl, prettyPath, compileTemplateToJS, renderTemplate } from './utils' -async function main () { +async function _runCLI () { const rootDir = resolve(process.cwd(), process.argv[2] || '.') // Config @@ -26,7 +26,7 @@ async function main () { logStartup: true } - Object.assign(config, tryImport(rootDir, './nuxt.config')!.deploy) + Object.assign(config, tryImport(rootDir, './nuxt.config')!.serverless) config.buildDir = resolve(config.rootDir, config.buildDir || '.nuxt') @@ -63,13 +63,19 @@ async function main () { consola.info(`Generating bundle for ${hl(target.target)}`) + const _targetDefaults = tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target) + if (!_targetDefaults) { + consola.warn('Cannot resolve target', target.target) + continue + } + const _config: any = defu( // Target specific config by user target, // Global user config config, // Target defaults - tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target), + _targetDefaults, // Generic defaults { outDir: resolve(config.buildDir, `dist/${target.target}`), outName: 'index.js' } ) @@ -109,7 +115,9 @@ async function main () { } } -main().catch((err) => { - consola.error(err) - process.exit(1) -}) +export function runCLI () { + _runCLI().catch((err) => { + consola.error(err) + process.exit(1) + }) +} diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts new file mode 100644 index 0000000000..876cc40e6e --- /dev/null +++ b/packages/nitro/src/index.ts @@ -0,0 +1 @@ +export { runCLI } from './cli' diff --git a/packages/nitro/src/rollup.config.ts b/packages/nitro/src/rollup/config.ts similarity index 95% rename from packages/nitro/src/rollup.config.ts rename to packages/nitro/src/rollup/config.ts index 27fa87e2b4..5782bab352 100644 --- a/packages/nitro/src/rollup.config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -83,10 +83,10 @@ 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': path.resolve(__dirname, '../runtime'), + '~renderer': require.resolve('../runtime/' + renderer), '~build': config.buildDir, - '~mock': require.resolve('./runtime/mock'), + '~mock': require.resolve('../runtime/mock'), ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}) } })) diff --git a/packages/nitro/src/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts similarity index 100% rename from packages/nitro/src/dynamic-require.ts rename to packages/nitro/src/rollup/dynamic-require.ts diff --git a/packages/nitro/src/targets/vercel/index.ts b/packages/nitro/src/targets/vercel/index.ts index 74824ee1fd..0fc011f944 100644 --- a/packages/nitro/src/targets/vercel/index.ts +++ b/packages/nitro/src/targets/vercel/index.ts @@ -5,7 +5,7 @@ export default { dynamicImporter: false, hooks: { 'done' () { - consola.info('Run `vercel deploy` to deploy!') + consola.info('Run `vercel serverless` to serverless!') } } } From 0bcee8202a2a286c93b95d690528d965dbcc9ea3 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 12:37:05 +0100 Subject: [PATCH 039/227] chore: fix package bin --- packages/nitro/src/runtime/server.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nitro/src/runtime/server.ts b/packages/nitro/src/runtime/server.ts index 81eff98744..03519eaaa5 100644 --- a/packages/nitro/src/runtime/server.ts +++ b/packages/nitro/src/runtime/server.ts @@ -47,6 +47,7 @@ export async function render (url, ctx: any) { status: 200, headers: { 'Content-Type': 'text/html;charset=UTF-8', + // @ts-ignore 'X-Nuxt-Coldstart': global._coldstart + 'ms', 'X-Nuxt-ResponseTime': time + 'ms' } From 05e8d538db6c73cbf1b204e6c36289bc444e0d7e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 13:34:18 +0100 Subject: [PATCH 040/227] refactor: cli ~> build, config --- packages/nitro/src/build.ts | 80 ++++++++++++++++++++++++++ packages/nitro/src/cli.ts | 107 +++-------------------------------- packages/nitro/src/config.ts | 27 +++++++++ 3 files changed, 115 insertions(+), 99 deletions(-) create mode 100644 packages/nitro/src/build.ts create mode 100644 packages/nitro/src/config.ts diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts new file mode 100644 index 0000000000..1c60dad82c --- /dev/null +++ b/packages/nitro/src/build.ts @@ -0,0 +1,80 @@ +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' + +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 hooks = new Hookable() + hooks.addHooks(config.hooks) + + await hooks.callHook('config', config) + + emptyDir(config.outDir) + + config.rollupConfig = getRollupConfig(config) + await hooks.callHook('rollup:before', config) + const build = await rollup(config.rollupConfig) + + const { output } = await build.write(config.rollupConfig.output as OutputOptions) + const size = prettyBytes(output[0].code.length) + const zSize = prettyBytes(await gzipSize(output[0].code)) + consola.success('Generated', prettyPath((config.rollupConfig.output as any).file), + chalk.gray(`(Size: ${size} Gzip: ${zSize})`) + ) + + for (const tmpl of config.templates) { + const dstPath = resolve(config.outDir, tmpl.dst) + await renderTemplate(tmpl.src, dstPath, { config }) + consola.info('Compiled', prettyPath(dstPath)) + } + + if (config.copyAssets) { + const publicDir = typeof config.copyAssets === 'string' ? config.copyAssets : 'public' + const dst = resolve(config.outDir, publicDir, '_nuxt') + await copy(resolve(config.buildDir, 'dist/client'), dst) + consola.info('Copied public assets to', prettyPath(dst)) + } + + await hooks.callHook('done', config) +} + +export async function compileHTMLTemplate (baseConfig) { + const htmlTemplateFile = resolve(baseConfig.buildDir, `views/${{ 2: 'app', 3: 'document' }[baseConfig.nuxt]}.template.html`) + const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') + await compileTemplateToJS(htmlTemplateFile, htmlTemplateFileJS) + consola.info('Generated', prettyPath(htmlTemplateFileJS)) +} + +export function ensureDist (baseConfig) { + if (!existsSync(resolve(baseConfig.buildDir, 'dist/server'))) { + return consola.error('Please use `nuxt build` first to build project!') + } else { + consola.success('Using existing nuxt build from', prettyPath(baseConfig.buildDir)) + } +} diff --git a/packages/nitro/src/cli.ts b/packages/nitro/src/cli.ts index b048857b45..11558f595c 100644 --- a/packages/nitro/src/cli.ts +++ b/packages/nitro/src/cli.ts @@ -1,117 +1,26 @@ import { resolve } from 'path' -import { rollup, OutputOptions } from 'rollup' import consola from 'consola' -import Hookable from 'hookable' -import defu from 'defu' -import { existsSync, copy, emptyDir } from 'fs-extra' -import prettyBytes from 'pretty-bytes' -import gzipSize from 'gzip-size' -import chalk from 'chalk' -import { getRollupConfig } from './rollup/config' -import { tryImport, hl, prettyPath, compileTemplateToJS, renderTemplate } from './utils' +import { build, compileHTMLTemplate, ensureDist } from './build' +import { getBaseConfig } from './config' async function _runCLI () { const rootDir = resolve(process.cwd(), process.argv[2] || '.') // Config - const config = { - rootDir, - buildDir: '', - targets: [], - templates: [], - nuxt: 2, - target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, - minify: process.argv.includes('--minify') ? true : null, - analyze: process.argv.includes('--analyze') ? true : null, - logStartup: true - } - - Object.assign(config, tryImport(rootDir, './nuxt.config')!.serverless) - - config.buildDir = resolve(config.rootDir, config.buildDir || '.nuxt') - - config.targets = config.targets.map(t => typeof t === 'string' ? { target: t } : t) - if (config.target && !config.targets.find(t => t.target === config.target)) { - config.targets.push({ target: config.target }) - } + const baseConfig = getBaseConfig(rootDir) // Ensure dist exists - if (!existsSync(resolve(config.buildDir, 'dist/server'))) { - return consola.error('Please use `nuxt build` first to build project!') - } else { - consola.success('Using existing nuxt build from', prettyPath(config.buildDir)) - } - - // Ensure relative operations are relative to build dir (fixes rollup dynamic imports) - process.chdir(config.buildDir) + await ensureDist(baseConfig) // Compile html template - const htmlTemplateFile = resolve(config.buildDir, `views/${{ 2: 'app', 3: 'document' }[config.nuxt]}.template.html`) - const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') - await compileTemplateToJS(htmlTemplateFile, htmlTemplateFileJS) - consola.info('Generated', prettyPath(htmlTemplateFileJS)) + await compileHTMLTemplate(baseConfig) // Bundle for each target - for (let target of config.targets) { - if (typeof target === 'string') { - target = { target } - } - - if (config.target && target.target !== config.target) { + for (const target of baseConfig.targets) { + if (baseConfig.target && target.target !== baseConfig.target) { continue } - - consola.info(`Generating bundle for ${hl(target.target)}`) - - const _targetDefaults = tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target) - if (!_targetDefaults) { - consola.warn('Cannot resolve target', target.target) - continue - } - - const _config: any = defu( - // Target specific config by user - target, - // Global user config - config, - // Target defaults - _targetDefaults, - // Generic defaults - { outDir: resolve(config.buildDir, `dist/${target.target}`), outName: 'index.js' } - ) - - const hooks = new Hookable() - hooks.addHooks(_config.hooks) - - await hooks.callHook('config', _config) - - emptyDir(_config.outDir) - - _config.rollupConfig = getRollupConfig(_config) - await hooks.callHook('rollup:before', _config) - const build = await rollup(_config.rollupConfig) - - const { output } = await build.write(_config.rollupConfig.output as OutputOptions) - const size = prettyBytes(output[0].code.length) - const zSize = prettyBytes(await gzipSize(output[0].code)) - consola.success('Generated', prettyPath((_config.rollupConfig.output as any).file), - chalk.gray(`(Size: ${size} Gzip: ${zSize})`) - ) - - for (const tmpl of _config.templates) { - const dstPath = resolve(_config.outDir, tmpl.dst) - await renderTemplate(tmpl.src, dstPath, { config: _config }) - consola.info('Compiled', prettyPath(dstPath)) - } - - if (_config.copyAssets) { - const publicDir = typeof _config.copyAssets === 'string' ? _config.copyAssets : 'public' - const dst = resolve(_config.outDir, publicDir, '_nuxt') - await copy(resolve(_config.buildDir, 'dist/client'), dst) - consola.info('Copied public assets to', prettyPath(dst)) - } - - await hooks.callHook('done', _config) + await build(baseConfig, target) } } diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts new file mode 100644 index 0000000000..33445067ce --- /dev/null +++ b/packages/nitro/src/config.ts @@ -0,0 +1,27 @@ +import { resolve } from 'path' +import { tryImport } from './utils' + +export function getBaseConfig (rootDir) { + const baseConfig = { + rootDir, + buildDir: '', + targets: [], + templates: [], + nuxt: 2, + target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, + minify: process.argv.includes('--minify') ? true : null, + analyze: process.argv.includes('--analyze') ? true : null, + logStartup: true + } + + Object.assign(baseConfig, tryImport(rootDir, './nuxt.config')!.serverless) + + baseConfig.buildDir = resolve(baseConfig.rootDir, baseConfig.buildDir || '.nuxt') + + baseConfig.targets = baseConfig.targets.map(t => typeof t === 'string' ? { target: t } : t) + if (baseConfig.target && !baseConfig.targets.find(t => t.target === baseConfig.target)) { + baseConfig.targets.push({ target: baseConfig.target }) + } + + return baseConfig +} From 5538f342f7fc2fdb392938085349c3dc09c57b98 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 14:15:38 +0100 Subject: [PATCH 041/227] refactror: separate lib --- packages/nitro/src/build.ts | 21 +------ packages/nitro/src/cli.ts | 10 +--- packages/nitro/src/config.ts | 34 +++++++++++- packages/nitro/src/nuxt-serverless.ts | 6 ++ packages/nitro/src/rollup/config.ts | 16 ++---- packages/nitro/src/runtime/mock.js | 25 --------- packages/nitro/src/runtime/server.ts | 55 ------------------- packages/nitro/src/runtime/vue2.ts | 14 ----- packages/nitro/src/runtime/vue3.ts | 2 - .../nitro/src/targets/cloudflare/entry.ts | 16 ------ .../nitro/src/targets/cloudflare/index.ts | 12 ---- packages/nitro/src/targets/node/entry.ts | 27 --------- packages/nitro/src/targets/node/index.ts | 11 ---- packages/nitro/src/targets/sw/entry.ts | 31 ----------- packages/nitro/src/targets/sw/index.html | 42 -------------- packages/nitro/src/targets/sw/index.ts | 24 -------- packages/nitro/src/targets/vercel/entry.ts | 17 ------ packages/nitro/src/targets/vercel/index.ts | 11 ---- packages/nitro/src/utils.ts | 8 ++- 19 files changed, 51 insertions(+), 331 deletions(-) create mode 100644 packages/nitro/src/nuxt-serverless.ts delete mode 100644 packages/nitro/src/runtime/mock.js delete mode 100644 packages/nitro/src/runtime/server.ts delete mode 100644 packages/nitro/src/runtime/vue2.ts delete mode 100644 packages/nitro/src/runtime/vue3.ts delete mode 100644 packages/nitro/src/targets/cloudflare/entry.ts delete mode 100644 packages/nitro/src/targets/cloudflare/index.ts delete mode 100644 packages/nitro/src/targets/node/entry.ts delete mode 100644 packages/nitro/src/targets/node/index.ts delete mode 100644 packages/nitro/src/targets/sw/entry.ts delete mode 100644 packages/nitro/src/targets/sw/index.html delete mode 100644 packages/nitro/src/targets/sw/index.ts delete mode 100644 packages/nitro/src/targets/vercel/entry.ts delete mode 100644 packages/nitro/src/targets/vercel/index.ts 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') From 16141efe25ae70485f96f138c5a655ae97182cac Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 14:52:12 +0100 Subject: [PATCH 042/227] fix: resolve runtime provided dependencies --- packages/nitro/src/rollup/config.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 68415758bb..ced7b90db8 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -32,6 +32,11 @@ export const getRollupConfig = (config) => { '@vue/compiler-ssr' ] + const providedDeps = [ + '@nuxt/devalue', + 'vue-bundle-renderer' + ] + const extensions = ['.ts', '.mjs', '.js', '.json', '.node'] const external = [] @@ -87,7 +92,8 @@ export const getRollupConfig = (config) => { '~renderer': require.resolve(path.resolve(RUNTIME_DIR, renderer)), '~build': config.buildDir, '~mock': require.resolve(path.resolve(RUNTIME_DIR, 'mock')), - ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}) + ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}), + ...providedDeps.reduce((p, c) => ({ ...p, [c]: require.resolve(c) }), {}) } })) From 114b5406acfebb04b5a4fa1823a12cfc70f3f889 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 19:19:20 +0100 Subject: [PATCH 043/227] feat: use dynamic require for node targets --- packages/nitro/src/rollup/config.ts | 1 + packages/nitro/src/rollup/dynamic-require.ts | 33 +++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index ced7b90db8..ac4db2a949 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -77,6 +77,7 @@ export const getRollupConfig = (config) => { // Dynamic Require Support options.plugins.push(dynamicRequire({ dir: path.resolve(config.buildDir, 'dist/server'), + outDir: config.node === false ? undefined : config.outDir, globbyOptions: { ignore: [ 'server.js' diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index c2d4894cfd..d7966fd0f5 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -1,12 +1,13 @@ -import { resolve } from 'path' +import { basename, resolve, dirname } from 'path' import globby, { GlobbyOptions } from 'globby' +import { copyFile, mkdirp } from 'fs-extra' const PLUGIN_NAME = 'dynamic-require' const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js` const DYNAMIC_REQUIRE_RE = /require\("\.\/" \+/g -function CJSTemplate ({ imports }) { - return `${imports.map(i => `import ${i.name} from '${i.import}'`).join('\n')} +const TMPL_INLINE = ({ imports }) => + `${imports.map(i => `import ${i.name} from '${i.import}'`).join('\n')} const dynamicChunks = { ${imports.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} }; @@ -14,14 +15,19 @@ const dynamicChunks = { export default function dynamicRequire(id) { return dynamicChunks[id]; };` -} + +const TMPL_CJS = ({ chunksDir }) => `export default function dynamicRequire(id) { +return require('./${chunksDir}/' + id); +};` interface Options { - dir: string, + dir: string globbyOptions: GlobbyOptions + outDir?: string + chunksDir?: string } -export default function dynamicRequire ({ dir, globbyOptions }: Options) { +export default function dynamicRequire ({ dir, globbyOptions, outDir, chunksDir }: Options) { return { name: PLUGIN_NAME, transform (code, _id) { @@ -33,12 +39,25 @@ export default function dynamicRequire ({ dir, globbyOptions }: Options) { async load (id) { if (id === HELPER_DYNAMIC) { const files = await globby('**/*.js', { cwd: dir, absolute: false, ...globbyOptions }) + const imports = files.map(id => ({ id, import: resolve(dir, id), name: id.replace(/[\\/.]/g, '_') })) - return CJSTemplate({ imports }) + + if (!outDir) { + return TMPL_INLINE({ imports }) + } + + // Write chunks + chunksDir = chunksDir || basename(dir) + await Promise.all(imports.map(async (i) => { + const dst = resolve(outDir, chunksDir, i.id) + await mkdirp(dirname(dst)) + await copyFile(i.import, dst) + })) + return TMPL_CJS({ chunksDir }) } return null } From 425941d1b46284014ddcdd2556bf1a0378960619 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 19:19:34 +0100 Subject: [PATCH 044/227] move artifacts to {buildDir}/sls --- packages/nitro/src/config.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 11f9f28aca..5f6337776e 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -50,6 +50,9 @@ export function getTargetConfig (baseConfig, target) { // Target defaults _targetDefaults, // Generic defaults - { outDir: resolve(baseConfig.buildDir, `dist/${target.target}`), outName: 'index.js' } + { + outDir: resolve(baseConfig.buildDir, `sls/${target.target}`), + outName: 'index.js' + } ) } From 0245bd65de00841ca898bb15bcadb15420af58e2 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 4 Nov 2020 20:01:53 +0100 Subject: [PATCH 045/227] feat: generate public (dist/) --- packages/nitro/src/build.ts | 24 ++++++++++++++++-------- packages/nitro/src/cli.ts | 5 ++++- packages/nitro/src/config.ts | 4 ++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 2e0d38e874..a8a2a51754 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -5,7 +5,7 @@ import Hookable from 'hookable' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' import chalk from 'chalk' -import { copy, emptyDir, existsSync } from 'fs-extra' +import { copy, emptyDir, existsSync, mkdirp } from 'fs-extra' import { getRollupConfig } from './rollup/config' import { getTargetConfig } from './config' import { hl, prettyPath, renderTemplate, compileTemplateToJS } from './utils' @@ -39,13 +39,6 @@ export async function build (baseConfig, target) { consola.info('Compiled', prettyPath(dstPath)) } - if (config.copyAssets) { - const publicDir = typeof config.copyAssets === 'string' ? config.copyAssets : 'public' - const dst = resolve(config.outDir, publicDir, '_nuxt') - await copy(resolve(config.buildDir, 'dist/client'), dst) - consola.info('Copied public assets to', prettyPath(dst)) - } - await hooks.callHook('done', config) } @@ -63,3 +56,18 @@ export function ensureDist (baseConfig) { consola.success('Using existing nuxt build from', prettyPath(baseConfig.buildDir)) } } + +export async function generatePublic (baseConfig) { + await emptyDir(baseConfig.publicDir) + await mkdirp(baseConfig.publicDir) + + await copy( + baseConfig.staticDir, + baseConfig.publicDir + ) + + await copy( + resolve(baseConfig.buildDir, 'dist/client'), + resolve(baseConfig.publicDir, '_nuxt') + ) +} diff --git a/packages/nitro/src/cli.ts b/packages/nitro/src/cli.ts index 24355d9da3..742df46f93 100644 --- a/packages/nitro/src/cli.ts +++ b/packages/nitro/src/cli.ts @@ -1,5 +1,5 @@ import { resolve } from 'path' -import { build, compileHTMLTemplate, ensureDist } from './build' +import { build, compileHTMLTemplate, ensureDist, generatePublic } from './build' import { getBaseConfig } from './config' export async function runCLI () { @@ -14,6 +14,9 @@ export async function runCLI () { // Compile html template await compileHTMLTemplate(baseConfig) + // Generate public dir + await generatePublic(baseConfig) + // Bundle for each target for (const target of baseConfig.targets) { if (baseConfig.target && target.target !== baseConfig.target) { diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 5f6337776e..52d072f3b3 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -6,6 +6,8 @@ export function getBaseConfig (rootDir) { let baseConfig = { rootDir, buildDir: '', + publicDir: '', + staticDir: '', targets: [], templates: [], nuxt: 2, @@ -24,6 +26,8 @@ export function getBaseConfig (rootDir) { } baseConfig.buildDir = resolve(baseConfig.rootDir, baseConfig.buildDir || '.nuxt') + baseConfig.publicDir = resolve(baseConfig.rootDir, baseConfig.publicDir || 'dist') + baseConfig.staticDir = resolve(baseConfig.rootDir, baseConfig.staticDir || 'static') baseConfig.targets = baseConfig.targets.map(t => typeof t === 'string' ? { target: t } : t) if (baseConfig.target && !baseConfig.targets.find(t => t.target === baseConfig.target)) { From 486c881b2dd1c1e547f31cf8babc68e259982df0 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 12:28:39 +0100 Subject: [PATCH 046/227] feat: rewrite as nuxt module --- packages/nitro/src/build.ts | 30 ++------------- packages/nitro/src/cli.ts | 27 -------------- packages/nitro/src/config.ts | 33 +++++++---------- packages/nitro/src/index.ts | 39 +++++++++++++++++++- packages/nitro/src/nuxt-serverless.ts | 6 --- packages/nitro/src/rollup/config.ts | 6 +-- packages/nitro/src/rollup/dynamic-require.ts | 2 +- 7 files changed, 59 insertions(+), 84 deletions(-) delete mode 100644 packages/nitro/src/cli.ts delete mode 100644 packages/nitro/src/nuxt-serverless.ts diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index a8a2a51754..221f68101b 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -5,12 +5,13 @@ import Hookable from 'hookable' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' import chalk from 'chalk' -import { copy, emptyDir, existsSync, mkdirp } from 'fs-extra' +import { emptyDir } from 'fs-extra' import { getRollupConfig } from './rollup/config' import { getTargetConfig } from './config' import { hl, prettyPath, renderTemplate, compileTemplateToJS } from './utils' export async function build (baseConfig, target) { + console.log('\n') consola.info(`Generating bundle for ${hl(target.target)}`) const config: any = getTargetConfig(baseConfig, target) @@ -20,7 +21,7 @@ export async function build (baseConfig, target) { await hooks.callHook('config', config) - emptyDir(config.outDir) + emptyDir(config.targetDir) config.rollupConfig = getRollupConfig(config) await hooks.callHook('rollup:before', config) @@ -34,7 +35,7 @@ export async function build (baseConfig, target) { ) for (const tmpl of config.templates) { - const dstPath = resolve(config.outDir, tmpl.dst) + const dstPath = resolve(config.targetDir, tmpl.dst) await renderTemplate(tmpl.src, dstPath, { config }) consola.info('Compiled', prettyPath(dstPath)) } @@ -48,26 +49,3 @@ export async function compileHTMLTemplate (baseConfig) { await compileTemplateToJS(htmlTemplateFile, htmlTemplateFileJS) consola.info('Generated', prettyPath(htmlTemplateFileJS)) } - -export function ensureDist (baseConfig) { - if (!existsSync(resolve(baseConfig.buildDir, 'dist/server'))) { - return consola.error('Please use `nuxt build` first to build project!') - } else { - consola.success('Using existing nuxt build from', prettyPath(baseConfig.buildDir)) - } -} - -export async function generatePublic (baseConfig) { - await emptyDir(baseConfig.publicDir) - await mkdirp(baseConfig.publicDir) - - await copy( - baseConfig.staticDir, - baseConfig.publicDir - ) - - await copy( - resolve(baseConfig.buildDir, 'dist/client'), - resolve(baseConfig.publicDir, '_nuxt') - ) -} diff --git a/packages/nitro/src/cli.ts b/packages/nitro/src/cli.ts deleted file mode 100644 index 742df46f93..0000000000 --- a/packages/nitro/src/cli.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { resolve } from 'path' -import { build, compileHTMLTemplate, ensureDist, generatePublic } from './build' -import { getBaseConfig } from './config' - -export async function runCLI () { - const rootDir = resolve(process.cwd(), process.argv[2] || '.') - - // Config - const baseConfig = getBaseConfig(rootDir) - - // Ensure dist exists - await ensureDist(baseConfig) - - // Compile html template - await compileHTMLTemplate(baseConfig) - - // Generate public dir - await generatePublic(baseConfig) - - // Bundle for each target - for (const target of baseConfig.targets) { - if (baseConfig.target && target.target !== baseConfig.target) { - continue - } - await build(baseConfig, target) - } -} diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 52d072f3b3..651ac0581d 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -2,32 +2,25 @@ import { resolve } from 'path' import defu from 'defu' import { tryImport, LIB_DIR } from './utils' -export function getBaseConfig (rootDir) { - let baseConfig = { - rootDir, - buildDir: '', - publicDir: '', - staticDir: '', +export function getBaseConfig (options) { + const baseConfig = { + rootDir: options.rootDir, + buildDir: options.buildDir, + publicDir: options.generate.dir, + slsDir: null, targets: [], templates: [], nuxt: 2, - target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null, - minify: process.argv.includes('--minify') ? true : null, - analyze: process.argv.includes('--analyze') ? true : null, - logStartup: true - } - - 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) + target: null, + minify: null, + analyze: null, + logStartup: true, + ...options.serverless } baseConfig.buildDir = resolve(baseConfig.rootDir, baseConfig.buildDir || '.nuxt') baseConfig.publicDir = resolve(baseConfig.rootDir, baseConfig.publicDir || 'dist') - baseConfig.staticDir = resolve(baseConfig.rootDir, baseConfig.staticDir || 'static') + baseConfig.slsDir = resolve(baseConfig.rootDir, baseConfig.slsDir || '.sls') baseConfig.targets = baseConfig.targets.map(t => typeof t === 'string' ? { target: t } : t) if (baseConfig.target && !baseConfig.targets.find(t => t.target === baseConfig.target)) { @@ -55,7 +48,7 @@ export function getTargetConfig (baseConfig, target) { _targetDefaults, // Generic defaults { - outDir: resolve(baseConfig.buildDir, `sls/${target.target}`), + targetDir: resolve(baseConfig.slsDir, target.target), outName: 'index.js' } ) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 876cc40e6e..21a3da0d8c 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1 +1,38 @@ -export { runCLI } from './cli' +import { build, compileHTMLTemplate } from './build' +import { getBaseConfig } from './config' + +export default function () { + const { nuxt } = this + + if (nuxt.options.dev) { + return + } + + // Config + const baseConfig = getBaseConfig(nuxt.options) + + if (baseConfig.minify !== false) { + nuxt.options.build._minifyServer = true + } + + nuxt.options.build.standalone = true + + nuxt.hook('generate:cache:ignore', (ignore) => { + ignore.push(baseConfig.slsDir) + }) + + nuxt.hook('generate:done', () => buildSLS(baseConfig)) +} + +async function buildSLS (baseConfig) { + // Compile html template + await compileHTMLTemplate(baseConfig) + + // Bundle for each target + for (const target of baseConfig.targets) { + if (baseConfig.target && target.target !== baseConfig.target) { + continue + } + await build(baseConfig, target) + } +} diff --git a/packages/nitro/src/nuxt-serverless.ts b/packages/nitro/src/nuxt-serverless.ts deleted file mode 100644 index c19e652658..0000000000 --- a/packages/nitro/src/nuxt-serverless.ts +++ /dev/null @@ -1,6 +0,0 @@ - -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 ac4db2a949..de45f74e42 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -50,7 +50,7 @@ export const getRollupConfig = (config) => { const options: RollupConfig = { input: config.entry, output: { - file: path.resolve(config.outDir, config.outName), + file: path.resolve(config.targetDir, config.outName), format: 'cjs', intro: '', outro: '', @@ -77,7 +77,7 @@ export const getRollupConfig = (config) => { // Dynamic Require Support options.plugins.push(dynamicRequire({ dir: path.resolve(config.buildDir, 'dist/server'), - outDir: config.node === false ? undefined : config.outDir, + outDir: (config.node === false || config.inlineChunks) ? undefined : config.targetDir, globbyOptions: { ignore: [ 'server.js' @@ -123,7 +123,7 @@ export const getRollupConfig = (config) => { options.plugins.push(analyze()) } - if (config.minify) { + if (config.minify !== false) { options.plugins.push(terser()) } diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index d7966fd0f5..7fc45cd57c 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -4,7 +4,7 @@ import { copyFile, mkdirp } from 'fs-extra' const PLUGIN_NAME = 'dynamic-require' const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js` -const DYNAMIC_REQUIRE_RE = /require\("\.\/" \+/g +const DYNAMIC_REQUIRE_RE = /require\("\.\/" ?\+/g const TMPL_INLINE = ({ imports }) => `${imports.map(i => `import ${i.name} from '${i.import}'`).join('\n')} From e0505568aa81fed775f7c156289457b2e9020bf6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 13:02:57 +0100 Subject: [PATCH 047/227] feat: whitelist static routes --- packages/nitro/src/config.ts | 3 +++ packages/nitro/src/index.ts | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 651ac0581d..da6f0aee1e 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -10,6 +10,9 @@ export function getBaseConfig (options) { slsDir: null, targets: [], templates: [], + static: [ + '/about' + ], nuxt: 2, target: null, minify: null, diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 21a3da0d8c..95d6158576 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -21,6 +21,13 @@ export default function () { ignore.push(baseConfig.slsDir) }) + nuxt.hook('generate:page', (page) => { + // TODO: Use ssrContext + if (!baseConfig.static.includes(page.route)) { + page.exclude = true + } + }) + nuxt.hook('generate:done', () => buildSLS(baseConfig)) } From dfdd466270899a1eaa8e8551c0d18c831a4ebcf9 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 5 Nov 2020 12:26:00 +0000 Subject: [PATCH 048/227] feat: improve types (#6) Co-authored-by: Pooya Parsa --- packages/nitro/src/build.ts | 4 ++-- packages/nitro/src/config.ts | 25 ++++++++++++++++++-- packages/nitro/src/index.ts | 3 ++- packages/nitro/src/rollup/config.ts | 4 +++- packages/nitro/src/rollup/dynamic-require.ts | 14 +++++++---- packages/nitro/src/utils.ts | 14 +++++------ 6 files changed, 47 insertions(+), 17 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 221f68101b..9f4397e155 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -7,8 +7,8 @@ import gzipSize from 'gzip-size' import chalk from 'chalk' import { emptyDir } from 'fs-extra' import { getRollupConfig } from './rollup/config' -import { getTargetConfig } from './config' import { hl, prettyPath, renderTemplate, compileTemplateToJS } from './utils' +import { getTargetConfig, SLSConfig } from './config' export async function build (baseConfig, target) { console.log('\n') @@ -43,7 +43,7 @@ export async function build (baseConfig, target) { await hooks.callHook('done', config) } -export async function compileHTMLTemplate (baseConfig) { +export async function compileHTMLTemplate (baseConfig: SLSConfig) { const htmlTemplateFile = resolve(baseConfig.buildDir, `views/${{ 2: 'app', 3: 'document' }[baseConfig.nuxt]}.template.html`) const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') await compileTemplateToJS(htmlTemplateFile, htmlTemplateFileJS) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index da6f0aee1e..3c7882341d 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -1,8 +1,29 @@ import { resolve } from 'path' import defu from 'defu' +import { NuxtOptions } from '@nuxt/types' import { tryImport, LIB_DIR } from './utils' -export function getBaseConfig (options) { +export interface SLSConfig { + node: false + entry: string + outDir: string + slsDir: string + outName: string + logStartup: boolean + buildDir: string + publicDir: string + staticDir: string + rootDir: string + targets: ((SLSConfig & { target: string }) | string)[] + target: string + templates: string[] + renderer: string + nuxt: 2 | 3 + analyze: boolean + minify: boolean +} + +export function getBaseConfig (options: NuxtOptions): SLSConfig { const baseConfig = { rootDir: options.rootDir, buildDir: options.buildDir, @@ -33,7 +54,7 @@ export function getBaseConfig (options) { return baseConfig } -export function getTargetConfig (baseConfig, target) { +export function getTargetConfig (baseConfig: SLSConfig, target: SLSConfig) { const _targetDefaults = tryImport(LIB_DIR, `./targets/${target.target}`) || tryImport(baseConfig.rootDir, target.target) if (!_targetDefaults) { diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 95d6158576..a9839ab8d9 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,7 +1,8 @@ +import type { Module } from '@nuxt/types' import { build, compileHTMLTemplate } from './build' import { getBaseConfig } from './config' -export default function () { +export default function slsModule () { const { nuxt } = this if (nuxt.options.dev) { diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index de45f74e42..6f9fd1e6e8 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -8,12 +8,14 @@ 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 { SLSConfig } from '../config' import { RUNTIME_DIR } from '../utils' import dynamicRequire from './dynamic-require' export type RollupConfig = InputOptions & { output: OutputOptions } -export const getRollupConfig = (config) => { +export const getRollupConfig = (config: SLSConfig) => { const mocks = [ // @nuxt/devalue 'consola', diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index 7fc45cd57c..00e4192446 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -6,7 +6,13 @@ const PLUGIN_NAME = 'dynamic-require' const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js` const DYNAMIC_REQUIRE_RE = /require\("\.\/" ?\+/g -const TMPL_INLINE = ({ imports }) => +interface Import { + name: string + id: string + import: string +} + +const TMPL_INLINE = ({ imports }: { imports: Import[]}) => `${imports.map(i => `import ${i.name} from '${i.import}'`).join('\n')} const dynamicChunks = { ${imports.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} @@ -30,13 +36,13 @@ interface Options { export default function dynamicRequire ({ dir, globbyOptions, outDir, chunksDir }: Options) { return { name: PLUGIN_NAME, - transform (code, _id) { + transform (code: string, _id: string) { return code.replace(DYNAMIC_REQUIRE_RE, `require('${HELPER_DYNAMIC}')(`) }, - resolveId (id) { + resolveId (id: string) { return id === HELPER_DYNAMIC ? id : null }, - async load (id) { + async load (id: string) { if (id === HELPER_DYNAMIC) { const files = await globby('**/*.js', { cwd: dir, absolute: false, ...globbyOptions }) diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index af766bea24..4972432600 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -4,19 +4,19 @@ import jiti from 'jiti' const pwd = process.cwd() -export const hl = str => '`' + str + '`' +export const hl = (str: string) => '`' + str + '`' -export function prettyPath (p, highlight = true) { +export function prettyPath (p: string, highlight = true) { p = relative(pwd, p) return highlight ? hl(p) : p } -export async function loadTemplate (src) { +export async function loadTemplate (src: string) { const contents = await readFile(src, 'utf-8') - return params => contents.replace(/{{ (\w+) }}/g, `${params.$1}`) + return (params: Record) => contents.replace(/{{ (\w+) }}/g, `${params.$1}`) } -export async function renderTemplate (src, dst: string, params: any) { +export async function renderTemplate (src: string, dst: string, params: any) { const tmpl = await loadTemplate(src) const rendered = tmpl(params) await mkdirp(dirname(dst)) @@ -31,8 +31,8 @@ export async function compileTemplateToJS (src: string, dst: string) { await writeFile(dst, compiled) } -export const jitiImport = (dir, path) => jiti(dir)(path) -export const tryImport = (dir, path) => { try { return jitiImport(dir, path) } catch (_err) { } } +export const jitiImport = (dir: string, path: string) => jiti(dir)(path) +export const tryImport = (dir: string, path: string) => { try { return jitiImport(dir, path) } catch (_err) { } } export const LIB_DIR = resolve(__dirname, '../lib') export const RUNTIME_DIR = resolve(LIB_DIR, 'runtime') From d4624abfb95e529a93af88372a2f6c71f0495e17 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Thu, 5 Nov 2020 12:28:40 +0000 Subject: [PATCH 049/227] fix: add prefix to dynamic imports name (#5) Co-authored-by: Pooya Parsa --- packages/nitro/src/rollup/dynamic-require.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index 00e4192446..01d2d81855 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -49,7 +49,7 @@ export default function dynamicRequire ({ dir, globbyOptions, outDir, chunksDir const imports = files.map(id => ({ id, import: resolve(dir, id), - name: id.replace(/[\\/.]/g, '_') + name: '_' + id.replace(/[\\/.]/g, '_') })) if (!outDir) { From 8f5534c90a03ec0fa68fa3d462961fcdaf6a9459 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 14:38:15 +0100 Subject: [PATCH 050/227] refactor: simplify usage with single target --- packages/nitro/src/build.ts | 36 ++++++------- packages/nitro/src/config.ts | 84 ++++++++++++----------------- packages/nitro/src/index.ts | 25 ++++----- packages/nitro/src/rollup/config.ts | 4 +- 4 files changed, 63 insertions(+), 86 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 9f4397e155..6d223c0fc8 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -8,43 +8,41 @@ import chalk from 'chalk' import { emptyDir } from 'fs-extra' import { getRollupConfig } from './rollup/config' import { hl, prettyPath, renderTemplate, compileTemplateToJS } from './utils' -import { getTargetConfig, SLSConfig } from './config' +import { SLSOptions } from './config' -export async function build (baseConfig, target) { +export async function build (options: SLSOptions) { console.log('\n') - consola.info(`Generating bundle for ${hl(target.target)}`) - - const config: any = getTargetConfig(baseConfig, target) + consola.info(`Generating bundle for ${hl(options.target)}`) const hooks = new Hookable() - hooks.addHooks(config.hooks) + hooks.addHooks(options.hooks) - await hooks.callHook('config', config) + await hooks.callHook('options', options) - emptyDir(config.targetDir) + emptyDir(options.targetDir) - config.rollupConfig = getRollupConfig(config) - await hooks.callHook('rollup:before', config) - const build = await rollup(config.rollupConfig) + options.rollupConfig = getRollupConfig(options) + await hooks.callHook('rollup:before', options) + const build = await rollup(options.rollupConfig) - const { output } = await build.write(config.rollupConfig.output as OutputOptions) + const { output } = await build.write(options.rollupConfig.output as OutputOptions) const size = prettyBytes(output[0].code.length) const zSize = prettyBytes(await gzipSize(output[0].code)) - consola.success('Generated', prettyPath((config.rollupConfig.output as any).file), + consola.success('Generated', prettyPath((options.rollupConfig.output as any).file), chalk.gray(`(Size: ${size} Gzip: ${zSize})`) ) - for (const tmpl of config.templates) { - const dstPath = resolve(config.targetDir, tmpl.dst) - await renderTemplate(tmpl.src, dstPath, { config }) + for (const tmpl of options.templates) { + const dstPath = resolve(options.targetDir, tmpl.dst) + await renderTemplate(tmpl.src, dstPath, { options }) consola.info('Compiled', prettyPath(dstPath)) } - await hooks.callHook('done', config) + await hooks.callHook('done', options) } -export async function compileHTMLTemplate (baseConfig: SLSConfig) { - const htmlTemplateFile = resolve(baseConfig.buildDir, `views/${{ 2: 'app', 3: 'document' }[baseConfig.nuxt]}.template.html`) +export async function compileHTMLTemplate (options: SLSOptions) { + const htmlTemplateFile = resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[options.nuxt]}.template.html`) const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') await compileTemplateToJS(htmlTemplateFile, htmlTemplateFileJS) consola.info('Generated', prettyPath(htmlTemplateFileJS)) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 3c7882341d..a42c9a8860 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -3,77 +3,61 @@ import defu from 'defu' import { NuxtOptions } from '@nuxt/types' import { tryImport, LIB_DIR } from './utils' -export interface SLSConfig { +export interface SLSOptions { node: false + target: 'vercel' | 'cloudflare' | 'node' | 'sw' | string entry: string outDir: string slsDir: string outName: string logStartup: boolean + inlineChunks: boolean buildDir: string publicDir: string staticDir: string + targetDir: string rootDir: string - targets: ((SLSConfig & { target: string }) | string)[] - target: string - templates: string[] + templates: { src: string, dst: string }[] + static: string[] renderer: string nuxt: 2 | 3 analyze: boolean minify: boolean + rollupConfig?: any + hooks: { [key: string]: any } // TODO: export from hookable } -export function getBaseConfig (options: NuxtOptions): SLSConfig { - const baseConfig = { - rootDir: options.rootDir, - buildDir: options.buildDir, - publicDir: options.generate.dir, - slsDir: null, - targets: [], +export interface SLSConfig extends Partial {} + +export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { + const defaults: SLSConfig = { + rootDir: nuxtOptions.rootDir, + buildDir: nuxtOptions.buildDir, + publicDir: nuxtOptions.generate.dir, + outName: 'index.js', templates: [], - static: [ - '/about' - ], + static: [], nuxt: 2, - target: null, - minify: null, - analyze: null, logStartup: true, - ...options.serverless + inlineChunks: false } - baseConfig.buildDir = resolve(baseConfig.rootDir, baseConfig.buildDir || '.nuxt') - baseConfig.publicDir = resolve(baseConfig.rootDir, baseConfig.publicDir || 'dist') - baseConfig.slsDir = resolve(baseConfig.rootDir, baseConfig.slsDir || '.sls') - - baseConfig.targets = baseConfig.targets.map(t => typeof t === 'string' ? { target: t } : t) - if (baseConfig.target && !baseConfig.targets.find(t => t.target === baseConfig.target)) { - baseConfig.targets.push({ target: baseConfig.target }) + let target = nuxtOptions.serverless.target || process.env.SLS_TARGET || 'node' + if (typeof target === 'function') { + target = target(nuxtOptions) + } + let targetDefaults = tryImport(LIB_DIR, `./targets/${target}`) || tryImport(nuxtOptions.rootDir, target) + targetDefaults = targetDefaults.default || targetDefaults + if (!targetDefaults) { + throw new Error('Cannot resolve target: ' + target) } - return baseConfig -} - -export function getTargetConfig (baseConfig: SLSConfig, target: SLSConfig) { - 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 - { - targetDir: resolve(baseConfig.slsDir, target.target), - outName: 'index.js' - } - ) + const options: SLSOptions = defu(nuxtOptions.serverless, targetDefaults, defaults, { target }) + + options.buildDir = resolve(options.rootDir, options.buildDir || '.nuxt') + options.publicDir = resolve(options.rootDir, options.publicDir || 'dist') + options.slsDir = resolve(options.rootDir, options.slsDir || '.sls') + options.targetDir = resolve(options.slsDir, target) + + return options } diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index a9839ab8d9..8219c15c62 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,6 +1,6 @@ import type { Module } from '@nuxt/types' import { build, compileHTMLTemplate } from './build' -import { getBaseConfig } from './config' +import { getoptions } from './config' export default function slsModule () { const { nuxt } = this @@ -10,37 +10,32 @@ export default function slsModule () { } // Config - const baseConfig = getBaseConfig(nuxt.options) + const options = getoptions(nuxt.options) - if (baseConfig.minify !== false) { + if (options.minify !== false) { nuxt.options.build._minifyServer = true } nuxt.options.build.standalone = true nuxt.hook('generate:cache:ignore', (ignore) => { - ignore.push(baseConfig.slsDir) + ignore.push(options.slsDir) }) nuxt.hook('generate:page', (page) => { // TODO: Use ssrContext - if (!baseConfig.static.includes(page.route)) { + if (!options.static.includes(page.route)) { page.exclude = true } }) - nuxt.hook('generate:done', () => buildSLS(baseConfig)) + nuxt.hook('generate:done', () => buildSLS(options)) } -async function buildSLS (baseConfig) { +async function buildSLS (options) { // Compile html template - await compileHTMLTemplate(baseConfig) + await compileHTMLTemplate(options) - // Bundle for each target - for (const target of baseConfig.targets) { - if (baseConfig.target && target.target !== baseConfig.target) { - continue - } - await build(baseConfig, target) - } + // Bundle target + await build(options) } diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 6f9fd1e6e8..aef1d40f6b 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -9,13 +9,13 @@ import json from '@rollup/plugin-json' import replace from '@rollup/plugin-replace' import analyze from 'rollup-plugin-analyzer' -import { SLSConfig } from '../config' +import { SLSOptions } from '../config' import { RUNTIME_DIR } from '../utils' import dynamicRequire from './dynamic-require' export type RollupConfig = InputOptions & { output: OutputOptions } -export const getRollupConfig = (config: SLSConfig) => { +export const getRollupConfig = (config: SLSOptions) => { const mocks = [ // @nuxt/devalue 'consola', From f2d10645604c00870a0b1325b45d3af5b962a39b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 15:12:35 +0100 Subject: [PATCH 051/227] refactor: simplify targets to node and worker --- packages/nitro/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index a42c9a8860..6e2c4af371 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -5,7 +5,7 @@ import { tryImport, LIB_DIR } from './utils' export interface SLSOptions { node: false - target: 'vercel' | 'cloudflare' | 'node' | 'sw' | string + target: 'worker' | 'node' | string entry: string outDir: string slsDir: string From 274c98f5aa475b3839c597a573f99bdf8cab0166 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 16:36:31 +0100 Subject: [PATCH 052/227] rename default ssr entry to server.js --- packages/nitro/src/config.ts | 4 ++-- packages/nitro/src/rollup/config.ts | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 6e2c4af371..4ea8a3e9d3 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -34,7 +34,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { rootDir: nuxtOptions.rootDir, buildDir: nuxtOptions.buildDir, publicDir: nuxtOptions.generate.dir, - outName: 'index.js', + outName: 'server.js', templates: [], static: [], nuxt: 2, @@ -47,10 +47,10 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { target = target(nuxtOptions) } let targetDefaults = tryImport(LIB_DIR, `./targets/${target}`) || tryImport(nuxtOptions.rootDir, target) - targetDefaults = targetDefaults.default || targetDefaults if (!targetDefaults) { throw new Error('Cannot resolve target: ' + target) } + targetDefaults = targetDefaults.default || targetDefaults const options: SLSOptions = defu(nuxtOptions.serverless, targetDefaults, defaults, { target }) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index aef1d40f6b..2b5f24e92f 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -1,9 +1,9 @@ import Module from 'module' -import path from 'path' +import { basename, extname, resolve } from 'path' import { InputOptions, OutputOptions } from 'rollup' import { terser } from 'rollup-plugin-terser' import commonjs from '@rollup/plugin-commonjs' -import resolve from '@rollup/plugin-node-resolve' +import nodeResolve from '@rollup/plugin-node-resolve' import alias from '@rollup/plugin-alias' import json from '@rollup/plugin-json' import replace from '@rollup/plugin-replace' @@ -52,7 +52,7 @@ export const getRollupConfig = (config: SLSOptions) => { const options: RollupConfig = { input: config.entry, output: { - file: path.resolve(config.targetDir, config.outName), + file: resolve(config.targetDir, config.outName), format: 'cjs', intro: '', outro: '', @@ -78,8 +78,9 @@ export const getRollupConfig = (config: SLSOptions) => { // Dynamic Require Support options.plugins.push(dynamicRequire({ - dir: path.resolve(config.buildDir, 'dist/server'), + dir: resolve(config.buildDir, 'dist/server'), outDir: (config.node === false || config.inlineChunks) ? undefined : config.targetDir, + chunksDir: '_' + basename(config.outName, extname(config.outName)), globbyOptions: { ignore: [ 'server.js' @@ -92,16 +93,16 @@ export const getRollupConfig = (config: SLSOptions) => { options.plugins.push(alias({ entries: { '~runtime': RUNTIME_DIR, - '~renderer': require.resolve(path.resolve(RUNTIME_DIR, renderer)), + '~renderer': require.resolve(resolve(RUNTIME_DIR, renderer)), '~build': config.buildDir, - '~mock': require.resolve(path.resolve(RUNTIME_DIR, 'mock')), + '~mock': require.resolve(resolve(RUNTIME_DIR, 'mock')), ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}), ...providedDeps.reduce((p, c) => ({ ...p, [c]: require.resolve(c) }), {}) } })) // https://github.com/rollup/plugins/tree/master/packages/node-resolve - options.plugins.push(resolve({ + options.plugins.push(nodeResolve({ extensions, preferBuiltins: true, rootDir: config.rootDir, From 4c485ba33a8d87ff0496756a975260093fb0e19b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 17:33:51 +0100 Subject: [PATCH 053/227] chore: enable inlineChunks by default --- packages/nitro/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 4ea8a3e9d3..8901d5562d 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -39,7 +39,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { static: [], nuxt: 2, logStartup: true, - inlineChunks: false + inlineChunks: true } let target = nuxtOptions.serverless.target || process.env.SLS_TARGET || 'node' From 005421e04df015a2fd5e7bcdf4913e5810ace47e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 17:49:44 +0100 Subject: [PATCH 054/227] NUXT_SLS_TARGET --- packages/nitro/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 8901d5562d..69db22cf06 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -42,7 +42,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { inlineChunks: true } - let target = nuxtOptions.serverless.target || process.env.SLS_TARGET || 'node' + let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless.target || 'node' if (typeof target === 'function') { target = target(nuxtOptions) } From 415db060b044e827057f6b0327c7c8d674c2a093 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 19:53:17 +0100 Subject: [PATCH 055/227] feat: support staticAssetsBase --- packages/nitro/src/config.ts | 10 ++++++++++ packages/nitro/src/rollup/config.ts | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 69db22cf06..a3163547be 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -24,6 +24,13 @@ export interface SLSOptions { analyze: boolean minify: boolean rollupConfig?: any + fullStatic: boolean, + staticAssets: { + base: string + versionBase: string + dir: string + version: string + } hooks: { [key: string]: any } // TODO: export from hookable } @@ -34,6 +41,9 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { rootDir: nuxtOptions.rootDir, buildDir: nuxtOptions.buildDir, publicDir: nuxtOptions.generate.dir, + fullStatic: nuxtOptions.target === 'static' && !nuxtOptions._legacyGenerate, + // @ts-ignore + staticAssets: nuxtOptions.generate.staticAssets, outName: 'server.js', templates: [], static: [], diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 2b5f24e92f..2d6b28618f 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -72,7 +72,10 @@ export const getRollupConfig = (config: SLSOptions) => { options.plugins.push(replace({ values: { 'process.env.NODE_ENV': '"production"', - 'typeof window': '"undefined"' + 'typeof window': '"undefined"', + 'process.env.NUXT_STATIC_BASE': JSON.stringify(config.staticAssets.base), + 'process.env.NUXT_STATIC_VERSION': JSON.stringify(config.staticAssets.version), + 'process.env.NUXT_FULL_STATIC': config.fullStatic } })) From a4952a057cb5d5172612371ffb93db82087f7ab0 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 20:13:50 +0100 Subject: [PATCH 056/227] fix: add generate.routes and disable crawler --- packages/nitro/src/config.ts | 4 ++++ packages/nitro/src/index.ts | 2 ++ 2 files changed, 6 insertions(+) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index a3163547be..dd7143eb5b 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -52,6 +52,10 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { inlineChunks: true } + if (Array.isArray(nuxtOptions.generate.routes)) { + defaults.static = nuxtOptions.generate.routes + } + let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless.target || 'node' if (typeof target === 'function') { target = target(nuxtOptions) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 8219c15c62..108cf714e5 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -18,6 +18,8 @@ export default function slsModule () { nuxt.options.build.standalone = true + nuxt.options.generate.crawler = false + nuxt.hook('generate:cache:ignore', (ignore) => { ignore.push(options.slsDir) }) From 4185ec896fd70fa1831d7b88d39a646bab4f075a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 21:42:40 +0100 Subject: [PATCH 057/227] fix: extend routes from serverless.static --- packages/nitro/src/config.ts | 4 ---- packages/nitro/src/index.ts | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index dd7143eb5b..a3163547be 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -52,10 +52,6 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { inlineChunks: true } - if (Array.isArray(nuxtOptions.generate.routes)) { - defaults.static = nuxtOptions.generate.routes - } - let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless.target || 'node' if (typeof target === 'function') { target = target(nuxtOptions) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 108cf714e5..eb2a531e86 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -19,6 +19,12 @@ export default function slsModule () { nuxt.options.build.standalone = true nuxt.options.generate.crawler = false + if (Array.isArray(nuxt.options.generate.routes)) { + nuxt.options.generate.routes = Array.from(new Set([ + ...nuxt.options.generate.routes, + ...options.static + ])) + } nuxt.hook('generate:cache:ignore', (ignore) => { ignore.push(options.slsDir) From 9d02552c3c1f3648a3c88ec8bbdb192cf39ff327 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 22:23:24 +0100 Subject: [PATCH 058/227] feat: make browser target working again --- packages/nitro/src/build.ts | 6 +++++- packages/nitro/src/config.ts | 18 +++++++++++------- packages/nitro/src/rollup/config.ts | 3 ++- packages/nitro/src/utils.ts | 5 +++++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 6d223c0fc8..5059fbb387 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -33,7 +33,11 @@ export async function build (options: SLSOptions) { ) for (const tmpl of options.templates) { - const dstPath = resolve(options.targetDir, tmpl.dst) + let dst = tmpl.dst + if (typeof dst === 'function') { + dst = dst(options) + } + const dstPath = resolve(options.targetDir, dst) await renderTemplate(tmpl.src, dstPath, { options }) consola.info('Compiled', prettyPath(dstPath)) } diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index a3163547be..3aca388882 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -1,13 +1,14 @@ import { resolve } from 'path' import defu from 'defu' import { NuxtOptions } from '@nuxt/types' -import { tryImport, LIB_DIR } from './utils' +import { tryImport, LIB_DIR, resolvePath } from './utils' + +export type UnresolvedPath = string | ((SLSOptions) => string) export interface SLSOptions { node: false - target: 'worker' | 'node' | string + target: string entry: string - outDir: string slsDir: string outName: string logStartup: boolean @@ -17,7 +18,7 @@ export interface SLSOptions { staticDir: string targetDir: string rootDir: string - templates: { src: string, dst: string }[] + templates: { src: string, dst: UnresolvedPath }[] static: string[] renderer: string nuxt: 2 | 3 @@ -34,7 +35,9 @@ export interface SLSOptions { hooks: { [key: string]: any } // TODO: export from hookable } -export interface SLSConfig extends Partial {} +export interface SLSConfig extends Omit, 'targetDir'> { + targetDir: UnresolvedPath +} export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { const defaults: SLSConfig = { @@ -49,7 +52,8 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { static: [], nuxt: 2, logStartup: true, - inlineChunks: true + inlineChunks: true, + targetDir: null } let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless.target || 'node' @@ -67,7 +71,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { options.buildDir = resolve(options.rootDir, options.buildDir || '.nuxt') options.publicDir = resolve(options.rootDir, options.publicDir || 'dist') options.slsDir = resolve(options.rootDir, options.slsDir || '.sls') - options.targetDir = resolve(options.slsDir, target) + options.targetDir = options.targetDir ? resolvePath(options, options.targetDir) : resolve(options.slsDir, target) return options } diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 2d6b28618f..5dc5f5ae51 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -10,7 +10,7 @@ import replace from '@rollup/plugin-replace' import analyze from 'rollup-plugin-analyzer' import { SLSOptions } from '../config' -import { RUNTIME_DIR } from '../utils' +import { RUNTIME_DIR, resolvePath } from '../utils' import dynamicRequire from './dynamic-require' export type RollupConfig = InputOptions & { output: OutputOptions } @@ -75,6 +75,7 @@ export const getRollupConfig = (config: SLSOptions) => { 'typeof window': '"undefined"', 'process.env.NUXT_STATIC_BASE': JSON.stringify(config.staticAssets.base), 'process.env.NUXT_STATIC_VERSION': JSON.stringify(config.staticAssets.version), + // @ts-ignore 'process.env.NUXT_FULL_STATIC': config.fullStatic } })) diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index 4972432600..d48414db53 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -1,6 +1,7 @@ import { relative, dirname, resolve } from 'path' import { readFile, writeFile, mkdirp } from 'fs-extra' import jiti from 'jiti' +import { SLSOptions, UnresolvedPath } from './config' const pwd = process.cwd() @@ -34,5 +35,9 @@ export async function compileTemplateToJS (src: string, dst: string) { export const jitiImport = (dir: string, path: string) => jiti(dir)(path) export const tryImport = (dir: string, path: string) => { try { return jitiImport(dir, path) } catch (_err) { } } +export function resolvePath (options: SLSOptions, path: UnresolvedPath, resolveBase: string = '') { + return resolve(resolveBase, typeof path === 'string' ? path : path(options)) +} + export const LIB_DIR = resolve(__dirname, '../lib') export const RUNTIME_DIR = resolve(LIB_DIR, 'runtime') From 360bba7d80bfdd2655308a82081500b113de5709 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 22:24:36 +0100 Subject: [PATCH 059/227] fix only empty slsDir --- packages/nitro/src/build.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 5059fbb387..58c5e9668b 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -19,7 +19,7 @@ export async function build (options: SLSOptions) { await hooks.callHook('options', options) - emptyDir(options.targetDir) + emptyDir(options.slsDir) options.rollupConfig = getRollupConfig(options) await hooks.callHook('rollup:before', options) From 6e1678316eb80f27dcd15c3e8006d1c8b7685e7f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 22:40:25 +0100 Subject: [PATCH 060/227] feat: inject sw script to pages --- packages/nitro/src/config.ts | 1 + packages/nitro/src/index.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 3aca388882..5fc80b3ee4 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -33,6 +33,7 @@ export interface SLSOptions { version: string } hooks: { [key: string]: any } // TODO: export from hookable + nuxtHooks: NuxtOptions['hooks'] } export interface SLSConfig extends Omit, 'targetDir'> { diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index eb2a531e86..4f5ad6d391 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -26,6 +26,10 @@ export default function slsModule () { ])) } + if (options.nuxtHooks) { + nuxt.addHooks(options.nuxtHooks) + } + nuxt.hook('generate:cache:ignore', (ignore) => { ignore.push(options.slsDir) }) From 04a25fc527a19763887d2dfaae08465a2b9907a2 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 22:56:40 +0100 Subject: [PATCH 061/227] feat(browser): inject script to js template --- packages/nitro/src/build.ts | 21 ++++++++++++--------- packages/nitro/src/index.ts | 10 +--------- packages/nitro/src/utils.ts | 11 +++++++---- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 58c5e9668b..0552f64a67 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -7,7 +7,7 @@ import gzipSize from 'gzip-size' import chalk from 'chalk' import { emptyDir } from 'fs-extra' import { getRollupConfig } from './rollup/config' -import { hl, prettyPath, renderTemplate, compileTemplateToJS } from './utils' +import { hl, prettyPath, renderTemplate, compileTemplateToJS, writeFileP } from './utils' import { SLSOptions } from './config' export async function build (options: SLSOptions) { @@ -17,7 +17,17 @@ export async function build (options: SLSOptions) { const hooks = new Hookable() hooks.addHooks(options.hooks) - await hooks.callHook('options', options) + // Compile html template + const htmlTemplate = { + src: resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[options.nuxt]}.template.html`), + dst: '', + compiled: '' + } + htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.') + htmlTemplate.compiled = await compileTemplateToJS(htmlTemplate.src) + await hooks.callHook('template:document', htmlTemplate) + await writeFileP(htmlTemplate.dst, htmlTemplate.compiled) + consola.info('Generated', prettyPath(htmlTemplate.dst)) emptyDir(options.slsDir) @@ -44,10 +54,3 @@ export async function build (options: SLSOptions) { await hooks.callHook('done', options) } - -export async function compileHTMLTemplate (options: SLSOptions) { - const htmlTemplateFile = resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[options.nuxt]}.template.html`) - const htmlTemplateFileJS = htmlTemplateFile.replace(/.html$/, '.js').replace('app.', 'document.') - await compileTemplateToJS(htmlTemplateFile, htmlTemplateFileJS) - consola.info('Generated', prettyPath(htmlTemplateFileJS)) -} diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 4f5ad6d391..0816693169 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -41,13 +41,5 @@ export default function slsModule () { } }) - nuxt.hook('generate:done', () => buildSLS(options)) -} - -async function buildSLS (options) { - // Compile html template - await compileHTMLTemplate(options) - - // Bundle target - await build(options) + nuxt.hook('generate:done', () => build(options)) } diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index d48414db53..584a670aa7 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -24,12 +24,15 @@ export async function renderTemplate (src: string, dst: string, params: any) { await writeFile(dst, rendered) } -export async function compileTemplateToJS (src: string, dst: string) { +export async function compileTemplateToJS (src: string) { const contents = await readFile(src, 'utf-8') // eslint-disable-next-line no-template-curly-in-string - const compiled = `export default (params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` - await mkdirp(dirname(dst)) - await writeFile(dst, compiled) + return `export default (params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` +} + +export async function writeFileP (path, contents) { + await mkdirp(dirname(path)) + await writeFile(path, contents) } export const jitiImport = (dir: string, path: string) => jiti(dir)(path) From 5fdc6ccfb66e9dd8912f4fc8f46fd5d3cd888214 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 5 Nov 2020 22:59:14 +0100 Subject: [PATCH 062/227] chore: fix eslint issues --- packages/nitro/src/index.ts | 2 +- packages/nitro/src/rollup/config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 0816693169..0e6e6086d0 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,5 +1,5 @@ import type { Module } from '@nuxt/types' -import { build, compileHTMLTemplate } from './build' +import { build } from './build' import { getoptions } from './config' export default function slsModule () { diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 5dc5f5ae51..c1f58114ed 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -10,7 +10,7 @@ import replace from '@rollup/plugin-replace' import analyze from 'rollup-plugin-analyzer' import { SLSOptions } from '../config' -import { RUNTIME_DIR, resolvePath } from '../utils' +import { RUNTIME_DIR } from '../utils' import dynamicRequire from './dynamic-require' export type RollupConfig = InputOptions & { output: OutputOptions } From ddccc9cb7848e454fc40e0ed5b9674c932732e9c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 10:12:57 +0100 Subject: [PATCH 063/227] feat: detect target Co-authored-by: Sebasiten Chopin --- packages/nitro/src/config.ts | 4 ++-- packages/nitro/src/utils.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 5fc80b3ee4..0b0ecc13dd 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -1,7 +1,7 @@ import { resolve } from 'path' import defu from 'defu' import { NuxtOptions } from '@nuxt/types' -import { tryImport, LIB_DIR, resolvePath } from './utils' +import { tryImport, LIB_DIR, resolvePath, detectTarget } from './utils' export type UnresolvedPath = string | ((SLSOptions) => string) @@ -57,7 +57,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { targetDir: null } - let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless.target || 'node' + let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless.target || detectTarget() if (typeof target === 'function') { target = target(nuxtOptions) } diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index 584a670aa7..8fa7bacd55 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -42,5 +42,17 @@ export function resolvePath (options: SLSOptions, path: UnresolvedPath, resolveB return resolve(resolveBase, typeof path === 'string' ? path : path(options)) } +export function detectTarget () { + if (process.env.NETLIFY) { + return 'netlify' + } + + if (process.env.VERCEL_URL) { + return 'vercel' + } + + return 'node' +} + export const LIB_DIR = resolve(__dirname, '../lib') export const RUNTIME_DIR = resolve(LIB_DIR, 'runtime') From 47d7644b728b4f09fc3b4ad8a830db26c9979cbb Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 10:51:35 +0100 Subject: [PATCH 064/227] refactor: move targets to src, remove template and improve runtime --- packages/nitro/src/build.ts | 24 +++-------- packages/nitro/src/config.ts | 15 ++++--- packages/nitro/src/rollup/config.ts | 10 ++--- packages/nitro/src/targets/browser.ts | 34 +++++++++++++++ packages/nitro/src/targets/cloudflare.ts | 7 ++++ packages/nitro/src/targets/index.ts | 7 ++++ packages/nitro/src/targets/lambda.ts | 14 +++++++ packages/nitro/src/targets/netlify.ts | 7 ++++ packages/nitro/src/targets/node.ts | 14 +++++++ packages/nitro/src/targets/vercel.ts | 7 ++++ packages/nitro/src/targets/worker.ts | 14 +++++++ packages/nitro/src/utils.ts | 53 ++++++++++++++---------- 12 files changed, 154 insertions(+), 52 deletions(-) create mode 100644 packages/nitro/src/targets/browser.ts create mode 100644 packages/nitro/src/targets/cloudflare.ts create mode 100644 packages/nitro/src/targets/index.ts create mode 100644 packages/nitro/src/targets/lambda.ts create mode 100644 packages/nitro/src/targets/netlify.ts create mode 100644 packages/nitro/src/targets/node.ts create mode 100644 packages/nitro/src/targets/vercel.ts create mode 100644 packages/nitro/src/targets/worker.ts diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 0552f64a67..735c39672b 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -5,9 +5,9 @@ import Hookable from 'hookable' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' import chalk from 'chalk' -import { emptyDir } from 'fs-extra' +import { emptyDir, readFile } from 'fs-extra' import { getRollupConfig } from './rollup/config' -import { hl, prettyPath, renderTemplate, compileTemplateToJS, writeFileP } from './utils' +import { hl, prettyPath, serializeTemplate, writeFileP } from './utils' import { SLSOptions } from './config' export async function build (options: SLSOptions) { @@ -18,13 +18,11 @@ export async function build (options: SLSOptions) { hooks.addHooks(options.hooks) // Compile html template - const htmlTemplate = { - src: resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[options.nuxt]}.template.html`), - dst: '', - compiled: '' - } + const htmlSrc = resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[options.nuxt]}.template.html`) + const htmlTemplate = { src: htmlSrc, contents: '', dst: '', compiled: '' } htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.') - htmlTemplate.compiled = await compileTemplateToJS(htmlTemplate.src) + htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8') + htmlTemplate.compiled = serializeTemplate(htmlTemplate.src) await hooks.callHook('template:document', htmlTemplate) await writeFileP(htmlTemplate.dst, htmlTemplate.compiled) consola.info('Generated', prettyPath(htmlTemplate.dst)) @@ -42,15 +40,5 @@ export async function build (options: SLSOptions) { chalk.gray(`(Size: ${size} Gzip: ${zSize})`) ) - for (const tmpl of options.templates) { - let dst = tmpl.dst - if (typeof dst === 'function') { - dst = dst(options) - } - const dstPath = resolve(options.targetDir, dst) - await renderTemplate(tmpl.src, dstPath, { options }) - consola.info('Compiled', prettyPath(dstPath)) - } - await hooks.callHook('done', options) } diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 0b0ecc13dd..f66238d56f 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -1,14 +1,15 @@ import { resolve } from 'path' import defu from 'defu' import { NuxtOptions } from '@nuxt/types' -import { tryImport, LIB_DIR, resolvePath, detectTarget } from './utils' +import { tryImport, resolvePath, detectTarget } from './utils' +import * as TARGETS from './targets' export type UnresolvedPath = string | ((SLSOptions) => string) export interface SLSOptions { node: false target: string - entry: string + entry: UnresolvedPath slsDir: string outName: string logStartup: boolean @@ -18,7 +19,7 @@ export interface SLSOptions { staticDir: string targetDir: string rootDir: string - templates: { src: string, dst: UnresolvedPath }[] + runtimeDir: string static: string[] renderer: string nuxt: 2 | 3 @@ -33,13 +34,15 @@ export interface SLSOptions { version: string } hooks: { [key: string]: any } // TODO: export from hookable - nuxtHooks: NuxtOptions['hooks'] + nuxtHooks: { [key: string]: Function } // NuxtOptions['hooks'] } export interface SLSConfig extends Omit, 'targetDir'> { targetDir: UnresolvedPath } +export type SLSTarget = Partial + export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { const defaults: SLSConfig = { rootDir: nuxtOptions.rootDir, @@ -49,7 +52,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { // @ts-ignore staticAssets: nuxtOptions.generate.staticAssets, outName: 'server.js', - templates: [], + runtimeDir: resolve(__dirname, '../runtime'), static: [], nuxt: 2, logStartup: true, @@ -61,7 +64,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { if (typeof target === 'function') { target = target(nuxtOptions) } - let targetDefaults = tryImport(LIB_DIR, `./targets/${target}`) || tryImport(nuxtOptions.rootDir, target) + let targetDefaults = TARGETS[target] || tryImport(nuxtOptions.rootDir, target) if (!targetDefaults) { throw new Error('Cannot resolve target: ' + target) } diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index c1f58114ed..6dde1e80d5 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -10,7 +10,7 @@ import replace from '@rollup/plugin-replace' import analyze from 'rollup-plugin-analyzer' import { SLSOptions } from '../config' -import { RUNTIME_DIR } from '../utils' +import { resolvePath } from '../utils' import dynamicRequire from './dynamic-require' export type RollupConfig = InputOptions & { output: OutputOptions } @@ -50,7 +50,7 @@ export const getRollupConfig = (config: SLSOptions) => { } const options: RollupConfig = { - input: config.entry, + input: resolvePath(config, config.entry), output: { file: resolve(config.targetDir, config.outName), format: 'cjs', @@ -96,10 +96,10 @@ export const getRollupConfig = (config: SLSOptions) => { const renderer = config.renderer || (config.nuxt === 2 ? 'vue2' : 'vue3') options.plugins.push(alias({ entries: { - '~runtime': RUNTIME_DIR, - '~renderer': require.resolve(resolve(RUNTIME_DIR, renderer)), + '~runtime': config.runtimeDir, + '~renderer': require.resolve(resolve(config.runtimeDir, renderer)), '~build': config.buildDir, - '~mock': require.resolve(resolve(RUNTIME_DIR, 'mock')), + '~mock': require.resolve(resolve(config.runtimeDir, 'mock')), ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}), ...providedDeps.reduce((p, c) => ({ ...p, [c]: require.resolve(c) }), {}) } diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts new file mode 100644 index 0000000000..a4ff9ebc8e --- /dev/null +++ b/packages/nitro/src/targets/browser.ts @@ -0,0 +1,34 @@ +import { resolve, relative } from 'path' +import { existsSync, copy } from 'fs-extra' +import consola from 'consola' +import { extendTarget } from '../utils' +import { SLSTarget } from '../config' +import { worker } from './worker' + +const getScriptTag = () => '' + +export const browser: SLSTarget = extendTarget(worker, { + targetDir: ({ publicDir }) => publicDir, + nuxtHooks: { + 'vue-renderer:ssr:templateParams' (params) { + params.APP += getScriptTag() + }, + 'vue-renderer:spa:templateParams' (params) { + params.APP += getScriptTag() + } + }, + hooks: { + 'template:document' (tmpl) { + tmpl.compiled = tmpl.compiled.replace('', getScriptTag() + '') + }, + async done ({ targetDir, publicDir }) { + const rootIndex = resolve(publicDir, 'index.html') + const rootFallback = resolve(publicDir, '200.html') + if (!existsSync(rootIndex) && existsSync(rootFallback)) { + await copy(rootFallback, rootIndex) + } + + consola.info(`Try with \`npx serve ${relative(process.cwd(), targetDir)}\``) + } + } +}) diff --git a/packages/nitro/src/targets/cloudflare.ts b/packages/nitro/src/targets/cloudflare.ts new file mode 100644 index 0000000000..fd1004455e --- /dev/null +++ b/packages/nitro/src/targets/cloudflare.ts @@ -0,0 +1,7 @@ +import { extendTarget } from '../utils' +import { SLSTarget } from '../config' +import { worker } from './worker' + +export const cloudflare: SLSTarget = extendTarget(worker, { + +}) diff --git a/packages/nitro/src/targets/index.ts b/packages/nitro/src/targets/index.ts new file mode 100644 index 0000000000..d7d4eb3c83 --- /dev/null +++ b/packages/nitro/src/targets/index.ts @@ -0,0 +1,7 @@ +export * from './browser' +export * from './cloudflare' +export * from './lambda' +export * from './netlify' +export * from './node' +export * from './vercel' +export * from './worker' diff --git a/packages/nitro/src/targets/lambda.ts b/packages/nitro/src/targets/lambda.ts new file mode 100644 index 0000000000..6603c97c1f --- /dev/null +++ b/packages/nitro/src/targets/lambda.ts @@ -0,0 +1,14 @@ + +import { relative } from 'path' +import consola from 'consola' +import { SLSTarget } from '../config' + +export const lambda: SLSTarget = { + entry: '{{ runtimeDir }}/lambda', + hooks: { + 'done' ({ rollupConfig }) { + const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') + consola.info(`Ready to deploy lambda: \`${entry}\``) + } + } +} diff --git a/packages/nitro/src/targets/netlify.ts b/packages/nitro/src/targets/netlify.ts new file mode 100644 index 0000000000..b5eaeed70e --- /dev/null +++ b/packages/nitro/src/targets/netlify.ts @@ -0,0 +1,7 @@ +import { extendTarget } from '../utils' +import { SLSTarget } from '../config' +import { lambda } from './lambda' + +export const netlify: SLSTarget = extendTarget(lambda, { + +}) diff --git a/packages/nitro/src/targets/node.ts b/packages/nitro/src/targets/node.ts new file mode 100644 index 0000000000..c203853883 --- /dev/null +++ b/packages/nitro/src/targets/node.ts @@ -0,0 +1,14 @@ +import { relative } from 'path' +import consola from 'consola' +import { SLSTarget } from '../config' + +export const node: SLSTarget = { + entry: '{{ runtimeDir }}/node', + hooks: { + 'done' ({ rollupConfig }) { + const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') + consola.info(`Ready to deploy lambda: \`${entry}\``) + consola.info(`You can try using \`node ${entry} [path]\``) + } + } +} diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts new file mode 100644 index 0000000000..fed5280130 --- /dev/null +++ b/packages/nitro/src/targets/vercel.ts @@ -0,0 +1,7 @@ +import { extendTarget } from '../utils' +import { SLSTarget } from '../config' +import { node } from './node' + +export const vercel: SLSTarget = extendTarget(node, { + +}) diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts new file mode 100644 index 0000000000..159a62c222 --- /dev/null +++ b/packages/nitro/src/targets/worker.ts @@ -0,0 +1,14 @@ +import { SLSTarget } from '../config' + +export const worker: SLSTarget = { + entry: '{{ runtimeDir }}/worker', + 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/utils.ts b/packages/nitro/src/utils.ts index 8fa7bacd55..3afe5661af 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -1,31 +1,23 @@ import { relative, dirname, resolve } from 'path' -import { readFile, writeFile, mkdirp } from 'fs-extra' +import { writeFile, mkdirp } from 'fs-extra' import jiti from 'jiti' -import { SLSOptions, UnresolvedPath } from './config' +import defu from 'defu' +import { SLSOptions, UnresolvedPath, SLSTarget } from './config' -const pwd = process.cwd() - -export const hl = (str: string) => '`' + str + '`' +export function hl (str: string) { + return '`' + str + '`' +} export function prettyPath (p: string, highlight = true) { - p = relative(pwd, p) + p = relative(process.cwd(), p) return highlight ? hl(p) : p } -export async function loadTemplate (src: string) { - const contents = await readFile(src, 'utf-8') - return (params: Record) => contents.replace(/{{ (\w+) }}/g, `${params.$1}`) +export function compileTemplate (contents: string) { + return (params: Record) => contents.replace(/{{ ?(\w+) ?}}/g, (_, match) => params[match] || '') } -export async function renderTemplate (src: string, dst: string, params: any) { - const tmpl = await loadTemplate(src) - const rendered = tmpl(params) - await mkdirp(dirname(dst)) - await writeFile(dst, rendered) -} - -export async function compileTemplateToJS (src: string) { - const contents = await readFile(src, 'utf-8') +export function serializeTemplate (contents: string) { // eslint-disable-next-line no-template-curly-in-string return `export default (params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` } @@ -35,11 +27,24 @@ export async function writeFileP (path, contents) { await writeFile(path, contents) } -export const jitiImport = (dir: string, path: string) => jiti(dir)(path) -export const tryImport = (dir: string, path: string) => { try { return jitiImport(dir, path) } catch (_err) { } } +export function jitiImport (dir: string, path: string) { + return jiti(dir)(path) +} + +export function tryImport (dir: string, path: string) { + try { + return jitiImport(dir, path) + } catch (_err) { } +} export function resolvePath (options: SLSOptions, path: UnresolvedPath, resolveBase: string = '') { - return resolve(resolveBase, typeof path === 'string' ? path : path(options)) + if (typeof path === 'function') { + path = path(options) + } + + path = compileTemplate(path)(options) + + return resolve(resolveBase, path) } export function detectTarget () { @@ -54,5 +59,7 @@ export function detectTarget () { return 'node' } -export const LIB_DIR = resolve(__dirname, '../lib') -export const RUNTIME_DIR = resolve(LIB_DIR, 'runtime') +export function extendTarget (base: SLSTarget, target: SLSTarget): SLSTarget { + // TODO: merge hooks + return defu(target, base) +} From ce71ec1347b6051b968d6004e38406cd085df6e6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 10:57:04 +0100 Subject: [PATCH 065/227] browser: inline sw register script --- packages/nitro/src/targets/browser.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts index a4ff9ebc8e..2f43aac1bd 100644 --- a/packages/nitro/src/targets/browser.ts +++ b/packages/nitro/src/targets/browser.ts @@ -5,7 +5,13 @@ import { extendTarget } from '../utils' import { SLSTarget } from '../config' import { worker } from './worker' -const getScriptTag = () => '' +const getScriptTag = () => ``.replace(/\n| +/g, '') export const browser: SLSTarget = extendTarget(worker, { targetDir: ({ publicDir }) => publicDir, From c99abd06ab3bb28dfcb5a02bfaa51ca7cb1b6a3d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 12:38:53 +0100 Subject: [PATCH 066/227] chore: default outName to _nuxt.js --- packages/nitro/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index f66238d56f..aa633735dd 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -51,7 +51,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { fullStatic: nuxtOptions.target === 'static' && !nuxtOptions._legacyGenerate, // @ts-ignore staticAssets: nuxtOptions.generate.staticAssets, - outName: 'server.js', + outName: '_nuxt.js', runtimeDir: resolve(__dirname, '../runtime'), static: [], nuxt: 2, From 00ccbdcfd821660640ce0589fb0ec4d832c0591e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 12:43:42 +0100 Subject: [PATCH 067/227] generate vercel into /api --- packages/nitro/src/targets/vercel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index fed5280130..d5328da5c5 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -3,5 +3,5 @@ import { SLSTarget } from '../config' import { node } from './node' export const vercel: SLSTarget = extendTarget(node, { - + targetDir: '{{ rootDir }}/api' }) From 374487ea291b4d7ff14e29a62eec433ca7a75a8a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 12:50:45 +0100 Subject: [PATCH 068/227] fix: use html.contents --- packages/nitro/src/build.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 735c39672b..34cd512d61 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -22,7 +22,7 @@ export async function build (options: SLSOptions) { const htmlTemplate = { src: htmlSrc, contents: '', dst: '', compiled: '' } htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.') htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8') - htmlTemplate.compiled = serializeTemplate(htmlTemplate.src) + htmlTemplate.compiled = serializeTemplate(htmlTemplate.contents) await hooks.callHook('template:document', htmlTemplate) await writeFileP(htmlTemplate.dst, htmlTemplate.compiled) consola.info('Generated', prettyPath(htmlTemplate.dst)) From d6aea1e0dfbfbd6442aba0e3091278c381831c1b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 12:51:29 +0100 Subject: [PATCH 069/227] fix: handle if serverless is not set in config --- packages/nitro/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index aa633735dd..9c6ea32d74 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -60,7 +60,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { targetDir: null } - let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless.target || detectTarget() + let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless?.target || detectTarget() if (typeof target === 'function') { target = target(nuxtOptions) } From b86eb3d7413c66b7be95968231d823aac65edc89 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 13:14:49 +0100 Subject: [PATCH 070/227] ignore target dir too --- packages/nitro/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 0e6e6086d0..517e6fd495 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -32,6 +32,7 @@ export default function slsModule () { nuxt.hook('generate:cache:ignore', (ignore) => { ignore.push(options.slsDir) + ignore.push(options.targetDir) }) nuxt.hook('generate:page', (page) => { From 5647d2dad079a6a271915a57d5fafec2713a4a35 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 13:41:33 +0100 Subject: [PATCH 071/227] add default files to ignore for smart rebuild --- packages/nitro/src/config.ts | 1 + packages/nitro/src/index.ts | 1 + packages/nitro/src/targets/netlify.ts | 5 ++++- packages/nitro/src/targets/vercel.ts | 5 ++++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 9c6ea32d74..01699cbf56 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -27,6 +27,7 @@ export interface SLSOptions { minify: boolean rollupConfig?: any fullStatic: boolean, + generateIgnore: string[] staticAssets: { base: string versionBase: string diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 517e6fd495..6459c03659 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -33,6 +33,7 @@ export default function slsModule () { nuxt.hook('generate:cache:ignore', (ignore) => { ignore.push(options.slsDir) ignore.push(options.targetDir) + ignore.push(...options.generateIgnore) }) nuxt.hook('generate:page', (page) => { diff --git a/packages/nitro/src/targets/netlify.ts b/packages/nitro/src/targets/netlify.ts index b5eaeed70e..2f476f6097 100644 --- a/packages/nitro/src/targets/netlify.ts +++ b/packages/nitro/src/targets/netlify.ts @@ -3,5 +3,8 @@ import { SLSTarget } from '../config' import { lambda } from './lambda' export const netlify: SLSTarget = extendTarget(lambda, { - + generateIgnore: [ + 'netlify.toml', + '_redirects' + ] }) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index d5328da5c5..2ea0803a32 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -3,5 +3,8 @@ import { SLSTarget } from '../config' import { node } from './node' export const vercel: SLSTarget = extendTarget(node, { - targetDir: '{{ rootDir }}/api' + targetDir: '{{ rootDir }}/api', + generateIgnore: [ + 'vercel.json' + ] }) From 91caf2c4709a5cb0687bf71ec37248acbd773e02 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 13:55:30 +0100 Subject: [PATCH 072/227] feat: support targer functions to consume nuxtOptions --- packages/nitro/src/config.ts | 10 ++++++++-- packages/nitro/src/utils.ts | 18 ++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 01699cbf56..07a4cd2a17 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -1,12 +1,13 @@ import { resolve } from 'path' import defu from 'defu' -import { NuxtOptions } from '@nuxt/types' +import type { NuxtOptions } from '@nuxt/types' import { tryImport, resolvePath, detectTarget } from './utils' import * as TARGETS from './targets' export type UnresolvedPath = string | ((SLSOptions) => string) export interface SLSOptions { + nuxtOptions: NuxtOptions node: false target: string entry: UnresolvedPath @@ -42,7 +43,7 @@ export interface SLSConfig extends Omit, 'targetDir'> { targetDir: UnresolvedPath } -export type SLSTarget = Partial +export type SLSTarget = Partial | ((NuxtOptions) => Partial) export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { const defaults: SLSConfig = { @@ -55,6 +56,7 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { outName: '_nuxt.js', runtimeDir: resolve(__dirname, '../runtime'), static: [], + generateIgnore: [], nuxt: 2, logStartup: true, inlineChunks: true, @@ -65,11 +67,15 @@ export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { if (typeof target === 'function') { target = target(nuxtOptions) } + let targetDefaults = TARGETS[target] || tryImport(nuxtOptions.rootDir, target) if (!targetDefaults) { throw new Error('Cannot resolve target: ' + target) } targetDefaults = targetDefaults.default || targetDefaults + if (typeof targetDefaults === 'function') { + targetDefaults = targetDefaults(nuxtOptions) + } const options: SLSOptions = defu(nuxtOptions.serverless, targetDefaults, defaults, { target }) diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index 3afe5661af..a615509b8e 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -2,6 +2,8 @@ import { relative, dirname, resolve } from 'path' import { writeFile, mkdirp } from 'fs-extra' import jiti from 'jiti' import defu from 'defu' +import Hookable from 'hookable' +import type { NuxtOptions } from '@nuxt/types' import { SLSOptions, UnresolvedPath, SLSTarget } from './config' export function hl (str: string) { @@ -60,6 +62,18 @@ export function detectTarget () { } export function extendTarget (base: SLSTarget, target: SLSTarget): SLSTarget { - // TODO: merge hooks - return defu(target, base) + return (nuxtOptions: NuxtOptions) => { + if (typeof target === 'function') { + target = target(nuxtOptions) + } + + if (typeof base === 'function') { + base = base(base) + } + + return defu({ + hooks: Hookable.mergeHooks(base.hooks, target.hooks), + nuxtHooks: Hookable.mergeHooks(base.nuxtHooks as any, target.nuxtHooks as any) + }, target, base) + } } From 3fa6717882c1f9da0269e3666a1a6e94e82a2b34 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 14:46:17 +0100 Subject: [PATCH 073/227] improve config extending --- packages/nitro/src/build.ts | 2 +- packages/nitro/src/config.ts | 103 +++++++++++++------------- packages/nitro/src/index.ts | 2 +- packages/nitro/src/rollup/config.ts | 2 +- packages/nitro/src/targets/browser.ts | 46 ++++++------ packages/nitro/src/utils.ts | 17 +++-- 6 files changed, 88 insertions(+), 84 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 34cd512d61..15926de966 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -18,7 +18,7 @@ export async function build (options: SLSOptions) { hooks.addHooks(options.hooks) // Compile html template - const htmlSrc = resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[options.nuxt]}.template.html`) + const htmlSrc = resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`) const htmlTemplate = { src: htmlSrc, contents: '', dst: '', compiled: '' } htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.') htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8') diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 07a4cd2a17..4aed031fe5 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -1,86 +1,87 @@ import { resolve } from 'path' import defu from 'defu' import type { NuxtOptions } from '@nuxt/types' -import { tryImport, resolvePath, detectTarget } from './utils' +import Hookable, { configHooksT } from 'hookable' +import { tryImport, resolvePath, detectTarget, extendTarget } from './utils' import * as TARGETS from './targets' export type UnresolvedPath = string | ((SLSOptions) => string) +export interface Nuxt extends Hookable{ + options: NuxtOptions +} + export interface SLSOptions { - nuxtOptions: NuxtOptions - node: false - target: string - entry: UnresolvedPath - slsDir: string - outName: string - logStartup: boolean - inlineChunks: boolean + hooks: configHooksT + nuxtHooks: configHooksT + + rootDir: string buildDir: string publicDir: string - staticDir: string - targetDir: string - rootDir: string - runtimeDir: string - static: string[] - renderer: string - nuxt: 2 | 3 - analyze: boolean + routerBase: string + fullStatic: boolean + staticAssets: any + + entry: UnresolvedPath + outName: string + node: false + target: string minify: boolean rollupConfig?: any - fullStatic: boolean, + logStartup: boolean + inlineChunks: boolean + renderer: string + analyze: boolean + + runtimeDir: string + slsDir: string + targetDir: string + + static: string[] generateIgnore: string[] - staticAssets: { - base: string - versionBase: string - dir: string - version: string - } - hooks: { [key: string]: any } // TODO: export from hookable - nuxtHooks: { [key: string]: Function } // NuxtOptions['hooks'] } export interface SLSConfig extends Omit, 'targetDir'> { - targetDir: UnresolvedPath + targetDir?: UnresolvedPath } -export type SLSTarget = Partial | ((NuxtOptions) => Partial) +export type SLSTargetFn = (SLSConfig) => SLSConfig +export type SLSTarget = SLSConfig | SLSTargetFn -export function getoptions (nuxtOptions: NuxtOptions): SLSOptions { +export function getoptions (nuxt: Nuxt): SLSOptions { const defaults: SLSConfig = { - rootDir: nuxtOptions.rootDir, - buildDir: nuxtOptions.buildDir, - publicDir: nuxtOptions.generate.dir, - fullStatic: nuxtOptions.target === 'static' && !nuxtOptions._legacyGenerate, + rootDir: nuxt.options.rootDir, + buildDir: nuxt.options.buildDir, + publicDir: nuxt.options.generate.dir, + routerBase: nuxt.options.router.base, + fullStatic: nuxt.options.target === 'static' && !nuxt.options._legacyGenerate, // @ts-ignore - staticAssets: nuxtOptions.generate.staticAssets, + staticAssets: nuxt.options.generate.staticAssets, + outName: '_nuxt.js', - runtimeDir: resolve(__dirname, '../runtime'), - static: [], - generateIgnore: [], - nuxt: 2, logStartup: true, inlineChunks: true, - targetDir: null + + runtimeDir: resolve(__dirname, '../runtime'), + slsDir: null, + targetDir: null, + + static: [], + generateIgnore: [] } - let target = process.env.NUXT_SLS_TARGET || nuxtOptions.serverless?.target || detectTarget() - if (typeof target === 'function') { - target = target(nuxtOptions) - } - - let targetDefaults = TARGETS[target] || tryImport(nuxtOptions.rootDir, target) + const target = process.env.NUXT_SLS_TARGET || nuxt.options.serverless?.target || detectTarget() + let targetDefaults = TARGETS[target] || tryImport(nuxt.options.rootDir, target) if (!targetDefaults) { throw new Error('Cannot resolve target: ' + target) } targetDefaults = targetDefaults.default || targetDefaults - if (typeof targetDefaults === 'function') { - targetDefaults = targetDefaults(nuxtOptions) - } - const options: SLSOptions = defu(nuxtOptions.serverless, targetDefaults, defaults, { target }) + const _defaults = defu(defaults, { target }) + const _targetInput = defu(nuxt.options.serverless, _defaults) + const _target = extendTarget(nuxt.options.serverless, targetDefaults)(_targetInput) + const options: SLSOptions = defu(nuxt.options.serverless, _target, _defaults) - options.buildDir = resolve(options.rootDir, options.buildDir || '.nuxt') - options.publicDir = resolve(options.rootDir, options.publicDir || 'dist') options.slsDir = resolve(options.rootDir, options.slsDir || '.sls') options.targetDir = options.targetDir ? resolvePath(options, options.targetDir) : resolve(options.slsDir, target) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 6459c03659..25451179be 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -10,7 +10,7 @@ export default function slsModule () { } // Config - const options = getoptions(nuxt.options) + const options = getoptions(nuxt) if (options.minify !== false) { nuxt.options.build._minifyServer = true diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 6dde1e80d5..9325f5d6e9 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -93,7 +93,7 @@ export const getRollupConfig = (config: SLSOptions) => { })) // https://github.com/rollup/plugins/tree/master/packages/alias - const renderer = config.renderer || (config.nuxt === 2 ? 'vue2' : 'vue3') + const renderer = config.renderer || 'vue2' options.plugins.push(alias({ entries: { '~runtime': config.runtimeDir, diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts index 2f43aac1bd..61369b0839 100644 --- a/packages/nitro/src/targets/browser.ts +++ b/packages/nitro/src/targets/browser.ts @@ -5,36 +5,38 @@ import { extendTarget } from '../utils' import { SLSTarget } from '../config' import { worker } from './worker' -const getScriptTag = () => ``.replace(/\n| +/g, '') -export const browser: SLSTarget = extendTarget(worker, { - targetDir: ({ publicDir }) => publicDir, - nuxtHooks: { - 'vue-renderer:ssr:templateParams' (params) { - params.APP += getScriptTag() - }, - 'vue-renderer:spa:templateParams' (params) { - params.APP += getScriptTag() - } - }, - hooks: { - 'template:document' (tmpl) { - tmpl.compiled = tmpl.compiled.replace('', getScriptTag() + '') - }, - async done ({ targetDir, publicDir }) { - const rootIndex = resolve(publicDir, 'index.html') - const rootFallback = resolve(publicDir, '200.html') - if (!existsSync(rootIndex) && existsSync(rootFallback)) { - await copy(rootFallback, rootIndex) + return { + targetDir: '{{ publicDir }}', + nuxtHooks: { + 'vue-renderer:ssr:templateParams' (params) { + params.APP += script + }, + 'vue-renderer:spa:templateParams' (params) { + params.APP += script } + }, + hooks: { + 'template:document' (tmpl) { + tmpl.compiled = tmpl.compiled.replace('', script + '') + }, + async done ({ targetDir, publicDir }) { + const rootIndex = resolve(publicDir, 'index.html') + const rootFallback = resolve(publicDir, '200.html') + if (!existsSync(rootIndex) && existsSync(rootFallback)) { + await copy(rootFallback, rootIndex) + } - consola.info(`Try with \`npx serve ${relative(process.cwd(), targetDir)}\``) + consola.info(`Try with \`npx serve ${relative(process.cwd(), targetDir)}\``) + } } } }) diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index a615509b8e..f5e2b54735 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -3,8 +3,7 @@ import { writeFile, mkdirp } from 'fs-extra' import jiti from 'jiti' import defu from 'defu' import Hookable from 'hookable' -import type { NuxtOptions } from '@nuxt/types' -import { SLSOptions, UnresolvedPath, SLSTarget } from './config' +import { SLSOptions, UnresolvedPath, SLSTarget, SLSTargetFn, SLSConfig } from './config' export function hl (str: string) { return '`' + str + '`' @@ -44,6 +43,10 @@ export function resolvePath (options: SLSOptions, path: UnresolvedPath, resolveB path = path(options) } + if (typeof path !== 'string') { + throw new TypeError('Invalid path: ' + path) + } + path = compileTemplate(path)(options) return resolve(resolveBase, path) @@ -61,16 +64,14 @@ export function detectTarget () { return 'node' } -export function extendTarget (base: SLSTarget, target: SLSTarget): SLSTarget { - return (nuxtOptions: NuxtOptions) => { +export function extendTarget (base: SLSTarget, target: SLSTarget): SLSTargetFn { + return (config: SLSConfig) => { if (typeof target === 'function') { - target = target(nuxtOptions) + target = target(config) } - if (typeof base === 'function') { - base = base(base) + base = base(config) } - return defu({ hooks: Hookable.mergeHooks(base.hooks, target.hooks), nuxtHooks: Hookable.mergeHooks(base.nuxtHooks as any, target.nuxtHooks as any) From 10c306aee0c7e52b1174f18b8e2f5a688a3f16c4 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 15:05:11 +0100 Subject: [PATCH 074/227] fix vercel env detection --- packages/nitro/src/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index f5e2b54735..02a990da1e 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -57,7 +57,7 @@ export function detectTarget () { return 'netlify' } - if (process.env.VERCEL_URL) { + if (process.env.NOW_BUILDER) { return 'vercel' } From 25290b7aa0f9391b3e4dcaf0f6f8a56db0ce4f33 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 15:07:35 +0100 Subject: [PATCH 075/227] fix script minification --- packages/nitro/src/targets/browser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts index 61369b0839..56749f9b96 100644 --- a/packages/nitro/src/targets/browser.ts +++ b/packages/nitro/src/targets/browser.ts @@ -12,7 +12,7 @@ if ('serviceWorker' in navigator) { navigator.serviceWorker.register('${options.routerBase}_nuxt.js'); }); } -`.replace(/\n| +/g, '') +`.replace(/\n| +/g, '') return { targetDir: '{{ publicDir }}', From 5b8314245ce335939c22317261278ad0a283d535 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 6 Nov 2020 17:40:00 +0100 Subject: [PATCH 076/227] feat: make cloudflare working --- packages/nitro/src/rollup/config.ts | 3 ++- packages/nitro/src/targets/cloudflare.ts | 24 +++++++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 9325f5d6e9..21f0af493e 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -36,7 +36,8 @@ export const getRollupConfig = (config: SLSOptions) => { const providedDeps = [ '@nuxt/devalue', - 'vue-bundle-renderer' + 'vue-bundle-renderer', + '@cloudflare/kv-asset-handler' ] const extensions = ['.ts', '.mjs', '.js', '.json', '.node'] diff --git a/packages/nitro/src/targets/cloudflare.ts b/packages/nitro/src/targets/cloudflare.ts index fd1004455e..a0c759a060 100644 --- a/packages/nitro/src/targets/cloudflare.ts +++ b/packages/nitro/src/targets/cloudflare.ts @@ -1,7 +1,25 @@ -import { extendTarget } from '../utils' -import { SLSTarget } from '../config' +import { resolve } from 'path' +import { writeFile } from 'fs-extra' +import consola from 'consola' +import { extendTarget, prettyPath } from '../utils' +import { SLSOptions, SLSTarget } from '../config' import { worker } from './worker' export const cloudflare: SLSTarget = extendTarget(worker, { - + entry: '{{ runtimeDir }}/cloudflare', + generateIgnore: [ + 'wrangler.toml' + ], + hooks: { + async done ({ targetDir }: SLSOptions) { + const pkgPath = resolve(targetDir, 'package.json') + const pkg = { + private: true, + main: './_nuxt.js' + } + await writeFile(pkgPath, JSON.stringify(pkg, null, 2)) + consola.info('Generated', prettyPath(pkgPath)) + consola.success('Ready to run `wrangler publish`') + } + } }) From 799e872b80fa089d8fc3c6771207896315e22e3f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sat, 7 Nov 2020 10:51:48 +0000 Subject: [PATCH 077/227] docs: node docs and small tweaks to limitations (#12) * docs: node docs and small tweaks to limitations * docs: update to use new entrypoint name --- packages/nitro/src/targets/node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/node.ts b/packages/nitro/src/targets/node.ts index c203853883..5c5a4a7a2b 100644 --- a/packages/nitro/src/targets/node.ts +++ b/packages/nitro/src/targets/node.ts @@ -7,7 +7,7 @@ export const node: SLSTarget = { hooks: { 'done' ({ rollupConfig }) { const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') - consola.info(`Ready to deploy lambda: \`${entry}\``) + consola.info(`Ready to deploy node entrypoint: \`${entry}\``) consola.info(`You can try using \`node ${entry} [path]\``) } } From fc0934dd0c8ff9fcd1eeb4c595f1582a42dd4440 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sun, 8 Nov 2020 23:19:23 +0000 Subject: [PATCH 078/227] fix: add more types (#16) --- packages/nitro/src/config.ts | 16 ++++++++++++---- packages/nitro/src/index.ts | 2 +- packages/nitro/src/utils.ts | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 4aed031fe5..cc0d8ddebd 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -5,7 +5,8 @@ import Hookable, { configHooksT } from 'hookable' import { tryImport, resolvePath, detectTarget, extendTarget } from './utils' import * as TARGETS from './targets' -export type UnresolvedPath = string | ((SLSOptions) => string) +// eslint-disable-next-line +export type UnresolvedPath = string | ((config: SLSOptions) => string) export interface Nuxt extends Hookable{ options: NuxtOptions @@ -45,17 +46,24 @@ export interface SLSConfig extends Omit, 'targetDir'> { targetDir?: UnresolvedPath } -export type SLSTargetFn = (SLSConfig) => SLSConfig +export type SLSTargetFn = (config: SLSConfig) => SLSConfig export type SLSTarget = SLSConfig | SLSTargetFn -export function getoptions (nuxt: Nuxt): SLSOptions { +interface SLSNuxt extends Nuxt { + options: Nuxt['options'] & { + generate: Nuxt['options']['generate'] & { + staticAssets: string[] + } + } +} + +export function getoptions (nuxt: SLSNuxt): SLSOptions { const defaults: SLSConfig = { rootDir: nuxt.options.rootDir, buildDir: nuxt.options.buildDir, publicDir: nuxt.options.generate.dir, routerBase: nuxt.options.router.base, fullStatic: nuxt.options.target === 'static' && !nuxt.options._legacyGenerate, - // @ts-ignore staticAssets: nuxt.options.generate.staticAssets, outName: '_nuxt.js', diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 25451179be..c1709273e2 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -30,7 +30,7 @@ export default function slsModule () { nuxt.addHooks(options.nuxtHooks) } - nuxt.hook('generate:cache:ignore', (ignore) => { + nuxt.hook('generate:cache:ignore', (ignore: string[]) => { ignore.push(options.slsDir) ignore.push(options.targetDir) ignore.push(...options.generateIgnore) diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index 02a990da1e..b2fcb96cc8 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -23,7 +23,7 @@ export function serializeTemplate (contents: string) { return `export default (params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` } -export async function writeFileP (path, contents) { +export async function writeFileP (path: string, contents: string) { await mkdirp(dirname(path)) await writeFile(path, contents) } From a2413dc5fd05b6d2bb1e1aafdce03c341ac5a5f0 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Mon, 9 Nov 2020 00:28:30 +0100 Subject: [PATCH 079/227] fix jiti issue should be fixed on jiti later on to support syntax --- packages/nitro/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index cc0d8ddebd..3459beaba1 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -78,7 +78,7 @@ export function getoptions (nuxt: SLSNuxt): SLSOptions { generateIgnore: [] } - const target = process.env.NUXT_SLS_TARGET || nuxt.options.serverless?.target || detectTarget() + const target = process.env.NUXT_SLS_TARGET || (nuxt.options.serverless || {}).target || detectTarget() let targetDefaults = TARGETS[target] || tryImport(nuxt.options.rootDir, target) if (!targetDefaults) { throw new Error('Cannot resolve target: ' + target) From 4b831fbd8d3b06d1699c361615ff85ed4f682d85 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Mon, 9 Nov 2020 01:41:00 +0100 Subject: [PATCH 080/227] feat(worker): support process.hrtime --- packages/nitro/src/targets/worker.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index 159a62c222..534bf3eb84 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -1,13 +1,20 @@ import { SLSTarget } from '../config' +// https://github.com/cabinjs/browser-hrtime +const hrTimeP = '!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).hrtime=n()}(this,(function(){"use strict";var e=function(e){!function(){if("performance"in window==0&&(window.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in window.performance==0){var e=Date.now();performance.timing&&performance.timing.navigationStart&&(e=performance.timing.navigationStart),window.performance.now=function(){return Date.now()-e}}}();var n=Math.floor(.001*(Date.now()-performance.now())),o=.001*performance.now(),r=Math.floor(o)+n,i=Math.floor(o%1*1e9);return e&&(r-=e[0],(i-=e[1])<0&&(r--,i+=1e9)),[r,i]};return e.bigint=function(n){var o=e(n);return 1e9*o[0]+o[1]},"undefined"!=typeof process&&void 0!==process.hrtime||void 0!==window.process||(window.process={}),void 0===process.hrtime?window.process.hrtime=e:process.hrtime}));' + +const cjsP = 'const exports = {}; const module = {exports};' +const processP = 'const process = {env: {}};' +const globalP = 'const global = { process }; const window = global;' + +const polyfill = cjsP + processP + globalP + hrTimeP + export const worker: SLSTarget = { entry: '{{ runtimeDir }}/worker', 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.intro = polyfill + rollupConfig.output.intro rollupConfig.output.format = 'iife' } } From 55f25aa8845fa330395ea562b67fef66b39f73b0 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 9 Nov 2020 15:31:57 +0100 Subject: [PATCH 081/227] fix windows issues --- packages/nitro/src/rollup/dynamic-require.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index 01d2d81855..5ae140fd0d 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -13,7 +13,7 @@ interface Import { } const TMPL_INLINE = ({ imports }: { imports: Import[]}) => - `${imports.map(i => `import ${i.name} from '${i.import}'`).join('\n')} + `${imports.map(i => `import ${i.name} from '${i.import.replace(/\\/g, '/')}'`).join('\n')} const dynamicChunks = { ${imports.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} }; From ffceb25ca24d56590b41ce7d5f2c2ade9e449ac0 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 9 Nov 2020 19:47:38 +0100 Subject: [PATCH 082/227] update vercel target --- packages/nitro/src/targets/vercel.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index 2ea0803a32..de477918c7 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -3,7 +3,9 @@ import { SLSTarget } from '../config' import { node } from './node' export const vercel: SLSTarget = extendTarget(node, { - targetDir: '{{ rootDir }}/api', + targetDir: '{{ rootDir }}/.vercel_build_output/functions/node/_nuxt', + outName: 'index.js', + inlineChunks: false, generateIgnore: [ 'vercel.json' ] From 1df092d08e062947b356224fdc80f591f7c9ca07 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 9 Nov 2020 19:49:58 +0100 Subject: [PATCH 083/227] fix(vercel): add api prefix --- packages/nitro/src/targets/vercel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index de477918c7..3bde7d5c3b 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -3,7 +3,7 @@ import { SLSTarget } from '../config' import { node } from './node' export const vercel: SLSTarget = extendTarget(node, { - targetDir: '{{ rootDir }}/.vercel_build_output/functions/node/_nuxt', + targetDir: '{{ rootDir }}/.vercel_build_output/functions/node/api/_nuxt', outName: 'index.js', inlineChunks: false, generateIgnore: [ From c7b88defa47450612961e90e531dd7519ab47588 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 10 Nov 2020 19:19:24 +0100 Subject: [PATCH 084/227] feat: update vercel and improve internals --- packages/nitro/src/build.ts | 5 ++-- packages/nitro/src/config.ts | 1 + packages/nitro/src/index.ts | 2 ++ packages/nitro/src/rollup/config.ts | 10 ++++--- packages/nitro/src/targets/vercel.ts | 43 +++++++++++++++++++++++++--- packages/nitro/src/utils.ts | 14 +++++---- 6 files changed, 58 insertions(+), 17 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 15926de966..1b3ebe09eb 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -7,7 +7,7 @@ import gzipSize from 'gzip-size' import chalk from 'chalk' import { emptyDir, readFile } from 'fs-extra' import { getRollupConfig } from './rollup/config' -import { hl, prettyPath, serializeTemplate, writeFileP } from './utils' +import { hl, prettyPath, serializeTemplate, writeFile } from './utils' import { SLSOptions } from './config' export async function build (options: SLSOptions) { @@ -24,8 +24,7 @@ export async function build (options: SLSOptions) { htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8') htmlTemplate.compiled = serializeTemplate(htmlTemplate.contents) await hooks.callHook('template:document', htmlTemplate) - await writeFileP(htmlTemplate.dst, htmlTemplate.compiled) - consola.info('Generated', prettyPath(htmlTemplate.dst)) + await writeFile(htmlTemplate.dst, htmlTemplate.compiled) emptyDir(options.slsDir) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 3459beaba1..9dfc464512 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -92,6 +92,7 @@ export function getoptions (nuxt: SLSNuxt): SLSOptions { options.slsDir = resolve(options.rootDir, options.slsDir || '.sls') options.targetDir = options.targetDir ? resolvePath(options, options.targetDir) : resolve(options.slsDir, target) + options.publicDir = resolvePath(options, options.publicDir) return options } diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index c1709273e2..6a4680561f 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -26,6 +26,8 @@ export default function slsModule () { ])) } + nuxt.options.generate.dir = options.publicDir + if (options.nuxtHooks) { nuxt.addHooks(options.nuxtHooks) } diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 21f0af493e..c9b98e9e37 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -1,5 +1,5 @@ import Module from 'module' -import { basename, extname, resolve } from 'path' +import { basename, dirname, extname, resolve } from 'path' import { InputOptions, OutputOptions } from 'rollup' import { terser } from 'rollup-plugin-terser' import commonjs from '@rollup/plugin-commonjs' @@ -50,10 +50,12 @@ export const getRollupConfig = (config: SLSOptions) => { external.push(...Module.builtinModules) } + const outFile = resolve(config.targetDir, config.outName) + const options: RollupConfig = { input: resolvePath(config, config.entry), output: { - file: resolve(config.targetDir, config.outName), + file: outFile, format: 'cjs', intro: '', outro: '', @@ -84,8 +86,8 @@ export const getRollupConfig = (config: SLSOptions) => { // Dynamic Require Support options.plugins.push(dynamicRequire({ dir: resolve(config.buildDir, 'dist/server'), - outDir: (config.node === false || config.inlineChunks) ? undefined : config.targetDir, - chunksDir: '_' + basename(config.outName, extname(config.outName)), + outDir: (config.node === false || config.inlineChunks) ? undefined : dirname(outFile), + chunksDir: '_' + basename(outFile, extname(outFile)), globbyOptions: { ignore: [ 'server.js' diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index 3bde7d5c3b..4efc56a961 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -1,12 +1,47 @@ -import { extendTarget } from '../utils' +import { resolve } from 'path' +import { extendTarget, writeFile } from '../utils' import { SLSTarget } from '../config' import { node } from './node' export const vercel: SLSTarget = extendTarget(node, { - targetDir: '{{ rootDir }}/.vercel_build_output/functions/node/api/_nuxt', - outName: 'index.js', + targetDir: '{{ rootDir }}/.vercel_build_output', + outName: 'functions/_nuxt/index.js', + publicDir: '{{ targetDir }}/static', inlineChunks: false, generateIgnore: [ 'vercel.json' - ] + ], + hooks: { + async done ({ targetDir }) { + await wrtieRoutes({ targetDir }) + } + } }) + +async function wrtieRoutes ({ targetDir }) { + const routes = [ + { + src: '/sw.js', + headers: { + 'cache-control': 'public, max-age=0, must-revalidate' + }, + continue: true + }, + { + src: '/_nuxt/(.*)', + headers: { + 'cache-control': 'public,max-age=31536000,immutable' + }, + continue: true + }, + { + handle: 'filesystem' + }, + { + src: '(.*)', + dest: '/.vercel/functions/_nuxt' + } + ] + + await writeFile(resolve(targetDir, 'routes.json'), JSON.stringify(routes, null, 2)) +} diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index b2fcb96cc8..6264cd9422 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -1,8 +1,9 @@ import { relative, dirname, resolve } from 'path' -import { writeFile, mkdirp } from 'fs-extra' +import fse from 'fs-extra' import jiti from 'jiti' import defu from 'defu' import Hookable from 'hookable' +import consola from 'consola' import { SLSOptions, UnresolvedPath, SLSTarget, SLSTargetFn, SLSConfig } from './config' export function hl (str: string) { @@ -23,11 +24,6 @@ export function serializeTemplate (contents: string) { return `export default (params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` } -export async function writeFileP (path: string, contents: string) { - await mkdirp(dirname(path)) - await writeFile(path, contents) -} - export function jitiImport (dir: string, path: string) { return jiti(dir)(path) } @@ -38,6 +34,12 @@ export function tryImport (dir: string, path: string) { } catch (_err) { } } +export async function writeFile (file, contents) { + await fse.mkdirp(dirname(file)) + await fse.writeFile(file, contents, 'utf-8') + consola.info('Generated ', prettyPath(file)) +} + export function resolvePath (options: SLSOptions, path: UnresolvedPath, resolveBase: string = '') { if (typeof path === 'function') { path = path(options) From a6c4a7e2cde16cab57083f654caf3247d83a8786 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 10 Nov 2020 20:24:05 +0100 Subject: [PATCH 085/227] fix(vercel): add missing node segment --- packages/nitro/src/targets/vercel.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index 4efc56a961..9b54c00803 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -5,7 +5,7 @@ import { node } from './node' export const vercel: SLSTarget = extendTarget(node, { targetDir: '{{ rootDir }}/.vercel_build_output', - outName: 'functions/_nuxt/index.js', + outName: 'functions/node/_nuxt/index.js', publicDir: '{{ targetDir }}/static', inlineChunks: false, generateIgnore: [ @@ -13,12 +13,12 @@ export const vercel: SLSTarget = extendTarget(node, { ], hooks: { async done ({ targetDir }) { - await wrtieRoutes({ targetDir }) + await writeRoutes({ targetDir }) } } }) -async function wrtieRoutes ({ targetDir }) { +async function writeRoutes ({ targetDir }) { const routes = [ { src: '/sw.js', From 2c4b8578934c65655acd72fb1161394c0eec9a4f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 10 Nov 2020 20:35:56 +0100 Subject: [PATCH 086/227] fix(vercel): add `/index` suffix to dst --- packages/nitro/src/targets/vercel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index 9b54c00803..0f591cbb73 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -39,7 +39,7 @@ async function writeRoutes ({ targetDir }) { }, { src: '(.*)', - dest: '/.vercel/functions/_nuxt' + dest: '/.vercel/functions/_nuxt/index' } ] From 7347e8ebda675ce9adf2a78a2e891651295cb6fd Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 10 Nov 2020 20:43:33 +0100 Subject: [PATCH 087/227] fix(vercel): generate to config/routes.json --- packages/nitro/src/targets/vercel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index 0f591cbb73..fe5b21c05e 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -43,5 +43,5 @@ async function writeRoutes ({ targetDir }) { } ] - await writeFile(resolve(targetDir, 'routes.json'), JSON.stringify(routes, null, 2)) + await writeFile(resolve(targetDir, 'config/routes.json'), JSON.stringify(routes, null, 2)) } From 72b877fe7cab5ef831bfe334f2ae551724510100 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 10 Nov 2020 21:29:46 +0100 Subject: [PATCH 088/227] fix: fix worker polyfill by adding performance --- packages/nitro/src/targets/worker.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index 534bf3eb84..f4fccd1f9c 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -1,13 +1,17 @@ import { SLSTarget } from '../config' +const polyfill = ` +const exports = {}; +const module = { exports }; +const process = { env: {} }; +const performance = {}; + // https://github.com/cabinjs/browser-hrtime -const hrTimeP = '!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).hrtime=n()}(this,(function(){"use strict";var e=function(e){!function(){if("performance"in window==0&&(window.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in window.performance==0){var e=Date.now();performance.timing&&performance.timing.navigationStart&&(e=performance.timing.navigationStart),window.performance.now=function(){return Date.now()-e}}}();var n=Math.floor(.001*(Date.now()-performance.now())),o=.001*performance.now(),r=Math.floor(o)+n,i=Math.floor(o%1*1e9);return e&&(r-=e[0],(i-=e[1])<0&&(r--,i+=1e9)),[r,i]};return e.bigint=function(n){var o=e(n);return 1e9*o[0]+o[1]},"undefined"!=typeof process&&void 0!==process.hrtime||void 0!==window.process||(window.process={}),void 0===process.hrtime?window.process.hrtime=e:process.hrtime}));' +'!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).hrtime=n()}(this,(function(){"use strict";var e=function(e){!function(){if("performance"in window==0&&(window.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in window.performance==0){var e=Date.now();performance.timing&&performance.timing.navigationStart&&(e=performance.timing.navigationStart),window.performance.now=function(){return Date.now()-e}}}();var n=Math.floor(.001*(Date.now()-performance.now())),o=.001*performance.now(),r=Math.floor(o)+n,i=Math.floor(o%1*1e9);return e&&(r-=e[0],(i-=e[1])<0&&(r--,i+=1e9)),[r,i]};return e.bigint=function(n){var o=e(n);return 1e9*o[0]+o[1]},"undefined"!=typeof process&&void 0!==process.hrtime||void 0!==window.process||(window.process={}),void 0===process.hrtime?window.process.hrtime=e:process.hrtime}));' -const cjsP = 'const exports = {}; const module = {exports};' -const processP = 'const process = {env: {}};' -const globalP = 'const global = { process }; const window = global;' - -const polyfill = cjsP + processP + globalP + hrTimeP +const global = { process }; +const window = global; +` export const worker: SLSTarget = { entry: '{{ runtimeDir }}/worker', From 2a6d4f38d036c5b4bbf1fba6264f3d71d19454c5 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 10 Nov 2020 23:21:00 +0100 Subject: [PATCH 089/227] fix(worker): smaller and working hrtime polyfill --- packages/nitro/src/targets/worker.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index f4fccd1f9c..2b392f3a30 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -1,16 +1,14 @@ import { SLSTarget } from '../config' +// https://gist.github.com/pi0/1476085924f8a2eb1df85929c20cb43f + const polyfill = ` const exports = {}; const module = { exports }; const process = { env: {} }; -const performance = {}; - -// https://github.com/cabinjs/browser-hrtime -'!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e="undefined"!=typeof globalThis?globalThis:e||self).hrtime=n()}(this,(function(){"use strict";var e=function(e){!function(){if("performance"in window==0&&(window.performance={}),Date.now=Date.now||function(){return(new Date).getTime()},"now"in window.performance==0){var e=Date.now();performance.timing&&performance.timing.navigationStart&&(e=performance.timing.navigationStart),window.performance.now=function(){return Date.now()-e}}}();var n=Math.floor(.001*(Date.now()-performance.now())),o=.001*performance.now(),r=Math.floor(o)+n,i=Math.floor(o%1*1e9);return e&&(r-=e[0],(i-=e[1])<0&&(r--,i+=1e9)),[r,i]};return e.bigint=function(n){var o=e(n);return 1e9*o[0]+o[1]},"undefined"!=typeof process&&void 0!==process.hrtime||void 0!==window.process||(window.process={}),void 0===process.hrtime?window.process.hrtime=e:process.hrtime}));' - const global = { process }; const window = global; +const o=Date.now(),t=()=>Date.now()-o;process.hrtime=o=>{const e=Math.floor(.001*(Date.now()-t())),n=.001*t();let a=Math.floor(n)+e,r=Math.floor(n%1*1e9);return o&&(a-=o[0],r-=o[1],r<0&&(a--,r+=1e9)),[a,r]}; ` export const worker: SLSTarget = { From dc6154fea8fc86515a584733c0dcb8ff1ecaa588 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 10 Nov 2020 23:38:22 +0100 Subject: [PATCH 090/227] cloudflare: generate package-lock.json --- packages/nitro/src/targets/cloudflare.ts | 13 ++++--------- packages/nitro/src/utils.ts | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/nitro/src/targets/cloudflare.ts b/packages/nitro/src/targets/cloudflare.ts index a0c759a060..e47522a0c5 100644 --- a/packages/nitro/src/targets/cloudflare.ts +++ b/packages/nitro/src/targets/cloudflare.ts @@ -1,7 +1,6 @@ import { resolve } from 'path' -import { writeFile } from 'fs-extra' import consola from 'consola' -import { extendTarget, prettyPath } from '../utils' +import { extendTarget, writeFile } from '../utils' import { SLSOptions, SLSTarget } from '../config' import { worker } from './worker' @@ -12,13 +11,9 @@ export const cloudflare: SLSTarget = extendTarget(worker, { ], hooks: { async done ({ targetDir }: SLSOptions) { - const pkgPath = resolve(targetDir, 'package.json') - const pkg = { - private: true, - main: './_nuxt.js' - } - await writeFile(pkgPath, JSON.stringify(pkg, null, 2)) - consola.info('Generated', prettyPath(pkgPath)) + await writeFile(resolve(targetDir, 'package.json'), JSON.stringify({ private: true, main: './_nuxt.js' }, null, 2)) + await writeFile(resolve(targetDir, 'package-lock.json'), JSON.stringify({ lockfileVersion: 1 }, null, 2)) + consola.success('Ready to run `wrangler publish`') } } diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index 6264cd9422..d228a8047c 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -37,7 +37,7 @@ export function tryImport (dir: string, path: string) { export async function writeFile (file, contents) { await fse.mkdirp(dirname(file)) await fse.writeFile(file, contents, 'utf-8') - consola.info('Generated ', prettyPath(file)) + consola.info('Generated', prettyPath(file)) } export function resolvePath (options: SLSOptions, path: UnresolvedPath, resolveBase: string = '') { From 4f7411973978a992e76806db1eea1f20715d1a22 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 11 Nov 2020 00:04:33 +0100 Subject: [PATCH 091/227] fix: fix issues with router.base support --- packages/nitro/src/rollup/config.ts | 1 + packages/nitro/src/targets/browser.ts | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index c9b98e9e37..186a8cf98a 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -76,6 +76,7 @@ export const getRollupConfig = (config: SLSOptions) => { values: { 'process.env.NODE_ENV': '"production"', 'typeof window': '"undefined"', + 'process.env.ROUTER_BASE': JSON.stringify(config.routerBase), 'process.env.NUXT_STATIC_BASE': JSON.stringify(config.staticAssets.base), 'process.env.NUXT_STATIC_VERSION': JSON.stringify(config.staticAssets.version), // @ts-ignore diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts index 56749f9b96..ae632d43b1 100644 --- a/packages/nitro/src/targets/browser.ts +++ b/packages/nitro/src/targets/browser.ts @@ -28,14 +28,13 @@ if ('serviceWorker' in navigator) { 'template:document' (tmpl) { tmpl.compiled = tmpl.compiled.replace('', script + '') }, - async done ({ targetDir, publicDir }) { - const rootIndex = resolve(publicDir, 'index.html') - const rootFallback = resolve(publicDir, '200.html') - if (!existsSync(rootIndex) && existsSync(rootFallback)) { - await copy(rootFallback, rootIndex) + async done ({ rootDir, publicDir }) { + const fallback200 = resolve(publicDir, '200.html') + const fallback400 = resolve(publicDir, '400.html') + if (!existsSync(fallback400) && existsSync(fallback200)) { + await copy(fallback200, fallback400) } - - consola.info(`Try with \`npx serve ${relative(process.cwd(), targetDir)}\``) + consola.info(`Try with \`nuxt start ${relative(process.cwd(), rootDir)}\``) } } } From 2e329d040321c4d1228dabddd93dcb7758582b74 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 11 Nov 2020 01:19:29 +0100 Subject: [PATCH 092/227] fix(browser): 400.html ~> 404.html --- packages/nitro/src/targets/browser.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts index ae632d43b1..46471fed0d 100644 --- a/packages/nitro/src/targets/browser.ts +++ b/packages/nitro/src/targets/browser.ts @@ -30,9 +30,9 @@ if ('serviceWorker' in navigator) { }, async done ({ rootDir, publicDir }) { const fallback200 = resolve(publicDir, '200.html') - const fallback400 = resolve(publicDir, '400.html') - if (!existsSync(fallback400) && existsSync(fallback200)) { - await copy(fallback200, fallback400) + const fallback404 = resolve(publicDir, '404.html') + if (!existsSync(fallback404) && existsSync(fallback200)) { + await copy(fallback200, fallback404) } consola.info(`Try with \`nuxt start ${relative(process.cwd(), rootDir)}\``) } From aff23726500de3050ba050bf0460eda2ed935b5e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 11 Nov 2020 14:42:10 +0100 Subject: [PATCH 093/227] fix: configurable publicPath (closes #21) --- packages/nitro/src/config.ts | 2 ++ packages/nitro/src/rollup/config.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 9dfc464512..d162134028 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -20,6 +20,7 @@ export interface SLSOptions { buildDir: string publicDir: string routerBase: string + publicPath: string fullStatic: boolean staticAssets: any @@ -63,6 +64,7 @@ export function getoptions (nuxt: SLSNuxt): SLSOptions { buildDir: nuxt.options.buildDir, publicDir: nuxt.options.generate.dir, routerBase: nuxt.options.router.base, + publicPath: nuxt.options.build.publicPath, fullStatic: nuxt.options.target === 'static' && !nuxt.options._legacyGenerate, staticAssets: nuxt.options.generate.staticAssets, diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 186a8cf98a..e3309e35c4 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -77,6 +77,7 @@ export const getRollupConfig = (config: SLSOptions) => { 'process.env.NODE_ENV': '"production"', 'typeof window': '"undefined"', 'process.env.ROUTER_BASE': JSON.stringify(config.routerBase), + 'process.env.PUBLIC_PATH': JSON.stringify(config.publicPath), 'process.env.NUXT_STATIC_BASE': JSON.stringify(config.staticAssets.base), 'process.env.NUXT_STATIC_VERSION': JSON.stringify(config.staticAssets.version), // @ts-ignore From 8414e64eeb26164e5b6cd1a9900e6ec806a0fe9b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 11 Nov 2020 15:03:55 +0100 Subject: [PATCH 094/227] refactor: add more tructure to runtime dir --- packages/nitro/src/rollup/config.ts | 4 ++-- packages/nitro/src/targets/browser.ts | 1 + packages/nitro/src/targets/cloudflare.ts | 2 +- packages/nitro/src/targets/lambda.ts | 2 +- packages/nitro/src/targets/node.ts | 2 +- packages/nitro/src/targets/worker.ts | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index e3309e35c4..eadcfe8f85 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -102,9 +102,9 @@ export const getRollupConfig = (config: SLSOptions) => { options.plugins.push(alias({ entries: { '~runtime': config.runtimeDir, - '~renderer': require.resolve(resolve(config.runtimeDir, renderer)), + '~renderer': require.resolve(resolve(config.runtimeDir, 'ssr', renderer)), '~build': config.buildDir, - '~mock': require.resolve(resolve(config.runtimeDir, 'mock')), + '~mock': require.resolve(resolve(config.runtimeDir, 'utils/mock')), ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}), ...providedDeps.reduce((p, c) => ({ ...p, [c]: require.resolve(c) }), {}) } diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts index 46471fed0d..33e45dfdda 100644 --- a/packages/nitro/src/targets/browser.ts +++ b/packages/nitro/src/targets/browser.ts @@ -15,6 +15,7 @@ if ('serviceWorker' in navigator) { `.replace(/\n| +/g, '') return { + entry: '{{ runtimeDir }}/targets/service-worker', targetDir: '{{ publicDir }}', nuxtHooks: { 'vue-renderer:ssr:templateParams' (params) { diff --git a/packages/nitro/src/targets/cloudflare.ts b/packages/nitro/src/targets/cloudflare.ts index e47522a0c5..76fbddff3d 100644 --- a/packages/nitro/src/targets/cloudflare.ts +++ b/packages/nitro/src/targets/cloudflare.ts @@ -5,7 +5,7 @@ import { SLSOptions, SLSTarget } from '../config' import { worker } from './worker' export const cloudflare: SLSTarget = extendTarget(worker, { - entry: '{{ runtimeDir }}/cloudflare', + entry: '{{ runtimeDir }}/targets/cloudflare', generateIgnore: [ 'wrangler.toml' ], diff --git a/packages/nitro/src/targets/lambda.ts b/packages/nitro/src/targets/lambda.ts index 6603c97c1f..a309641f8e 100644 --- a/packages/nitro/src/targets/lambda.ts +++ b/packages/nitro/src/targets/lambda.ts @@ -4,7 +4,7 @@ import consola from 'consola' import { SLSTarget } from '../config' export const lambda: SLSTarget = { - entry: '{{ runtimeDir }}/lambda', + entry: '{{ runtimeDir }}/targets/lambda', hooks: { 'done' ({ rollupConfig }) { const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') diff --git a/packages/nitro/src/targets/node.ts b/packages/nitro/src/targets/node.ts index 5c5a4a7a2b..b687c0761d 100644 --- a/packages/nitro/src/targets/node.ts +++ b/packages/nitro/src/targets/node.ts @@ -3,7 +3,7 @@ import consola from 'consola' import { SLSTarget } from '../config' export const node: SLSTarget = { - entry: '{{ runtimeDir }}/node', + entry: '{{ runtimeDir }}/targets/node', hooks: { 'done' ({ rollupConfig }) { const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index 2b392f3a30..76806a186e 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -12,7 +12,7 @@ const o=Date.now(),t=()=>Date.now()-o;process.hrtime=o=>{const e=Math.floor(.001 ` export const worker: SLSTarget = { - entry: '{{ runtimeDir }}/worker', + entry: null, // Abstract node: false, hooks: { 'rollup:before' ({ rollupConfig }) { From 696556aef8ab8aed41c450b299432a87d8b7af96 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 11 Nov 2020 15:06:20 +0100 Subject: [PATCH 095/227] fix: only generate .sls directory when needed --- packages/nitro/src/build.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 1b3ebe09eb..e592a61434 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -26,7 +26,9 @@ export async function build (options: SLSOptions) { await hooks.callHook('template:document', htmlTemplate) await writeFile(htmlTemplate.dst, htmlTemplate.compiled) - emptyDir(options.slsDir) + if (options.targetDir.startsWith(options.slsDir)) { + emptyDir(options.slsDir) + } options.rollupConfig = getRollupConfig(options) await hooks.callHook('rollup:before', options) From 35720380c2166cbbd2399d87fbe7cc765939eae6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 11 Nov 2020 15:12:11 +0100 Subject: [PATCH 096/227] update default sls dir to make usage easier (without gitignore) --- packages/nitro/src/config.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index d162134028..72343bddd3 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -73,8 +73,8 @@ export function getoptions (nuxt: SLSNuxt): SLSOptions { inlineChunks: true, runtimeDir: resolve(__dirname, '../runtime'), - slsDir: null, - targetDir: null, + slsDir: '{{ rootDir }}/.nuxt/serverless', + targetDir: '{{ slsDir }}/{{ target }}', static: [], generateIgnore: [] @@ -92,8 +92,8 @@ export function getoptions (nuxt: SLSNuxt): SLSOptions { const _target = extendTarget(nuxt.options.serverless, targetDefaults)(_targetInput) const options: SLSOptions = defu(nuxt.options.serverless, _target, _defaults) - options.slsDir = resolve(options.rootDir, options.slsDir || '.sls') - options.targetDir = options.targetDir ? resolvePath(options, options.targetDir) : resolve(options.slsDir, target) + options.slsDir = resolvePath(options, options.slsDir) + options.targetDir = resolvePath(options, options.targetDir) options.publicDir = resolvePath(options, options.publicDir) return options From b258c2af2c274ceef05efb9335e6cb33785c5841 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 11 Nov 2020 15:27:08 +0100 Subject: [PATCH 097/227] explicitly set outName in targets to avoid regression --- packages/nitro/src/targets/browser.ts | 1 + packages/nitro/src/targets/cloudflare.ts | 1 + packages/nitro/src/targets/lambda.ts | 1 + packages/nitro/src/targets/netlify.ts | 1 + packages/nitro/src/targets/node.ts | 5 ++++- 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts index 33e45dfdda..26baff5f78 100644 --- a/packages/nitro/src/targets/browser.ts +++ b/packages/nitro/src/targets/browser.ts @@ -17,6 +17,7 @@ if ('serviceWorker' in navigator) { return { entry: '{{ runtimeDir }}/targets/service-worker', targetDir: '{{ publicDir }}', + outName: '_nuxt.js', nuxtHooks: { 'vue-renderer:ssr:templateParams' (params) { params.APP += script diff --git a/packages/nitro/src/targets/cloudflare.ts b/packages/nitro/src/targets/cloudflare.ts index 76fbddff3d..c37c9dcf66 100644 --- a/packages/nitro/src/targets/cloudflare.ts +++ b/packages/nitro/src/targets/cloudflare.ts @@ -6,6 +6,7 @@ import { worker } from './worker' export const cloudflare: SLSTarget = extendTarget(worker, { entry: '{{ runtimeDir }}/targets/cloudflare', + outName: '_nuxt.js', generateIgnore: [ 'wrangler.toml' ], diff --git a/packages/nitro/src/targets/lambda.ts b/packages/nitro/src/targets/lambda.ts index a309641f8e..44a18ce0fd 100644 --- a/packages/nitro/src/targets/lambda.ts +++ b/packages/nitro/src/targets/lambda.ts @@ -5,6 +5,7 @@ import { SLSTarget } from '../config' export const lambda: SLSTarget = { entry: '{{ runtimeDir }}/targets/lambda', + outName: '_nuxt.js', hooks: { 'done' ({ rollupConfig }) { const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') diff --git a/packages/nitro/src/targets/netlify.ts b/packages/nitro/src/targets/netlify.ts index 2f476f6097..501d527d2b 100644 --- a/packages/nitro/src/targets/netlify.ts +++ b/packages/nitro/src/targets/netlify.ts @@ -3,6 +3,7 @@ import { SLSTarget } from '../config' import { lambda } from './lambda' export const netlify: SLSTarget = extendTarget(lambda, { + outName: '_nuxt.js', generateIgnore: [ 'netlify.toml', '_redirects' diff --git a/packages/nitro/src/targets/node.ts b/packages/nitro/src/targets/node.ts index b687c0761d..88814fddcd 100644 --- a/packages/nitro/src/targets/node.ts +++ b/packages/nitro/src/targets/node.ts @@ -4,9 +4,12 @@ import { SLSTarget } from '../config' export const node: SLSTarget = { entry: '{{ runtimeDir }}/targets/node', + outName: 'index.js', hooks: { 'done' ({ rollupConfig }) { - const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') + const entry = relative(process.cwd(), rollupConfig.output.file) + .replace(/\.js$/, '') + .replace(/\/index$/, '') consola.info(`Ready to deploy node entrypoint: \`${entry}\``) consola.info(`You can try using \`node ${entry} [path]\``) } From 75ed76219266e6017849111a63d977eccad6423d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 11 Nov 2020 23:06:29 +0100 Subject: [PATCH 098/227] feat: support serverMiddleware --- packages/nitro/src/config.ts | 9 +++++++++ packages/nitro/src/index.ts | 25 +++++++++++++++++++++++-- packages/nitro/src/rollup/config.ts | 18 +++++++++++++++--- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 72343bddd3..70533398aa 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -12,6 +12,11 @@ export interface Nuxt extends Hookable{ options: NuxtOptions } +export interface ServerMiddleware { + route: string + handle: string +} + export interface SLSOptions { hooks: configHooksT nuxtHooks: configHooksT @@ -39,6 +44,8 @@ export interface SLSOptions { slsDir: string targetDir: string + serverMiddleware: ServerMiddleware[], + static: string[] generateIgnore: string[] } @@ -76,6 +83,8 @@ export function getoptions (nuxt: SLSNuxt): SLSOptions { slsDir: '{{ rootDir }}/.nuxt/serverless', targetDir: '{{ slsDir }}/{{ target }}', + serverMiddleware: [], + static: [], generateIgnore: [] } diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 6a4680561f..e473f98fa5 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,3 +1,4 @@ +import hasha from 'hasha' import type { Module } from '@nuxt/types' import { build } from './build' import { getoptions } from './config' @@ -12,12 +13,13 @@ export default function slsModule () { // Config const options = getoptions(nuxt) + // Tune webpack config if (options.minify !== false) { nuxt.options.build._minifyServer = true } - nuxt.options.build.standalone = true + // Tune generator nuxt.options.generate.crawler = false if (Array.isArray(nuxt.options.generate.routes)) { nuxt.options.generate.routes = Array.from(new Set([ @@ -25,9 +27,28 @@ export default function slsModule () { ...options.static ])) } - nuxt.options.generate.dir = options.publicDir + // serverMiddleware + // TODO: render:setupMiddleware hook + // TODO: support m.prefix and m.route + nuxt.hook('modules:done', () => { + for (let m of nuxt.options.serverMiddleware) { + if (typeof m === 'string') { + m = { handler: m } + } + if (typeof m.handler !== 'string') { + console.warn('[Serverless] Unsupported serverMiddleware format:', m) + continue + } + + const route = m.path || m.route || '/' + const handle = nuxt.resolver.resolvePath(m.handler || m.handle) + const id = '_' + hasha(handle).substr(0, 6) + options.serverMiddleware.push({ route, id, handle }) + } + }) + if (options.nuxtHooks) { nuxt.addHooks(options.nuxtHooks) } diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index eadcfe8f85..e79aeeb9da 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -7,8 +7,10 @@ import nodeResolve from '@rollup/plugin-node-resolve' import alias from '@rollup/plugin-alias' import json from '@rollup/plugin-json' import replace from '@rollup/plugin-replace' +import virtual from '@rollup/plugin-virtual' import analyze from 'rollup-plugin-analyzer' +import hasha from 'hasha' import { SLSOptions } from '../config' import { resolvePath } from '../utils' import dynamicRequire from './dynamic-require' @@ -97,6 +99,18 @@ export const getRollupConfig = (config: SLSOptions) => { } })) + // Provide serverMiddleware + const getImportId = p => '_' + hasha(p).substr(0, 6) + options.plugins.push(virtual({ + '~serverMiddleware': ` + ${config.serverMiddleware.map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} + + export default [ + ${config.serverMiddleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)} }`).join(',\n')} + ]; + ` + })) + // https://github.com/rollup/plugins/tree/master/packages/alias const renderer = config.renderer || 'vue2' options.plugins.push(alias({ @@ -116,9 +130,7 @@ export const getRollupConfig = (config: SLSOptions) => { preferBuiltins: true, rootDir: config.rootDir, // https://www.npmjs.com/package/resolve - customResolveOptions: { - basedir: config.rootDir - }, + customResolveOptions: { basedir: config.rootDir }, mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) })) From 72d2dcc5826b04401e8e4bdbe4f2b534633456a2 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 12 Nov 2020 19:18:33 +0100 Subject: [PATCH 099/227] add content playground --- packages/nitro/src/index.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index e473f98fa5..7cf6856ef7 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,4 +1,3 @@ -import hasha from 'hasha' import type { Module } from '@nuxt/types' import { build } from './build' import { getoptions } from './config' @@ -33,19 +32,25 @@ export default function slsModule () { // TODO: render:setupMiddleware hook // TODO: support m.prefix and m.route nuxt.hook('modules:done', () => { + const unsupported = [] for (let m of nuxt.options.serverMiddleware) { if (typeof m === 'string') { m = { handler: m } } - if (typeof m.handler !== 'string') { - console.warn('[Serverless] Unsupported serverMiddleware format:', m) - continue - } const route = m.path || m.route || '/' const handle = nuxt.resolver.resolvePath(m.handler || m.handle) - const id = '_' + hasha(handle).substr(0, 6) - options.serverMiddleware.push({ route, id, handle }) + + if (typeof handle !== 'string' || typeof route !== 'string') { + unsupported.push(m) + continue + } + + options.serverMiddleware.push({ route, handle }) + } + if (unsupported.length) { + console.warn('[serverless] Unsupported Server middleware used: ', unsupported) + console.info('Supported format is `{ path: string, handler: string }` and handler should export `(req, res) => {}`') } }) From af92c53dcdb7a70cd83eab084961f9f1de7505d4 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Thu, 12 Nov 2020 19:20:55 +0100 Subject: [PATCH 100/227] feat: support serverMiddleware (#26) * feat: support node req, res claases in all envs * feat: support serverMiddleware --- packages/nitro/src/config.ts | 9 +++++++++ packages/nitro/src/index.ts | 25 +++++++++++++++++++++++-- packages/nitro/src/rollup/config.ts | 18 +++++++++++++++--- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 72343bddd3..70533398aa 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -12,6 +12,11 @@ export interface Nuxt extends Hookable{ options: NuxtOptions } +export interface ServerMiddleware { + route: string + handle: string +} + export interface SLSOptions { hooks: configHooksT nuxtHooks: configHooksT @@ -39,6 +44,8 @@ export interface SLSOptions { slsDir: string targetDir: string + serverMiddleware: ServerMiddleware[], + static: string[] generateIgnore: string[] } @@ -76,6 +83,8 @@ export function getoptions (nuxt: SLSNuxt): SLSOptions { slsDir: '{{ rootDir }}/.nuxt/serverless', targetDir: '{{ slsDir }}/{{ target }}', + serverMiddleware: [], + static: [], generateIgnore: [] } diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 6a4680561f..e473f98fa5 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,3 +1,4 @@ +import hasha from 'hasha' import type { Module } from '@nuxt/types' import { build } from './build' import { getoptions } from './config' @@ -12,12 +13,13 @@ export default function slsModule () { // Config const options = getoptions(nuxt) + // Tune webpack config if (options.minify !== false) { nuxt.options.build._minifyServer = true } - nuxt.options.build.standalone = true + // Tune generator nuxt.options.generate.crawler = false if (Array.isArray(nuxt.options.generate.routes)) { nuxt.options.generate.routes = Array.from(new Set([ @@ -25,9 +27,28 @@ export default function slsModule () { ...options.static ])) } - nuxt.options.generate.dir = options.publicDir + // serverMiddleware + // TODO: render:setupMiddleware hook + // TODO: support m.prefix and m.route + nuxt.hook('modules:done', () => { + for (let m of nuxt.options.serverMiddleware) { + if (typeof m === 'string') { + m = { handler: m } + } + if (typeof m.handler !== 'string') { + console.warn('[Serverless] Unsupported serverMiddleware format:', m) + continue + } + + const route = m.path || m.route || '/' + const handle = nuxt.resolver.resolvePath(m.handler || m.handle) + const id = '_' + hasha(handle).substr(0, 6) + options.serverMiddleware.push({ route, id, handle }) + } + }) + if (options.nuxtHooks) { nuxt.addHooks(options.nuxtHooks) } diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index eadcfe8f85..e79aeeb9da 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -7,8 +7,10 @@ import nodeResolve from '@rollup/plugin-node-resolve' import alias from '@rollup/plugin-alias' import json from '@rollup/plugin-json' import replace from '@rollup/plugin-replace' +import virtual from '@rollup/plugin-virtual' import analyze from 'rollup-plugin-analyzer' +import hasha from 'hasha' import { SLSOptions } from '../config' import { resolvePath } from '../utils' import dynamicRequire from './dynamic-require' @@ -97,6 +99,18 @@ export const getRollupConfig = (config: SLSOptions) => { } })) + // Provide serverMiddleware + const getImportId = p => '_' + hasha(p).substr(0, 6) + options.plugins.push(virtual({ + '~serverMiddleware': ` + ${config.serverMiddleware.map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} + + export default [ + ${config.serverMiddleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)} }`).join(',\n')} + ]; + ` + })) + // https://github.com/rollup/plugins/tree/master/packages/alias const renderer = config.renderer || 'vue2' options.plugins.push(alias({ @@ -116,9 +130,7 @@ export const getRollupConfig = (config: SLSOptions) => { preferBuiltins: true, rootDir: config.rootDir, // https://www.npmjs.com/package/resolve - customResolveOptions: { - basedir: config.rootDir - }, + customResolveOptions: { basedir: config.rootDir }, mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) })) From 5fbffb2e26eefbf19d88e086394a941a871ca4eb Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 12 Nov 2020 19:22:20 +0100 Subject: [PATCH 101/227] fix lint error --- packages/nitro/src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index e473f98fa5..7062eaef5a 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -44,8 +44,7 @@ export default function slsModule () { const route = m.path || m.route || '/' const handle = nuxt.resolver.resolvePath(m.handler || m.handle) - const id = '_' + hasha(handle).substr(0, 6) - options.serverMiddleware.push({ route, id, handle }) + options.serverMiddleware.push({ route, handle }) } }) From b3850facf316a850c6bf59b1816bedabc36dd1bc Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 12 Nov 2020 19:22:37 +0100 Subject: [PATCH 102/227] chore: fix lint error --- packages/nitro/src/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 7062eaef5a..da143f39c2 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,4 +1,3 @@ -import hasha from 'hasha' import type { Module } from '@nuxt/types' import { build } from './build' import { getoptions } from './config' From 6ff7c7e02eff6c0b82712c7f7263b06eaae7f9a4 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 14:18:07 +0100 Subject: [PATCH 103/227] feat: improve mocks --- packages/nitro/src/rollup/config.ts | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index e79aeeb9da..58c3ae4b4a 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -18,7 +18,7 @@ import dynamicRequire from './dynamic-require' export type RollupConfig = InputOptions & { output: OutputOptions } export const getRollupConfig = (config: SLSOptions) => { - const mocks = [ + const genericMocks = [ // @nuxt/devalue 'consola', // vue2 @@ -46,8 +46,21 @@ export const getRollupConfig = (config: SLSOptions) => { const external = [] + const aliases: {[key: string]: string} = {} + if (config.node === false) { - mocks.push(...Module.builtinModules) + // Generic mocks + Object.assign(aliases, [...genericMocks, ...Module.builtinModules].reduce((p, c) => ({ ...p, [c]: '~mock' }), {})) + + // Custom + aliases.depd = '~runtime/mocks/depd' + aliases.http = '~runtime/mocks/http' + + // Builtin (browserify) + aliases.buffer = require.resolve('buffer/index.js') + aliases.util = require.resolve('util/util.js') + aliases.events = require.resolve('events/events.js') + aliases.inherits = require.resolve('inherits/inherits_browser.js') } else { external.push(...Module.builtinModules) } @@ -118,9 +131,9 @@ export const getRollupConfig = (config: SLSOptions) => { '~runtime': config.runtimeDir, '~renderer': require.resolve(resolve(config.runtimeDir, 'ssr', renderer)), '~build': config.buildDir, - '~mock': require.resolve(resolve(config.runtimeDir, 'utils/mock')), - ...mocks.reduce((p, c) => ({ ...p, [c]: '~mock' }), {}), - ...providedDeps.reduce((p, c) => ({ ...p, [c]: require.resolve(c) }), {}) + '~mock': require.resolve(resolve(config.runtimeDir, 'mocks/generic')), + ...providedDeps.reduce((p, c) => ({ ...p, [c]: require.resolve(c) }), {}), + ...aliases } })) From 2ad4a81362e23e34b6a249f9c80edf92ac4a3d9c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 15:52:02 +0100 Subject: [PATCH 104/227] feat: mock mime packages and fix v1 compat --- packages/nitro/src/rollup/config.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 58c3ae4b4a..fef9c40a52 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -55,6 +55,9 @@ export const getRollupConfig = (config: SLSOptions) => { // Custom aliases.depd = '~runtime/mocks/depd' aliases.http = '~runtime/mocks/http' + aliases['mime-db'] = '~runtime/mocks/mime-db' + aliases['mime/lite'] = require.resolve('mime/lite') + aliases.mime = '~runtime/mocks/mime' // Builtin (browserify) aliases.buffer = require.resolve('buffer/index.js') From 4d4ae7a115f0666c645bde521d5983120a029ae3 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 17:13:18 +0100 Subject: [PATCH 105/227] chore: add prefix to rollup errors --- packages/nitro/src/build.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index e592a61434..c689411f83 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -32,7 +32,10 @@ export async function build (options: SLSOptions) { options.rollupConfig = getRollupConfig(options) await hooks.callHook('rollup:before', options) - const build = await rollup(options.rollupConfig) + const build = await rollup(options.rollupConfig).catch((error) => { + error.message = '[serverless] Rollup Error: ' + error.message + throw error + }) const { output } = await build.write(options.rollupConfig.output as OutputOptions) const size = prettyBytes(output[0].code.length) From 2384b8269ed4a133670a2c2575bad1d7d75788a8 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 17:14:17 +0100 Subject: [PATCH 106/227] feat: improve mocking --- packages/nitro/src/rollup/config.ts | 83 +++++++++++++++++------------ 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index fef9c40a52..9251f1ce32 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -8,6 +8,7 @@ import alias from '@rollup/plugin-alias' import json from '@rollup/plugin-json' import replace from '@rollup/plugin-replace' import virtual from '@rollup/plugin-virtual' +import inject from '@rollup/plugin-inject' import analyze from 'rollup-plugin-analyzer' import hasha from 'hasha' @@ -15,55 +16,67 @@ import { SLSOptions } from '../config' import { resolvePath } from '../utils' import dynamicRequire from './dynamic-require' +const mapArrToVal = (val, arr) => arr.reduce((p, c) => ({ ...p, [c]: val })) + export type RollupConfig = InputOptions & { output: OutputOptions } export const getRollupConfig = (config: SLSOptions) => { - const genericMocks = [ - // @nuxt/devalue - 'consola', - // vue2 - 'encoding', - 'stream', - 'he', - 'resolve', - 'source-map', - 'lodash.template', - 'serialize-javascript', - // vue3 - '@babel/parser', - '@vue/compiler-core', - '@vue/compiler-dom', - '@vue/compiler-ssr' - ] - const providedDeps = [ '@nuxt/devalue', 'vue-bundle-renderer', '@cloudflare/kv-asset-handler' ] - const extensions = ['.ts', '.mjs', '.js', '.json', '.node'] + const extensions: string[] = ['.ts', '.mjs', '.js', '.json', '.node'] - const external = [] + const external: string[] = [] + + const injects:{ [key: string]: string| string[] } = {} const aliases: {[key: string]: string} = {} if (config.node === false) { - // Generic mocks - Object.assign(aliases, [...genericMocks, ...Module.builtinModules].reduce((p, c) => ({ ...p, [c]: '~mock' }), {})) + // Globals + injects.Buffer = ['buffer', 'Buffer'] - // Custom - aliases.depd = '~runtime/mocks/depd' - aliases.http = '~runtime/mocks/http' - aliases['mime-db'] = '~runtime/mocks/mime-db' - aliases['mime/lite'] = require.resolve('mime/lite') - aliases.mime = '~runtime/mocks/mime' + // Aliases + Object.assign(aliases, { + ...mapArrToVal('~mocks/generic', [ + // @nuxt/devalue + 'consola', + // vue2 + 'encoding', + 'stream', + 'he', + 'resolve', + 'source-map', + 'lodash.template', + 'serialize-javascript', + // vue3 + '@babel/parser', + '@vue/compiler-core', + '@vue/compiler-dom', + '@vue/compiler-ssr' + ]), - // Builtin (browserify) - aliases.buffer = require.resolve('buffer/index.js') - aliases.util = require.resolve('util/util.js') - aliases.events = require.resolve('events/events.js') - aliases.inherits = require.resolve('inherits/inherits_browser.js') + // Node + ...mapArrToVal('~mocks/generic', Module.builtinModules), + http: '~mocks/node/http', + fs: '~mocks/node/fs', + buffer: require.resolve('buffer/index.js'), + util: require.resolve('util/util.js'), + events: require.resolve('events/events.js'), + inherits: require.resolve('inherits/inherits_browser.js'), + + // Custom + depd: '~mocks/custom/depd', + etag: '~mocks/generic/noop', + + // Mime + 'mime-db': '~mocks/custom/mime-db', + 'mime/lite': require.resolve('mime/lite'), + mime: '~mocks/custom/mime' + }) } else { external.push(...Module.builtinModules) } @@ -132,6 +145,7 @@ export const getRollupConfig = (config: SLSOptions) => { options.plugins.push(alias({ entries: { '~runtime': config.runtimeDir, + '~mocks': resolve(config.runtimeDir, 'mocks'), '~renderer': require.resolve(resolve(config.runtimeDir, 'ssr', renderer)), '~build': config.buildDir, '~mock': require.resolve(resolve(config.runtimeDir, 'mocks/generic')), @@ -155,6 +169,9 @@ export const getRollupConfig = (config: SLSOptions) => { extensions: extensions.filter(ext => ext !== '.json') })) + // https://github.com/rollup/plugins/tree/master/packages/inject + options.plugins.push(inject(injects)) + // https://github.com/rollup/plugins/tree/master/packages/json options.plugins.push(json()) From b65cd7862a829df4de6cc356037499765683b42f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 17:18:27 +0100 Subject: [PATCH 107/227] fix: always mock generic dependencies also inject after json --- packages/nitro/src/rollup/config.ts | 44 ++++++++++++++--------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 9251f1ce32..b9f6b0a9d9 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -33,7 +33,25 @@ export const getRollupConfig = (config: SLSOptions) => { const injects:{ [key: string]: string| string[] } = {} - const aliases: {[key: string]: string} = {} + const aliases: { [key: string]: string } = {} + + Object.assign(aliases, mapArrToVal('~mocks/generic', [ + // @nuxt/devalue + 'consola', + // vue2 + 'encoding', + 'stream', + 'he', + 'resolve', + 'source-map', + 'lodash.template', + 'serialize-javascript', + // vue3 + '@babel/parser', + '@vue/compiler-core', + '@vue/compiler-dom', + '@vue/compiler-ssr' + ])) if (config.node === false) { // Globals @@ -41,24 +59,6 @@ export const getRollupConfig = (config: SLSOptions) => { // Aliases Object.assign(aliases, { - ...mapArrToVal('~mocks/generic', [ - // @nuxt/devalue - 'consola', - // vue2 - 'encoding', - 'stream', - 'he', - 'resolve', - 'source-map', - 'lodash.template', - 'serialize-javascript', - // vue3 - '@babel/parser', - '@vue/compiler-core', - '@vue/compiler-dom', - '@vue/compiler-ssr' - ]), - // Node ...mapArrToVal('~mocks/generic', Module.builtinModules), http: '~mocks/node/http', @@ -169,12 +169,12 @@ export const getRollupConfig = (config: SLSOptions) => { extensions: extensions.filter(ext => ext !== '.json') })) - // https://github.com/rollup/plugins/tree/master/packages/inject - options.plugins.push(inject(injects)) - // https://github.com/rollup/plugins/tree/master/packages/json options.plugins.push(json()) + // https://github.com/rollup/plugins/tree/master/packages/inject + options.plugins.push(inject(injects)) + if (config.analyze) { // https://github.com/doesdev/rollup-plugin-analyzer options.plugins.push(analyze()) From eaf4603d9ce804d482d67ce7165f09e17f2cb689 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 18:13:51 +0100 Subject: [PATCH 108/227] fix(worker): wrap polyfill to iife --- packages/nitro/src/targets/worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index 76806a186e..129bce060a 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -8,7 +8,7 @@ const module = { exports }; const process = { env: {} }; const global = { process }; const window = global; -const o=Date.now(),t=()=>Date.now()-o;process.hrtime=o=>{const e=Math.floor(.001*(Date.now()-t())),n=.001*t();let a=Math.floor(n)+e,r=Math.floor(n%1*1e9);return o&&(a-=o[0],r-=o[1],r<0&&(a--,r+=1e9)),[a,r]}; +(function(){const o=Date.now(),t=()=>Date.now()-o;process.hrtime=o=>{const e=Math.floor(.001*(Date.now()-t())),n=.001*t();let a=Math.floor(n)+e,r=Math.floor(n%1*1e9);return o&&(a-=o[0],r-=o[1],r<0&&(a--,r+=1e9)),[a,r]};})(); ` export const worker: SLSTarget = { From 989f6811c2d20255cf568265e9889604f8baa50d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 18:45:03 +0100 Subject: [PATCH 109/227] feat: better process polyfill --- packages/nitro/src/rollup/config.ts | 7 +++++-- packages/nitro/src/targets/worker.ts | 5 ++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index b9f6b0a9d9..92aaff77ce 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -56,6 +56,7 @@ export const getRollupConfig = (config: SLSOptions) => { if (config.node === false) { // Globals injects.Buffer = ['buffer', 'Buffer'] + injects.process = '~mocks/node/process' // Aliases Object.assign(aliases, { @@ -63,6 +64,8 @@ export const getRollupConfig = (config: SLSOptions) => { ...mapArrToVal('~mocks/generic', Module.builtinModules), http: '~mocks/node/http', fs: '~mocks/node/fs', + process: '~mocks/node/process', + 'node-process': require.resolve('process/browser.js'), buffer: require.resolve('buffer/index.js'), util: require.resolve('util/util.js'), events: require.resolve('events/events.js'), @@ -97,9 +100,9 @@ export const getRollupConfig = (config: SLSOptions) => { } if (config.logStartup) { - options.output.intro += 'global._startTime = process.hrtime();' + options.output.intro += 'global._startTime = global.process.hrtime();' // eslint-disable-next-line no-template-curly-in-string - options.output.outro += 'global._endTime = process.hrtime(global._startTime); global._coldstart = ((global._endTime[0] * 1e9) + global._endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms`);' + options.output.outro += 'global._endTime = global.process.hrtime(global._startTime); global._coldstart = ((global._endTime[0] * 1e9) + global._endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms`);' } // https://github.com/rollup/plugins/tree/master/packages/replace diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index 129bce060a..687d4a25e8 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -5,10 +5,9 @@ import { SLSTarget } from '../config' const polyfill = ` const exports = {}; const module = { exports }; -const process = { env: {} }; -const global = { process }; +const global = { process: {} }; const window = global; -(function(){const o=Date.now(),t=()=>Date.now()-o;process.hrtime=o=>{const e=Math.floor(.001*(Date.now()-t())),n=.001*t();let a=Math.floor(n)+e,r=Math.floor(n%1*1e9);return o&&(a-=o[0],r-=o[1],r<0&&(a--,r+=1e9)),[a,r]};})(); +(function(){const o=Date.now(),t=()=>Date.now()-o;global.process.hrtime=o=>{const e=Math.floor(.001*(Date.now()-t())),n=.001*t();let a=Math.floor(n)+e,r=Math.floor(n%1*1e9);return o&&(a-=o[0],r-=o[1],r<0&&(a--,r+=1e9)),[a,r]};})(); ` export const worker: SLSTarget = { From e8f52bd383d173156d831afd92703931be6dfa7c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 19:05:45 +0100 Subject: [PATCH 110/227] fix: use same global to inject process.hrtime --- packages/nitro/src/targets/worker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index 687d4a25e8..f0dd931831 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -5,8 +5,8 @@ import { SLSTarget } from '../config' const polyfill = ` const exports = {}; const module = { exports }; -const global = { process: {} }; -const window = global; +const global = typeof globalThis !== 'undefined' ? globalThis : "undefined" !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; +global.process = global.process || {}; (function(){const o=Date.now(),t=()=>Date.now()-o;global.process.hrtime=o=>{const e=Math.floor(.001*(Date.now()-t())),n=.001*t();let a=Math.floor(n)+e,r=Math.floor(n%1*1e9);return o&&(a-=o[0],r-=o[1],r<0&&(a--,r+=1e9)),[a,r]};})(); ` From c8f495752063a19c11d624012897a5079a1571e7 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 13 Nov 2020 19:29:47 +0100 Subject: [PATCH 111/227] fix: fix mocks and disable buffer since is unnecessary --- packages/nitro/src/rollup/config.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 92aaff77ce..d8df5a441b 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -16,7 +16,7 @@ import { SLSOptions } from '../config' import { resolvePath } from '../utils' import dynamicRequire from './dynamic-require' -const mapArrToVal = (val, arr) => arr.reduce((p, c) => ({ ...p, [c]: val })) +const mapArrToVal = (val, arr) => arr.reduce((p, c) => ({ ...p, [c]: val }), {}) export type RollupConfig = InputOptions & { output: OutputOptions } @@ -55,7 +55,7 @@ export const getRollupConfig = (config: SLSOptions) => { if (config.node === false) { // Globals - injects.Buffer = ['buffer', 'Buffer'] + // injects.Buffer = ['buffer', 'Buffer'] <-- TODO: Make it opt-in injects.process = '~mocks/node/process' // Aliases @@ -66,7 +66,7 @@ export const getRollupConfig = (config: SLSOptions) => { fs: '~mocks/node/fs', process: '~mocks/node/process', 'node-process': require.resolve('process/browser.js'), - buffer: require.resolve('buffer/index.js'), + // buffer: require.resolve('buffer/index.js'), util: require.resolve('util/util.js'), events: require.resolve('events/events.js'), inherits: require.resolve('inherits/inherits_browser.js'), @@ -75,6 +75,12 @@ export const getRollupConfig = (config: SLSOptions) => { depd: '~mocks/custom/depd', etag: '~mocks/generic/noop', + // Express + ...mapArrToVal('~mocks/generic', [ + 'serve-static', + 'iconv-lite' + ]), + // Mime 'mime-db': '~mocks/custom/mime-db', 'mime/lite': require.resolve('mime/lite'), From 9e638e96fab064324c29f1c0b4968e6cbabf176b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 01:03:26 +0100 Subject: [PATCH 112/227] feat: support universalFetch during generate --- packages/nitro/src/build.ts | 8 ++++---- packages/nitro/src/config.ts | 39 +++++++++++++++--------------------- packages/nitro/src/index.ts | 13 +++++++++++- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index c689411f83..b9fa3f9599 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -26,10 +26,6 @@ export async function build (options: SLSOptions) { await hooks.callHook('template:document', htmlTemplate) await writeFile(htmlTemplate.dst, htmlTemplate.compiled) - if (options.targetDir.startsWith(options.slsDir)) { - emptyDir(options.slsDir) - } - options.rollupConfig = getRollupConfig(options) await hooks.callHook('rollup:before', options) const build = await rollup(options.rollupConfig).catch((error) => { @@ -45,4 +41,8 @@ export async function build (options: SLSOptions) { ) await hooks.callHook('done', options) + + return { + entry: options.rollupConfig.output.file + } } diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 70533398aa..ed1a44b4d9 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -31,7 +31,7 @@ export interface SLSOptions { entry: UnresolvedPath outName: string - node: false + node: false | true target: string minify: boolean rollupConfig?: any @@ -57,23 +57,16 @@ export interface SLSConfig extends Omit, 'targetDir'> { export type SLSTargetFn = (config: SLSConfig) => SLSConfig export type SLSTarget = SLSConfig | SLSTargetFn -interface SLSNuxt extends Nuxt { - options: Nuxt['options'] & { - generate: Nuxt['options']['generate'] & { - staticAssets: string[] - } - } -} - -export function getoptions (nuxt: SLSNuxt): SLSOptions { +export function getoptions (nuxtOptions: Nuxt['options'], serverless: SLSConfig): SLSOptions { const defaults: SLSConfig = { - rootDir: nuxt.options.rootDir, - buildDir: nuxt.options.buildDir, - publicDir: nuxt.options.generate.dir, - routerBase: nuxt.options.router.base, - publicPath: nuxt.options.build.publicPath, - fullStatic: nuxt.options.target === 'static' && !nuxt.options._legacyGenerate, - staticAssets: nuxt.options.generate.staticAssets, + rootDir: nuxtOptions.rootDir, + buildDir: nuxtOptions.buildDir, + publicDir: nuxtOptions.generate.dir, + routerBase: nuxtOptions.router.base, + publicPath: nuxtOptions.build.publicPath, + fullStatic: nuxtOptions.target === 'static' && !nuxtOptions._legacyGenerate, + // @ts-ignore + staticAssets: nuxtOptions.generate.staticAssets, outName: '_nuxt.js', logStartup: true, @@ -83,23 +76,23 @@ export function getoptions (nuxt: SLSNuxt): SLSOptions { slsDir: '{{ rootDir }}/.nuxt/serverless', targetDir: '{{ slsDir }}/{{ target }}', - serverMiddleware: [], + serverMiddleware: serverless.serverMiddleware || [], static: [], generateIgnore: [] } - const target = process.env.NUXT_SLS_TARGET || (nuxt.options.serverless || {}).target || detectTarget() - let targetDefaults = TARGETS[target] || tryImport(nuxt.options.rootDir, target) + const target = serverless.target || process.env.NUXT_SLS_TARGET || detectTarget() + let targetDefaults = TARGETS[target] || tryImport(nuxtOptions.rootDir, target) if (!targetDefaults) { throw new Error('Cannot resolve target: ' + target) } targetDefaults = targetDefaults.default || targetDefaults const _defaults = defu(defaults, { target }) - const _targetInput = defu(nuxt.options.serverless, _defaults) - const _target = extendTarget(nuxt.options.serverless, targetDefaults)(_targetInput) - const options: SLSOptions = defu(nuxt.options.serverless, _target, _defaults) + const _targetInput = defu(nuxtOptions.serverless, _defaults) + const _target = extendTarget(nuxtOptions.serverless, targetDefaults)(_targetInput) + const options: SLSOptions = defu(nuxtOptions.serverless, _target, _defaults) options.slsDir = resolvePath(options, options.slsDir) options.targetDir = resolvePath(options, options.targetDir) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 7cf6856ef7..f5eff85471 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -10,7 +10,7 @@ export default function slsModule () { } // Config - const options = getoptions(nuxt) + const options = getoptions(nuxt.options, nuxt.options.serverless || {}) // Tune webpack config if (options.minify !== false) { @@ -71,5 +71,16 @@ export default function slsModule () { } }) + nuxt.hook('generate:before', async () => { + const { entry } = await build(getoptions(nuxt.options, { + target: 'node', + serverMiddleware: options.serverMiddleware, + node: true, + minify: false, + analyze: false + })) + require(entry) + }) + nuxt.hook('generate:done', () => build(options)) } From a5e70eb4b0bc1442c127ab5fcd7034c3ca91aa3c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 01:11:26 +0100 Subject: [PATCH 113/227] fix: use native fetch when node is disabled --- packages/nitro/src/rollup/config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index d8df5a441b..b67b760b8b 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -72,6 +72,7 @@ export const getRollupConfig = (config: SLSOptions) => { inherits: require.resolve('inherits/inherits_browser.js'), // Custom + 'node-fetch': '~mocks/custom/node-fetch', depd: '~mocks/custom/depd', etag: '~mocks/generic/noop', From 3d2c019a6ac8c608d171ba1e43ac5bace11345be Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 01:23:22 +0100 Subject: [PATCH 114/227] tweak target defaults to disable minify and inlining for non workers --- packages/nitro/src/config.ts | 1 + packages/nitro/src/index.ts | 5 +---- packages/nitro/src/targets/lambda.ts | 1 + packages/nitro/src/targets/node.ts | 1 + packages/nitro/src/targets/vercel.ts | 1 - packages/nitro/src/targets/worker.ts | 1 + 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index ed1a44b4d9..b9c047afa4 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -71,6 +71,7 @@ export function getoptions (nuxtOptions: Nuxt['options'], serverless: SLSConfig) outName: '_nuxt.js', logStartup: true, inlineChunks: true, + minify: false, runtimeDir: resolve(__dirname, '../runtime'), slsDir: '{{ rootDir }}/.nuxt/serverless', diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index f5eff85471..0e0c7dc49d 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -74,10 +74,7 @@ export default function slsModule () { nuxt.hook('generate:before', async () => { const { entry } = await build(getoptions(nuxt.options, { target: 'node', - serverMiddleware: options.serverMiddleware, - node: true, - minify: false, - analyze: false + serverMiddleware: options.serverMiddleware })) require(entry) }) diff --git a/packages/nitro/src/targets/lambda.ts b/packages/nitro/src/targets/lambda.ts index 44a18ce0fd..d151019663 100644 --- a/packages/nitro/src/targets/lambda.ts +++ b/packages/nitro/src/targets/lambda.ts @@ -6,6 +6,7 @@ import { SLSTarget } from '../config' export const lambda: SLSTarget = { entry: '{{ runtimeDir }}/targets/lambda', outName: '_nuxt.js', + inlineChunks: false, hooks: { 'done' ({ rollupConfig }) { const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') diff --git a/packages/nitro/src/targets/node.ts b/packages/nitro/src/targets/node.ts index 88814fddcd..f1a009917e 100644 --- a/packages/nitro/src/targets/node.ts +++ b/packages/nitro/src/targets/node.ts @@ -5,6 +5,7 @@ import { SLSTarget } from '../config' export const node: SLSTarget = { entry: '{{ runtimeDir }}/targets/node', outName: 'index.js', + inlineChunks: false, hooks: { 'done' ({ rollupConfig }) { const entry = relative(process.cwd(), rollupConfig.output.file) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index fe5b21c05e..3a9360d2a1 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -7,7 +7,6 @@ export const vercel: SLSTarget = extendTarget(node, { targetDir: '{{ rootDir }}/.vercel_build_output', outName: 'functions/node/_nuxt/index.js', publicDir: '{{ targetDir }}/static', - inlineChunks: false, generateIgnore: [ 'vercel.json' ], diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index f0dd931831..6f2eaa5fc5 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -13,6 +13,7 @@ global.process = global.process || {}; export const worker: SLSTarget = { entry: null, // Abstract node: false, + minify: true, hooks: { 'rollup:before' ({ rollupConfig }) { rollupConfig.output.intro = polyfill + rollupConfig.output.intro From 04bb2fa9063b70f86bfa64daac359b841828c206 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 01:25:12 +0100 Subject: [PATCH 115/227] chore: fix lint error --- packages/nitro/src/build.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index b9fa3f9599..08a0293027 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -5,7 +5,7 @@ import Hookable from 'hookable' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' import chalk from 'chalk' -import { emptyDir, readFile } from 'fs-extra' +import { readFile } from 'fs-extra' import { getRollupConfig } from './rollup/config' import { hl, prettyPath, serializeTemplate, writeFile } from './utils' import { SLSOptions } from './config' From 536155825b6410c33d2a848cd8931d02ea6079cb Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 01:49:37 +0100 Subject: [PATCH 116/227] fix: add hack for encoding --- packages/nitro/src/rollup/config.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index b67b760b8b..c131d7a440 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -138,6 +138,15 @@ export const getRollupConfig = (config: SLSOptions) => { } })) + // https://github.com/rollup/plugins/tree/master/packages/replace + // TODO: better fix for node-fetch issue + options.plugins.push(replace({ + delimiters: ['', ''], + values: { + 'require(\'encoding\')': '{}' + } + })) + // Provide serverMiddleware const getImportId = p => '_' + hasha(p).substr(0, 6) options.plugins.push(virtual({ From f7378db9e0ef72c860879c04459a0fd92d846a66 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 02:43:13 +0100 Subject: [PATCH 117/227] feat: add hint to dynamic require for netlify --- packages/nitro/src/rollup/dynamic-require.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index 5ae140fd0d..36602e520d 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -12,7 +12,7 @@ interface Import { import: string } -const TMPL_INLINE = ({ imports }: { imports: Import[]}) => +const TMPL_ESM_INLINE = ({ imports }: { imports: Import[]}) => `${imports.map(i => `import ${i.name} from '${i.import.replace(/\\/g, '/')}'`).join('\n')} const dynamicChunks = { ${imports.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} @@ -22,10 +22,19 @@ export default function dynamicRequire(id) { return dynamicChunks[id]; };` -const TMPL_CJS = ({ chunksDir }) => `export default function dynamicRequire(id) { -return require('./${chunksDir}/' + id); +const TMPL_CJS_LAZY = ({ imports, chunksDir }) => + `const dynamicChunks = { +${imports.map(i => ` ['${i.id}']: () => require('./${chunksDir}/${i.id}')`).join(',\n')} +}; + +export default function dynamicRequire(id) { + return dynamicChunks[id]; };` +// const TMPL_CJS = ({ chunksDir }) => `export default function dynamicRequire(id) { +// return require('./${chunksDir}/' + id); +// };` + interface Options { dir: string globbyOptions: GlobbyOptions @@ -53,7 +62,7 @@ export default function dynamicRequire ({ dir, globbyOptions, outDir, chunksDir })) if (!outDir) { - return TMPL_INLINE({ imports }) + return TMPL_ESM_INLINE({ imports }) } // Write chunks @@ -63,7 +72,7 @@ export default function dynamicRequire ({ dir, globbyOptions, outDir, chunksDir await mkdirp(dirname(dst)) await copyFile(i.import, dst) })) - return TMPL_CJS({ chunksDir }) + return TMPL_CJS_LAZY({ chunksDir, imports }) } return null } From e3609b6d8a1e6a6274270e582e0422ff197a8785 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 02:44:33 +0100 Subject: [PATCH 118/227] fix: exec require before return --- packages/nitro/src/rollup/dynamic-require.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index 36602e520d..d33082f123 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -28,7 +28,7 @@ ${imports.map(i => ` ['${i.id}']: () => require('./${chunksDir}/${i.id}')`).join }; export default function dynamicRequire(id) { - return dynamicChunks[id]; + return dynamicChunks[id](); };` // const TMPL_CJS = ({ chunksDir }) => `export default function dynamicRequire(id) { From 1e34041e8d4d16c63735bdeb06e1e2ae22f0b5dc Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 14:05:09 +0100 Subject: [PATCH 119/227] feat: support dynamic chunks, lazy middleware and cjs target --- packages/nitro/src/build.ts | 15 +-- packages/nitro/src/config.ts | 5 + packages/nitro/src/index.ts | 14 ++- packages/nitro/src/rollup/config.ts | 126 +++++++++++-------- packages/nitro/src/rollup/dynamic-require.ts | 123 ++++++++++-------- packages/nitro/src/rollup/externals.ts | 24 ++++ packages/nitro/src/targets/browser.ts | 1 + packages/nitro/src/targets/cjs.ts | 10 ++ packages/nitro/src/targets/index.ts | 1 + packages/nitro/src/targets/lambda.ts | 10 +- packages/nitro/src/targets/node.ts | 13 +- packages/nitro/src/utils.ts | 23 +++- 12 files changed, 221 insertions(+), 144 deletions(-) create mode 100644 packages/nitro/src/rollup/externals.ts create mode 100644 packages/nitro/src/targets/cjs.ts diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 08a0293027..1f00c10969 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -5,24 +5,27 @@ import Hookable from 'hookable' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' import chalk from 'chalk' -import { readFile } from 'fs-extra' +import { readFile, emptyDir } from 'fs-extra' import { getRollupConfig } from './rollup/config' import { hl, prettyPath, serializeTemplate, writeFile } from './utils' import { SLSOptions } from './config' export async function build (options: SLSOptions) { - console.log('\n') consola.info(`Generating bundle for ${hl(options.target)}`) const hooks = new Hookable() hooks.addHooks(options.hooks) + if (options.cleanTargetDir) { + await emptyDir(options.targetDir) + } + // Compile html template const htmlSrc = resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`) const htmlTemplate = { src: htmlSrc, contents: '', dst: '', compiled: '' } htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.') htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8') - htmlTemplate.compiled = serializeTemplate(htmlTemplate.contents) + htmlTemplate.compiled = 'module.exports = ' + serializeTemplate(htmlTemplate.contents) await hooks.callHook('template:document', htmlTemplate) await writeFile(htmlTemplate.dst, htmlTemplate.compiled) @@ -36,13 +39,11 @@ export async function build (options: SLSOptions) { const { output } = await build.write(options.rollupConfig.output as OutputOptions) const size = prettyBytes(output[0].code.length) const zSize = prettyBytes(await gzipSize(output[0].code)) - consola.success('Generated', prettyPath((options.rollupConfig.output as any).file), - chalk.gray(`(Size: ${size} Gzip: ${zSize})`) - ) + consola.success('Generated bundle in', prettyPath(options.targetDir), chalk.gray(`(Size: ${size} Gzip: ${zSize})`)) await hooks.callHook('done', options) return { - entry: options.rollupConfig.output.file + entry: resolve(options.rollupConfig.output.dir, options.rollupConfig.output.entryFileNames) } } diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index b9c047afa4..6a2c05f7ab 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -15,6 +15,7 @@ export interface Nuxt extends Hookable{ export interface ServerMiddleware { route: string handle: string + lazy?: boolean } export interface SLSOptions { @@ -34,11 +35,13 @@ export interface SLSOptions { node: false | true target: string minify: boolean + externals: boolean rollupConfig?: any logStartup: boolean inlineChunks: boolean renderer: string analyze: boolean + cleanTargetDir: boolean runtimeDir: string slsDir: string @@ -72,6 +75,8 @@ export function getoptions (nuxtOptions: Nuxt['options'], serverless: SLSConfig) logStartup: true, inlineChunks: true, minify: false, + externals: false, + cleanTargetDir: true, runtimeDir: resolve(__dirname, '../runtime'), slsDir: '{{ rootDir }}/.nuxt/serverless', diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 0e0c7dc49d..19f20170df 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -13,9 +13,7 @@ export default function slsModule () { const options = getoptions(nuxt.options, nuxt.options.serverless || {}) // Tune webpack config - if (options.minify !== false) { - nuxt.options.build._minifyServer = true - } + nuxt.options.build._minifyServer = options.minify !== false nuxt.options.build.standalone = true // Tune generator @@ -46,7 +44,7 @@ export default function slsModule () { continue } - options.serverMiddleware.push({ route, handle }) + options.serverMiddleware.push({ ...m, route, handle }) } if (unsupported.length) { console.warn('[serverless] Unsupported Server middleware used: ', unsupported) @@ -72,12 +70,16 @@ export default function slsModule () { }) nuxt.hook('generate:before', async () => { + console.info('Building light version for `nuxt generate`') const { entry } = await build(getoptions(nuxt.options, { - target: 'node', + target: 'cjs', serverMiddleware: options.serverMiddleware })) + console.info('Loading lambda') require(entry) }) - nuxt.hook('generate:done', () => build(options)) + nuxt.hook('generate:done', async () => { + await build(options) + }) } diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index c131d7a440..5a2e41d41d 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -1,5 +1,5 @@ import Module from 'module' -import { basename, dirname, extname, resolve } from 'path' +import { join, resolve } from 'path' import { InputOptions, OutputOptions } from 'rollup' import { terser } from 'rollup-plugin-terser' import commonjs from '@rollup/plugin-commonjs' @@ -13,23 +13,18 @@ import analyze from 'rollup-plugin-analyzer' import hasha from 'hasha' import { SLSOptions } from '../config' -import { resolvePath } from '../utils' -import dynamicRequire from './dynamic-require' +import { resolvePath, MODULE_DIR } from '../utils' +import { dynamicRequire } from './dynamic-require' +import { externals } from './externals' const mapArrToVal = (val, arr) => arr.reduce((p, c) => ({ ...p, [c]: val }), {}) export type RollupConfig = InputOptions & { output: OutputOptions } -export const getRollupConfig = (config: SLSOptions) => { - const providedDeps = [ - '@nuxt/devalue', - 'vue-bundle-renderer', - '@cloudflare/kv-asset-handler' - ] - +export const getRollupConfig = (options: SLSOptions) => { const extensions: string[] = ['.ts', '.mjs', '.js', '.json', '.node'] - const external: string[] = [] + const external: InputOptions['external'] = [] const injects:{ [key: string]: string| string[] } = {} @@ -53,7 +48,10 @@ export const getRollupConfig = (config: SLSOptions) => { '@vue/compiler-ssr' ])) - if (config.node === false) { + // Uses eval + aliases.depd = '~mocks/custom/depd' + + if (options.node === false) { // Globals // injects.Buffer = ['buffer', 'Buffer'] <-- TODO: Make it opt-in injects.process = '~mocks/node/process' @@ -73,7 +71,6 @@ export const getRollupConfig = (config: SLSOptions) => { // Custom 'node-fetch': '~mocks/custom/node-fetch', - depd: '~mocks/custom/depd', etag: '~mocks/generic/noop', // Express @@ -91,13 +88,15 @@ export const getRollupConfig = (config: SLSOptions) => { external.push(...Module.builtinModules) } - const outFile = resolve(config.targetDir, config.outName) - - const options: RollupConfig = { - input: resolvePath(config, config.entry), + const rollupConfig: RollupConfig = { + input: resolvePath(options, options.entry), output: { - file: outFile, + dir: options.targetDir, + entryFileNames: options.outName, + chunkFileNames: 'chunks/_[name].js', + inlineDynamicImports: options.inlineChunks, format: 'cjs', + exports: 'auto', intro: '', outro: '', preferConst: true @@ -106,31 +105,32 @@ export const getRollupConfig = (config: SLSOptions) => { plugins: [] } - if (config.logStartup) { - options.output.intro += 'global._startTime = global.process.hrtime();' + if (options.logStartup) { + rollupConfig.output.intro += 'global._startTime = global.process.hrtime();' // eslint-disable-next-line no-template-curly-in-string - options.output.outro += 'global._endTime = global.process.hrtime(global._startTime); global._coldstart = ((global._endTime[0] * 1e9) + global._endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms`);' + rollupConfig.output.outro += 'global._endTime = global.process.hrtime(global._startTime); global._coldstart = ((global._endTime[0] * 1e9) + global._endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms (${typeof __filename !== "undefined" ? __filename.replace(process.cwd(), "") : ""})`);' } // https://github.com/rollup/plugins/tree/master/packages/replace - options.plugins.push(replace({ + rollupConfig.plugins.push(replace({ values: { 'process.env.NODE_ENV': '"production"', 'typeof window': '"undefined"', - 'process.env.ROUTER_BASE': JSON.stringify(config.routerBase), - 'process.env.PUBLIC_PATH': JSON.stringify(config.publicPath), - 'process.env.NUXT_STATIC_BASE': JSON.stringify(config.staticAssets.base), - 'process.env.NUXT_STATIC_VERSION': JSON.stringify(config.staticAssets.version), + 'process.env.ROUTER_BASE': JSON.stringify(options.routerBase), + 'process.env.PUBLIC_PATH': JSON.stringify(options.publicPath), + 'process.env.NUXT_STATIC_BASE': JSON.stringify(options.staticAssets.base), + 'process.env.NUXT_STATIC_VERSION': JSON.stringify(options.staticAssets.version), // @ts-ignore - 'process.env.NUXT_FULL_STATIC': config.fullStatic + 'process.env.NUXT_FULL_STATIC': options.fullStatic } })) // Dynamic Require Support - options.plugins.push(dynamicRequire({ - dir: resolve(config.buildDir, 'dist/server'), - outDir: (config.node === false || config.inlineChunks) ? undefined : dirname(outFile), - chunksDir: '_' + basename(outFile, extname(outFile)), + rollupConfig.plugins.push(dynamicRequire({ + dir: resolve(options.buildDir, 'dist/server'), + inline: options.node === false || options.inlineChunks, + outDir: join(options.targetDir, 'chunks'), + prefix: './', globbyOptions: { ignore: [ 'server.js' @@ -140,7 +140,7 @@ export const getRollupConfig = (config: SLSOptions) => { // https://github.com/rollup/plugins/tree/master/packages/replace // TODO: better fix for node-fetch issue - options.plugins.push(replace({ + rollupConfig.plugins.push(replace({ delimiters: ['', ''], values: { 'require(\'encoding\')': '{}' @@ -149,59 +149,77 @@ export const getRollupConfig = (config: SLSOptions) => { // Provide serverMiddleware const getImportId = p => '_' + hasha(p).substr(0, 6) - options.plugins.push(virtual({ + rollupConfig.plugins.push(virtual({ '~serverMiddleware': ` - ${config.serverMiddleware.map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} + ${options.serverMiddleware.filter(m => !m.lazy).map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} + + ${options.serverMiddleware.filter(m => m.lazy).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} export default [ - ${config.serverMiddleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)} }`).join(',\n')} + ${options.serverMiddleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || false} }`).join(',\n')} ]; ` })) // https://github.com/rollup/plugins/tree/master/packages/alias - const renderer = config.renderer || 'vue2' - options.plugins.push(alias({ + const renderer = options.renderer || 'vue2' + rollupConfig.plugins.push(alias({ entries: { - '~runtime': config.runtimeDir, - '~mocks': resolve(config.runtimeDir, 'mocks'), - '~renderer': require.resolve(resolve(config.runtimeDir, 'ssr', renderer)), - '~build': config.buildDir, - '~mock': require.resolve(resolve(config.runtimeDir, 'mocks/generic')), - ...providedDeps.reduce((p, c) => ({ ...p, [c]: require.resolve(c) }), {}), + '~runtime': options.runtimeDir, + '~mocks': resolve(options.runtimeDir, 'mocks'), + '~renderer': require.resolve(resolve(options.runtimeDir, 'ssr', renderer)), + '~build': options.buildDir, + '~mock': require.resolve(resolve(options.runtimeDir, 'mocks/generic')), ...aliases } })) + // External Plugin + if (options.externals) { + rollupConfig.plugins.push(externals({ + relativeTo: options.targetDir, + include: [ + options.runtimeDir, + ...options.serverMiddleware.map(m => m.handle) + ] + })) + } + // https://github.com/rollup/plugins/tree/master/packages/node-resolve - options.plugins.push(nodeResolve({ + rollupConfig.plugins.push(nodeResolve({ extensions, preferBuiltins: true, - rootDir: config.rootDir, + rootDir: options.rootDir, // https://www.npmjs.com/package/resolve - customResolveOptions: { basedir: config.rootDir }, + customResolveOptions: { + basedir: options.rootDir, + paths: [ + resolve(options.rootDir, 'node_modukes'), + resolve(MODULE_DIR, 'node_modules') + ] + }, mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) })) // https://github.com/rollup/plugins/tree/master/packages/commonjs - options.plugins.push(commonjs({ + rollupConfig.plugins.push(commonjs({ extensions: extensions.filter(ext => ext !== '.json') })) // https://github.com/rollup/plugins/tree/master/packages/json - options.plugins.push(json()) + rollupConfig.plugins.push(json()) // https://github.com/rollup/plugins/tree/master/packages/inject - options.plugins.push(inject(injects)) + rollupConfig.plugins.push(inject(injects)) - if (config.analyze) { + if (options.analyze) { // https://github.com/doesdev/rollup-plugin-analyzer - options.plugins.push(analyze()) + rollupConfig.plugins.push(analyze()) } - if (config.minify !== false) { - options.plugins.push(terser()) + if (options.minify !== false) { + rollupConfig.plugins.push(terser()) } - return options + return rollupConfig } diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index d33082f123..487d940baa 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -1,4 +1,4 @@ -import { basename, resolve, dirname } from 'path' +import { resolve, dirname } from 'path' import globby, { GlobbyOptions } from 'globby' import { copyFile, mkdirp } from 'fs-extra' @@ -6,43 +6,26 @@ const PLUGIN_NAME = 'dynamic-require' const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js` const DYNAMIC_REQUIRE_RE = /require\("\.\/" ?\+/g -interface Import { - name: string - id: string - import: string -} - -const TMPL_ESM_INLINE = ({ imports }: { imports: Import[]}) => - `${imports.map(i => `import ${i.name} from '${i.import.replace(/\\/g, '/')}'`).join('\n')} -const dynamicChunks = { - ${imports.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} -}; - -export default function dynamicRequire(id) { - return dynamicChunks[id]; -};` - -const TMPL_CJS_LAZY = ({ imports, chunksDir }) => - `const dynamicChunks = { -${imports.map(i => ` ['${i.id}']: () => require('./${chunksDir}/${i.id}')`).join(',\n')} -}; - -export default function dynamicRequire(id) { - return dynamicChunks[id](); -};` - -// const TMPL_CJS = ({ chunksDir }) => `export default function dynamicRequire(id) { -// return require('./${chunksDir}/' + id); -// };` - interface Options { dir: string + inline: boolean globbyOptions: GlobbyOptions outDir?: string - chunksDir?: string + prefix?: string } -export default function dynamicRequire ({ dir, globbyOptions, outDir, chunksDir }: Options) { +interface Chunk { + name: string + id: string + src: string +} + +interface TemplateContext { + chunks: Chunk[] + prefix: string +} + +export function dynamicRequire ({ dir, globbyOptions, inline, outDir, prefix = '' }: Options) { return { name: PLUGIN_NAME, transform (code: string, _id: string) { @@ -51,30 +34,60 @@ export default function dynamicRequire ({ dir, globbyOptions, outDir, chunksDir resolveId (id: string) { return id === HELPER_DYNAMIC ? id : null }, - async load (id: string) { - if (id === HELPER_DYNAMIC) { - const files = await globby('**/*.js', { cwd: dir, absolute: false, ...globbyOptions }) - - const imports = files.map(id => ({ - id, - import: resolve(dir, id), - name: '_' + id.replace(/[\\/.]/g, '_') - })) - - if (!outDir) { - return TMPL_ESM_INLINE({ imports }) - } - - // Write chunks - chunksDir = chunksDir || basename(dir) - await Promise.all(imports.map(async (i) => { - const dst = resolve(outDir, chunksDir, i.id) - await mkdirp(dirname(dst)) - await copyFile(i.import, dst) - })) - return TMPL_CJS_LAZY({ chunksDir, imports }) + async load (_id: string) { + if (_id !== HELPER_DYNAMIC) { + return null } - return null + + // Scan chunks + const files = await globby('**/*.js', { cwd: dir, absolute: false, ...globbyOptions }) + const chunks = files.map(id => ({ + id, + src: resolve(dir, id).replace(/\\/g, '/'), + out: prefix + id, + name: '_' + id.replace(/[\\/.]/g, '_') + })) + + // Inline mode + if (inline) { + return TMPL_ESM_INLINE({ chunks, prefix }) + } + + // Write chunks + await Promise.all(chunks.map(async (chunk) => { + const dst = resolve(outDir, prefix + chunk.id) + await mkdirp(dirname(dst)) + await copyFile(chunk.src, dst) + })) + + return TMPL_CJS_LAZY({ chunks, prefix }) } } } + +function TMPL_ESM_INLINE ({ chunks }: TemplateContext) { + return `${chunks.map(i => `import ${i.name} from '${i.src}'`).join('\n')} +const dynamicChunks = { + ${chunks.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} +}; + +export default function dynamicRequire(id) { + return dynamicChunks[id]; +};` +} + +function TMPL_CJS_LAZY ({ chunks, prefix }: TemplateContext) { + return `const dynamicChunks = { +${chunks.map(i => ` ['${i.id}']: () => require('${prefix}${i.id}')`).join(',\n')} +}; + +export default function dynamicRequire(id) { + return dynamicChunks[id](); +};` +} + +// function TMPL_CJS ({ prefix }: TemplateContext) { +// return `export default function dynamicRequire(id) { +// return require('${prefix}' + id); +// };` +// } diff --git a/packages/nitro/src/rollup/externals.ts b/packages/nitro/src/rollup/externals.ts new file mode 100644 index 0000000000..f0515d73a9 --- /dev/null +++ b/packages/nitro/src/rollup/externals.ts @@ -0,0 +1,24 @@ +import { isAbsolute, relative } from 'path' + +export function externals ({ include = [], relativeTo }) { + return { + name: 'externals', + resolveId (source) { + if ( + source[0] === '.' || // Compile relative imports + source[0] === '\x00' || // Skip helpers + source.includes('?') || // Skip helpers + include.find(i => source.startsWith(i)) + ) { return null } + + if (!isAbsolute(source)) { + source = require.resolve(source) + } + + return { + id: relative(relativeTo, source), + external: true + } + } + } +} diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts index 26baff5f78..deac5e57f2 100644 --- a/packages/nitro/src/targets/browser.ts +++ b/packages/nitro/src/targets/browser.ts @@ -18,6 +18,7 @@ if ('serviceWorker' in navigator) { entry: '{{ runtimeDir }}/targets/service-worker', targetDir: '{{ publicDir }}', outName: '_nuxt.js', + cleanTargetDir: false, nuxtHooks: { 'vue-renderer:ssr:templateParams' (params) { params.APP += script diff --git a/packages/nitro/src/targets/cjs.ts b/packages/nitro/src/targets/cjs.ts new file mode 100644 index 0000000000..4a6a8aaa00 --- /dev/null +++ b/packages/nitro/src/targets/cjs.ts @@ -0,0 +1,10 @@ +import { extendTarget } from '../utils' +import { SLSTarget } from '../config' +import { node } from './node' + +export const cjs: SLSTarget = extendTarget(node, { + entry: '{{ runtimeDir }}/targets/cjs', + minify: false, + externals: true, + inlineChunks: true +}) diff --git a/packages/nitro/src/targets/index.ts b/packages/nitro/src/targets/index.ts index d7d4eb3c83..cba2c91749 100644 --- a/packages/nitro/src/targets/index.ts +++ b/packages/nitro/src/targets/index.ts @@ -3,5 +3,6 @@ export * from './cloudflare' export * from './lambda' export * from './netlify' export * from './node' +export * from './cjs' export * from './vercel' export * from './worker' diff --git a/packages/nitro/src/targets/lambda.ts b/packages/nitro/src/targets/lambda.ts index d151019663..2c151980ed 100644 --- a/packages/nitro/src/targets/lambda.ts +++ b/packages/nitro/src/targets/lambda.ts @@ -1,16 +1,8 @@ -import { relative } from 'path' -import consola from 'consola' import { SLSTarget } from '../config' export const lambda: SLSTarget = { entry: '{{ runtimeDir }}/targets/lambda', outName: '_nuxt.js', - inlineChunks: false, - hooks: { - 'done' ({ rollupConfig }) { - const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '') - consola.info(`Ready to deploy lambda: \`${entry}\``) - } - } + inlineChunks: false } diff --git a/packages/nitro/src/targets/node.ts b/packages/nitro/src/targets/node.ts index f1a009917e..71025fd15a 100644 --- a/packages/nitro/src/targets/node.ts +++ b/packages/nitro/src/targets/node.ts @@ -1,18 +1,7 @@ -import { relative } from 'path' -import consola from 'consola' import { SLSTarget } from '../config' export const node: SLSTarget = { entry: '{{ runtimeDir }}/targets/node', outName: 'index.js', - inlineChunks: false, - hooks: { - 'done' ({ rollupConfig }) { - const entry = relative(process.cwd(), rollupConfig.output.file) - .replace(/\.js$/, '') - .replace(/\/index$/, '') - consola.info(`Ready to deploy node entrypoint: \`${entry}\``) - consola.info(`You can try using \`node ${entry} [path]\``) - } - } + inlineChunks: false } diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils.ts index d228a8047c..83246a8ee0 100644 --- a/packages/nitro/src/utils.ts +++ b/packages/nitro/src/utils.ts @@ -6,6 +6,8 @@ import Hookable from 'hookable' import consola from 'consola' import { SLSOptions, UnresolvedPath, SLSTarget, SLSTargetFn, SLSConfig } from './config' +export const MODULE_DIR = resolve(__dirname, '..') + export function hl (str: string) { return '`' + str + '`' } @@ -21,7 +23,7 @@ export function compileTemplate (contents: string) { export function serializeTemplate (contents: string) { // eslint-disable-next-line no-template-curly-in-string - return `export default (params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` + return `(params) => \`${contents.replace(/{{ (\w+) }}/g, '${params.$1}')}\`` } export function jitiImport (dir: string, path: string) { @@ -80,3 +82,22 @@ export function extendTarget (base: SLSTarget, target: SLSTarget): SLSTargetFn { }, target, base) } } + +const _getDependenciesMode = { + dev: ['devDependencies'], + prod: ['dependencies'], + all: ['devDependencies', 'dependencies'] +} +export function getDependencies (dir: string, mode: keyof typeof _getDependenciesMode = 'all') { + const fields = _getDependenciesMode[mode] + const pkg = require(resolve(dir, 'package.json')) + const dependencies = [] + for (const field of fields) { + if (pkg[field]) { + for (const name in pkg[field]) { + dependencies.push(name) + } + } + } + return dependencies +} From e16aee43ba871de01579a294031508774e5cd6ce Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 14:33:31 +0100 Subject: [PATCH 120/227] fix: resolve chunksDirName based on outNames dirname (vercel) --- packages/nitro/src/rollup/config.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 5a2e41d41d..817bd82a96 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -1,5 +1,5 @@ import Module from 'module' -import { join, resolve } from 'path' +import { dirname, join, resolve } from 'path' import { InputOptions, OutputOptions } from 'rollup' import { terser } from 'rollup-plugin-terser' import commonjs from '@rollup/plugin-commonjs' @@ -88,12 +88,14 @@ export const getRollupConfig = (options: SLSOptions) => { external.push(...Module.builtinModules) } + const chunksDirName = join(dirname(options.outName), 'chunks') + const rollupConfig: RollupConfig = { input: resolvePath(options, options.entry), output: { dir: options.targetDir, entryFileNames: options.outName, - chunkFileNames: 'chunks/_[name].js', + chunkFileNames: join(chunksDirName, '_[name].js'), inlineDynamicImports: options.inlineChunks, format: 'cjs', exports: 'auto', @@ -129,7 +131,7 @@ export const getRollupConfig = (options: SLSOptions) => { rollupConfig.plugins.push(dynamicRequire({ dir: resolve(options.buildDir, 'dist/server'), inline: options.node === false || options.inlineChunks, - outDir: join(options.targetDir, 'chunks'), + outDir: join(options.targetDir, chunksDirName), prefix: './', globbyOptions: { ignore: [ From 609796a9449fec2ac54940ce26d95d2841909ef7 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 18:51:56 +0100 Subject: [PATCH 121/227] feat: natively parse and import async webpack chunks --- packages/nitro/src/rollup/config.ts | 4 +- packages/nitro/src/rollup/dynamic-require.ts | 81 +++++++++++++------- 2 files changed, 54 insertions(+), 31 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 817bd82a96..0b1b50da21 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -95,7 +95,7 @@ export const getRollupConfig = (options: SLSOptions) => { output: { dir: options.targetDir, entryFileNames: options.outName, - chunkFileNames: join(chunksDirName, '_[name].js'), + chunkFileNames: join(chunksDirName, '[name].js'), inlineDynamicImports: options.inlineChunks, format: 'cjs', exports: 'auto', @@ -131,8 +131,6 @@ export const getRollupConfig = (options: SLSOptions) => { rollupConfig.plugins.push(dynamicRequire({ dir: resolve(options.buildDir, 'dist/server'), inline: options.node === false || options.inlineChunks, - outDir: join(options.targetDir, chunksDirName), - prefix: './', globbyOptions: { ignore: [ 'server.js' diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index 487d940baa..8a2f42039c 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -1,6 +1,6 @@ -import { resolve, dirname } from 'path' +import { resolve } from 'path' import globby, { GlobbyOptions } from 'globby' -import { copyFile, mkdirp } from 'fs-extra' +import type { Plugin } from 'rollup' const PLUGIN_NAME = 'dynamic-require' const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js` @@ -15,17 +15,21 @@ interface Options { } interface Chunk { - name: string id: string src: string + name: string + meta?: { + id?: string + ids?: string[] + moduleIds?: string[] + } } interface TemplateContext { chunks: Chunk[] - prefix: string } -export function dynamicRequire ({ dir, globbyOptions, inline, outDir, prefix = '' }: Options) { +export function dynamicRequire ({ dir, globbyOptions, inline }: Options): Plugin { return { name: PLUGIN_NAME, transform (code: string, _id: string) { @@ -34,6 +38,12 @@ export function dynamicRequire ({ dir, globbyOptions, inline, outDir, prefix = ' resolveId (id: string) { return id === HELPER_DYNAMIC ? id : null }, + // TODO: Async chunk loading over netwrok! + // renderDynamicImport () { + // return { + // left: 'fetch(', right: ')' + // } + // }, async load (_id: string) { if (_id !== HELPER_DYNAMIC) { return null @@ -44,28 +54,30 @@ export function dynamicRequire ({ dir, globbyOptions, inline, outDir, prefix = ' const chunks = files.map(id => ({ id, src: resolve(dir, id).replace(/\\/g, '/'), - out: prefix + id, - name: '_' + id.replace(/[\\/.]/g, '_') + name: '_' + id.replace(/[\\/.]/g, '_'), + meta: getWebpackChunkMeta(resolve(dir, id)) })) - // Inline mode if (inline) { - return TMPL_ESM_INLINE({ chunks, prefix }) + return TMPL_INLINE({ chunks }) + } else { + return TMPL_LAZY({ chunks }) } - - // Write chunks - await Promise.all(chunks.map(async (chunk) => { - const dst = resolve(outDir, prefix + chunk.id) - await mkdirp(dirname(dst)) - await copyFile(chunk.src, dst) - })) - - return TMPL_CJS_LAZY({ chunks, prefix }) } } } -function TMPL_ESM_INLINE ({ chunks }: TemplateContext) { +function getWebpackChunkMeta (src) { + const chunk = require(src) || {} + const { id, ids, modules } = chunk + return { + id, + ids, + moduleIds: Object.keys(modules) + } +} + +function TMPL_INLINE ({ chunks }: TemplateContext) { return `${chunks.map(i => `import ${i.name} from '${i.src}'`).join('\n')} const dynamicChunks = { ${chunks.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')} @@ -76,18 +88,31 @@ export default function dynamicRequire(id) { };` } -function TMPL_CJS_LAZY ({ chunks, prefix }: TemplateContext) { - return `const dynamicChunks = { -${chunks.map(i => ` ['${i.id}']: () => require('${prefix}${i.id}')`).join(',\n')} +function TMPL_LAZY ({ chunks }: TemplateContext) { + return ` +function asyncWebpackModule(promise, id) { + return function (module, exports, require) { + module.exports = promise.then(r => { + const realModule = { exports: {}, require }; + r.modules[id](realModule, realModule.exports, realModule.require); + return realModule.exports; + }); + }; +}; + +function webpackChunk (meta, promise) { + const chunk = { ...meta, modules: {} }; + for (const id of meta.moduleIds) { + chunk.modules[id] = asyncWebpackModule(promise, id); + }; + return chunk; +}; + +const dynamicChunks = { +${chunks.map(i => ` ['${i.id}']: () => webpackChunk(${JSON.stringify(i.meta)}, import('${i.src}'))`).join(',\n')} }; export default function dynamicRequire(id) { return dynamicChunks[id](); };` } - -// function TMPL_CJS ({ prefix }: TemplateContext) { -// return `export default function dynamicRequire(id) { -// return require('${prefix}' + id); -// };` -// } From 6875d5535bf384007dfa01860302e18f073b2889 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 21:41:38 +0100 Subject: [PATCH 122/227] feat: show fs tree for output --- packages/nitro/src/build.ts | 17 +++++----- .../nitro/src/{utils.ts => utils/index.ts} | 0 packages/nitro/src/utils/tree.ts | 34 +++++++++++++++++++ 3 files changed, 42 insertions(+), 9 deletions(-) rename packages/nitro/src/{utils.ts => utils/index.ts} (100%) create mode 100644 packages/nitro/src/utils/tree.ts diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 1f00c10969..121a489ac8 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -1,13 +1,11 @@ import { resolve } from 'path' import consola from 'consola' -import { rollup, OutputOptions } from 'rollup' +import { rollup } from 'rollup' import Hookable from 'hookable' -import prettyBytes from 'pretty-bytes' -import gzipSize from 'gzip-size' -import chalk from 'chalk' import { readFile, emptyDir } from 'fs-extra' +import { printFSTree } from './utils/tree' import { getRollupConfig } from './rollup/config' -import { hl, prettyPath, serializeTemplate, writeFile } from './utils' +import { hl, serializeTemplate, writeFile } from './utils' import { SLSOptions } from './config' export async function build (options: SLSOptions) { @@ -30,16 +28,17 @@ export async function build (options: SLSOptions) { await writeFile(htmlTemplate.dst, htmlTemplate.compiled) options.rollupConfig = getRollupConfig(options) + await hooks.callHook('rollup:before', options) + const build = await rollup(options.rollupConfig).catch((error) => { error.message = '[serverless] Rollup Error: ' + error.message throw error }) - const { output } = await build.write(options.rollupConfig.output as OutputOptions) - const size = prettyBytes(output[0].code.length) - const zSize = prettyBytes(await gzipSize(output[0].code)) - consola.success('Generated bundle in', prettyPath(options.targetDir), chalk.gray(`(Size: ${size} Gzip: ${zSize})`)) + await build.write(options.rollupConfig.output) + + await printFSTree(options.targetDir) await hooks.callHook('done', options) diff --git a/packages/nitro/src/utils.ts b/packages/nitro/src/utils/index.ts similarity index 100% rename from packages/nitro/src/utils.ts rename to packages/nitro/src/utils/index.ts diff --git a/packages/nitro/src/utils/tree.ts b/packages/nitro/src/utils/tree.ts new file mode 100644 index 0000000000..34472fef28 --- /dev/null +++ b/packages/nitro/src/utils/tree.ts @@ -0,0 +1,34 @@ +import { resolve, extname, basename, dirname, relative } from 'path' +import globby from 'globby' +import prettyBytes from 'pretty-bytes' +import gzipSize from 'gzip-size' +import { readFile } from 'fs-extra' +import chalk from 'chalk' + +export async function printFSTree (dir) { + const files = await globby('**/*.js', { cwd: dir }) + + const items = (await Promise.all(files.map(async (file) => { + const path = resolve(dir, file) + const src = await readFile(path) + const size = src.byteLength + const gzip = await gzipSize(src) + return { file, path, size, gzip } + }))).sort((a, b) => b.size - a.size) + + let totalSize = 0 + let totalGzip = 0 + + for (const item of items) { + let dir = dirname(item.file) + if (dir === '.') { dir = '' } + const name = basename(item.file, extname(item.file)) + const rpath = relative(process.cwd(), item.path) + process.stdout.write(chalk.gray(`[${dir ? `${dir}/` : ''}${name}] at ${rpath} (${prettyBytes(item.size)}) (${prettyBytes(item.gzip)} gzip)\n`)) + + totalSize += item.size + totalGzip += item.gzip + } + + process.stdout.write(`${chalk.cyan('λ Total size:')} ${prettyBytes(totalSize)} (${prettyBytes(totalGzip)} gzip)\n`) +} From 8b071c4efd4e45a87c33b395fe2afdde80c233c8 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 21:47:14 +0100 Subject: [PATCH 123/227] chore: simplify tree --- packages/nitro/src/utils/tree.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/utils/tree.ts b/packages/nitro/src/utils/tree.ts index 34472fef28..94a0386d1c 100644 --- a/packages/nitro/src/utils/tree.ts +++ b/packages/nitro/src/utils/tree.ts @@ -1,4 +1,4 @@ -import { resolve, extname, basename, dirname, relative } from 'path' +import { resolve, dirname, relative } from 'path' import globby from 'globby' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' @@ -19,16 +19,16 @@ export async function printFSTree (dir) { let totalSize = 0 let totalGzip = 0 - for (const item of items) { + items.forEach((item, index) => { let dir = dirname(item.file) if (dir === '.') { dir = '' } - const name = basename(item.file, extname(item.file)) const rpath = relative(process.cwd(), item.path) - process.stdout.write(chalk.gray(`[${dir ? `${dir}/` : ''}${name}] at ${rpath} (${prettyBytes(item.size)}) (${prettyBytes(item.gzip)} gzip)\n`)) + const treeChar = index === items.length - 1 ? '└─' : '├─' + process.stdout.write(chalk.gray(` ${treeChar} ${rpath} (${prettyBytes(item.size)}) (${prettyBytes(item.gzip)} gzip)\n`)) totalSize += item.size totalGzip += item.gzip - } + }) process.stdout.write(`${chalk.cyan('λ Total size:')} ${prettyBytes(totalSize)} (${prettyBytes(totalGzip)} gzip)\n`) } From d2e8c3bd7896f894fe7da85e18583d71a6175d7a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 23:01:57 +0100 Subject: [PATCH 124/227] chore: disable webpack standalone, minify and enable minify for node by default --- packages/nitro/src/index.ts | 4 ++-- packages/nitro/src/targets/node.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 19f20170df..80e6fbf074 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -13,8 +13,8 @@ export default function slsModule () { const options = getoptions(nuxt.options, nuxt.options.serverless || {}) // Tune webpack config - nuxt.options.build._minifyServer = options.minify !== false - nuxt.options.build.standalone = true + nuxt.options.build._minifyServer = false + nuxt.options.build.standalone = false // Tune generator nuxt.options.generate.crawler = false diff --git a/packages/nitro/src/targets/node.ts b/packages/nitro/src/targets/node.ts index 71025fd15a..c3bd71724d 100644 --- a/packages/nitro/src/targets/node.ts +++ b/packages/nitro/src/targets/node.ts @@ -3,5 +3,6 @@ import { SLSTarget } from '../config' export const node: SLSTarget = { entry: '{{ runtimeDir }}/targets/node', outName: 'index.js', - inlineChunks: false + inlineChunks: false, + minify: true } From 5bd6531f5d5a70dfce48b4b19f61d96e3e810a9c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 14 Nov 2020 23:23:17 +0100 Subject: [PATCH 125/227] chore: tweak terser options to improve debugging --- packages/nitro/src/rollup/config.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 0b1b50da21..d63328d374 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -217,8 +217,18 @@ export const getRollupConfig = (options: SLSOptions) => { rollupConfig.plugins.push(analyze()) } + // https://github.com/TrySound/rollup-plugin-terser + // https://github.com/terser/terser#minify-options if (options.minify !== false) { - rollupConfig.plugins.push(terser()) + rollupConfig.plugins.push(terser({ + mangle: { + keep_fnames: true, + keep_classnames: true + }, + format: { + comments: false + } + })) } return rollupConfig From 740bf073b2bec66b36c2fc685556eb3d80b5df90 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 15 Nov 2020 01:52:18 +0100 Subject: [PATCH 126/227] feat: timing plugin and Server-Timing --- packages/nitro/src/config.ts | 4 ++-- packages/nitro/src/rollup/config.ts | 8 ++++---- packages/nitro/src/rollup/timing.ts | 31 +++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 packages/nitro/src/rollup/timing.ts diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts index 6a2c05f7ab..5fdef9687d 100644 --- a/packages/nitro/src/config.ts +++ b/packages/nitro/src/config.ts @@ -37,7 +37,7 @@ export interface SLSOptions { minify: boolean externals: boolean rollupConfig?: any - logStartup: boolean + timing: boolean inlineChunks: boolean renderer: string analyze: boolean @@ -72,7 +72,7 @@ export function getoptions (nuxtOptions: Nuxt['options'], serverless: SLSConfig) staticAssets: nuxtOptions.generate.staticAssets, outName: '_nuxt.js', - logStartup: true, + timing: true, inlineChunks: true, minify: false, externals: false, diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index d63328d374..71dce30371 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -14,8 +14,10 @@ import analyze from 'rollup-plugin-analyzer' import hasha from 'hasha' import { SLSOptions } from '../config' import { resolvePath, MODULE_DIR } from '../utils' + import { dynamicRequire } from './dynamic-require' import { externals } from './externals' +import { timing } from './timing' const mapArrToVal = (val, arr) => arr.reduce((p, c) => ({ ...p, [c]: val }), {}) @@ -107,10 +109,8 @@ export const getRollupConfig = (options: SLSOptions) => { plugins: [] } - if (options.logStartup) { - rollupConfig.output.intro += 'global._startTime = global.process.hrtime();' - // eslint-disable-next-line no-template-curly-in-string - rollupConfig.output.outro += 'global._endTime = global.process.hrtime(global._startTime); global._coldstart = ((global._endTime[0] * 1e9) + global._endTime[1]) / 1e6; console.log(`λ Cold start took: ${global._coldstart}ms (${typeof __filename !== "undefined" ? __filename.replace(process.cwd(), "") : ""})`);' + if (options.timing) { + rollupConfig.plugins.push(timing()) } // https://github.com/rollup/plugins/tree/master/packages/replace diff --git a/packages/nitro/src/rollup/timing.ts b/packages/nitro/src/rollup/timing.ts new file mode 100644 index 0000000000..97b26f1e53 --- /dev/null +++ b/packages/nitro/src/rollup/timing.ts @@ -0,0 +1,31 @@ +import { extname } from 'path' +import type { Plugin, RenderedChunk } from 'rollup' + +export interface Options { } + +const TIMING = 'global.__timing__' + +const iife = code => `(function() { ${code.trim()} })();`.replace(/\n/g, '') + +const HELPER = TIMING + '=' + iife(` +const hrtime = global.process.hrtime; +const start = () => hrtime(); +const end = s => { const d = hrtime(s); return ((d[0] * 1e9) + d[1]) / 1e6; }; + +const _s = {}; +const metrics = []; +const logStart = id => { _s[id] = hrtime(); }; +const logEnd = id => { const t = end(_s[id]); delete _s[id]; metrics.push([id, t]); console.log('◈', id, t, 'ms'); }; +return { hrtime, start, end, metrics, logStart, logEnd }; +`) + +export function timing (_opts: Options = {}): Plugin { + return { + name: 'timing', + renderChunk (code, chunk: RenderedChunk) { + let name = chunk.fileName || '' + name = name.replace(extname(name), '') + return "'use strict';" + HELPER + `${TIMING}.logStart('import:${name}');` + code + `;${TIMING}.logEnd('import:${name}');` + } + } +} From ef85ddfbc9dfbed4177677d6ad21564d503e840a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 15 Nov 2020 01:53:08 +0100 Subject: [PATCH 127/227] chore: fix ts lint --- packages/nitro/src/utils/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/utils/index.ts b/packages/nitro/src/utils/index.ts index 83246a8ee0..f4bb220b71 100644 --- a/packages/nitro/src/utils/index.ts +++ b/packages/nitro/src/utils/index.ts @@ -4,7 +4,7 @@ import jiti from 'jiti' import defu from 'defu' import Hookable from 'hookable' import consola from 'consola' -import { SLSOptions, UnresolvedPath, SLSTarget, SLSTargetFn, SLSConfig } from './config' +import type { SLSOptions, UnresolvedPath, SLSTarget, SLSTargetFn, SLSConfig } from '../config' export const MODULE_DIR = resolve(__dirname, '..') From 3939ea9e4d1740eb52b87e5835275a2bf34bf957 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 15 Nov 2020 02:03:35 +0100 Subject: [PATCH 128/227] chore: sort tree by length --- packages/nitro/src/utils/tree.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/utils/tree.ts b/packages/nitro/src/utils/tree.ts index 94a0386d1c..862347a907 100644 --- a/packages/nitro/src/utils/tree.ts +++ b/packages/nitro/src/utils/tree.ts @@ -14,7 +14,7 @@ export async function printFSTree (dir) { const size = src.byteLength const gzip = await gzipSize(src) return { file, path, size, gzip } - }))).sort((a, b) => b.size - a.size) + }))).sort((a, b) => b.path.localeCompare(a.path)) let totalSize = 0 let totalGzip = 0 From aa71b515383d12870b81fe858b3fde553b4186a8 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 15 Nov 2020 02:31:50 +0100 Subject: [PATCH 129/227] feat: generate meaningful chunkNames --- packages/nitro/src/rollup/config.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 71dce30371..0cfdfc5135 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -1,5 +1,5 @@ import Module from 'module' -import { dirname, join, resolve } from 'path' +import { dirname, join, relative, resolve } from 'path' import { InputOptions, OutputOptions } from 'rollup' import { terser } from 'rollup-plugin-terser' import commonjs from '@rollup/plugin-commonjs' @@ -50,7 +50,7 @@ export const getRollupConfig = (options: SLSOptions) => { '@vue/compiler-ssr' ])) - // Uses eval + // Uses eval 😈 aliases.depd = '~mocks/custom/depd' if (options.node === false) { @@ -91,13 +91,28 @@ export const getRollupConfig = (options: SLSOptions) => { } const chunksDirName = join(dirname(options.outName), 'chunks') + const serverDir = join(options.buildDir, 'dist/server') const rollupConfig: RollupConfig = { input: resolvePath(options, options.entry), output: { dir: options.targetDir, entryFileNames: options.outName, - chunkFileNames: join(chunksDirName, '[name].js'), + chunkFileNames (chunkInfo) { + let prefix = '' + const modules = Object.keys(chunkInfo.modules) + const lastModule = modules[modules.length - 1] + if (lastModule.startsWith(serverDir)) { + prefix = join('ssr', relative(serverDir, dirname(lastModule))) + } else if (lastModule.startsWith(options.buildDir)) { + prefix = 'ssr' + } else if (lastModule.startsWith(options.runtimeDir)) { + prefix = 'runtime' + } else if (!prefix && options.serverMiddleware.find(m => lastModule.startsWith(m.handle))) { + prefix = 'middleware' + } + return join(chunksDirName, prefix, '[name].js') + }, inlineDynamicImports: options.inlineChunks, format: 'cjs', exports: 'auto', From f2c1589472ab62d806d9db5e962b3b4cb004fd7e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 15 Nov 2020 02:34:43 +0100 Subject: [PATCH 130/227] fix(timing): include helpers only in entries --- packages/nitro/src/rollup/timing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/timing.ts b/packages/nitro/src/rollup/timing.ts index 97b26f1e53..f05e0d2b4d 100644 --- a/packages/nitro/src/rollup/timing.ts +++ b/packages/nitro/src/rollup/timing.ts @@ -25,7 +25,7 @@ export function timing (_opts: Options = {}): Plugin { renderChunk (code, chunk: RenderedChunk) { let name = chunk.fileName || '' name = name.replace(extname(name), '') - return "'use strict';" + HELPER + `${TIMING}.logStart('import:${name}');` + code + `;${TIMING}.logEnd('import:${name}');` + return "'use strict';" + (chunk.isEntry ? HELPER : '') + `${TIMING}.logStart('import:${name}');` + code + `;${TIMING}.logEnd('import:${name}');` } } } From e874d4db59479eb30257cc647a580e4764df2349 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 15 Nov 2020 02:43:50 +0100 Subject: [PATCH 131/227] fix: disable cleanTargetDir for vercel --- packages/nitro/src/targets/vercel.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts index 3a9360d2a1..d0f24e81cd 100644 --- a/packages/nitro/src/targets/vercel.ts +++ b/packages/nitro/src/targets/vercel.ts @@ -7,6 +7,7 @@ export const vercel: SLSTarget = extendTarget(node, { targetDir: '{{ rootDir }}/.vercel_build_output', outName: 'functions/node/_nuxt/index.js', publicDir: '{{ targetDir }}/static', + cleanTargetDir: false, generateIgnore: [ 'vercel.json' ], From 047761f8b7719d6aac8e318022b4d04dfe479a0f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 15 Nov 2020 03:43:43 +0100 Subject: [PATCH 132/227] fix: move hrtime polyfill to timing plugin --- packages/nitro/src/rollup/timing.ts | 9 +++++++-- packages/nitro/src/targets/worker.ts | 11 ----------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/nitro/src/rollup/timing.ts b/packages/nitro/src/rollup/timing.ts index f05e0d2b4d..7b1fd3c95a 100644 --- a/packages/nitro/src/rollup/timing.ts +++ b/packages/nitro/src/rollup/timing.ts @@ -7,7 +7,12 @@ const TIMING = 'global.__timing__' const iife = code => `(function() { ${code.trim()} })();`.replace(/\n/g, '') -const HELPER = TIMING + '=' + iife(` +// https://gist.github.com/pi0/1476085924f8a2eb1df85929c20cb43f +const POLYFILL = `const global="undefined"!=typeof globalThis?globalThis:void 0!==o?o:"undefined"!=typeof self?self:{}; +global.process = global.process || {}; +const o=Date.now(),t=()=>Date.now()-o;global.process.hrtime=global.process.hrtime||(o=>{const e=Math.floor(.001*(Date.now()-t())),a=.001*t();let l=Math.floor(a)+e,n=Math.floor(a%1*1e9);return o&&(l-=o[0],n-=o[1],n<0&&(l--,n+=1e9)),[l,n]});` + +const HELPER = POLYFILL + iife(` const hrtime = global.process.hrtime; const start = () => hrtime(); const end = s => { const d = hrtime(s); return ((d[0] * 1e9) + d[1]) / 1e6; }; @@ -16,7 +21,7 @@ const _s = {}; const metrics = []; const logStart = id => { _s[id] = hrtime(); }; const logEnd = id => { const t = end(_s[id]); delete _s[id]; metrics.push([id, t]); console.log('◈', id, t, 'ms'); }; -return { hrtime, start, end, metrics, logStart, logEnd }; +${TIMING} = { hrtime, start, end, metrics, logStart, logEnd }; `) export function timing (_opts: Options = {}): Plugin { diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts index 6f2eaa5fc5..1c8429dae0 100644 --- a/packages/nitro/src/targets/worker.ts +++ b/packages/nitro/src/targets/worker.ts @@ -1,22 +1,11 @@ import { SLSTarget } from '../config' -// https://gist.github.com/pi0/1476085924f8a2eb1df85929c20cb43f - -const polyfill = ` -const exports = {}; -const module = { exports }; -const global = typeof globalThis !== 'undefined' ? globalThis : "undefined" !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; -global.process = global.process || {}; -(function(){const o=Date.now(),t=()=>Date.now()-o;global.process.hrtime=o=>{const e=Math.floor(.001*(Date.now()-t())),n=.001*t();let a=Math.floor(n)+e,r=Math.floor(n%1*1e9);return o&&(a-=o[0],r-=o[1],r<0&&(a--,r+=1e9)),[a,r]};})(); -` - export const worker: SLSTarget = { entry: null, // Abstract node: false, minify: true, hooks: { 'rollup:before' ({ rollupConfig }) { - rollupConfig.output.intro = polyfill + rollupConfig.output.intro rollupConfig.output.format = 'iife' } } From c06f09e9ab9e7272ca039563089f4b8e44db62a1 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Fri, 20 Nov 2020 01:16:31 +0100 Subject: [PATCH 133/227] sigma (#36) --- packages/nitro/src/build.ts | 97 +++++++--- packages/nitro/src/config.ts | 108 ----------- packages/nitro/src/context.ts | 110 +++++++++++ packages/nitro/src/index.ts | 85 +-------- packages/nitro/src/module/nuxt2.ts | 126 +++++++++++++ packages/nitro/src/presets/browser.ts | 40 ++++ packages/nitro/src/presets/cli.ts | 15 ++ packages/nitro/src/presets/cloudflare.ts | 19 ++ packages/nitro/src/presets/dev.ts | 11 ++ .../nitro/src/{targets => presets}/index.ts | 4 +- packages/nitro/src/presets/lambda.ts | 7 + packages/nitro/src/presets/netlify.ts | 10 + packages/nitro/src/presets/node.ts | 6 + packages/nitro/src/presets/server.ts | 16 ++ packages/nitro/src/presets/vercel.ts | 48 +++++ packages/nitro/src/presets/worker.ts | 11 ++ packages/nitro/src/rollup/config.ts | 171 +++++++----------- packages/nitro/src/rollup/dynamic-require.ts | 2 +- packages/nitro/src/rollup/externals.ts | 2 +- packages/nitro/src/rollup/timing.ts | 7 +- packages/nitro/src/server.ts | 137 ++++++++++++++ packages/nitro/src/targets/browser.ts | 44 ----- packages/nitro/src/targets/cjs.ts | 10 - packages/nitro/src/targets/cloudflare.ts | 21 --- packages/nitro/src/targets/lambda.ts | 8 - packages/nitro/src/targets/netlify.ts | 11 -- packages/nitro/src/targets/node.ts | 8 - packages/nitro/src/targets/vercel.ts | 47 ----- packages/nitro/src/targets/worker.ts | 12 -- packages/nitro/src/utils/index.ts | 37 ++-- packages/nitro/src/utils/tree.ts | 4 +- packages/nitro/src/utils/wpfs.ts | 7 + 32 files changed, 735 insertions(+), 506 deletions(-) delete mode 100644 packages/nitro/src/config.ts create mode 100644 packages/nitro/src/context.ts create mode 100644 packages/nitro/src/module/nuxt2.ts create mode 100644 packages/nitro/src/presets/browser.ts create mode 100644 packages/nitro/src/presets/cli.ts create mode 100644 packages/nitro/src/presets/cloudflare.ts create mode 100644 packages/nitro/src/presets/dev.ts rename packages/nitro/src/{targets => presets}/index.ts (72%) create mode 100644 packages/nitro/src/presets/lambda.ts create mode 100644 packages/nitro/src/presets/netlify.ts create mode 100644 packages/nitro/src/presets/node.ts create mode 100644 packages/nitro/src/presets/server.ts create mode 100644 packages/nitro/src/presets/vercel.ts create mode 100644 packages/nitro/src/presets/worker.ts create mode 100644 packages/nitro/src/server.ts delete mode 100644 packages/nitro/src/targets/browser.ts delete mode 100644 packages/nitro/src/targets/cjs.ts delete mode 100644 packages/nitro/src/targets/cloudflare.ts delete mode 100644 packages/nitro/src/targets/lambda.ts delete mode 100644 packages/nitro/src/targets/netlify.ts delete mode 100644 packages/nitro/src/targets/node.ts delete mode 100644 packages/nitro/src/targets/vercel.ts delete mode 100644 packages/nitro/src/targets/worker.ts create mode 100644 packages/nitro/src/utils/wpfs.ts diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 121a489ac8..4c13bb2d8e 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -1,48 +1,97 @@ -import { resolve } from 'path' +import { resolve, join } from 'upath' import consola from 'consola' -import { rollup } from 'rollup' -import Hookable from 'hookable' -import { readFile, emptyDir } from 'fs-extra' +import { rollup, watch as rollupWatch } from 'rollup' +import ora from 'ora' +import { readFile, emptyDir, copy } from 'fs-extra' import { printFSTree } from './utils/tree' import { getRollupConfig } from './rollup/config' import { hl, serializeTemplate, writeFile } from './utils' -import { SLSOptions } from './config' +import { SigmaContext } from './context' -export async function build (options: SLSOptions) { - consola.info(`Generating bundle for ${hl(options.target)}`) +export async function build (sigmaContext: SigmaContext) { + consola.info(`Sigma preset is ${hl(sigmaContext.preset)}`) - const hooks = new Hookable() - hooks.addHooks(options.hooks) - - if (options.cleanTargetDir) { - await emptyDir(options.targetDir) - } + // Cleanup output dir + await emptyDir(sigmaContext.output.dir) // Compile html template - const htmlSrc = resolve(options.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`) + const htmlSrc = resolve(sigmaContext._nuxt.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`) const htmlTemplate = { src: htmlSrc, contents: '', dst: '', compiled: '' } htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.') htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8') htmlTemplate.compiled = 'module.exports = ' + serializeTemplate(htmlTemplate.contents) - await hooks.callHook('template:document', htmlTemplate) + await sigmaContext._internal.hooks.callHook('sigma:template:document', htmlTemplate) await writeFile(htmlTemplate.dst, htmlTemplate.compiled) - options.rollupConfig = getRollupConfig(options) + await generate(sigmaContext) - await hooks.callHook('rollup:before', options) + sigmaContext.rollupConfig = getRollupConfig(sigmaContext) - const build = await rollup(options.rollupConfig).catch((error) => { - error.message = '[serverless] Rollup Error: ' + error.message + await sigmaContext._internal.hooks.callHook('sigma:rollup:before', sigmaContext) + + return sigmaContext._nuxt.dev ? _watch(sigmaContext) : _build(sigmaContext) +} + +export async function generate (sigmaContext: SigmaContext) { + await copy( + resolve(sigmaContext._nuxt.buildDir, 'dist/client'), + join(sigmaContext.output.publicDir, sigmaContext._nuxt.publicPath) + ) + await copy( + resolve(sigmaContext._nuxt.rootDir, sigmaContext._nuxt.staticDir), + sigmaContext.output.publicDir + ) +} + +async function _build (sigmaContext: SigmaContext) { + const spinner = ora() + + spinner.start('Building server...') + const build = await rollup(sigmaContext.rollupConfig).catch((error) => { + spinner.fail('Rollup error: ' + error.messsage) throw error }) - await build.write(options.rollupConfig.output) + spinner.start('Wrting Sigma bundle...') + await build.write(sigmaContext.rollupConfig.output) - await printFSTree(options.targetDir) - - await hooks.callHook('done', options) + spinner.succeed('Sigma built') + await printFSTree(sigmaContext.output.serverDir) + await sigmaContext._internal.hooks.callHook('sigma:compiled', sigmaContext) return { - entry: resolve(options.rollupConfig.output.dir, options.rollupConfig.output.entryFileNames) + entry: resolve(sigmaContext.rollupConfig.output.dir, sigmaContext.rollupConfig.output.entryFileNames) } } + +function _watch (sigmaContext: SigmaContext) { + const spinner = ora() + + const watcher = rollupWatch(sigmaContext.rollupConfig) + + let start + + watcher.on('event', (event) => { + switch (event.code) { + // The watcher is (re)starting + case 'START': + return + + // Building an individual bundle + case 'BUNDLE_START': + start = Date.now() + spinner.start('Building Sigma...') + return + + // Finished building all bundles + case 'END': + sigmaContext._internal.hooks.callHook('sigma:compiled', sigmaContext) + return spinner.succeed(`Sigma built in ${Date.now() - start} ms`) + + // Encountered an error while bundling + case 'ERROR': + spinner.fail('Rollup error: ' + event.error) + // consola.error(event.error) + } + }) +} diff --git a/packages/nitro/src/config.ts b/packages/nitro/src/config.ts deleted file mode 100644 index 5fdef9687d..0000000000 --- a/packages/nitro/src/config.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { resolve } from 'path' -import defu from 'defu' -import type { NuxtOptions } from '@nuxt/types' -import Hookable, { configHooksT } from 'hookable' -import { tryImport, resolvePath, detectTarget, extendTarget } from './utils' -import * as TARGETS from './targets' - -// eslint-disable-next-line -export type UnresolvedPath = string | ((config: SLSOptions) => string) - -export interface Nuxt extends Hookable{ - options: NuxtOptions -} - -export interface ServerMiddleware { - route: string - handle: string - lazy?: boolean -} - -export interface SLSOptions { - hooks: configHooksT - nuxtHooks: configHooksT - - rootDir: string - buildDir: string - publicDir: string - routerBase: string - publicPath: string - fullStatic: boolean - staticAssets: any - - entry: UnresolvedPath - outName: string - node: false | true - target: string - minify: boolean - externals: boolean - rollupConfig?: any - timing: boolean - inlineChunks: boolean - renderer: string - analyze: boolean - cleanTargetDir: boolean - - runtimeDir: string - slsDir: string - targetDir: string - - serverMiddleware: ServerMiddleware[], - - static: string[] - generateIgnore: string[] -} - -export interface SLSConfig extends Omit, 'targetDir'> { - targetDir?: UnresolvedPath -} - -export type SLSTargetFn = (config: SLSConfig) => SLSConfig -export type SLSTarget = SLSConfig | SLSTargetFn - -export function getoptions (nuxtOptions: Nuxt['options'], serverless: SLSConfig): SLSOptions { - const defaults: SLSConfig = { - rootDir: nuxtOptions.rootDir, - buildDir: nuxtOptions.buildDir, - publicDir: nuxtOptions.generate.dir, - routerBase: nuxtOptions.router.base, - publicPath: nuxtOptions.build.publicPath, - fullStatic: nuxtOptions.target === 'static' && !nuxtOptions._legacyGenerate, - // @ts-ignore - staticAssets: nuxtOptions.generate.staticAssets, - - outName: '_nuxt.js', - timing: true, - inlineChunks: true, - minify: false, - externals: false, - cleanTargetDir: true, - - runtimeDir: resolve(__dirname, '../runtime'), - slsDir: '{{ rootDir }}/.nuxt/serverless', - targetDir: '{{ slsDir }}/{{ target }}', - - serverMiddleware: serverless.serverMiddleware || [], - - static: [], - generateIgnore: [] - } - - const target = serverless.target || process.env.NUXT_SLS_TARGET || detectTarget() - let targetDefaults = TARGETS[target] || tryImport(nuxtOptions.rootDir, target) - if (!targetDefaults) { - throw new Error('Cannot resolve target: ' + target) - } - targetDefaults = targetDefaults.default || targetDefaults - - const _defaults = defu(defaults, { target }) - const _targetInput = defu(nuxtOptions.serverless, _defaults) - const _target = extendTarget(nuxtOptions.serverless, targetDefaults)(_targetInput) - const options: SLSOptions = defu(nuxtOptions.serverless, _target, _defaults) - - options.slsDir = resolvePath(options, options.slsDir) - options.targetDir = resolvePath(options, options.targetDir) - options.publicDir = resolvePath(options, options.publicDir) - - return options -} diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts new file mode 100644 index 0000000000..709ce9ddf6 --- /dev/null +++ b/packages/nitro/src/context.ts @@ -0,0 +1,110 @@ +import { resolve } from 'upath' +import defu from 'defu' +import type { NuxtOptions } from '@nuxt/types' +import Hookable, { configHooksT } from 'hookable' +import { tryImport, resolvePath, detectTarget, extendPreset } from './utils' +import * as PRESETS from './presets' + +export interface ServerMiddleware { + route: string + handle: string + lazy?: boolean +} + +export interface SigmaContext { + timing: boolean + inlineChunks: boolean + minify: boolean + externals: boolean + analyze: boolean + entry: string + node: boolean + preset: string + rollupConfig?: any + renderer: string + middleware: ServerMiddleware[] + hooks: configHooksT + ignore: string[] + output: { + dir: string + serverDir: string + publicDir: string + } + _nuxt: { + dev: boolean + rootDir: string + buildDir: string + staticDir: string + routerBase: string + publicPath: string + fullStatic: boolean + staticAssets: any + } + _internal: { + runtimeDir: string + hooks: Hookable + } +} + +export interface SigmaInput extends Partial {} + +export type SigmaPreset = SigmaInput | ((input: SigmaInput) => SigmaInput) + +export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): SigmaContext { + const defaults: SigmaContext = { + timing: true, + inlineChunks: true, + minify: true, + externals: false, + analyze: false, + entry: undefined, + node: undefined, + preset: undefined, + rollupConfig: undefined, + renderer: undefined, + middleware: [], + ignore: [], + hooks: {}, + output: { + dir: '{{ _nuxt.rootDir }}/.output', + serverDir: '{{ output.dir }}/server', + publicDir: '{{ output.dir }}/public' + }, + _nuxt: { + dev: nuxtOptions.dev, + rootDir: nuxtOptions.rootDir, + buildDir: nuxtOptions.buildDir, + staticDir: nuxtOptions.dir.static, + routerBase: nuxtOptions.router.base, + publicPath: nuxtOptions.build.publicPath, + fullStatic: nuxtOptions.preset === 'static' && !nuxtOptions._legacyGenerate, + // @ts-ignore + staticAssets: nuxtOptions.generate.staticAssets + }, + _internal: { + runtimeDir: resolve(__dirname, '../runtime'), + hooks: undefined + } + } + + defaults.preset = input.preset || process.env.SIGMA_PRESET || detectTarget() || 'server' + let presetDefaults = PRESETS[defaults.preset] || tryImport(nuxtOptions.rootDir, defaults.preset) + if (!presetDefaults) { + throw new Error('Cannot resolve preset: ' + defaults.preset) + } + presetDefaults = presetDefaults.default || presetDefaults + + const _presetInput = defu(input, defaults) + // @ts-ignore + const _preset = extendPreset(input, presetDefaults)(_presetInput) + const sigmaContext: SigmaContext = defu(input, _preset, defaults) as any + + sigmaContext.output.dir = resolvePath(sigmaContext, sigmaContext.output.dir) + sigmaContext.output.publicDir = resolvePath(sigmaContext, sigmaContext.output.publicDir) + sigmaContext.output.serverDir = resolvePath(sigmaContext, sigmaContext.output.serverDir) + + // console.log(sigmaContext) + // process.exit(1) + + return sigmaContext +} diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 80e6fbf074..8c14ac283c 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,85 +1,6 @@ -import type { Module } from '@nuxt/types' -import { build } from './build' -import { getoptions } from './config' +import nuxt2 from './module/nuxt2' -export default function slsModule () { +export default function () { const { nuxt } = this - - if (nuxt.options.dev) { - return - } - - // Config - const options = getoptions(nuxt.options, nuxt.options.serverless || {}) - - // Tune webpack config - nuxt.options.build._minifyServer = false - nuxt.options.build.standalone = false - - // Tune generator - nuxt.options.generate.crawler = false - if (Array.isArray(nuxt.options.generate.routes)) { - nuxt.options.generate.routes = Array.from(new Set([ - ...nuxt.options.generate.routes, - ...options.static - ])) - } - nuxt.options.generate.dir = options.publicDir - - // serverMiddleware - // TODO: render:setupMiddleware hook - // TODO: support m.prefix and m.route - nuxt.hook('modules:done', () => { - const unsupported = [] - for (let m of nuxt.options.serverMiddleware) { - if (typeof m === 'string') { - m = { handler: m } - } - - const route = m.path || m.route || '/' - const handle = nuxt.resolver.resolvePath(m.handler || m.handle) - - if (typeof handle !== 'string' || typeof route !== 'string') { - unsupported.push(m) - continue - } - - options.serverMiddleware.push({ ...m, route, handle }) - } - if (unsupported.length) { - console.warn('[serverless] Unsupported Server middleware used: ', unsupported) - console.info('Supported format is `{ path: string, handler: string }` and handler should export `(req, res) => {}`') - } - }) - - if (options.nuxtHooks) { - nuxt.addHooks(options.nuxtHooks) - } - - nuxt.hook('generate:cache:ignore', (ignore: string[]) => { - ignore.push(options.slsDir) - ignore.push(options.targetDir) - ignore.push(...options.generateIgnore) - }) - - nuxt.hook('generate:page', (page) => { - // TODO: Use ssrContext - if (!options.static.includes(page.route)) { - page.exclude = true - } - }) - - nuxt.hook('generate:before', async () => { - console.info('Building light version for `nuxt generate`') - const { entry } = await build(getoptions(nuxt.options, { - target: 'cjs', - serverMiddleware: options.serverMiddleware - })) - console.info('Loading lambda') - require(entry) - }) - - nuxt.hook('generate:done', async () => { - await build(options) - }) + return nuxt2(nuxt) } diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts new file mode 100644 index 0000000000..74072f998d --- /dev/null +++ b/packages/nitro/src/module/nuxt2.ts @@ -0,0 +1,126 @@ +import fetch from 'node-fetch' +import { resolve } from 'upath' +import { build } from '../build' +import { getsigmaContext, SigmaContext } from '../context' +import { createDevServer } from '../server' +import wpfs from '../utils/wpfs' + +export default function (nuxt) { + // Build in node_modules/.cache/nuxt + const oldBuildDir = nuxt.options.buildDir + nuxt.options.buildDir = resolve(nuxt.options.rootDir, 'node_modules/.cache/nuxt') + nuxt.options.build.transpile = nuxt.options.build.transpile || [] + nuxt.options.build.transpile.push(nuxt.options.buildDir) + nuxt.options.appTemplatePath = nuxt.options.appTemplatePath + .replace(oldBuildDir, nuxt.options.buildDir) + + // Create contexts + const sigmaContext = getsigmaContext(nuxt.options, nuxt.options.sigma || {}) + const sigmaDevContext = getsigmaContext(nuxt.options, { preset: 'dev' }) + + // Use nuxt as main hooks host + sigmaContext._internal.hooks = nuxt + sigmaDevContext._internal.hooks = nuxt + nuxt.addHooks(sigmaContext.hooks) + + // Replace nuxt server + if (nuxt.server) { + nuxt.server.__closed = true + nuxt.server = createNuxt2DevServer(sigmaDevContext) + nuxt.addHooks(sigmaDevContext.hooks) + } + + // serverMiddleware bridge + // TODO: render:setupMiddleware hook + // TODO: support m.prefix and m.route + nuxt.hook('modules:done', () => { + const unsupported = [] + for (let m of nuxt.options.serverMiddleware) { + if (typeof m === 'string') { m = { handler: m } } + const route = m.path || m.route || '/' + let handle = m.handler || m.handle + if (typeof handle !== 'string' || typeof route !== 'string') { + if (route === '/_loading') { + nuxt.server.setLoadingMiddleware(handle) + continue + } + unsupported.push(m) + continue + } + handle = nuxt.resolver.resolvePath(handle) + sigmaContext.middleware.push({ ...m, route, handle }) + sigmaDevContext.middleware.push({ ...m, route, handle }) + } + nuxt.options.serverMiddleware = [...unsupported] + if (unsupported.length) { + console.warn('[sigma] Unsupported Server middleware used: \n', ...unsupported) + console.info('Supported format is `{ path: string, handler: string }` and handler should export `(req, res) => {}`') + } + }) + + // nuxt build/dev + nuxt.options.build._minifyServer = false + nuxt.options.build.standalone = false + nuxt.hook('build:done', async () => { + await build(nuxt.options.dev ? sigmaDevContext : sigmaContext) + }) + + // nude dev + if (nuxt.options.dev) { + nuxt.hook('sigma:compiled', () => { nuxt.server.watch() }) + nuxt.hook('build:compile', ({ compiler }) => { compiler.outputFileSystem = wpfs }) + nuxt.hook('server:devMiddleware', (m) => { nuxt.server.setDevMiddleware(m) }) + } + + // nuxt generate + nuxt.hook('generate:cache:ignore', (ignore: string[]) => { + ignore.push(sigmaContext.output.dir) + ignore.push(sigmaContext.output.serverDir) + ignore.push(sigmaContext.output.publicDir) + ignore.push(...sigmaContext.ignore) + }) + + // generate:bfore is before webpack build that we need! + nuxt.hook('generate:extendRoutes', async () => { + await build(sigmaDevContext) + await nuxt.server.reload() + }) +} + +function createNuxt2DevServer (sigmaContext: SigmaContext) { + const server = createDevServer(sigmaContext) + + const listeners = [] + async function listen (port) { + const listener = await server.listen(port) + listeners.push(listener) + return listeners + } + + async function renderRoute (route = '/', renderContext = {}) { + const [listener] = listeners + if (!listener) { + throw new Error('There is no server listener to call `server.renderRoute()`') + } + const html = await fetch(listener.url + route, { + headers: { 'nuxt-render-context': encodeQuery(renderContext) } + }).then(r => r.text()) + + return { html } + } + + return { + ...server, + listeners, + renderRoute, + listen, + serverMiddlewarePaths () { return [] }, + ready () {} + } +} + +function encodeQuery (obj) { + return Object.entries(obj).map( + ([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(val))}` + ).join('&') +} diff --git a/packages/nitro/src/presets/browser.ts b/packages/nitro/src/presets/browser.ts new file mode 100644 index 0000000000..cfd2875615 --- /dev/null +++ b/packages/nitro/src/presets/browser.ts @@ -0,0 +1,40 @@ +import { writeFile } from 'fs-extra' +import { resolve } from 'upath' +import consola from 'consola' +import { extendPreset, prettyPath } from '../utils' +import { SigmaPreset, SigmaContext, SigmaInput } from '../context' +import { worker } from './worker' + +export const browser: SigmaPreset = extendPreset(worker, (input: SigmaInput) => { + const script = `` + + return { + entry: '{{ _internal.runtimeDir }}/entries/service-worker', + output: { + dir: '{{ _nuxt.rootDir }}/.output/public', + publicDir: '{{ output.dir }}', + serverDir: '{{ output.dir }}' + }, + hooks: { + 'vue-renderer:ssr:templateParams' (params) { + params.APP += script + }, + 'vue-renderer:spa:templateParams' (params) { + params.APP += script + }, + 'sigma:template:document' (tmpl) { + tmpl.compiled = tmpl.compiled.replace('', script + '') + }, + async 'sigma:compiled' ({ output }: SigmaContext) { + await writeFile(resolve(output.publicDir, 'index.html'), script) // TODO + consola.info('Ready to deploy to static hosting:', prettyPath(output.publicDir)) + } + } + } +}) diff --git a/packages/nitro/src/presets/cli.ts b/packages/nitro/src/presets/cli.ts new file mode 100644 index 0000000000..ca9ca98350 --- /dev/null +++ b/packages/nitro/src/presets/cli.ts @@ -0,0 +1,15 @@ +import consola from 'consola' +import { extendPreset, prettyPath } from '../utils' +import { SigmaPreset, SigmaContext } from '../context' +import { node } from './node' + +export const cli: SigmaPreset = extendPreset(node, { + entry: '{{ _internal.runtimeDir }}/entries/cli', + externals: true, + inlineChunks: true, + hooks: { + 'sigma:compiled' ({ output }: SigmaContext) { + consola.info('Run with `node ' + prettyPath(output.serverDir) + ' [route]`') + } + } +}) diff --git a/packages/nitro/src/presets/cloudflare.ts b/packages/nitro/src/presets/cloudflare.ts new file mode 100644 index 0000000000..43715ac0fb --- /dev/null +++ b/packages/nitro/src/presets/cloudflare.ts @@ -0,0 +1,19 @@ +import { resolve } from 'upath' +import consola from 'consola' +import { extendPreset, writeFile, prettyPath } from '../utils' +import { SigmaContext, SigmaPreset } from '../context' +import { worker } from './worker' + +export const cloudflare: SigmaPreset = extendPreset(worker, { + entry: '{{ _internal.runtimeDir }}/entries/cloudflare', + ignore: [ + 'wrangler.toml' + ], + hooks: { + async 'sigma:compiled' ({ output, _nuxt }: SigmaContext) { + await writeFile(resolve(output.dir, 'package.json'), JSON.stringify({ private: true, main: './server/index.js' }, null, 2)) + await writeFile(resolve(output.dir, 'package-lock.json'), JSON.stringify({ lockfileVersion: 1 }, null, 2)) + consola.success('Ready to run `wrangler publish` in', prettyPath(_nuxt.rootDir)) + } + } +}) diff --git a/packages/nitro/src/presets/dev.ts b/packages/nitro/src/presets/dev.ts new file mode 100644 index 0000000000..d2e661b569 --- /dev/null +++ b/packages/nitro/src/presets/dev.ts @@ -0,0 +1,11 @@ +import { extendPreset } from '../utils' +import { SigmaPreset } from '../context' +import { node } from './node' + +export const dev: SigmaPreset = extendPreset(node, { + entry: '{{ _internal.runtimeDir }}/entries/dev', + minify: false, + externals: true, + inlineChunks: true, + timing: true +}) diff --git a/packages/nitro/src/targets/index.ts b/packages/nitro/src/presets/index.ts similarity index 72% rename from packages/nitro/src/targets/index.ts rename to packages/nitro/src/presets/index.ts index cba2c91749..c59d83d2fb 100644 --- a/packages/nitro/src/targets/index.ts +++ b/packages/nitro/src/presets/index.ts @@ -3,6 +3,8 @@ export * from './cloudflare' export * from './lambda' export * from './netlify' export * from './node' -export * from './cjs' +export * from './dev' +export * from './server' +export * from './cli' export * from './vercel' export * from './worker' diff --git a/packages/nitro/src/presets/lambda.ts b/packages/nitro/src/presets/lambda.ts new file mode 100644 index 0000000000..812aeeae76 --- /dev/null +++ b/packages/nitro/src/presets/lambda.ts @@ -0,0 +1,7 @@ + +import { SigmaPreset } from '../context' + +export const lambda: SigmaPreset = { + entry: '{{ _internal.runtimeDir }}/entries/lambda', + inlineChunks: false +} diff --git a/packages/nitro/src/presets/netlify.ts b/packages/nitro/src/presets/netlify.ts new file mode 100644 index 0000000000..f4ed81841f --- /dev/null +++ b/packages/nitro/src/presets/netlify.ts @@ -0,0 +1,10 @@ +import { extendPreset } from '../utils' +import { SigmaPreset } from '../context' +import { lambda } from './lambda' + +export const netlify: SigmaPreset = extendPreset(lambda, { + ignore: [ + 'netlify.toml', + '_redirects' + ] +}) diff --git a/packages/nitro/src/presets/node.ts b/packages/nitro/src/presets/node.ts new file mode 100644 index 0000000000..e9581aeb2d --- /dev/null +++ b/packages/nitro/src/presets/node.ts @@ -0,0 +1,6 @@ +import { SigmaPreset } from '../context' + +export const node: SigmaPreset = { + entry: '{{ _internal.runtimeDir }}/entries/node', + inlineChunks: false +} diff --git a/packages/nitro/src/presets/server.ts b/packages/nitro/src/presets/server.ts new file mode 100644 index 0000000000..1d331c68f6 --- /dev/null +++ b/packages/nitro/src/presets/server.ts @@ -0,0 +1,16 @@ +import consola from 'consola' +import { extendPreset, hl, prettyPath } from '../utils' +import { SigmaPreset, SigmaContext } from '../context' +import { node } from './node' + +export const server: SigmaPreset = extendPreset(node, { + entry: '{{ _internal.runtimeDir }}/entries/server', + externals: false, + inlineChunks: false, + timing: true, + hooks: { + 'sigma:compiled' ({ output }: SigmaContext) { + consola.success('Ready to run', hl('node ' + prettyPath(output.serverDir))) + } + } +}) diff --git a/packages/nitro/src/presets/vercel.ts b/packages/nitro/src/presets/vercel.ts new file mode 100644 index 0000000000..b4ed58decf --- /dev/null +++ b/packages/nitro/src/presets/vercel.ts @@ -0,0 +1,48 @@ +import { resolve } from 'upath' +import { extendPreset, writeFile } from '../utils' +import { SigmaPreset, SigmaContext } from '../context' +import { node } from './node' + +export const vercel: SigmaPreset = extendPreset(node, { + output: { + dir: '{{ _nuxt.rootDir }}/.vercel_build_output', + serverDir: '{{ output.dir }}/functions/node/_nuxt/index.js', + publicDir: '{{ output.dir }}/static' + }, + ignore: [ + 'vercel.json' + ], + hooks: { + async 'sigma:compiled' (ctx: SigmaContext) { + await writeRoutes(ctx) + } + } +}) + +async function writeRoutes ({ output }: SigmaContext) { + const routes = [ + { + src: '/sw.js', + headers: { + 'cache-control': 'public, max-age=0, must-revalidate' + }, + continue: true + }, + { + src: '/_nuxt/(.*)', + headers: { + 'cache-control': 'public,max-age=31536000,immutable' + }, + continue: true + }, + { + handle: 'filesystem' + }, + { + src: '(.*)', + dest: '/.vercel/functions/_nuxt/index' + } + ] + + await writeFile(resolve(output.dir, 'config/routes.json'), JSON.stringify(routes, null, 2)) +} diff --git a/packages/nitro/src/presets/worker.ts b/packages/nitro/src/presets/worker.ts new file mode 100644 index 0000000000..3f80a2bb44 --- /dev/null +++ b/packages/nitro/src/presets/worker.ts @@ -0,0 +1,11 @@ +import { SigmaPreset, SigmaContext } from '../context' + +export const worker: SigmaPreset = { + entry: null, // Abstract + node: false, + hooks: { + 'sigma:rollup:before' ({ rollupConfig }: SigmaContext) { + rollupConfig.output.format = 'iife' + } + } +} diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 0cfdfc5135..a939feb191 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -1,5 +1,5 @@ import Module from 'module' -import { dirname, join, relative, resolve } from 'path' +import { dirname, join, relative, resolve } from 'upath' import { InputOptions, OutputOptions } from 'rollup' import { terser } from 'rollup-plugin-terser' import commonjs from '@rollup/plugin-commonjs' @@ -10,110 +10,64 @@ import replace from '@rollup/plugin-replace' import virtual from '@rollup/plugin-virtual' import inject from '@rollup/plugin-inject' import analyze from 'rollup-plugin-analyzer' +import * as un from '@nuxt/un' import hasha from 'hasha' -import { SLSOptions } from '../config' +import { SigmaContext } from '../context' import { resolvePath, MODULE_DIR } from '../utils' import { dynamicRequire } from './dynamic-require' import { externals } from './externals' import { timing } from './timing' -const mapArrToVal = (val, arr) => arr.reduce((p, c) => ({ ...p, [c]: val }), {}) - export type RollupConfig = InputOptions & { output: OutputOptions } -export const getRollupConfig = (options: SLSOptions) => { - const extensions: string[] = ['.ts', '.mjs', '.js', '.json', '.node'] +export const getRollupConfig = (sigmaContext: SigmaContext) => { + const extensions: string[] = ['.ts', '.js', '.json', '.node'] const external: InputOptions['external'] = [] - const injects:{ [key: string]: string| string[] } = {} + const presets = [] - const aliases: { [key: string]: string } = {} - - Object.assign(aliases, mapArrToVal('~mocks/generic', [ - // @nuxt/devalue - 'consola', - // vue2 - 'encoding', - 'stream', - 'he', - 'resolve', - 'source-map', - 'lodash.template', - 'serialize-javascript', - // vue3 - '@babel/parser', - '@vue/compiler-core', - '@vue/compiler-dom', - '@vue/compiler-ssr' - ])) - - // Uses eval 😈 - aliases.depd = '~mocks/custom/depd' - - if (options.node === false) { - // Globals - // injects.Buffer = ['buffer', 'Buffer'] <-- TODO: Make it opt-in - injects.process = '~mocks/node/process' - - // Aliases - Object.assign(aliases, { - // Node - ...mapArrToVal('~mocks/generic', Module.builtinModules), - http: '~mocks/node/http', - fs: '~mocks/node/fs', - process: '~mocks/node/process', - 'node-process': require.resolve('process/browser.js'), - // buffer: require.resolve('buffer/index.js'), - util: require.resolve('util/util.js'), - events: require.resolve('events/events.js'), - inherits: require.resolve('inherits/inherits_browser.js'), - - // Custom - 'node-fetch': '~mocks/custom/node-fetch', - etag: '~mocks/generic/noop', - - // Express - ...mapArrToVal('~mocks/generic', [ - 'serve-static', - 'iconv-lite' - ]), - - // Mime - 'mime-db': '~mocks/custom/mime-db', - 'mime/lite': require.resolve('mime/lite'), - mime: '~mocks/custom/mime' - }) + if (sigmaContext.node === false) { + presets.push(un.nodeless) } else { + presets.push(un.node) external.push(...Module.builtinModules) } - const chunksDirName = join(dirname(options.outName), 'chunks') - const serverDir = join(options.buildDir, 'dist/server') + const env = un.env(...presets, { + alias: { + depd: require.resolve('@nuxt/un/runtime/npm/depd') + } + }) + + const buildServerDir = join(sigmaContext._nuxt.buildDir, 'dist/server') + const runtimeAppDir = join(sigmaContext._internal.runtimeDir, 'app') const rollupConfig: RollupConfig = { - input: resolvePath(options, options.entry), + input: resolvePath(sigmaContext, sigmaContext.entry), output: { - dir: options.targetDir, - entryFileNames: options.outName, + dir: sigmaContext.output.serverDir, + entryFileNames: 'index.js', chunkFileNames (chunkInfo) { let prefix = '' const modules = Object.keys(chunkInfo.modules) const lastModule = modules[modules.length - 1] - if (lastModule.startsWith(serverDir)) { - prefix = join('ssr', relative(serverDir, dirname(lastModule))) - } else if (lastModule.startsWith(options.buildDir)) { - prefix = 'ssr' - } else if (lastModule.startsWith(options.runtimeDir)) { - prefix = 'runtime' - } else if (!prefix && options.serverMiddleware.find(m => lastModule.startsWith(m.handle))) { + if (lastModule.startsWith(buildServerDir)) { + prefix = join('app', relative(buildServerDir, dirname(lastModule))) + } else if (lastModule.startsWith(runtimeAppDir)) { + prefix = 'app' + } else if (lastModule.startsWith(sigmaContext._nuxt.buildDir)) { + prefix = 'nuxt' + } else if (lastModule.startsWith(sigmaContext._internal.runtimeDir)) { + prefix = 'sigma' + } else if (!prefix && sigmaContext.middleware.find(m => lastModule.startsWith(m.handle))) { prefix = 'middleware' } - return join(chunksDirName, prefix, '[name].js') + return join('chunks', prefix, '[name].js') }, - inlineDynamicImports: options.inlineChunks, + inlineDynamicImports: sigmaContext.inlineChunks, format: 'cjs', exports: 'auto', intro: '', @@ -124,28 +78,28 @@ export const getRollupConfig = (options: SLSOptions) => { plugins: [] } - if (options.timing) { + if (sigmaContext.timing) { rollupConfig.plugins.push(timing()) } // https://github.com/rollup/plugins/tree/master/packages/replace rollupConfig.plugins.push(replace({ values: { - 'process.env.NODE_ENV': '"production"', + 'process.env.NODE_ENV': sigmaContext._nuxt.dev ? '"development"' : '"production"', 'typeof window': '"undefined"', - 'process.env.ROUTER_BASE': JSON.stringify(options.routerBase), - 'process.env.PUBLIC_PATH': JSON.stringify(options.publicPath), - 'process.env.NUXT_STATIC_BASE': JSON.stringify(options.staticAssets.base), - 'process.env.NUXT_STATIC_VERSION': JSON.stringify(options.staticAssets.version), + 'process.env.ROUTER_BASE': JSON.stringify(sigmaContext._nuxt.routerBase), + 'process.env.PUBLIC_PATH': JSON.stringify(sigmaContext._nuxt.publicPath), + 'process.env.NUXT_STATIC_BASE': JSON.stringify(sigmaContext._nuxt.staticAssets.base), + 'process.env.NUXT_STATIC_VERSION': JSON.stringify(sigmaContext._nuxt.staticAssets.version), // @ts-ignore - 'process.env.NUXT_FULL_STATIC': options.fullStatic + 'process.env.NUXT_FULL_STATIC': sigmaContext.fullStatic } })) // Dynamic Require Support rollupConfig.plugins.push(dynamicRequire({ - dir: resolve(options.buildDir, 'dist/server'), - inline: options.node === false || options.inlineChunks, + dir: resolve(sigmaContext._nuxt.buildDir, 'dist/server'), + inline: sigmaContext.node === false || sigmaContext.inlineChunks, globbyOptions: { ignore: [ 'server.js' @@ -166,36 +120,39 @@ export const getRollupConfig = (options: SLSOptions) => { const getImportId = p => '_' + hasha(p).substr(0, 6) rollupConfig.plugins.push(virtual({ '~serverMiddleware': ` - ${options.serverMiddleware.filter(m => !m.lazy).map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} + ${sigmaContext.middleware.filter(m => !m.lazy).map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} - ${options.serverMiddleware.filter(m => m.lazy).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} + ${sigmaContext.middleware.filter(m => m.lazy).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} export default [ - ${options.serverMiddleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || false} }`).join(',\n')} + ${sigmaContext.middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || false} }`).join(',\n')} ]; ` })) + // Polyfill + rollupConfig.plugins.push(virtual({ + '~polyfill': env.polyfill.map(p => `require('${p}');`).join('\n') + })) + // https://github.com/rollup/plugins/tree/master/packages/alias - const renderer = options.renderer || 'vue2' + const renderer = sigmaContext.renderer || 'vue2' rollupConfig.plugins.push(alias({ entries: { - '~runtime': options.runtimeDir, - '~mocks': resolve(options.runtimeDir, 'mocks'), - '~renderer': require.resolve(resolve(options.runtimeDir, 'ssr', renderer)), - '~build': options.buildDir, - '~mock': require.resolve(resolve(options.runtimeDir, 'mocks/generic')), - ...aliases + '~runtime': sigmaContext._internal.runtimeDir, + '~renderer': require.resolve(resolve(sigmaContext._internal.runtimeDir, 'app', renderer)), + '~build': sigmaContext._nuxt.buildDir, + ...env.alias } })) // External Plugin - if (options.externals) { + if (sigmaContext.externals) { rollupConfig.plugins.push(externals({ - relativeTo: options.targetDir, + relativeTo: sigmaContext.output.serverDir, include: [ - options.runtimeDir, - ...options.serverMiddleware.map(m => m.handle) + sigmaContext._internal.runtimeDir, + ...sigmaContext.middleware.map(m => m.handle) ] })) } @@ -204,12 +161,12 @@ export const getRollupConfig = (options: SLSOptions) => { rollupConfig.plugins.push(nodeResolve({ extensions, preferBuiltins: true, - rootDir: options.rootDir, + rootDir: sigmaContext._nuxt.rootDir, // https://www.npmjs.com/package/resolve customResolveOptions: { - basedir: options.rootDir, + basedir: sigmaContext._nuxt.rootDir, paths: [ - resolve(options.rootDir, 'node_modukes'), + resolve(sigmaContext._nuxt.rootDir, 'node_modules'), resolve(MODULE_DIR, 'node_modules') ] }, @@ -225,16 +182,16 @@ export const getRollupConfig = (options: SLSOptions) => { rollupConfig.plugins.push(json()) // https://github.com/rollup/plugins/tree/master/packages/inject - rollupConfig.plugins.push(inject(injects)) + rollupConfig.plugins.push(inject(env.inject)) - if (options.analyze) { + if (sigmaContext.analyze) { // https://github.com/doesdev/rollup-plugin-analyzer rollupConfig.plugins.push(analyze()) } // https://github.com/TrySound/rollup-plugin-terser - // https://github.com/terser/terser#minify-options - if (options.minify !== false) { + // https://github.com/terser/terser#minify-sigmaContext + if (sigmaContext.minify) { rollupConfig.plugins.push(terser({ mangle: { keep_fnames: true, diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/dynamic-require.ts index 8a2f42039c..2bc2bae7e9 100644 --- a/packages/nitro/src/rollup/dynamic-require.ts +++ b/packages/nitro/src/rollup/dynamic-require.ts @@ -1,4 +1,4 @@ -import { resolve } from 'path' +import { resolve } from 'upath' import globby, { GlobbyOptions } from 'globby' import type { Plugin } from 'rollup' diff --git a/packages/nitro/src/rollup/externals.ts b/packages/nitro/src/rollup/externals.ts index f0515d73a9..e05537c9b7 100644 --- a/packages/nitro/src/rollup/externals.ts +++ b/packages/nitro/src/rollup/externals.ts @@ -1,4 +1,4 @@ -import { isAbsolute, relative } from 'path' +import { isAbsolute, relative } from 'upath' export function externals ({ include = [], relativeTo }) { return { diff --git a/packages/nitro/src/rollup/timing.ts b/packages/nitro/src/rollup/timing.ts index 7b1fd3c95a..b5cc67170f 100644 --- a/packages/nitro/src/rollup/timing.ts +++ b/packages/nitro/src/rollup/timing.ts @@ -1,4 +1,4 @@ -import { extname } from 'path' +import { extname } from 'upath' import type { Plugin, RenderedChunk } from 'rollup' export interface Options { } @@ -20,7 +20,7 @@ const end = s => { const d = hrtime(s); return ((d[0] * 1e9) + d[1]) / 1e6; }; const _s = {}; const metrics = []; const logStart = id => { _s[id] = hrtime(); }; -const logEnd = id => { const t = end(_s[id]); delete _s[id]; metrics.push([id, t]); console.log('◈', id, t, 'ms'); }; +const logEnd = id => { const t = end(_s[id]); delete _s[id]; metrics.push([id, t]); console.debug('>', id + ' (' + t + 'ms)'); }; ${TIMING} = { hrtime, start, end, metrics, logStart, logEnd }; `) @@ -30,7 +30,8 @@ export function timing (_opts: Options = {}): Plugin { renderChunk (code, chunk: RenderedChunk) { let name = chunk.fileName || '' name = name.replace(extname(name), '') - return "'use strict';" + (chunk.isEntry ? HELPER : '') + `${TIMING}.logStart('import:${name}');` + code + `;${TIMING}.logEnd('import:${name}');` + const logName = name === 'index' ? 'entry' : name + return "'use strict';" + (chunk.isEntry ? HELPER : '') + `${TIMING}.logStart('${logName}');` + code + `;${TIMING}.logEnd('${logName}');` } } } diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts new file mode 100644 index 0000000000..bdc8f02398 --- /dev/null +++ b/packages/nitro/src/server.ts @@ -0,0 +1,137 @@ +import { Worker } from 'worker_threads' +import { Server } from 'http' +import { resolve } from 'upath' +import debounce from 'debounce' +import connect from 'connect' +import getPort from 'get-port-please' +import chokidar from 'chokidar' +import serveStatic from 'serve-static' +import { createProxy } from 'http-proxy' +import { stat } from 'fs-extra' +import type { SigmaContext } from './context' + +export function createDevServer (sigmaContext: SigmaContext) { + // Worker + const workerEntry = resolve(sigmaContext.output.dir, sigmaContext.output.serverDir, 'index.js') + let pendingWorker: Worker + let activeWorker: Worker + let workerAddress: string + async function reload () { + if (pendingWorker) { + await pendingWorker.terminate() + workerAddress = null + pendingWorker = null + } + if (!(await stat(workerEntry)).isFile) { + throw new Error('Entry not found: ' + workerEntry) + } + return new Promise((resolve, reject) => { + const worker = pendingWorker = new Worker(workerEntry) + worker.once('exit', (code) => { + if (code) { + reject(new Error('[worker] exited with code: ' + code)) + } + }) + worker.on('error', (err) => { + err.message = '[worker] ' + err.message + reject(err) + }) + worker.on('message', (event) => { + if (event && event.port) { + workerAddress = 'http://localhost:' + event.port + activeWorker = worker + pendingWorker = null + resolve(workerAddress) + } + }) + }) + } + + // App + const app = connect() + + // _nuxt and static + app.use(sigmaContext._nuxt.publicPath, serveStatic(resolve(sigmaContext._nuxt.buildDir, 'dist/client'))) + app.use(sigmaContext._nuxt.routerBase, serveStatic(resolve(sigmaContext._nuxt.staticDir))) + + // Dev Middleware + let loadingMiddleware, devMiddleware + const setLoadingMiddleware = (m) => { loadingMiddleware = m } + const setDevMiddleware = (m) => { devMiddleware = m } + app.use((req, res, next) => { + if (loadingMiddleware && req.url.startsWith('/_loading')) { + req.url = req.url.replace('/_loading', '') + return loadingMiddleware(req, res) + } + if (devMiddleware) { + return devMiddleware(req, res, next) + } + return next() + }) + + // SSR Proxy + const proxy = createProxy() + app.use((req, res) => { + if (workerAddress) { + proxy.web(req, res, { target: workerAddress }) + } else if (loadingMiddleware) { + // TODO:serverIndex method is not exposed + // loadingMiddleware(req, res) + sigmaContext._internal.hooks.callHook('server:nuxt:renderLoading', req, res) + } else { + res.end('Worker not ready!') + } + }) + + // Listen + const listeners: Server[] = [] + async function listen (port) { + port = await getPort({ name: 'nuxt' }) + const listener = await new Promise((resolve, reject) => { + const l = app.listen(port, err => err ? reject(err) : resolve(l)) + }) + listeners.push(listener) + return { + url: 'http://localhost:' + port + } + } + + // Watch for dist and reload worker + const pattern = '**/*.{js,json}' + const events = ['add', 'change'] + let watcher + function watch () { + if (watcher) { return } + const dReload = debounce(() => reload().catch(console.warn), 200, true) + watcher = chokidar.watch([ + resolve(sigmaContext.output.serverDir, pattern), + resolve(sigmaContext._nuxt.buildDir, 'dist/server', pattern) + ]).on('all', event => events.includes(event) && dReload()) + } + + // Close handler + async function close () { + if (watcher) { + await watcher.close() + } + if (activeWorker) { + await activeWorker.terminate() + } + if (pendingWorker) { + await pendingWorker.terminate() + } + await Promise.all(listeners.map(l => new Promise((resolve, reject) => { + l.close(err => err ? reject(err) : resolve()) + }))) + } + sigmaContext._internal.hooks.hook('close', close) + + return { + reload, + listen, + close, + watch, + setLoadingMiddleware, + setDevMiddleware + } +} diff --git a/packages/nitro/src/targets/browser.ts b/packages/nitro/src/targets/browser.ts deleted file mode 100644 index deac5e57f2..0000000000 --- a/packages/nitro/src/targets/browser.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { resolve, relative } from 'path' -import { existsSync, copy } from 'fs-extra' -import consola from 'consola' -import { extendTarget } from '../utils' -import { SLSTarget } from '../config' -import { worker } from './worker' - -export const browser: SLSTarget = extendTarget(worker, (options) => { - const script = ``.replace(/\n| +/g, '') - - return { - entry: '{{ runtimeDir }}/targets/service-worker', - targetDir: '{{ publicDir }}', - outName: '_nuxt.js', - cleanTargetDir: false, - nuxtHooks: { - 'vue-renderer:ssr:templateParams' (params) { - params.APP += script - }, - 'vue-renderer:spa:templateParams' (params) { - params.APP += script - } - }, - hooks: { - 'template:document' (tmpl) { - tmpl.compiled = tmpl.compiled.replace('', script + '') - }, - async done ({ rootDir, publicDir }) { - const fallback200 = resolve(publicDir, '200.html') - const fallback404 = resolve(publicDir, '404.html') - if (!existsSync(fallback404) && existsSync(fallback200)) { - await copy(fallback200, fallback404) - } - consola.info(`Try with \`nuxt start ${relative(process.cwd(), rootDir)}\``) - } - } - } -}) diff --git a/packages/nitro/src/targets/cjs.ts b/packages/nitro/src/targets/cjs.ts deleted file mode 100644 index 4a6a8aaa00..0000000000 --- a/packages/nitro/src/targets/cjs.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { extendTarget } from '../utils' -import { SLSTarget } from '../config' -import { node } from './node' - -export const cjs: SLSTarget = extendTarget(node, { - entry: '{{ runtimeDir }}/targets/cjs', - minify: false, - externals: true, - inlineChunks: true -}) diff --git a/packages/nitro/src/targets/cloudflare.ts b/packages/nitro/src/targets/cloudflare.ts deleted file mode 100644 index c37c9dcf66..0000000000 --- a/packages/nitro/src/targets/cloudflare.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { resolve } from 'path' -import consola from 'consola' -import { extendTarget, writeFile } from '../utils' -import { SLSOptions, SLSTarget } from '../config' -import { worker } from './worker' - -export const cloudflare: SLSTarget = extendTarget(worker, { - entry: '{{ runtimeDir }}/targets/cloudflare', - outName: '_nuxt.js', - generateIgnore: [ - 'wrangler.toml' - ], - hooks: { - async done ({ targetDir }: SLSOptions) { - await writeFile(resolve(targetDir, 'package.json'), JSON.stringify({ private: true, main: './_nuxt.js' }, null, 2)) - await writeFile(resolve(targetDir, 'package-lock.json'), JSON.stringify({ lockfileVersion: 1 }, null, 2)) - - consola.success('Ready to run `wrangler publish`') - } - } -}) diff --git a/packages/nitro/src/targets/lambda.ts b/packages/nitro/src/targets/lambda.ts deleted file mode 100644 index 2c151980ed..0000000000 --- a/packages/nitro/src/targets/lambda.ts +++ /dev/null @@ -1,8 +0,0 @@ - -import { SLSTarget } from '../config' - -export const lambda: SLSTarget = { - entry: '{{ runtimeDir }}/targets/lambda', - outName: '_nuxt.js', - inlineChunks: false -} diff --git a/packages/nitro/src/targets/netlify.ts b/packages/nitro/src/targets/netlify.ts deleted file mode 100644 index 501d527d2b..0000000000 --- a/packages/nitro/src/targets/netlify.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { extendTarget } from '../utils' -import { SLSTarget } from '../config' -import { lambda } from './lambda' - -export const netlify: SLSTarget = extendTarget(lambda, { - outName: '_nuxt.js', - generateIgnore: [ - 'netlify.toml', - '_redirects' - ] -}) diff --git a/packages/nitro/src/targets/node.ts b/packages/nitro/src/targets/node.ts deleted file mode 100644 index c3bd71724d..0000000000 --- a/packages/nitro/src/targets/node.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { SLSTarget } from '../config' - -export const node: SLSTarget = { - entry: '{{ runtimeDir }}/targets/node', - outName: 'index.js', - inlineChunks: false, - minify: true -} diff --git a/packages/nitro/src/targets/vercel.ts b/packages/nitro/src/targets/vercel.ts deleted file mode 100644 index d0f24e81cd..0000000000 --- a/packages/nitro/src/targets/vercel.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { resolve } from 'path' -import { extendTarget, writeFile } from '../utils' -import { SLSTarget } from '../config' -import { node } from './node' - -export const vercel: SLSTarget = extendTarget(node, { - targetDir: '{{ rootDir }}/.vercel_build_output', - outName: 'functions/node/_nuxt/index.js', - publicDir: '{{ targetDir }}/static', - cleanTargetDir: false, - generateIgnore: [ - 'vercel.json' - ], - hooks: { - async done ({ targetDir }) { - await writeRoutes({ targetDir }) - } - } -}) - -async function writeRoutes ({ targetDir }) { - const routes = [ - { - src: '/sw.js', - headers: { - 'cache-control': 'public, max-age=0, must-revalidate' - }, - continue: true - }, - { - src: '/_nuxt/(.*)', - headers: { - 'cache-control': 'public,max-age=31536000,immutable' - }, - continue: true - }, - { - handle: 'filesystem' - }, - { - src: '(.*)', - dest: '/.vercel/functions/_nuxt/index' - } - ] - - await writeFile(resolve(targetDir, 'config/routes.json'), JSON.stringify(routes, null, 2)) -} diff --git a/packages/nitro/src/targets/worker.ts b/packages/nitro/src/targets/worker.ts deleted file mode 100644 index 1c8429dae0..0000000000 --- a/packages/nitro/src/targets/worker.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { SLSTarget } from '../config' - -export const worker: SLSTarget = { - entry: null, // Abstract - node: false, - minify: true, - hooks: { - 'rollup:before' ({ rollupConfig }) { - rollupConfig.output.format = 'iife' - } - } -} diff --git a/packages/nitro/src/utils/index.ts b/packages/nitro/src/utils/index.ts index f4bb220b71..53c468d1d0 100644 --- a/packages/nitro/src/utils/index.ts +++ b/packages/nitro/src/utils/index.ts @@ -1,15 +1,17 @@ -import { relative, dirname, resolve } from 'path' +import { relative, dirname, resolve } from 'upath' import fse from 'fs-extra' import jiti from 'jiti' import defu from 'defu' import Hookable from 'hookable' import consola from 'consola' -import type { SLSOptions, UnresolvedPath, SLSTarget, SLSTargetFn, SLSConfig } from '../config' +import chalk from 'chalk' +import { get } from 'dot-prop' +import type { SigmaPreset, SigmaInput } from '../context' export const MODULE_DIR = resolve(__dirname, '..') export function hl (str: string) { - return '`' + str + '`' + return chalk.cyan(str) } export function prettyPath (p: string, highlight = true) { @@ -18,7 +20,13 @@ export function prettyPath (p: string, highlight = true) { } export function compileTemplate (contents: string) { - return (params: Record) => contents.replace(/{{ ?(\w+) ?}}/g, (_, match) => params[match] || '') + return (params: Record) => contents.replace(/{{ ?([\w.]+) ?}}/g, (_, match) => { + const val = get(params, match) + if (!val) { + consola.warn(`cannot resolve template param '${match}' in ${contents.substr(0, 20)}`) + } + return val as string || `${match}` + }) } export function serializeTemplate (contents: string) { @@ -42,16 +50,16 @@ export async function writeFile (file, contents) { consola.info('Generated', prettyPath(file)) } -export function resolvePath (options: SLSOptions, path: UnresolvedPath, resolveBase: string = '') { +export function resolvePath (sigmaContext: SigmaInput, path: string | ((sigmaContext) => string), resolveBase: string = ''): string { if (typeof path === 'function') { - path = path(options) + path = path(sigmaContext) } if (typeof path !== 'string') { throw new TypeError('Invalid path: ' + path) } - path = compileTemplate(path)(options) + path = compileTemplate(path)(sigmaContext) return resolve(resolveBase, path) } @@ -64,22 +72,19 @@ export function detectTarget () { if (process.env.NOW_BUILDER) { return 'vercel' } - - return 'node' } -export function extendTarget (base: SLSTarget, target: SLSTarget): SLSTargetFn { - return (config: SLSConfig) => { - if (typeof target === 'function') { - target = target(config) +export function extendPreset (base: SigmaPreset, preset: SigmaPreset): SigmaPreset { + return (config: SigmaInput) => { + if (typeof preset === 'function') { + preset = preset(config) } if (typeof base === 'function') { base = base(config) } return defu({ - hooks: Hookable.mergeHooks(base.hooks, target.hooks), - nuxtHooks: Hookable.mergeHooks(base.nuxtHooks as any, target.nuxtHooks as any) - }, target, base) + hooks: Hookable.mergeHooks(base.hooks, preset.hooks) + }, preset, base) } } diff --git a/packages/nitro/src/utils/tree.ts b/packages/nitro/src/utils/tree.ts index 862347a907..15dad502b9 100644 --- a/packages/nitro/src/utils/tree.ts +++ b/packages/nitro/src/utils/tree.ts @@ -1,4 +1,4 @@ -import { resolve, dirname, relative } from 'path' +import { resolve, dirname, relative } from 'upath' import globby from 'globby' import prettyBytes from 'pretty-bytes' import gzipSize from 'gzip-size' @@ -30,5 +30,5 @@ export async function printFSTree (dir) { totalGzip += item.gzip }) - process.stdout.write(`${chalk.cyan('λ Total size:')} ${prettyBytes(totalSize)} (${prettyBytes(totalGzip)} gzip)\n`) + process.stdout.write(`${chalk.cyan('Σ Total size:')} ${prettyBytes(totalSize)} (${prettyBytes(totalGzip)} gzip)\n`) } diff --git a/packages/nitro/src/utils/wpfs.ts b/packages/nitro/src/utils/wpfs.ts new file mode 100644 index 0000000000..8636ac8567 --- /dev/null +++ b/packages/nitro/src/utils/wpfs.ts @@ -0,0 +1,7 @@ +import { join } from 'upath' +import fsExtra from 'fs-extra' + +export default { + ...fsExtra, + join +} From 16451a35886224d83906e1d9d8637ebd93d2777b Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Fri, 20 Nov 2020 00:38:35 +0000 Subject: [PATCH 134/227] fix: static dir is in `srcDir` (#37) --- packages/nitro/src/build.ts | 2 +- packages/nitro/src/context.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 4c13bb2d8e..85319ff092 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -38,7 +38,7 @@ export async function generate (sigmaContext: SigmaContext) { join(sigmaContext.output.publicDir, sigmaContext._nuxt.publicPath) ) await copy( - resolve(sigmaContext._nuxt.rootDir, sigmaContext._nuxt.staticDir), + resolve(sigmaContext._nuxt.srcDir, sigmaContext._nuxt.staticDir), sigmaContext.output.publicDir ) } diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 709ce9ddf6..3e3b5dc21a 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -33,6 +33,7 @@ export interface SigmaContext { _nuxt: { dev: boolean rootDir: string + srcDir: string buildDir: string staticDir: string routerBase: string @@ -73,6 +74,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S _nuxt: { dev: nuxtOptions.dev, rootDir: nuxtOptions.rootDir, + srcDir: nuxtOptions.srcDir, buildDir: nuxtOptions.buildDir, staticDir: nuxtOptions.dir.static, routerBase: nuxtOptions.router.base, From ec291dafc1d981b332f9131f039952a540c74914 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 02:38:06 +0100 Subject: [PATCH 135/227] fix issues with generate and dev --- packages/nitro/src/build.ts | 8 +++++++- packages/nitro/src/context.ts | 18 ++++++++++++++---- packages/nitro/src/module/nuxt2.ts | 13 +++++++------ packages/nitro/src/presets/browser.ts | 11 +++++++---- packages/nitro/src/presets/dev.ts | 6 ++++++ packages/nitro/src/presets/vercel.ts | 7 ++++--- packages/nitro/src/server.ts | 2 +- 7 files changed, 46 insertions(+), 19 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 85319ff092..c9ebc5324c 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -12,7 +12,9 @@ export async function build (sigmaContext: SigmaContext) { consola.info(`Sigma preset is ${hl(sigmaContext.preset)}`) // Cleanup output dir - await emptyDir(sigmaContext.output.dir) + if (sigmaContext.output.clean) { + await emptyDir(sigmaContext.output.dir) + } // Compile html template const htmlSrc = resolve(sigmaContext._nuxt.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`) @@ -23,6 +25,7 @@ export async function build (sigmaContext: SigmaContext) { await sigmaContext._internal.hooks.callHook('sigma:template:document', htmlTemplate) await writeFile(htmlTemplate.dst, htmlTemplate.compiled) + // TODO: only when not generate await generate(sigmaContext) sigmaContext.rollupConfig = getRollupConfig(sigmaContext) @@ -33,6 +36,9 @@ export async function build (sigmaContext: SigmaContext) { } export async function generate (sigmaContext: SigmaContext) { + if (!sigmaContext.output.publicDir) { + return + } await copy( resolve(sigmaContext._nuxt.buildDir, 'dist/client'), join(sigmaContext.output.publicDir, sigmaContext._nuxt.publicPath) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 3e3b5dc21a..7d94673130 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -24,17 +24,20 @@ export interface SigmaContext { renderer: string middleware: ServerMiddleware[] hooks: configHooksT + nuxtHooks: configHooksT ignore: string[] output: { dir: string serverDir: string - publicDir: string + publicDir: string | false + clean: boolean } _nuxt: { dev: boolean rootDir: string srcDir: string buildDir: string + generateDir: string staticDir: string routerBase: string publicPath: string @@ -66,16 +69,19 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S middleware: [], ignore: [], hooks: {}, + nuxtHooks: {}, output: { dir: '{{ _nuxt.rootDir }}/.output', serverDir: '{{ output.dir }}/server', - publicDir: '{{ output.dir }}/public' + publicDir: '{{ output.dir }}/public', + clean: true }, _nuxt: { dev: nuxtOptions.dev, rootDir: nuxtOptions.rootDir, srcDir: nuxtOptions.srcDir, buildDir: nuxtOptions.buildDir, + generateDir: nuxtOptions.generate.dir, staticDir: nuxtOptions.dir.static, routerBase: nuxtOptions.router.base, publicPath: nuxtOptions.build.publicPath, @@ -85,7 +91,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S }, _internal: { runtimeDir: resolve(__dirname, '../runtime'), - hooks: undefined + hooks: new Hookable() } } @@ -102,9 +108,13 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S const sigmaContext: SigmaContext = defu(input, _preset, defaults) as any sigmaContext.output.dir = resolvePath(sigmaContext, sigmaContext.output.dir) - sigmaContext.output.publicDir = resolvePath(sigmaContext, sigmaContext.output.publicDir) + sigmaContext.output.publicDir = sigmaContext.output.publicDir + ? resolvePath(sigmaContext, sigmaContext.output.publicDir) + : false sigmaContext.output.serverDir = resolvePath(sigmaContext, sigmaContext.output.serverDir) + sigmaContext._internal.hooks.addHooks(sigmaContext.hooks) + // console.log(sigmaContext) // process.exit(1) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 74072f998d..51d2a1ace4 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -19,15 +19,13 @@ export default function (nuxt) { const sigmaDevContext = getsigmaContext(nuxt.options, { preset: 'dev' }) // Use nuxt as main hooks host - sigmaContext._internal.hooks = nuxt - sigmaDevContext._internal.hooks = nuxt - nuxt.addHooks(sigmaContext.hooks) + nuxt.addHooks(sigmaContext.nuxtHooks) // Replace nuxt server if (nuxt.server) { nuxt.server.__closed = true nuxt.server = createNuxt2DevServer(sigmaDevContext) - nuxt.addHooks(sigmaDevContext.hooks) + nuxt.addHooks(sigmaDevContext.nuxtHooks) } // serverMiddleware bridge @@ -73,10 +71,9 @@ export default function (nuxt) { } // nuxt generate + nuxt.options.generate.dir = sigmaContext.output.publicDir nuxt.hook('generate:cache:ignore', (ignore: string[]) => { ignore.push(sigmaContext.output.dir) - ignore.push(sigmaContext.output.serverDir) - ignore.push(sigmaContext.output.publicDir) ignore.push(...sigmaContext.ignore) }) @@ -85,6 +82,10 @@ export default function (nuxt) { await build(sigmaDevContext) await nuxt.server.reload() }) + + nuxt.hook('generate:done', async () => { + await nuxt.server.close() + }) } function createNuxt2DevServer (sigmaContext: SigmaContext) { diff --git a/packages/nitro/src/presets/browser.ts b/packages/nitro/src/presets/browser.ts index cfd2875615..8fa3191667 100644 --- a/packages/nitro/src/presets/browser.ts +++ b/packages/nitro/src/presets/browser.ts @@ -19,21 +19,24 @@ if ('serviceWorker' in navigator) { output: { dir: '{{ _nuxt.rootDir }}/.output/public', publicDir: '{{ output.dir }}', - serverDir: '{{ output.dir }}' + serverDir: '{{ output.dir }}', + clean: true }, - hooks: { + nuxtHooks: { 'vue-renderer:ssr:templateParams' (params) { params.APP += script }, 'vue-renderer:spa:templateParams' (params) { params.APP += script - }, + } + }, + hooks: { 'sigma:template:document' (tmpl) { tmpl.compiled = tmpl.compiled.replace('', script + '') }, async 'sigma:compiled' ({ output }: SigmaContext) { await writeFile(resolve(output.publicDir, 'index.html'), script) // TODO - consola.info('Ready to deploy to static hosting:', prettyPath(output.publicDir)) + consola.info('Ready to deploy to static hosting:', prettyPath(output.publicDir as string)) } } } diff --git a/packages/nitro/src/presets/dev.ts b/packages/nitro/src/presets/dev.ts index d2e661b569..4910e9edf6 100644 --- a/packages/nitro/src/presets/dev.ts +++ b/packages/nitro/src/presets/dev.ts @@ -4,6 +4,12 @@ import { node } from './node' export const dev: SigmaPreset = extendPreset(node, { entry: '{{ _internal.runtimeDir }}/entries/dev', + // @ts-ignore + output: { + dir: '{{ _nuxt.rootDir }}/node_modules/.cache/sigma', + publicDir: false, + clean: false + }, minify: false, externals: true, inlineChunks: true, diff --git a/packages/nitro/src/presets/vercel.ts b/packages/nitro/src/presets/vercel.ts index b4ed58decf..64c35321dd 100644 --- a/packages/nitro/src/presets/vercel.ts +++ b/packages/nitro/src/presets/vercel.ts @@ -6,8 +6,9 @@ import { node } from './node' export const vercel: SigmaPreset = extendPreset(node, { output: { dir: '{{ _nuxt.rootDir }}/.vercel_build_output', - serverDir: '{{ output.dir }}/functions/node/_nuxt/index.js', - publicDir: '{{ output.dir }}/static' + serverDir: '{{ output.dir }}/functions/node/server/index.js', + publicDir: '{{ output.dir }}/static', + clean: true }, ignore: [ 'vercel.json' @@ -40,7 +41,7 @@ async function writeRoutes ({ output }: SigmaContext) { }, { src: '(.*)', - dest: '/.vercel/functions/_nuxt/index' + dest: '/.vercel/functions/server/index' } ] diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index bdc8f02398..d23b360a3e 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -121,7 +121,7 @@ export function createDevServer (sigmaContext: SigmaContext) { await pendingWorker.terminate() } await Promise.all(listeners.map(l => new Promise((resolve, reject) => { - l.close(err => err ? reject(err) : resolve()) + l.close(err => err ? reject(err) : resolve(undefined)) }))) } sigmaContext._internal.hooks.hook('close', close) From f638a445687af08da8b281c1efbd153856696873 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 02:49:43 +0100 Subject: [PATCH 136/227] fix: use dist for netlify as default --- packages/nitro/src/presets/netlify.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/nitro/src/presets/netlify.ts b/packages/nitro/src/presets/netlify.ts index f4ed81841f..59c608f7eb 100644 --- a/packages/nitro/src/presets/netlify.ts +++ b/packages/nitro/src/presets/netlify.ts @@ -3,6 +3,10 @@ import { SigmaPreset } from '../context' import { lambda } from './lambda' export const netlify: SigmaPreset = extendPreset(lambda, { + // @ts-ignore + output: { + publicDir: '{{ _nuxt.rootDir }}/dist' + }, ignore: [ 'netlify.toml', '_redirects' From 6080927c1602d510d8fd0a168dbcebee07e6409c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 03:22:22 +0100 Subject: [PATCH 137/227] fixes for dev and static target --- packages/nitro/src/context.ts | 4 +++- packages/nitro/src/module/nuxt2.ts | 25 ++++++++++++++++++------- packages/nitro/src/server.ts | 6 ++++-- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 7d94673130..3b2160d182 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -41,6 +41,7 @@ export interface SigmaContext { staticDir: string routerBase: string publicPath: string + isStatic: boolean fullStatic: boolean staticAssets: any } @@ -85,7 +86,8 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S staticDir: nuxtOptions.dir.static, routerBase: nuxtOptions.router.base, publicPath: nuxtOptions.build.publicPath, - fullStatic: nuxtOptions.preset === 'static' && !nuxtOptions._legacyGenerate, + isStatic: nuxtOptions.target === 'static' && !nuxtOptions.dev, + fullStatic: nuxtOptions.target === 'static' && !nuxtOptions._legacyGenerate, // @ts-ignore staticAssets: nuxtOptions.generate.staticAssets }, diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 51d2a1ace4..552f7dcce8 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -18,14 +18,19 @@ export default function (nuxt) { const sigmaContext = getsigmaContext(nuxt.options, nuxt.options.sigma || {}) const sigmaDevContext = getsigmaContext(nuxt.options, { preset: 'dev' }) - // Use nuxt as main hooks host + // Connect hooks nuxt.addHooks(sigmaContext.nuxtHooks) + nuxt.hook('close', () => sigmaContext._internal.hooks.callHook('close')) + + nuxt.addHooks(sigmaDevContext.nuxtHooks) + nuxt.hook('close', () => sigmaDevContext._internal.hooks.callHook('close')) + sigmaDevContext._internal.hooks.hook('renderLoading', + (req, res) => nuxt.callHook('server:nuxt:renderLoading', req, res)) // Replace nuxt server if (nuxt.server) { nuxt.server.__closed = true nuxt.server = createNuxt2DevServer(sigmaDevContext) - nuxt.addHooks(sigmaDevContext.nuxtHooks) } // serverMiddleware bridge @@ -60,12 +65,16 @@ export default function (nuxt) { nuxt.options.build._minifyServer = false nuxt.options.build.standalone = false nuxt.hook('build:done', async () => { - await build(nuxt.options.dev ? sigmaDevContext : sigmaContext) + if (nuxt.options.dev) { + await build(sigmaDevContext) + } else if (!sigmaContext._nuxt.isStatic) { + await build(sigmaContext) + } }) // nude dev if (nuxt.options.dev) { - nuxt.hook('sigma:compiled', () => { nuxt.server.watch() }) + sigmaDevContext._internal.hooks.hook('sigma:compiled', () => { nuxt.server.watch() }) nuxt.hook('build:compile', ({ compiler }) => { compiler.outputFileSystem = wpfs }) nuxt.hook('server:devMiddleware', (m) => { nuxt.server.setDevMiddleware(m) }) } @@ -74,17 +83,19 @@ export default function (nuxt) { nuxt.options.generate.dir = sigmaContext.output.publicDir nuxt.hook('generate:cache:ignore', (ignore: string[]) => { ignore.push(sigmaContext.output.dir) + ignore.push(sigmaContext.output.serverDir) + if (sigmaContext.output.publicDir) { + ignore.push(sigmaContext.output.publicDir) + } ignore.push(...sigmaContext.ignore) }) - - // generate:bfore is before webpack build that we need! nuxt.hook('generate:extendRoutes', async () => { await build(sigmaDevContext) await nuxt.server.reload() }) - nuxt.hook('generate:done', async () => { await nuxt.server.close() + await build(sigmaContext) }) } diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index d23b360a3e..74f8fbe5b8 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -73,11 +73,13 @@ export function createDevServer (sigmaContext: SigmaContext) { const proxy = createProxy() app.use((req, res) => { if (workerAddress) { - proxy.web(req, res, { target: workerAddress }) + proxy.web(req, res, { target: workerAddress }, (err) => { + console.error('[proxy]', err) + }) } else if (loadingMiddleware) { // TODO:serverIndex method is not exposed // loadingMiddleware(req, res) - sigmaContext._internal.hooks.callHook('server:nuxt:renderLoading', req, res) + sigmaContext._internal.hooks.callHook('renderLoading', req, res) } else { res.end('Worker not ready!') } From bde0c7c286c28a3dd4eeae9510ed9dc47f18711b Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 03:34:15 +0100 Subject: [PATCH 138/227] fix: ignore close listeners --- packages/nitro/src/server.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index 74f8fbe5b8..db0e5ab6eb 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -86,7 +86,7 @@ export function createDevServer (sigmaContext: SigmaContext) { }) // Listen - const listeners: Server[] = [] + let listeners: Server[] = [] async function listen (port) { port = await getPort({ name: 'nuxt' }) const listener = await new Promise((resolve, reject) => { @@ -122,9 +122,10 @@ export function createDevServer (sigmaContext: SigmaContext) { if (pendingWorker) { await pendingWorker.terminate() } - await Promise.all(listeners.map(l => new Promise((resolve, reject) => { - l.close(err => err ? reject(err) : resolve(undefined)) + await Promise.all(listeners.map(l => new Promise((resolve) => { + l.close(() => resolve()) }))) + listeners = [] } sigmaContext._internal.hooks.hook('close', close) From b15d16abd3b7aa9bdb29f83f1e7a842c3189af72 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 12:55:55 +0100 Subject: [PATCH 139/227] fix: support both targets by adding prepare step --- packages/nitro/src/build.ts | 59 +++++++++++-------- packages/nitro/src/context.ts | 14 ++--- packages/nitro/src/module/nuxt2.ts | 9 ++- packages/nitro/src/presets/browser.ts | 9 +-- packages/nitro/src/presets/index.ts | 2 +- .../nitro/src/presets/{dev.ts => local.ts} | 8 +-- packages/nitro/src/presets/vercel.ts | 3 +- 7 files changed, 54 insertions(+), 50 deletions(-) rename packages/nitro/src/presets/{dev.ts => local.ts} (52%) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index c9ebc5324c..9f8e07015e 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -5,17 +5,43 @@ import ora from 'ora' import { readFile, emptyDir, copy } from 'fs-extra' import { printFSTree } from './utils/tree' import { getRollupConfig } from './rollup/config' -import { hl, serializeTemplate, writeFile } from './utils' +import { hl, prettyPath, serializeTemplate, writeFile } from './utils' import { SigmaContext } from './context' -export async function build (sigmaContext: SigmaContext) { +export async function prepare (sigmaContext: SigmaContext) { consola.info(`Sigma preset is ${hl(sigmaContext.preset)}`) - // Cleanup output dir - if (sigmaContext.output.clean) { - await emptyDir(sigmaContext.output.dir) + await cleanupDir(sigmaContext.output.dir) + + if (!sigmaContext.output.publicDir.startsWith(sigmaContext.output.dir)) { + await cleanupDir(sigmaContext.output.publicDir) } + if (!sigmaContext.output.serverDir.startsWith(sigmaContext.output.dir)) { + await cleanupDir(sigmaContext.output.serverDir) + } +} + +async function cleanupDir (dir: string) { + consola.info('Cleaning up', prettyPath(dir)) + await emptyDir(dir) +} + +export async function generate (sigmaContext: SigmaContext) { + const spinner = ora() + spinner.start('Generating public...') + await copy( + resolve(sigmaContext._nuxt.buildDir, 'dist/client'), + join(sigmaContext.output.publicDir, sigmaContext._nuxt.publicPath) + ) + await copy( + resolve(sigmaContext._nuxt.srcDir, sigmaContext._nuxt.staticDir), + sigmaContext.output.publicDir + ) + spinner.succeed('Generated public ' + prettyPath(sigmaContext.output.publicDir)) +} + +export async function build (sigmaContext: SigmaContext) { // Compile html template const htmlSrc = resolve(sigmaContext._nuxt.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`) const htmlTemplate = { src: htmlSrc, contents: '', dst: '', compiled: '' } @@ -25,30 +51,11 @@ export async function build (sigmaContext: SigmaContext) { await sigmaContext._internal.hooks.callHook('sigma:template:document', htmlTemplate) await writeFile(htmlTemplate.dst, htmlTemplate.compiled) - // TODO: only when not generate - await generate(sigmaContext) - sigmaContext.rollupConfig = getRollupConfig(sigmaContext) - await sigmaContext._internal.hooks.callHook('sigma:rollup:before', sigmaContext) - return sigmaContext._nuxt.dev ? _watch(sigmaContext) : _build(sigmaContext) } -export async function generate (sigmaContext: SigmaContext) { - if (!sigmaContext.output.publicDir) { - return - } - await copy( - resolve(sigmaContext._nuxt.buildDir, 'dist/client'), - join(sigmaContext.output.publicDir, sigmaContext._nuxt.publicPath) - ) - await copy( - resolve(sigmaContext._nuxt.srcDir, sigmaContext._nuxt.staticDir), - sigmaContext.output.publicDir - ) -} - async function _build (sigmaContext: SigmaContext) { const spinner = ora() @@ -58,10 +65,10 @@ async function _build (sigmaContext: SigmaContext) { throw error }) - spinner.start('Wrting Sigma bundle...') + spinner.start('Wrting server bundle...') await build.write(sigmaContext.rollupConfig.output) - spinner.succeed('Sigma built') + spinner.succeed('Server built') await printFSTree(sigmaContext.output.serverDir) await sigmaContext._internal.hooks.callHook('sigma:compiled', sigmaContext) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 3b2160d182..44210f7237 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -29,8 +29,7 @@ export interface SigmaContext { output: { dir: string serverDir: string - publicDir: string | false - clean: boolean + publicDir: string } _nuxt: { dev: boolean @@ -51,7 +50,9 @@ export interface SigmaContext { } } -export interface SigmaInput extends Partial {} +type DeepPartial = { [P in keyof T]?: DeepPartial } + +export interface SigmaInput extends DeepPartial {} export type SigmaPreset = SigmaInput | ((input: SigmaInput) => SigmaInput) @@ -74,8 +75,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S output: { dir: '{{ _nuxt.rootDir }}/.output', serverDir: '{{ output.dir }}/server', - publicDir: '{{ output.dir }}/public', - clean: true + publicDir: '{{ output.dir }}/public' }, _nuxt: { dev: nuxtOptions.dev, @@ -110,9 +110,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S const sigmaContext: SigmaContext = defu(input, _preset, defaults) as any sigmaContext.output.dir = resolvePath(sigmaContext, sigmaContext.output.dir) - sigmaContext.output.publicDir = sigmaContext.output.publicDir - ? resolvePath(sigmaContext, sigmaContext.output.publicDir) - : false + sigmaContext.output.publicDir = resolvePath(sigmaContext, sigmaContext.output.publicDir) sigmaContext.output.serverDir = resolvePath(sigmaContext, sigmaContext.output.serverDir) sigmaContext._internal.hooks.addHooks(sigmaContext.hooks) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 552f7dcce8..edfa8219aa 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -1,6 +1,6 @@ import fetch from 'node-fetch' import { resolve } from 'upath' -import { build } from '../build' +import { build, generate, prepare } from '../build' import { getsigmaContext, SigmaContext } from '../context' import { createDevServer } from '../server' import wpfs from '../utils/wpfs' @@ -16,7 +16,7 @@ export default function (nuxt) { // Create contexts const sigmaContext = getsigmaContext(nuxt.options, nuxt.options.sigma || {}) - const sigmaDevContext = getsigmaContext(nuxt.options, { preset: 'dev' }) + const sigmaDevContext = getsigmaContext(nuxt.options, { preset: 'local' }) // Connect hooks nuxt.addHooks(sigmaContext.nuxtHooks) @@ -68,6 +68,8 @@ export default function (nuxt) { if (nuxt.options.dev) { await build(sigmaDevContext) } else if (!sigmaContext._nuxt.isStatic) { + await prepare(sigmaContext) + await generate(sigmaContext) await build(sigmaContext) } }) @@ -89,6 +91,9 @@ export default function (nuxt) { } ignore.push(...sigmaContext.ignore) }) + nuxt.hook('generate:before', async () => { + await prepare(sigmaContext) + }) nuxt.hook('generate:extendRoutes', async () => { await build(sigmaDevContext) await nuxt.server.reload() diff --git a/packages/nitro/src/presets/browser.ts b/packages/nitro/src/presets/browser.ts index 8fa3191667..64275712b1 100644 --- a/packages/nitro/src/presets/browser.ts +++ b/packages/nitro/src/presets/browser.ts @@ -9,7 +9,7 @@ export const browser: SigmaPreset = extendPreset(worker, (input: SigmaInput) => const script = `` @@ -17,10 +17,7 @@ if ('serviceWorker' in navigator) { return { entry: '{{ _internal.runtimeDir }}/entries/service-worker', output: { - dir: '{{ _nuxt.rootDir }}/.output/public', - publicDir: '{{ output.dir }}', - serverDir: '{{ output.dir }}', - clean: true + serverDir: '{{ output.dir }}/public/_server' }, nuxtHooks: { 'vue-renderer:ssr:templateParams' (params) { @@ -35,7 +32,7 @@ if ('serviceWorker' in navigator) { tmpl.compiled = tmpl.compiled.replace('', script + '') }, async 'sigma:compiled' ({ output }: SigmaContext) { - await writeFile(resolve(output.publicDir, 'index.html'), script) // TODO + await writeFile(resolve(output.publicDir, 'sw.js'), 'self.importScripts(\'/server/index.js\');') consola.info('Ready to deploy to static hosting:', prettyPath(output.publicDir as string)) } } diff --git a/packages/nitro/src/presets/index.ts b/packages/nitro/src/presets/index.ts index c59d83d2fb..be1e44a1a7 100644 --- a/packages/nitro/src/presets/index.ts +++ b/packages/nitro/src/presets/index.ts @@ -3,7 +3,7 @@ export * from './cloudflare' export * from './lambda' export * from './netlify' export * from './node' -export * from './dev' +export * from './local' export * from './server' export * from './cli' export * from './vercel' diff --git a/packages/nitro/src/presets/dev.ts b/packages/nitro/src/presets/local.ts similarity index 52% rename from packages/nitro/src/presets/dev.ts rename to packages/nitro/src/presets/local.ts index 4910e9edf6..f3c44f352f 100644 --- a/packages/nitro/src/presets/dev.ts +++ b/packages/nitro/src/presets/local.ts @@ -2,13 +2,11 @@ import { extendPreset } from '../utils' import { SigmaPreset } from '../context' import { node } from './node' -export const dev: SigmaPreset = extendPreset(node, { - entry: '{{ _internal.runtimeDir }}/entries/dev', +export const local: SigmaPreset = extendPreset(node, { + entry: '{{ _internal.runtimeDir }}/entries/local', // @ts-ignore output: { - dir: '{{ _nuxt.rootDir }}/node_modules/.cache/sigma', - publicDir: false, - clean: false + dir: '{{ _nuxt.rootDir }}/node_modules/.cache/sigma' }, minify: false, externals: true, diff --git a/packages/nitro/src/presets/vercel.ts b/packages/nitro/src/presets/vercel.ts index 64c35321dd..3569434132 100644 --- a/packages/nitro/src/presets/vercel.ts +++ b/packages/nitro/src/presets/vercel.ts @@ -7,8 +7,7 @@ export const vercel: SigmaPreset = extendPreset(node, { output: { dir: '{{ _nuxt.rootDir }}/.vercel_build_output', serverDir: '{{ output.dir }}/functions/node/server/index.js', - publicDir: '{{ output.dir }}/static', - clean: true + publicDir: '{{ output.dir }}/static' }, ignore: [ 'vercel.json' From 1524377708e6cbb429dbfd084a7382a533f9ff83 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 12:56:51 +0100 Subject: [PATCH 140/227] fix ts error --- packages/nitro/src/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index db0e5ab6eb..476c441465 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -123,7 +123,7 @@ export function createDevServer (sigmaContext: SigmaContext) { await pendingWorker.terminate() } await Promise.all(listeners.map(l => new Promise((resolve) => { - l.close(() => resolve()) + l.close(() => resolve(undefined)) }))) listeners = [] } From 15fff5117fc4ad54f8b934b99a246dbba4883bf6 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 13:04:16 +0100 Subject: [PATCH 141/227] fix(vercel): remove index.js from serverDir --- packages/nitro/src/presets/vercel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/presets/vercel.ts b/packages/nitro/src/presets/vercel.ts index 3569434132..c1109c5bde 100644 --- a/packages/nitro/src/presets/vercel.ts +++ b/packages/nitro/src/presets/vercel.ts @@ -6,7 +6,7 @@ import { node } from './node' export const vercel: SigmaPreset = extendPreset(node, { output: { dir: '{{ _nuxt.rootDir }}/.vercel_build_output', - serverDir: '{{ output.dir }}/functions/node/server/index.js', + serverDir: '{{ output.dir }}/functions/node/server', publicDir: '{{ output.dir }}/static' }, ignore: [ From cb98031cff942b14d71e12f751a17be165972bac Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 13:14:16 +0100 Subject: [PATCH 142/227] fix: cloudflare and polyfill --- packages/nitro/src/presets/cloudflare.ts | 6 +++++- packages/nitro/src/rollup/config.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/presets/cloudflare.ts b/packages/nitro/src/presets/cloudflare.ts index 43715ac0fb..cc6a2603dd 100644 --- a/packages/nitro/src/presets/cloudflare.ts +++ b/packages/nitro/src/presets/cloudflare.ts @@ -13,7 +13,11 @@ export const cloudflare: SigmaPreset = extendPreset(worker, { async 'sigma:compiled' ({ output, _nuxt }: SigmaContext) { await writeFile(resolve(output.dir, 'package.json'), JSON.stringify({ private: true, main: './server/index.js' }, null, 2)) await writeFile(resolve(output.dir, 'package-lock.json'), JSON.stringify({ lockfileVersion: 1 }, null, 2)) - consola.success('Ready to run `wrangler publish` in', prettyPath(_nuxt.rootDir)) + let inDir = prettyPath(_nuxt.rootDir) + if (inDir) { + inDir = 'in ' + inDir + } + consola.success('Ready to run `wrangler publish`', inDir) } } }) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index a939feb191..a4dfd1abd4 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -132,7 +132,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { // Polyfill rollupConfig.plugins.push(virtual({ - '~polyfill': env.polyfill.map(p => `require('${p}');`).join('\n') + '~polyfill': env.polyfill.map(p => `import '${p}';`).join('\n') })) // https://github.com/rollup/plugins/tree/master/packages/alias From d3d3c0a2ea1f8e4a2fd7106ca74cf75378dcdb86 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 13:49:21 +0100 Subject: [PATCH 143/227] fix(vercel): entry should export handle as default --- packages/nitro/src/presets/vercel.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nitro/src/presets/vercel.ts b/packages/nitro/src/presets/vercel.ts index c1109c5bde..eb117055a2 100644 --- a/packages/nitro/src/presets/vercel.ts +++ b/packages/nitro/src/presets/vercel.ts @@ -4,6 +4,7 @@ import { SigmaPreset, SigmaContext } from '../context' import { node } from './node' export const vercel: SigmaPreset = extendPreset(node, { + entry: '{{ _internal.runtimeDir }}/entries/vercel', output: { dir: '{{ _nuxt.rootDir }}/.vercel_build_output', serverDir: '{{ output.dir }}/functions/node/server', From a7d158798c026fd3a072d275eecd8d9427a77fea Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 14:31:14 +0100 Subject: [PATCH 144/227] feat: add $fetch to client --- packages/nitro/src/index.ts | 2 +- packages/nitro/src/module/nuxt2.ts | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 8c14ac283c..01b14171aa 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -2,5 +2,5 @@ import nuxt2 from './module/nuxt2' export default function () { const { nuxt } = this - return nuxt2(nuxt) + return nuxt2(nuxt, this) } diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index edfa8219aa..4d3ff921b1 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -5,7 +5,7 @@ import { getsigmaContext, SigmaContext } from '../context' import { createDevServer } from '../server' import wpfs from '../utils/wpfs' -export default function (nuxt) { +export default function (nuxt, moduleContainer) { // Build in node_modules/.cache/nuxt const oldBuildDir = nuxt.options.buildDir nuxt.options.buildDir = resolve(nuxt.options.rootDir, 'node_modules/.cache/nuxt') @@ -33,6 +33,12 @@ export default function (nuxt) { nuxt.server = createNuxt2DevServer(sigmaDevContext) } + // $fetch support in client + moduleContainer.addPlugin({ + fileName: 'fetch.client.js', + src: resolve(sigmaContext._internal.runtimeDir, 'app/fetch.client.js') + }) + // serverMiddleware bridge // TODO: render:setupMiddleware hook // TODO: support m.prefix and m.route From abf65f21761bbff7ace8d4871c94bc07448266c9 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 14:46:55 +0100 Subject: [PATCH 145/227] feat: sigma.client --- packages/nitro/src/module/nuxt2.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 4d3ff921b1..3fee09c3f8 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -33,10 +33,10 @@ export default function (nuxt, moduleContainer) { nuxt.server = createNuxt2DevServer(sigmaDevContext) } - // $fetch support in client + // Sigma client plugin moduleContainer.addPlugin({ - fileName: 'fetch.client.js', - src: resolve(sigmaContext._internal.runtimeDir, 'app/fetch.client.js') + fileName: 'sigma.client.js', + src: resolve(sigmaContext._internal.runtimeDir, 'app/sigma.client.js') }) // serverMiddleware bridge From 37c7e892d5998a513a35d4879fd969943d93f03c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 14:57:02 +0100 Subject: [PATCH 146/227] fix: add temp fix for browser --- packages/nitro/src/presets/browser.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/presets/browser.ts b/packages/nitro/src/presets/browser.ts index 64275712b1..1b5c4d42e1 100644 --- a/packages/nitro/src/presets/browser.ts +++ b/packages/nitro/src/presets/browser.ts @@ -32,7 +32,13 @@ if ('serviceWorker' in navigator) { tmpl.compiled = tmpl.compiled.replace('', script + '') }, async 'sigma:compiled' ({ output }: SigmaContext) { - await writeFile(resolve(output.publicDir, 'sw.js'), 'self.importScripts(\'/server/index.js\');') + await writeFile(resolve(output.publicDir, 'sw.js'), 'self.importScripts(\'/_server/index.js\');') + + // Temp fix + await writeFile(resolve(output.publicDir, 'index.html'), script) + await writeFile(resolve(output.publicDir, '200.html'), script) + await writeFile(resolve(output.publicDir, '404.html'), script) + consola.info('Ready to deploy to static hosting:', prettyPath(output.publicDir as string)) } } From 0b51fb3bc31e4c470a747660d28df955d3d1ad2a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 15:25:40 +0100 Subject: [PATCH 147/227] register page for browser --- packages/nitro/src/presets/browser.ts | 43 +++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/presets/browser.ts b/packages/nitro/src/presets/browser.ts index 1b5c4d42e1..5e262ad882 100644 --- a/packages/nitro/src/presets/browser.ts +++ b/packages/nitro/src/presets/browser.ts @@ -6,14 +6,47 @@ import { SigmaPreset, SigmaContext, SigmaInput } from '../context' import { worker } from './worker' export const browser: SigmaPreset = extendPreset(worker, (input: SigmaInput) => { + const routerBase = input._nuxt.routerBase + const script = `` + // TEMP FIX + const html = ` + + + + + + + + + + Loading... + + +` + return { entry: '{{ _internal.runtimeDir }}/entries/service-worker', output: { @@ -32,12 +65,12 @@ if ('serviceWorker' in navigator) { tmpl.compiled = tmpl.compiled.replace('', script + '') }, async 'sigma:compiled' ({ output }: SigmaContext) { - await writeFile(resolve(output.publicDir, 'sw.js'), 'self.importScripts(\'/_server/index.js\');') + await writeFile(resolve(output.publicDir, 'sw.js'), `self.importScripts('${input._nuxt.routerBase}_server/index.js');`) // Temp fix - await writeFile(resolve(output.publicDir, 'index.html'), script) - await writeFile(resolve(output.publicDir, '200.html'), script) - await writeFile(resolve(output.publicDir, '404.html'), script) + await writeFile(resolve(output.publicDir, 'index.html'), html) + await writeFile(resolve(output.publicDir, '200.html'), html) + await writeFile(resolve(output.publicDir, '404.html'), html) consola.info('Ready to deploy to static hosting:', prettyPath(output.publicDir as string)) } From 02a66ab40c6e1e438ba00c48c681a4711f18a23a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 15:34:47 +0100 Subject: [PATCH 148/227] feat: expose process.env.SIGMA_PRESET --- packages/nitro/src/module/nuxt2.ts | 3 +++ packages/nitro/src/rollup/config.ts | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 3fee09c3f8..9682cdc27a 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -27,6 +27,9 @@ export default function (nuxt, moduleContainer) { sigmaDevContext._internal.hooks.hook('renderLoading', (req, res) => nuxt.callHook('server:nuxt:renderLoading', req, res)) + // Expose process.env.SIGMA_PRESET + nuxt.options.env.SIGMA_PRESET = sigmaContext.preset + // Replace nuxt server if (nuxt.server) { nuxt.server.__closed = true diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index a4dfd1abd4..66d6cb89e5 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -92,7 +92,8 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { 'process.env.NUXT_STATIC_BASE': JSON.stringify(sigmaContext._nuxt.staticAssets.base), 'process.env.NUXT_STATIC_VERSION': JSON.stringify(sigmaContext._nuxt.staticAssets.version), // @ts-ignore - 'process.env.NUXT_FULL_STATIC': sigmaContext.fullStatic + 'process.env.NUXT_FULL_STATIC': sigmaContext.fullStatic, + 'process.env.SIGMA_PRESET': JSON.stringify(sigmaContext.preset) } })) From cd0dd009e0c1d62f8c770961f69057a09a69b524 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 21:06:59 +0100 Subject: [PATCH 149/227] feat: use h2@10 --- packages/nitro/src/context.ts | 3 ++- packages/nitro/src/rollup/config.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 44210f7237..bb713abc55 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -8,7 +8,8 @@ import * as PRESETS from './presets' export interface ServerMiddleware { route: string handle: string - lazy?: boolean + lazy?: boolean // Default is true + promisify?: boolean // Default is true } export interface SigmaContext { diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 66d6cb89e5..4e45645ac7 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -126,7 +126,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { ${sigmaContext.middleware.filter(m => m.lazy).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} export default [ - ${sigmaContext.middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || false} }`).join(',\n')} + ${sigmaContext.middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify || true} }`).join(',\n')} ]; ` })) From 68fc2082994c641a195c18d49d1ac861c2dc369e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 21:11:46 +0100 Subject: [PATCH 150/227] fix: lazy is true by default --- packages/nitro/src/rollup/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 4e45645ac7..a498fbcb03 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -121,9 +121,9 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { const getImportId = p => '_' + hasha(p).substr(0, 6) rollupConfig.plugins.push(virtual({ '~serverMiddleware': ` - ${sigmaContext.middleware.filter(m => !m.lazy).map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} + ${sigmaContext.middleware.filter(m => m.lazy === false).map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} - ${sigmaContext.middleware.filter(m => m.lazy).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} + ${sigmaContext.middleware.filter(m => m.lazy !== false).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} export default [ ${sigmaContext.middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify || true} }`).join(',\n')} From 82f6db6bcaa90ea4a9477ae67696b8b2e8be4ce9 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 21:13:23 +0100 Subject: [PATCH 151/227] fix: promisify: false support --- packages/nitro/src/rollup/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index a498fbcb03..437533610f 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -126,7 +126,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { ${sigmaContext.middleware.filter(m => m.lazy !== false).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} export default [ - ${sigmaContext.middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify || true} }`).join(',\n')} + ${sigmaContext.middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify !== undefined ? m.promisify : true} }`).join(',\n')} ]; ` })) From 5c8ac226f1a64268b8248a21947e7feaf40c451e Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 22:04:48 +0100 Subject: [PATCH 152/227] fix: hide rollup circular and eval --- packages/nitro/src/rollup/config.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 437533610f..e76d91cd91 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -75,7 +75,12 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { preferConst: true }, external, - plugins: [] + plugins: [], + onwarn (warning, rollupWarn) { + if (!['CIRCULAR_DEPENDENCY', 'EVAL'].includes(warning.code)) { + rollupWarn(warning) + } + } } if (sigmaContext.timing) { From b5b585c0c80fac688947433df0a73d5d6a823397 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 22:08:57 +0100 Subject: [PATCH 153/227] feat: automatically mock unresolved externals --- packages/nitro/src/rollup/automock.ts | 16 ++++++++++++++++ packages/nitro/src/rollup/config.ts | 4 ++++ 2 files changed, 20 insertions(+) create mode 100644 packages/nitro/src/rollup/automock.ts diff --git a/packages/nitro/src/rollup/automock.ts b/packages/nitro/src/rollup/automock.ts new file mode 100644 index 0000000000..7cec8a51f5 --- /dev/null +++ b/packages/nitro/src/rollup/automock.ts @@ -0,0 +1,16 @@ +import consola from 'consola' + +export function autoMock () { + return { + name: 'auto-mock', + resolveId (src: string) { + if (src && !src.startsWith('.') && !src.includes('?') && !src.includes('.js')) { + consola.info('Automatically mocking', src) + return { + id: require.resolve('@nuxt/un/runtime/mock/proxy') + } + } + return null + } + } +} diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index e76d91cd91..8e811154d9 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -19,6 +19,7 @@ import { resolvePath, MODULE_DIR } from '../utils' import { dynamicRequire } from './dynamic-require' import { externals } from './externals' import { timing } from './timing' +import { autoMock } from './automock' export type RollupConfig = InputOptions & { output: OutputOptions } @@ -179,6 +180,9 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) })) + // Automatically mock unresolved externals + rollupConfig.plugins.push(autoMock()) + // https://github.com/rollup/plugins/tree/master/packages/commonjs rollupConfig.plugins.push(commonjs({ extensions: extensions.filter(ext => ext !== '.json') From 6794b01404d99e58b9bbab677a1c2fa79bcefb05 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 20 Nov 2020 22:09:53 +0100 Subject: [PATCH 154/227] chore: hide automock warn --- packages/nitro/src/rollup/automock.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/nitro/src/rollup/automock.ts b/packages/nitro/src/rollup/automock.ts index 7cec8a51f5..7393c5820d 100644 --- a/packages/nitro/src/rollup/automock.ts +++ b/packages/nitro/src/rollup/automock.ts @@ -1,11 +1,8 @@ -import consola from 'consola' - export function autoMock () { return { name: 'auto-mock', resolveId (src: string) { if (src && !src.startsWith('.') && !src.includes('?') && !src.includes('.js')) { - consola.info('Automatically mocking', src) return { id: require.resolve('@nuxt/un/runtime/mock/proxy') } From ba0943aa22ab42a8a011ec058353602b60c0a5cb Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 21 Nov 2020 12:06:51 +0100 Subject: [PATCH 155/227] revert back auto mock warning --- packages/nitro/src/rollup/automock.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/nitro/src/rollup/automock.ts b/packages/nitro/src/rollup/automock.ts index 7393c5820d..f5aad11b10 100644 --- a/packages/nitro/src/rollup/automock.ts +++ b/packages/nitro/src/rollup/automock.ts @@ -1,8 +1,11 @@ +import consola from 'consola' + export function autoMock () { return { name: 'auto-mock', resolveId (src: string) { if (src && !src.startsWith('.') && !src.includes('?') && !src.includes('.js')) { + consola.warn('Auto mock external ', src) return { id: require.resolve('@nuxt/un/runtime/mock/proxy') } From 227e04b92e3bfa2f00054f5f973296104039546a Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 21 Nov 2020 12:42:02 +0100 Subject: [PATCH 156/227] feat: improved env support --- packages/nitro/src/context.ts | 3 +++ packages/nitro/src/rollup/config.ts | 39 +++++++++++++++++------------ 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index bb713abc55..44d45fde09 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -2,6 +2,7 @@ import { resolve } from 'upath' import defu from 'defu' import type { NuxtOptions } from '@nuxt/types' import Hookable, { configHooksT } from 'hookable' +import type { Preset } from '@nuxt/un' import { tryImport, resolvePath, detectTarget, extendPreset } from './utils' import * as PRESETS from './presets' @@ -27,6 +28,7 @@ export interface SigmaContext { hooks: configHooksT nuxtHooks: configHooksT ignore: string[] + env: Preset output: { dir: string serverDir: string @@ -71,6 +73,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S renderer: undefined, middleware: [], ignore: [], + env: {}, hooks: {}, nuxtHooks: {}, output: { diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 8e811154d9..5f5e6a230b 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -1,4 +1,3 @@ -import Module from 'module' import { dirname, join, relative, resolve } from 'upath' import { InputOptions, OutputOptions } from 'rollup' import { terser } from 'rollup-plugin-terser' @@ -10,6 +9,7 @@ import replace from '@rollup/plugin-replace' import virtual from '@rollup/plugin-virtual' import inject from '@rollup/plugin-inject' import analyze from 'rollup-plugin-analyzer' +import type { Preset } from '@nuxt/un' import * as un from '@nuxt/un' import hasha from 'hasha' @@ -24,24 +24,31 @@ import { autoMock } from './automock' export type RollupConfig = InputOptions & { output: OutputOptions } export const getRollupConfig = (sigmaContext: SigmaContext) => { - const extensions: string[] = ['.ts', '.js', '.json', '.node'] + const extensions: string[] = ['.ts', '.mjs', '.js', '.json', '.node'] - const external: InputOptions['external'] = [] + const nodePreset = sigmaContext.node === false ? un.nodeless : un.node - const presets = [] - - if (sigmaContext.node === false) { - presets.push(un.nodeless) - } else { - presets.push(un.node) - external.push(...Module.builtinModules) + const builtinPreset: Preset = { + alias: { + // General + depd: require.resolve('@nuxt/un/runtime/npm/depd'), + // Vue 2 + encoding: 'un/mock/proxy', + he: 'un/mock/proxy', + resolve: 'un/mock/proxy', + 'source-map': 'un/mock/proxy', + 'lodash.template': 'un/mock/proxy', + 'serialize-javascript': 'un/mock/proxy', + // Vue 3 + '@babel/parser': 'un/mock/proxy', + '@vue/compiler-core': 'un/mock/proxy', + '@vue/compiler-dom': 'un/mock/proxy', + '@vue/compiler-ssr': 'un/mock/proxy' + } } - const env = un.env(...presets, { - alias: { - depd: require.resolve('@nuxt/un/runtime/npm/depd') - } - }) + const env = un.env(nodePreset, builtinPreset, sigmaContext.env) + // console.log(env) const buildServerDir = join(sigmaContext._nuxt.buildDir, 'dist/server') const runtimeAppDir = join(sigmaContext._internal.runtimeDir, 'app') @@ -75,7 +82,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { outro: '', preferConst: true }, - external, + external: env.external, plugins: [], onwarn (warning, rollupWarn) { if (!['CIRCULAR_DEPENDENCY', 'EVAL'].includes(warning.code)) { From 04fc395149b45ead0dff6e8dc18693708ec55601 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 21 Nov 2020 12:42:46 +0100 Subject: [PATCH 157/227] chore: unnecessary resolve --- packages/nitro/src/rollup/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 5f5e6a230b..d0c36e1ba1 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -31,7 +31,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { const builtinPreset: Preset = { alias: { // General - depd: require.resolve('@nuxt/un/runtime/npm/depd'), + depd: 'un/runtime/npm/depd', // Vue 2 encoding: 'un/mock/proxy', he: 'un/mock/proxy', From dbce482b7e2cb873d038be0ba4dae746c4385f66 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 21 Nov 2020 14:55:41 +0100 Subject: [PATCH 158/227] feat: improved sever timing --- packages/nitro/src/rollup/timing.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/timing.ts b/packages/nitro/src/rollup/timing.ts index b5cc67170f..23bc2847e3 100644 --- a/packages/nitro/src/rollup/timing.ts +++ b/packages/nitro/src/rollup/timing.ts @@ -30,7 +30,7 @@ export function timing (_opts: Options = {}): Plugin { renderChunk (code, chunk: RenderedChunk) { let name = chunk.fileName || '' name = name.replace(extname(name), '') - const logName = name === 'index' ? 'entry' : name + const logName = name === 'index' ? 'Cold Start' : ('Load ' + name) return "'use strict';" + (chunk.isEntry ? HELPER : '') + `${TIMING}.logStart('${logName}');` + code + `;${TIMING}.logEnd('${logName}');` } } From 1f5e82a5bc966fc2eda93679a5042cd2ffc74d20 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 21 Nov 2020 14:58:24 +0100 Subject: [PATCH 159/227] fix NUXT_FULL_STATIC --- packages/nitro/src/rollup/config.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index d0c36e1ba1..2424c31cb9 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -104,8 +104,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { 'process.env.PUBLIC_PATH': JSON.stringify(sigmaContext._nuxt.publicPath), 'process.env.NUXT_STATIC_BASE': JSON.stringify(sigmaContext._nuxt.staticAssets.base), 'process.env.NUXT_STATIC_VERSION': JSON.stringify(sigmaContext._nuxt.staticAssets.version), - // @ts-ignore - 'process.env.NUXT_FULL_STATIC': sigmaContext.fullStatic, + 'process.env.NUXT_FULL_STATIC': sigmaContext._nuxt.fullStatic as unknown as string, 'process.env.SIGMA_PRESET': JSON.stringify(sigmaContext.preset) } })) From 531f6b1e083baebd0763bbfd5a1c2bcc7ba0b8f9 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sun, 22 Nov 2020 22:54:08 +0100 Subject: [PATCH 160/227] fix: remove runtime/ prefix --- packages/nitro/src/rollup/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 2424c31cb9..181f03279c 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -31,7 +31,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { const builtinPreset: Preset = { alias: { // General - depd: 'un/runtime/npm/depd', + depd: 'un/npm/depd', // Vue 2 encoding: 'un/mock/proxy', he: 'un/mock/proxy', From 976dff7ce1e5021e64acc8fca71c4e305b2c58ad Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Sat, 28 Nov 2020 11:50:55 +0000 Subject: [PATCH 161/227] feat: add azure functions preset (#45) --- packages/nitro/src/presets/azure.ts | 117 ++++++++++++++++++++++++++++ packages/nitro/src/presets/index.ts | 1 + 2 files changed, 118 insertions(+) create mode 100644 packages/nitro/src/presets/azure.ts diff --git a/packages/nitro/src/presets/azure.ts b/packages/nitro/src/presets/azure.ts new file mode 100644 index 0000000000..14bd9f4ced --- /dev/null +++ b/packages/nitro/src/presets/azure.ts @@ -0,0 +1,117 @@ +import replace from '@rollup/plugin-replace' +import archiver from 'archiver' +import consola from 'consola' +import createEtag from 'etag' +import { createWriteStream, readdirSync, readFileSync, statSync } from 'fs-extra' +import mime from 'mime' +import { join, relative, resolve } from 'upath' + +import { prettyPath, writeFile } from '../utils' +import { SigmaPreset, SigmaContext } from '../context' + +export const azure: SigmaPreset = { + inlineChunks: false, + entry: '{{ _internal.runtimeDir }}/entries/azure', + hooks: { + 'sigma:rollup:before' (ctx: SigmaContext) { + const manifest = JSON.stringify(getStaticManifest(ctx)).replace(/\\"/g, '\\\\"') + ctx.rollupConfig.plugins.push(replace({ + values: { + 'process.env.STATIC_MANIFEST': `\`${manifest}\`` + } + })) + }, + async 'sigma:compiled' (ctx: SigmaContext) { + await writeRoutes(ctx) + } + } +} + +function getStaticManifest ({ output: { dir } }: SigmaContext) { + const files = [] + const staticRoot = resolve(dir, 'public') + + const addFiles = (directory: string) => { + const listing = readdirSync(directory) + listing.forEach((filename) => { + const fullPath = resolve(directory, filename) + if (statSync(fullPath).isDirectory()) { + return addFiles(fullPath) + } + files.push('/' + relative(staticRoot, fullPath)) + }) + } + + addFiles(staticRoot) + const metadata = files.reduce((metadata, filename) => { + let mimeType = mime.getType(filename) || 'text/plain' + if (mimeType.startsWith('text')) { + mimeType += '; charset=utf-8' + } + const etag = createEtag(readFileSync(join(staticRoot, filename))) + metadata[filename] = [mimeType, etag] + return metadata + }, {} as Record) + + return { + files, + metadata + } +} + +function zipDirectory (dir: string, outfile: string): Promise { + const archive = archiver('zip', { zlib: { level: 9 } }) + const stream = createWriteStream(outfile) + + return new Promise((resolve, reject) => { + archive + .directory(dir, false) + .on('error', (err: Error) => reject(err)) + .pipe(stream) + + stream.on('close', () => resolve(undefined)) + archive.finalize() + }) +} + +async function writeRoutes ({ output: { dir, serverDir } }: SigmaContext) { + const host = { + version: '2.0', + extensions: { http: { routePrefix: '' } } + } + + const functionDefinition = { + entryPoint: 'handle', + bindings: [ + { + authLevel: 'anonymous', + type: 'httpTrigger', + direction: 'in', + name: 'req', + route: '{*url}', + methods: [ + 'delete', + 'get', + 'head', + 'options', + 'patch', + 'post', + 'put' + ] + }, + { + type: 'http', + direction: 'out', + name: 'res' + } + ] + } + + await writeFile(resolve(serverDir, 'function.json'), JSON.stringify(functionDefinition)) + await writeFile(resolve(dir, 'host.json'), JSON.stringify(host)) + + await zipDirectory(dir, join(dir, 'deploy.zip')) + const zipPath = prettyPath(resolve(dir, 'deploy.zip')) + + consola.success(`Ready to run \`az functionapp deployment source config-zip -g -n --src ${zipPath}\``) +} diff --git a/packages/nitro/src/presets/index.ts b/packages/nitro/src/presets/index.ts index be1e44a1a7..ea589398c8 100644 --- a/packages/nitro/src/presets/index.ts +++ b/packages/nitro/src/presets/index.ts @@ -1,3 +1,4 @@ +export * from './azure' export * from './browser' export * from './cloudflare' export * from './lambda' From ca015deda60b45d2bb7f48343a2815bad74ac9ef Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 28 Nov 2020 21:50:02 +0100 Subject: [PATCH 162/227] feat: support runtimeConfig (closes #43) --- packages/nitro/src/context.ts | 7 ++++++- packages/nitro/src/rollup/config.ts | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 44d45fde09..3e81fc3d93 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -46,6 +46,7 @@ export interface SigmaContext { isStatic: boolean fullStatic: boolean staticAssets: any + runtimeConfig: { public: any, private: any } } _internal: { runtimeDir: string @@ -93,7 +94,11 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S isStatic: nuxtOptions.target === 'static' && !nuxtOptions.dev, fullStatic: nuxtOptions.target === 'static' && !nuxtOptions._legacyGenerate, // @ts-ignore - staticAssets: nuxtOptions.generate.staticAssets + staticAssets: nuxtOptions.generate.staticAssets, + runtimeConfig: { + public: nuxtOptions.publicRuntimeConfig, + private: nuxtOptions.privateRuntimeConfig + } }, _internal: { runtimeDir: resolve(__dirname, '../runtime'), diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 181f03279c..0a69e70aaf 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -105,7 +105,8 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { 'process.env.NUXT_STATIC_BASE': JSON.stringify(sigmaContext._nuxt.staticAssets.base), 'process.env.NUXT_STATIC_VERSION': JSON.stringify(sigmaContext._nuxt.staticAssets.version), 'process.env.NUXT_FULL_STATIC': sigmaContext._nuxt.fullStatic as unknown as string, - 'process.env.SIGMA_PRESET': JSON.stringify(sigmaContext.preset) + 'process.env.SIGMA_PRESET': JSON.stringify(sigmaContext.preset), + 'process.env.RUNTIME_CONFIG': JSON.stringify(sigmaContext._nuxt.runtimeConfig) } })) From 7ae8483d21f3f5a229e48a9aabb5d1c0402d4045 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 28 Nov 2020 22:11:14 +0100 Subject: [PATCH 163/227] feat: support typescript via esbuild (closes #42) --- packages/nitro/src/module/nuxt2.ts | 3 + packages/nitro/src/rollup/config.ts | 4 + packages/nitro/src/rollup/esbuild.ts | 165 +++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 packages/nitro/src/rollup/esbuild.ts diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 9682cdc27a..b80a17088c 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -30,6 +30,9 @@ export default function (nuxt, moduleContainer) { // Expose process.env.SIGMA_PRESET nuxt.options.env.SIGMA_PRESET = sigmaContext.preset + // .ts is supported for serverMiddleware + nuxt.options.extensions.push('ts') + // Replace nuxt server if (nuxt.server) { nuxt.server.__closed = true diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 0a69e70aaf..748693819a 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -20,6 +20,7 @@ import { dynamicRequire } from './dynamic-require' import { externals } from './externals' import { timing } from './timing' import { autoMock } from './automock' +import esbuild from './esbuild' export type RollupConfig = InputOptions & { output: OutputOptions } @@ -110,6 +111,9 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { } })) + // ESBuild (typescript) + rollupConfig.plugins.push(esbuild({})) + // Dynamic Require Support rollupConfig.plugins.push(dynamicRequire({ dir: resolve(sigmaContext._nuxt.buildDir, 'dist/server'), diff --git a/packages/nitro/src/rollup/esbuild.ts b/packages/nitro/src/rollup/esbuild.ts new file mode 100644 index 0000000000..163aa27256 --- /dev/null +++ b/packages/nitro/src/rollup/esbuild.ts @@ -0,0 +1,165 @@ +// Based on https://github.com/egoist/rollup-plugin-esbuild (MIT) + +import { existsSync, statSync } from 'fs' +import { extname, resolve, dirname, join, relative } from 'path' +import { Plugin, PluginContext } from 'rollup' +import { startService, Loader, Service, TransformResult } from 'esbuild' +import { createFilter, FilterPattern } from '@rollup/pluginutils' + +const defaultLoaders: { [ext: string]: Loader } = { + '.ts': 'ts' +} + +export type Options = { + include?: FilterPattern + exclude?: FilterPattern + sourceMap?: boolean + minify?: boolean + target?: string | string[] + jsxFactory?: string + jsxFragment?: string + define?: { + [k: string]: string + } + /** + * Use this tsconfig file instead + * Disable it by setting to `false` + */ + tsconfig?: string | false + /** + * Map extension to esbuild loader + * Note that each entry (the extension) needs to start with a dot + */ + loaders?: { + [ext: string]: Loader | false + } +} + +export default (options: Options = {}): Plugin => { + let target: string | string[] + + const loaders = { + ...defaultLoaders + } + + if (options.loaders) { + for (const key of Object.keys(options.loaders)) { + const value = options.loaders[key] + if (typeof value === 'string') { + loaders[key] = value + } else if (value === false) { + delete loaders[key] + } + } + } + + const extensions: string[] = Object.keys(loaders) + const INCLUDE_REGEXP = new RegExp( + `\\.(${extensions.map(ext => ext.slice(1)).join('|')})$` + ) + const EXCLUDE_REGEXP = /node_modules/ + + const filter = createFilter( + options.include || INCLUDE_REGEXP, + options.exclude || EXCLUDE_REGEXP + ) + + let service: Service | undefined + + const stopService = () => { + if (service) { + service.stop() + service = undefined + } + } + + return { + name: 'esbuild', + + async buildStart () { + if (!service) { + service = await startService() + } + }, + + async transform (code, id) { + if (!filter(id)) { + return null + } + + const ext = extname(id) + const loader = loaders[ext] + + if (!loader || !service) { + return null + } + + target = options.target || 'node12' + + const result = await service.transform(code, { + loader, + target, + define: options.define, + sourcemap: options.sourceMap !== false, + sourcefile: id + }) + + printWarnings(id, result, this) + + return ( + result.code && { + code: result.code, + map: result.map || null + } + ) + }, + + buildEnd (error) { + // Stop the service early if there's error + if (error && !this.meta.watchMode) { + stopService() + } + }, + + async renderChunk (code) { + if (options.minify && service) { + const result = await service.transform(code, { + loader: 'js', + minify: true, + target + }) + if (result.code) { + return { + code: result.code, + map: result.map || null + } + } + } + return null + }, + + generateBundle () { + if (!this.meta.watchMode) { + stopService() + } + } + } +} + +function printWarnings ( + id: string, + result: TransformResult, + plugin: PluginContext +) { + if (result.warnings) { + for (const warning of result.warnings) { + let message = '[esbuild]' + if (warning.location) { + message += ` (${relative(process.cwd(), id)}:${warning.location.line}:${warning.location.column + })` + } + message += ` ${warning.text}` + plugin.warn(message) + } + } +} From b010e830089c3db83524da2518c175bb11d6d150 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 28 Nov 2020 22:13:16 +0100 Subject: [PATCH 164/227] chore: fix lint issues --- packages/nitro/src/rollup/esbuild.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/nitro/src/rollup/esbuild.ts b/packages/nitro/src/rollup/esbuild.ts index 163aa27256..81723ae980 100644 --- a/packages/nitro/src/rollup/esbuild.ts +++ b/packages/nitro/src/rollup/esbuild.ts @@ -1,7 +1,6 @@ // Based on https://github.com/egoist/rollup-plugin-esbuild (MIT) -import { existsSync, statSync } from 'fs' -import { extname, resolve, dirname, join, relative } from 'path' +import { extname, relative } from 'path' import { Plugin, PluginContext } from 'rollup' import { startService, Loader, Service, TransformResult } from 'esbuild' import { createFilter, FilterPattern } from '@rollup/pluginutils' From a9b9d19e6644d63ab54af5e7705971433fa5d426 Mon Sep 17 00:00:00 2001 From: pooya parsa Date: Sat, 28 Nov 2020 23:49:39 +0100 Subject: [PATCH 165/227] feat: serveStatic (#47) --- packages/nitro/src/context.ts | 2 + packages/nitro/src/presets/azure.ts | 49 ++----------------- packages/nitro/src/presets/server.ts | 3 +- packages/nitro/src/rollup/config.ts | 44 +++++++---------- .../src/rollup/{ => plugins}/automock.ts | 0 .../rollup/{ => plugins}/dynamic-require.ts | 0 .../nitro/src/rollup/{ => plugins}/esbuild.ts | 2 +- .../src/rollup/{ => plugins}/externals.ts | 0 .../nitro/src/rollup/plugins/middleware.ts | 21 ++++++++ packages/nitro/src/rollup/plugins/static.ts | 47 ++++++++++++++++++ .../nitro/src/rollup/{ => plugins}/timing.ts | 0 11 files changed, 93 insertions(+), 75 deletions(-) rename packages/nitro/src/rollup/{ => plugins}/automock.ts (100%) rename packages/nitro/src/rollup/{ => plugins}/dynamic-require.ts (100%) rename packages/nitro/src/rollup/{ => plugins}/esbuild.ts (98%) rename packages/nitro/src/rollup/{ => plugins}/externals.ts (100%) create mode 100644 packages/nitro/src/rollup/plugins/middleware.ts create mode 100644 packages/nitro/src/rollup/plugins/static.ts rename packages/nitro/src/rollup/{ => plugins}/timing.ts (100%) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 3e81fc3d93..188e46278e 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -24,6 +24,7 @@ export interface SigmaContext { preset: string rollupConfig?: any renderer: string + serveStatic: boolean middleware: ServerMiddleware[] hooks: configHooksT nuxtHooks: configHooksT @@ -72,6 +73,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S preset: undefined, rollupConfig: undefined, renderer: undefined, + serveStatic: false, middleware: [], ignore: [], env: {}, diff --git a/packages/nitro/src/presets/azure.ts b/packages/nitro/src/presets/azure.ts index 14bd9f4ced..e69e28c23f 100644 --- a/packages/nitro/src/presets/azure.ts +++ b/packages/nitro/src/presets/azure.ts @@ -1,64 +1,21 @@ -import replace from '@rollup/plugin-replace' import archiver from 'archiver' import consola from 'consola' -import createEtag from 'etag' -import { createWriteStream, readdirSync, readFileSync, statSync } from 'fs-extra' -import mime from 'mime' -import { join, relative, resolve } from 'upath' - +import { createWriteStream } from 'fs-extra' +import { join, resolve } from 'upath' import { prettyPath, writeFile } from '../utils' import { SigmaPreset, SigmaContext } from '../context' export const azure: SigmaPreset = { inlineChunks: false, + serveStatic: true, entry: '{{ _internal.runtimeDir }}/entries/azure', hooks: { - 'sigma:rollup:before' (ctx: SigmaContext) { - const manifest = JSON.stringify(getStaticManifest(ctx)).replace(/\\"/g, '\\\\"') - ctx.rollupConfig.plugins.push(replace({ - values: { - 'process.env.STATIC_MANIFEST': `\`${manifest}\`` - } - })) - }, async 'sigma:compiled' (ctx: SigmaContext) { await writeRoutes(ctx) } } } -function getStaticManifest ({ output: { dir } }: SigmaContext) { - const files = [] - const staticRoot = resolve(dir, 'public') - - const addFiles = (directory: string) => { - const listing = readdirSync(directory) - listing.forEach((filename) => { - const fullPath = resolve(directory, filename) - if (statSync(fullPath).isDirectory()) { - return addFiles(fullPath) - } - files.push('/' + relative(staticRoot, fullPath)) - }) - } - - addFiles(staticRoot) - const metadata = files.reduce((metadata, filename) => { - let mimeType = mime.getType(filename) || 'text/plain' - if (mimeType.startsWith('text')) { - mimeType += '; charset=utf-8' - } - const etag = createEtag(readFileSync(join(staticRoot, filename))) - metadata[filename] = [mimeType, etag] - return metadata - }, {} as Record) - - return { - files, - metadata - } -} - function zipDirectory (dir: string, outfile: string): Promise { const archive = archiver('zip', { zlib: { level: 9 } }) const stream = createWriteStream(outfile) diff --git a/packages/nitro/src/presets/server.ts b/packages/nitro/src/presets/server.ts index 1d331c68f6..617a78a45e 100644 --- a/packages/nitro/src/presets/server.ts +++ b/packages/nitro/src/presets/server.ts @@ -7,7 +7,8 @@ export const server: SigmaPreset = extendPreset(node, { entry: '{{ _internal.runtimeDir }}/entries/server', externals: false, inlineChunks: false, - timing: true, + serveStatic: true, + minify: false, hooks: { 'sigma:compiled' ({ output }: SigmaContext) { consola.success('Ready to run', hl('node ' + prettyPath(output.serverDir))) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 748693819a..5594d92b00 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -12,15 +12,16 @@ import analyze from 'rollup-plugin-analyzer' import type { Preset } from '@nuxt/un' import * as un from '@nuxt/un' -import hasha from 'hasha' import { SigmaContext } from '../context' import { resolvePath, MODULE_DIR } from '../utils' -import { dynamicRequire } from './dynamic-require' -import { externals } from './externals' -import { timing } from './timing' -import { autoMock } from './automock' -import esbuild from './esbuild' +import { dynamicRequire } from './plugins/dynamic-require' +import { externals } from './plugins/externals' +import { timing } from './plugins/timing' +import { autoMock } from './plugins/automock' +import { staticAssets } from './plugins/static' +import { middleware } from './plugins/middleware' +import { esbuild } from './plugins/esbuild' export type RollupConfig = InputOptions & { output: OutputOptions } @@ -125,28 +126,17 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { } })) - // https://github.com/rollup/plugins/tree/master/packages/replace - // TODO: better fix for node-fetch issue - rollupConfig.plugins.push(replace({ - delimiters: ['', ''], - values: { - 'require(\'encoding\')': '{}' - } - })) + // Static + if (sigmaContext.serveStatic) { + rollupConfig.plugins.push(staticAssets(sigmaContext)) + } - // Provide serverMiddleware - const getImportId = p => '_' + hasha(p).substr(0, 6) - rollupConfig.plugins.push(virtual({ - '~serverMiddleware': ` - ${sigmaContext.middleware.filter(m => m.lazy === false).map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} - - ${sigmaContext.middleware.filter(m => m.lazy !== false).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} - - export default [ - ${sigmaContext.middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify !== undefined ? m.promisify : true} }`).join(',\n')} - ]; - ` - })) + // Middleware + const _middleware = [...sigmaContext.middleware] + if (sigmaContext.serveStatic) { + _middleware.unshift({ route: '/', handle: '~runtime/server/static' }) + } + rollupConfig.plugins.push(middleware(_middleware)) // Polyfill rollupConfig.plugins.push(virtual({ diff --git a/packages/nitro/src/rollup/automock.ts b/packages/nitro/src/rollup/plugins/automock.ts similarity index 100% rename from packages/nitro/src/rollup/automock.ts rename to packages/nitro/src/rollup/plugins/automock.ts diff --git a/packages/nitro/src/rollup/dynamic-require.ts b/packages/nitro/src/rollup/plugins/dynamic-require.ts similarity index 100% rename from packages/nitro/src/rollup/dynamic-require.ts rename to packages/nitro/src/rollup/plugins/dynamic-require.ts diff --git a/packages/nitro/src/rollup/esbuild.ts b/packages/nitro/src/rollup/plugins/esbuild.ts similarity index 98% rename from packages/nitro/src/rollup/esbuild.ts rename to packages/nitro/src/rollup/plugins/esbuild.ts index 81723ae980..1a85664120 100644 --- a/packages/nitro/src/rollup/esbuild.ts +++ b/packages/nitro/src/rollup/plugins/esbuild.ts @@ -34,7 +34,7 @@ export type Options = { } } -export default (options: Options = {}): Plugin => { +export function esbuild (options: Options = {}): Plugin { let target: string | string[] const loaders = { diff --git a/packages/nitro/src/rollup/externals.ts b/packages/nitro/src/rollup/plugins/externals.ts similarity index 100% rename from packages/nitro/src/rollup/externals.ts rename to packages/nitro/src/rollup/plugins/externals.ts diff --git a/packages/nitro/src/rollup/plugins/middleware.ts b/packages/nitro/src/rollup/plugins/middleware.ts new file mode 100644 index 0000000000..fa78b98627 --- /dev/null +++ b/packages/nitro/src/rollup/plugins/middleware.ts @@ -0,0 +1,21 @@ +import hasha from 'hasha' +import virtual from '@rollup/plugin-virtual' +import type { ServerMiddleware } from '../../context' + +export function middleware (middleware: ServerMiddleware[]) { + const getImportId = p => '_' + hasha(p).substr(0, 6) + + return virtual({ + '~serverMiddleware': ` +${middleware.filter(m => m.lazy === false).map(m => `import ${getImportId(m.handle)} from '${m.handle}';`).join('\n')} + +${middleware.filter(m => m.lazy !== false).map(m => `const ${getImportId(m.handle)} = () => import('${m.handle}');`).join('\n')} + +const middleware = [ + ${middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify !== undefined ? m.promisify : true} }`).join(',\n')} +]; + +export default middleware +` + }) +} diff --git a/packages/nitro/src/rollup/plugins/static.ts b/packages/nitro/src/rollup/plugins/static.ts new file mode 100644 index 0000000000..9f27ef3964 --- /dev/null +++ b/packages/nitro/src/rollup/plugins/static.ts @@ -0,0 +1,47 @@ +import createEtag from 'etag' +import { readFileSync, statSync } from 'fs-extra' +import mime from 'mime' +import { relative, resolve } from 'upath' +import virtual from '@rollup/plugin-virtual' +import globby from 'globby' +import type { SigmaContext } from '../../context' + +export function staticAssets (context: SigmaContext) { + const assets: Record = {} + + const files = globby.sync('**/*.*', { cwd: context.output.publicDir, absolute: false }) + + for (const id of files) { + let type = mime.getType(id) || 'text/plain' + if (type.startsWith('text')) { type += '; charset=utf-8' } + const fullPath = resolve(context.output.publicDir, id) + const etag = createEtag(readFileSync(fullPath)) + const stat = statSync(fullPath) + + assets[id] = { + type, + etag, + mtime: stat.mtime.toJSON(), + path: relative(context.output.serverDir, fullPath) + } + } + + return virtual({ + '~static-assets': `export default ${JSON.stringify(assets, null, 2)};`, + '~static': ` +import { readFile } from 'fs/promises' +import { resolve, dirname } from 'path' +import assets from '~static-assets' + +const mainDir = dirname(require.main.filename) + +export function readAsset (id) { + return readFile(resolve(mainDir, getAsset(id).path)) +} + +export function getAsset (id) { + return assets[id] +} +` + }) +} diff --git a/packages/nitro/src/rollup/timing.ts b/packages/nitro/src/rollup/plugins/timing.ts similarity index 100% rename from packages/nitro/src/rollup/timing.ts rename to packages/nitro/src/rollup/plugins/timing.ts From 9c25d68511b2236fbff5b77f0ccc316b66d1885a Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 1 Dec 2020 23:28:42 +0000 Subject: [PATCH 166/227] fix: addresses static assets/azure issues (#49) --- packages/nitro/src/rollup/config.ts | 3 ++- packages/nitro/src/rollup/plugins/static.ts | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 5594d92b00..9f6fd07e13 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -19,7 +19,7 @@ import { dynamicRequire } from './plugins/dynamic-require' import { externals } from './plugins/externals' import { timing } from './plugins/timing' import { autoMock } from './plugins/automock' -import { staticAssets } from './plugins/static' +import { staticAssets, dirnames } from './plugins/static' import { middleware } from './plugins/middleware' import { esbuild } from './plugins/esbuild' @@ -128,6 +128,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { // Static if (sigmaContext.serveStatic) { + rollupConfig.plugins.push(dirnames()) rollupConfig.plugins.push(staticAssets(sigmaContext)) } diff --git a/packages/nitro/src/rollup/plugins/static.ts b/packages/nitro/src/rollup/plugins/static.ts index 9f27ef3964..095416be40 100644 --- a/packages/nitro/src/rollup/plugins/static.ts +++ b/packages/nitro/src/rollup/plugins/static.ts @@ -4,6 +4,7 @@ import mime from 'mime' import { relative, resolve } from 'upath' import virtual from '@rollup/plugin-virtual' import globby from 'globby' +import type { Plugin } from 'rollup' import type { SigmaContext } from '../../context' export function staticAssets (context: SigmaContext) { @@ -29,14 +30,12 @@ export function staticAssets (context: SigmaContext) { return virtual({ '~static-assets': `export default ${JSON.stringify(assets, null, 2)};`, '~static': ` -import { readFile } from 'fs/promises' -import { resolve, dirname } from 'path' +import { promises } from 'fs' +import { resolve } from 'path' import assets from '~static-assets' -const mainDir = dirname(require.main.filename) - export function readAsset (id) { - return readFile(resolve(mainDir, getAsset(id).path)) + return promises.readFile(resolve(mainDir, getAsset(id).path)) } export function getAsset (id) { @@ -45,3 +44,12 @@ export function getAsset (id) { ` }) } + +export function dirnames (): Plugin { + return { + name: 'dirnames', + renderChunk (code, chunk) { + return code + (chunk.isEntry ? 'global.mainDir="undefined"!=typeof __dirname?__dirname:require.main.filename;' : '') + } + } +} From 0a2f9a39495ea432527498011cec7f79e55f7b3f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 2 Dec 2020 14:12:29 +0100 Subject: [PATCH 167/227] fix: update node-resolve options --- packages/nitro/src/rollup/config.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 9f6fd07e13..b0f66c07b4 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -171,14 +171,10 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { extensions, preferBuiltins: true, rootDir: sigmaContext._nuxt.rootDir, - // https://www.npmjs.com/package/resolve - customResolveOptions: { - basedir: sigmaContext._nuxt.rootDir, - paths: [ - resolve(sigmaContext._nuxt.rootDir, 'node_modules'), - resolve(MODULE_DIR, 'node_modules') - ] - }, + moduleDirectories: [ + resolve(sigmaContext._nuxt.rootDir, 'node_modules'), + resolve(MODULE_DIR, 'node_modules') + ], mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) })) From 133b44d3c026eea52e6fc263ce346974d36cf1ea Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 2 Dec 2020 14:19:18 +0100 Subject: [PATCH 168/227] fix: disable static manifest generation (resolves #53) --- packages/nitro/src/module/nuxt2.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index b80a17088c..fcbf13337f 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -95,6 +95,7 @@ export default function (nuxt, moduleContainer) { // nuxt generate nuxt.options.generate.dir = sigmaContext.output.publicDir + nuxt.options.generate.manifest = false nuxt.hook('generate:cache:ignore', (ignore: string[]) => { ignore.push(sigmaContext.output.dir) ignore.push(sigmaContext.output.serverDir) From 4890205b6eae11cea5f6e393074f5882f0e34d65 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 2 Dec 2020 14:21:49 +0100 Subject: [PATCH 169/227] fix: temporary disable auto mock plugin --- packages/nitro/src/rollup/config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index b0f66c07b4..e0c84e12e9 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -18,7 +18,7 @@ import { resolvePath, MODULE_DIR } from '../utils' import { dynamicRequire } from './plugins/dynamic-require' import { externals } from './plugins/externals' import { timing } from './plugins/timing' -import { autoMock } from './plugins/automock' +// import { autoMock } from './plugins/automock' import { staticAssets, dirnames } from './plugins/static' import { middleware } from './plugins/middleware' import { esbuild } from './plugins/esbuild' @@ -179,7 +179,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { })) // Automatically mock unresolved externals - rollupConfig.plugins.push(autoMock()) + // rollupConfig.plugins.push(autoMock()) // https://github.com/rollup/plugins/tree/master/packages/commonjs rollupConfig.plugins.push(commonjs({ From 4685108c16d908ffae93610da8c7e15703ee4313 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 2 Dec 2020 14:22:34 +0100 Subject: [PATCH 170/227] fix: add `node_modules` from cwd to nodeResolve --- packages/nitro/src/rollup/config.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index e0c84e12e9..80fae2c5f8 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -173,7 +173,8 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { rootDir: sigmaContext._nuxt.rootDir, moduleDirectories: [ resolve(sigmaContext._nuxt.rootDir, 'node_modules'), - resolve(MODULE_DIR, 'node_modules') + resolve(MODULE_DIR, 'node_modules'), + 'node_modules' ], mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) })) From 3c9bb27148457a186f9caaee001c072d16689c50 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 2 Dec 2020 13:27:01 +0000 Subject: [PATCH 171/227] fix: temporary remove dev warning for pwa module (#40) --- packages/nitro/src/module/nuxt2.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index fcbf13337f..443db1bcd6 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -59,6 +59,10 @@ export default function (nuxt, moduleContainer) { nuxt.server.setLoadingMiddleware(handle) continue } + // Temporary hide for @nuxt/pwa module + if (route === '/_nuxt/' && process.env.NODE_ENV === 'development') { + continue + } unsupported.push(m) continue } From 0742e0ff3363d042e77865d6b5d8722bd8f8e09f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 7 Dec 2020 13:13:45 +0100 Subject: [PATCH 172/227] chore: move local dist to .output for easier debugging --- packages/nitro/src/presets/local.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/nitro/src/presets/local.ts b/packages/nitro/src/presets/local.ts index f3c44f352f..310812647b 100644 --- a/packages/nitro/src/presets/local.ts +++ b/packages/nitro/src/presets/local.ts @@ -4,9 +4,8 @@ import { node } from './node' export const local: SigmaPreset = extendPreset(node, { entry: '{{ _internal.runtimeDir }}/entries/local', - // @ts-ignore output: { - dir: '{{ _nuxt.rootDir }}/node_modules/.cache/sigma' + serverDir: '{{ output.dir }}/.local' }, minify: false, externals: true, From daf0c3e6a577cade2f1ed4620d3a6ed520521e42 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 7 Dec 2020 13:36:43 +0100 Subject: [PATCH 173/227] feat: sourcemap support --- packages/nitro/src/context.ts | 2 ++ packages/nitro/src/presets/local.ts | 3 ++- packages/nitro/src/rollup/config.ts | 18 ++++++++++++++---- .../src/rollup/plugins/dynamic-require.ts | 5 ++++- packages/nitro/src/rollup/plugins/esbuild.ts | 3 ++- packages/nitro/src/rollup/plugins/timing.ts | 5 ++++- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 188e46278e..8cd5f0e561 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -17,6 +17,7 @@ export interface SigmaContext { timing: boolean inlineChunks: boolean minify: boolean + sourceMap: boolean externals: boolean analyze: boolean entry: string @@ -66,6 +67,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S timing: true, inlineChunks: true, minify: true, + sourceMap: false, externals: false, analyze: false, entry: undefined, diff --git a/packages/nitro/src/presets/local.ts b/packages/nitro/src/presets/local.ts index 310812647b..561c93e8ed 100644 --- a/packages/nitro/src/presets/local.ts +++ b/packages/nitro/src/presets/local.ts @@ -10,5 +10,6 @@ export const local: SigmaPreset = extendPreset(node, { minify: false, externals: true, inlineChunks: true, - timing: true + timing: false, + sourceMap: true }) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 80fae2c5f8..b278487e7c 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -50,7 +50,10 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { } const env = un.env(nodePreset, builtinPreset, sigmaContext.env) - // console.log(env) + + if (sigmaContext.sourceMap) { + env.polyfill.push('source-map-support/register') + } const buildServerDir = join(sigmaContext._nuxt.buildDir, 'dist/server') const runtimeAppDir = join(sigmaContext._internal.runtimeDir, 'app') @@ -82,7 +85,12 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { exports: 'auto', intro: '', outro: '', - preferConst: true + preferConst: true, + sourcemap: sigmaContext.sourceMap, + sourcemapExcludeSources: true, + sourcemapPathTransform (relativePath, sourcemapPath) { + return resolve(dirname(sourcemapPath), relativePath) + } }, external: env.external, plugins: [], @@ -112,8 +120,10 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { } })) - // ESBuild (typescript) - rollupConfig.plugins.push(esbuild({})) + // ESBuild + rollupConfig.plugins.push(esbuild({ + sourceMap: true + })) // Dynamic Require Support rollupConfig.plugins.push(dynamicRequire({ diff --git a/packages/nitro/src/rollup/plugins/dynamic-require.ts b/packages/nitro/src/rollup/plugins/dynamic-require.ts index 2bc2bae7e9..98eead7675 100644 --- a/packages/nitro/src/rollup/plugins/dynamic-require.ts +++ b/packages/nitro/src/rollup/plugins/dynamic-require.ts @@ -33,7 +33,10 @@ export function dynamicRequire ({ dir, globbyOptions, inline }: Options): Plugin return { name: PLUGIN_NAME, transform (code: string, _id: string) { - return code.replace(DYNAMIC_REQUIRE_RE, `require('${HELPER_DYNAMIC}')(`) + return { + code: code.replace(DYNAMIC_REQUIRE_RE, `require('${HELPER_DYNAMIC}')(`), + map: null + } }, resolveId (id: string) { return id === HELPER_DYNAMIC ? id : null diff --git a/packages/nitro/src/rollup/plugins/esbuild.ts b/packages/nitro/src/rollup/plugins/esbuild.ts index 1a85664120..feaef7b1d2 100644 --- a/packages/nitro/src/rollup/plugins/esbuild.ts +++ b/packages/nitro/src/rollup/plugins/esbuild.ts @@ -6,7 +6,8 @@ import { startService, Loader, Service, TransformResult } from 'esbuild' import { createFilter, FilterPattern } from '@rollup/pluginutils' const defaultLoaders: { [ext: string]: Loader } = { - '.ts': 'ts' + '.ts': 'ts', + '.js': 'js' } export type Options = { diff --git a/packages/nitro/src/rollup/plugins/timing.ts b/packages/nitro/src/rollup/plugins/timing.ts index 23bc2847e3..2b8453d344 100644 --- a/packages/nitro/src/rollup/plugins/timing.ts +++ b/packages/nitro/src/rollup/plugins/timing.ts @@ -31,7 +31,10 @@ export function timing (_opts: Options = {}): Plugin { let name = chunk.fileName || '' name = name.replace(extname(name), '') const logName = name === 'index' ? 'Cold Start' : ('Load ' + name) - return "'use strict';" + (chunk.isEntry ? HELPER : '') + `${TIMING}.logStart('${logName}');` + code + `;${TIMING}.logEnd('${logName}');` + return { + code: (chunk.isEntry ? HELPER : '') + `${TIMING}.logStart('${logName}');` + code + `;${TIMING}.logEnd('${logName}');`, + map: null + } } } } From 6de295cc9f8f0c24e4e93068f48bfe877c9c1ba8 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 7 Dec 2020 13:48:29 +0100 Subject: [PATCH 174/227] fix: skip static dir if not exists --- packages/nitro/src/build.ts | 21 ++++++++++++--------- packages/nitro/src/utils/index.ts | 8 ++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 9f8e07015e..495aad89a1 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -5,7 +5,7 @@ import ora from 'ora' import { readFile, emptyDir, copy } from 'fs-extra' import { printFSTree } from './utils/tree' import { getRollupConfig } from './rollup/config' -import { hl, prettyPath, serializeTemplate, writeFile } from './utils' +import { hl, prettyPath, serializeTemplate, writeFile, isDirectory } from './utils' import { SigmaContext } from './context' export async function prepare (sigmaContext: SigmaContext) { @@ -30,14 +30,17 @@ async function cleanupDir (dir: string) { export async function generate (sigmaContext: SigmaContext) { const spinner = ora() spinner.start('Generating public...') - await copy( - resolve(sigmaContext._nuxt.buildDir, 'dist/client'), - join(sigmaContext.output.publicDir, sigmaContext._nuxt.publicPath) - ) - await copy( - resolve(sigmaContext._nuxt.srcDir, sigmaContext._nuxt.staticDir), - sigmaContext.output.publicDir - ) + + const clientDist = resolve(sigmaContext._nuxt.buildDir, 'dist/client') + if (await isDirectory(clientDist)) { + await copy(clientDist, join(sigmaContext.output.publicDir, sigmaContext._nuxt.publicPath)) + } + + const staticDir = resolve(sigmaContext._nuxt.srcDir, sigmaContext._nuxt.staticDir) + if (await isDirectory(staticDir)) { + await copy(staticDir, sigmaContext.output.publicDir) + } + spinner.succeed('Generated public ' + prettyPath(sigmaContext.output.publicDir)) } diff --git a/packages/nitro/src/utils/index.ts b/packages/nitro/src/utils/index.ts index 53c468d1d0..d2b0cf9701 100644 --- a/packages/nitro/src/utils/index.ts +++ b/packages/nitro/src/utils/index.ts @@ -74,6 +74,14 @@ export function detectTarget () { } } +export async function isDirectory (path: string) { + try { + return (await fse.stat(path)).isDirectory() + } catch (_err) { + return false + } +} + export function extendPreset (base: SigmaPreset, preset: SigmaPreset): SigmaPreset { return (config: SigmaInput) => { if (typeof preset === 'function') { From 0199610834e603e052db5767a1fca36c7ce47d34 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 7 Dec 2020 13:53:32 +0100 Subject: [PATCH 175/227] chore: enable back automock plugin --- packages/nitro/src/rollup/config.ts | 4 ++-- packages/nitro/src/rollup/plugins/automock.ts | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index b278487e7c..34f994c8ce 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -18,7 +18,7 @@ import { resolvePath, MODULE_DIR } from '../utils' import { dynamicRequire } from './plugins/dynamic-require' import { externals } from './plugins/externals' import { timing } from './plugins/timing' -// import { autoMock } from './plugins/automock' +import { autoMock } from './plugins/automock' import { staticAssets, dirnames } from './plugins/static' import { middleware } from './plugins/middleware' import { esbuild } from './plugins/esbuild' @@ -190,7 +190,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { })) // Automatically mock unresolved externals - // rollupConfig.plugins.push(autoMock()) + rollupConfig.plugins.push(autoMock()) // https://github.com/rollup/plugins/tree/master/packages/commonjs rollupConfig.plugins.push(commonjs({ diff --git a/packages/nitro/src/rollup/plugins/automock.ts b/packages/nitro/src/rollup/plugins/automock.ts index f5aad11b10..7393c5820d 100644 --- a/packages/nitro/src/rollup/plugins/automock.ts +++ b/packages/nitro/src/rollup/plugins/automock.ts @@ -1,11 +1,8 @@ -import consola from 'consola' - export function autoMock () { return { name: 'auto-mock', resolveId (src: string) { if (src && !src.startsWith('.') && !src.includes('?') && !src.includes('.js')) { - consola.warn('Auto mock external ', src) return { id: require.resolve('@nuxt/un/runtime/mock/proxy') } From 921bb15130e37fb81a7fc8f1c1f9f45eeddecd7c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 7 Dec 2020 14:09:09 +0100 Subject: [PATCH 176/227] feat: swtich to h2 stack for dev server --- packages/nitro/src/server.ts | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index 476c441465..7393a1a3ed 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -1,10 +1,9 @@ import { Worker } from 'worker_threads' -import { Server } from 'http' import { resolve } from 'upath' import debounce from 'debounce' -import connect from 'connect' -import getPort from 'get-port-please' import chokidar from 'chokidar' +import { createApp } from '@nuxt/h2' +import { listen, Listener } from 'listhen' import serveStatic from 'serve-static' import { createProxy } from 'http-proxy' import { stat } from 'fs-extra' @@ -48,7 +47,7 @@ export function createDevServer (sigmaContext: SigmaContext) { } // App - const app = connect() + const app = createApp() // _nuxt and static app.use(sigmaContext._nuxt.publicPath, serveStatic(resolve(sigmaContext._nuxt.buildDir, 'dist/client'))) @@ -86,16 +85,11 @@ export function createDevServer (sigmaContext: SigmaContext) { }) // Listen - let listeners: Server[] = [] - async function listen (port) { - port = await getPort({ name: 'nuxt' }) - const listener = await new Promise((resolve, reject) => { - const l = app.listen(port, err => err ? reject(err) : resolve(l)) - }) + let listeners: Listener[] = [] + const _listen = async (port) => { + const listener = await listen(app, { port }) listeners.push(listener) - return { - url: 'http://localhost:' + port - } + return listener } // Watch for dist and reload worker @@ -122,16 +116,14 @@ export function createDevServer (sigmaContext: SigmaContext) { if (pendingWorker) { await pendingWorker.terminate() } - await Promise.all(listeners.map(l => new Promise((resolve) => { - l.close(() => resolve(undefined)) - }))) + await Promise.all(listeners.map(l => l.close())) listeners = [] } sigmaContext._internal.hooks.hook('close', close) return { reload, - listen, + listen: _listen, close, watch, setLoadingMiddleware, From 28be995ef42ac16d208fa6ed08e27cbbdd75fc61 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 7 Dec 2020 21:49:03 +0100 Subject: [PATCH 177/227] chore: move local artifacts to buildDir/sigma --- packages/nitro/src/presets/local.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/presets/local.ts b/packages/nitro/src/presets/local.ts index 561c93e8ed..c00f2a1280 100644 --- a/packages/nitro/src/presets/local.ts +++ b/packages/nitro/src/presets/local.ts @@ -5,7 +5,7 @@ import { node } from './node' export const local: SigmaPreset = extendPreset(node, { entry: '{{ _internal.runtimeDir }}/entries/local', output: { - serverDir: '{{ output.dir }}/.local' + serverDir: '{{ _nuxt.buildDir }}/sigma' }, minify: false, externals: true, From a05c806f85757cc5ad321a812f8beeef8ccce15d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 7 Dec 2020 21:49:37 +0100 Subject: [PATCH 178/227] chore: hide listen message for dev --- packages/nitro/src/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index 7393a1a3ed..1733d729c6 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -87,7 +87,7 @@ export function createDevServer (sigmaContext: SigmaContext) { // Listen let listeners: Listener[] = [] const _listen = async (port) => { - const listener = await listen(app, { port }) + const listener = await listen(app, { port, showURL: false, isProd: true }) listeners.push(listener) return listener } From 5bbdc2bc65043c66b07cb07a230c564c4e379ee2 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 7 Dec 2020 22:59:24 +0100 Subject: [PATCH 179/227] feat: improved externals and experimental trace with vercel/nft --- packages/nitro/src/context.ts | 3 +- packages/nitro/src/rollup/config.ts | 33 ++++++---- .../nitro/src/rollup/plugins/externals.ts | 66 +++++++++++++++---- packages/nitro/src/utils/tree.ts | 17 ++++- 4 files changed, 90 insertions(+), 29 deletions(-) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 8cd5f0e561..e0a917a95a 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -5,6 +5,7 @@ import Hookable, { configHooksT } from 'hookable' import type { Preset } from '@nuxt/un' import { tryImport, resolvePath, detectTarget, extendPreset } from './utils' import * as PRESETS from './presets' +import type { NodeExternalsOptions } from './rollup/plugins/externals' export interface ServerMiddleware { route: string @@ -18,7 +19,7 @@ export interface SigmaContext { inlineChunks: boolean minify: boolean sourceMap: boolean - externals: boolean + externals: boolean | NodeExternalsOptions analyze: boolean entry: string node: boolean diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 34f994c8ce..56491792a0 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -1,5 +1,6 @@ import { dirname, join, relative, resolve } from 'upath' import { InputOptions, OutputOptions } from 'rollup' +import defu from 'defu' import { terser } from 'rollup-plugin-terser' import commonjs from '@rollup/plugin-commonjs' import nodeResolve from '@rollup/plugin-node-resolve' @@ -51,6 +52,8 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { const env = un.env(nodePreset, builtinPreset, sigmaContext.env) + delete env.alias['node-fetch'] // FIX ME + if (sigmaContext.sourceMap) { env.polyfill.push('source-map-support/register') } @@ -165,15 +168,27 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { } })) - // External Plugin + const moduleDirectories = [ + resolve(sigmaContext._nuxt.rootDir, 'node_modules'), + resolve(MODULE_DIR, 'node_modules'), + resolve(MODULE_DIR, '../node_modules'), + 'node_modules' + ] + + // Externals Plugin if (sigmaContext.externals) { - rollupConfig.plugins.push(externals({ - relativeTo: sigmaContext.output.serverDir, - include: [ + rollupConfig.plugins.push(externals(defu(sigmaContext.externals as any, { + outDir: sigmaContext.output.serverDir, + moduleDirectories, + ignore: [ sigmaContext._internal.runtimeDir, + ...(sigmaContext._nuxt.dev ? [] : [sigmaContext._nuxt.buildDir]), ...sigmaContext.middleware.map(m => m.handle) - ] - })) + ], + traceOptions: { + base: sigmaContext._nuxt.rootDir + } + }))) } // https://github.com/rollup/plugins/tree/master/packages/node-resolve @@ -181,11 +196,7 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { extensions, preferBuiltins: true, rootDir: sigmaContext._nuxt.rootDir, - moduleDirectories: [ - resolve(sigmaContext._nuxt.rootDir, 'node_modules'), - resolve(MODULE_DIR, 'node_modules'), - 'node_modules' - ], + moduleDirectories, mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils) })) diff --git a/packages/nitro/src/rollup/plugins/externals.ts b/packages/nitro/src/rollup/plugins/externals.ts index e05537c9b7..71aefa4ca8 100644 --- a/packages/nitro/src/rollup/plugins/externals.ts +++ b/packages/nitro/src/rollup/plugins/externals.ts @@ -1,24 +1,62 @@ -import { isAbsolute, relative } from 'upath' +import { isAbsolute, relative } from 'path' +import type { Plugin } from 'rollup' +import { resolve, dirname } from 'upath' +import { copyFile, mkdirp } from 'fs-extra' +import { nodeFileTrace, NodeFileTraceOptions } from '@vercel/nft' -export function externals ({ include = [], relativeTo }) { +export interface NodeExternalsOptions { + ignore?: string[] + outDir?: string + trace?: boolean + traceOptions?: NodeFileTraceOptions + moduleDirectories?: string[] +} + +export function externals (opts: NodeExternalsOptions): Plugin { + const resolvedExternals = {} return { - name: 'externals', - resolveId (source) { - if ( - source[0] === '.' || // Compile relative imports - source[0] === '\x00' || // Skip helpers - source.includes('?') || // Skip helpers - include.find(i => source.startsWith(i)) - ) { return null } - - if (!isAbsolute(source)) { - source = require.resolve(source) + name: 'node-externals', + resolveId (id) { + // Internals + if (id.startsWith('\x00') || id.includes('?')) { + return null } + // Resolve relative paths and exceptions + if (id.startsWith('.') || opts.ignore.find(i => id.startsWith(i))) { + return null + } + + for (const dir of opts.moduleDirectories) { + if (id.startsWith(dir)) { + id = id.substr(dir.length + 1) + break + } + } + + try { + resolvedExternals[id] = require.resolve(id, { paths: opts.moduleDirectories }) + } catch (_err) { } + return { - id: relative(relativeTo, source), + id: isAbsolute(id) ? relative(opts.outDir, id) : id, external: true } + }, + async buildEnd () { + if (opts.trace) { + const { fileList } = await nodeFileTrace(Object.values(resolvedExternals), opts.traceOptions) + await Promise.all(fileList.map(async (file) => { + if (!file.startsWith('node_modules')) { + return + } + // TODO: Minify package.json + const src = resolve(opts.traceOptions.base, file) + const dst = resolve(opts.outDir, file) + await mkdirp(dirname(dst)) + await copyFile(src, dst) + })) + } } } } diff --git a/packages/nitro/src/utils/tree.ts b/packages/nitro/src/utils/tree.ts index 15dad502b9..15e6607774 100644 --- a/packages/nitro/src/utils/tree.ts +++ b/packages/nitro/src/utils/tree.ts @@ -6,7 +6,7 @@ import { readFile } from 'fs-extra' import chalk from 'chalk' export async function printFSTree (dir) { - const files = await globby('**/*.js', { cwd: dir }) + const files = await globby('**/*.*', { cwd: dir }) const items = (await Promise.all(files.map(async (file) => { const path = resolve(dir, file) @@ -19,16 +19,27 @@ export async function printFSTree (dir) { let totalSize = 0 let totalGzip = 0 + let totalNodeModulesSize = 0 + let totalNodeModulesGzip = 0 + items.forEach((item, index) => { let dir = dirname(item.file) if (dir === '.') { dir = '' } const rpath = relative(process.cwd(), item.path) const treeChar = index === items.length - 1 ? '└─' : '├─' - process.stdout.write(chalk.gray(` ${treeChar} ${rpath} (${prettyBytes(item.size)}) (${prettyBytes(item.gzip)} gzip)\n`)) + const isNodeModules = item.file.includes('node_modules') + + if (isNodeModules) { + totalNodeModulesSize += item.size + totalNodeModulesGzip += item.gzip + return + } + + process.stdout.write(chalk.gray(` ${treeChar} ${rpath} (${prettyBytes(item.size)}) (${prettyBytes(item.gzip)} gzip)\n`)) totalSize += item.size totalGzip += item.gzip }) - process.stdout.write(`${chalk.cyan('Σ Total size:')} ${prettyBytes(totalSize)} (${prettyBytes(totalGzip)} gzip)\n`) + process.stdout.write(`${chalk.cyan('Σ Total size:')} ${prettyBytes(totalSize + totalNodeModulesSize)} (${prettyBytes(totalGzip + totalNodeModulesGzip)} gzip)\n`) } From e56178a8727470d861d00afdbf16718da1405f40 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 12 Dec 2020 15:20:55 +0100 Subject: [PATCH 180/227] fix: use connect for dev server due to loading-screen issue --- packages/nitro/src/server.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index 1733d729c6..fdc25d2cf0 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -1,8 +1,8 @@ import { Worker } from 'worker_threads' +import connect from 'connect' import { resolve } from 'upath' import debounce from 'debounce' import chokidar from 'chokidar' -import { createApp } from '@nuxt/h2' import { listen, Listener } from 'listhen' import serveStatic from 'serve-static' import { createProxy } from 'http-proxy' @@ -47,7 +47,7 @@ export function createDevServer (sigmaContext: SigmaContext) { } // App - const app = createApp() + const app = connect() // _nuxt and static app.use(sigmaContext._nuxt.publicPath, serveStatic(resolve(sigmaContext._nuxt.buildDir, 'dist/client'))) From 239c69d92afc56821158670053e7fc4c5114adf1 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 12 Dec 2020 15:21:12 +0100 Subject: [PATCH 181/227] fix: silent proxy errors --- packages/nitro/src/server.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index fdc25d2cf0..70bfd90041 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -72,8 +72,8 @@ export function createDevServer (sigmaContext: SigmaContext) { const proxy = createProxy() app.use((req, res) => { if (workerAddress) { - proxy.web(req, res, { target: workerAddress }, (err) => { - console.error('[proxy]', err) + proxy.web(req, res, { target: workerAddress }, (_err) => { + // console.error('[proxy]', err) }) } else if (loadingMiddleware) { // TODO:serverIndex method is not exposed From 2c83f6ea6afd79ff9ba59a89d4ed669cb44c0a6c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 12 Dec 2020 15:46:54 +0100 Subject: [PATCH 182/227] feat: integrate $fetch with ohmyfetch --- packages/nitro/src/index.ts | 1 + packages/nitro/src/types.ts | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 packages/nitro/src/types.ts diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index 01b14171aa..a66a35c2fb 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,4 +1,5 @@ import nuxt2 from './module/nuxt2' +export * from './types' export default function () { const { nuxt } = this diff --git a/packages/nitro/src/types.ts b/packages/nitro/src/types.ts new file mode 100644 index 0000000000..2c632eaff2 --- /dev/null +++ b/packages/nitro/src/types.ts @@ -0,0 +1,11 @@ +import type { $Fetch } from 'ohmyfetch' + +declare global { + const $fetch: $Fetch + + namespace NodeJS { + interface Global { + $fetch: $Fetch + } + } +} From 7e682ed66344814b74162b00f91b5163d375277c Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 12 Dec 2020 19:15:56 +0100 Subject: [PATCH 183/227] feat: better error handler --- packages/nitro/src/module/nuxt2.ts | 4 +++- packages/nitro/src/rollup/config.ts | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 443db1bcd6..7669c623d5 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -8,7 +8,9 @@ import wpfs from '../utils/wpfs' export default function (nuxt, moduleContainer) { // Build in node_modules/.cache/nuxt const oldBuildDir = nuxt.options.buildDir - nuxt.options.buildDir = resolve(nuxt.options.rootDir, 'node_modules/.cache/nuxt') + if (!nuxt.options.dev) { + nuxt.options.buildDir = resolve(nuxt.options.rootDir, 'node_modules/.cache/nuxt') + } nuxt.options.build.transpile = nuxt.options.build.transpile || [] nuxt.options.build.transpile.push(nuxt.options.buildDir) nuxt.options.appTemplatePath = nuxt.options.appTemplatePath diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 56491792a0..4723ba03ea 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -119,7 +119,8 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { 'process.env.NUXT_STATIC_VERSION': JSON.stringify(sigmaContext._nuxt.staticAssets.version), 'process.env.NUXT_FULL_STATIC': sigmaContext._nuxt.fullStatic as unknown as string, 'process.env.SIGMA_PRESET': JSON.stringify(sigmaContext.preset), - 'process.env.RUNTIME_CONFIG': JSON.stringify(sigmaContext._nuxt.runtimeConfig) + 'process.env.RUNTIME_CONFIG': JSON.stringify(sigmaContext._nuxt.runtimeConfig), + 'process.env.DEBUG': JSON.stringify(sigmaContext._nuxt.dev) } })) @@ -159,10 +160,12 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { // https://github.com/rollup/plugins/tree/master/packages/alias const renderer = sigmaContext.renderer || 'vue2' + const vueServerRenderer = 'vue-server-renderer/' + (sigmaContext._nuxt.dev ? 'build.dev.js' : 'build.prod.js') rollupConfig.plugins.push(alias({ entries: { '~runtime': sigmaContext._internal.runtimeDir, '~renderer': require.resolve(resolve(sigmaContext._internal.runtimeDir, 'app', renderer)), + '~vueServerRenderer': vueServerRenderer, '~build': sigmaContext._nuxt.buildDir, ...env.alias } From 8a8840c9706fdba86b1b9e2398bf356968a27564 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Chopin?= Date: Mon, 11 Jan 2021 19:02:11 +0100 Subject: [PATCH 184/227] chore: typo --- packages/nitro/src/build.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 495aad89a1..2c40a808ad 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -68,7 +68,7 @@ async function _build (sigmaContext: SigmaContext) { throw error }) - spinner.start('Wrting server bundle...') + spinner.start('Writing server bundle...') await build.write(sigmaContext.rollupConfig.output) spinner.succeed('Server built') From 19e6542d273a9595c05b8214004da6be0f734793 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Tue, 12 Jan 2021 16:58:05 +0100 Subject: [PATCH 185/227] feat: enable externals.trace by default --- packages/nitro/src/rollup/plugins/externals.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/rollup/plugins/externals.ts b/packages/nitro/src/rollup/plugins/externals.ts index 71aefa4ca8..be032b389b 100644 --- a/packages/nitro/src/rollup/plugins/externals.ts +++ b/packages/nitro/src/rollup/plugins/externals.ts @@ -44,7 +44,7 @@ export function externals (opts: NodeExternalsOptions): Plugin { } }, async buildEnd () { - if (opts.trace) { + if (opts.trace !== false) { const { fileList } = await nodeFileTrace(Object.values(resolvedExternals), opts.traceOptions) await Promise.all(fileList.map(async (file) => { if (!file.startsWith('node_modules')) { From b07a4a5c8d9309bd2a040fe9664ccf4e95760623 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 18 Jan 2021 11:57:38 +0100 Subject: [PATCH 186/227] refactor: move runtime to src (typescript) --- packages/nitro/src/context.ts | 2 +- packages/nitro/src/runtime/app/config.ts | 19 +++++ packages/nitro/src/runtime/app/render.ts | 71 +++++++++++++++++++ .../nitro/src/runtime/app/sigma.client.js | 7 ++ packages/nitro/src/runtime/app/vue2.basic.ts | 12 ++++ packages/nitro/src/runtime/app/vue2.ts | 14 ++++ packages/nitro/src/runtime/app/vue3.ts | 1 + packages/nitro/src/runtime/entries/azure.ts | 19 +++++ packages/nitro/src/runtime/entries/cli.ts | 23 ++++++ .../nitro/src/runtime/entries/cloudflare.ts | 46 ++++++++++++ packages/nitro/src/runtime/entries/lambda.ts | 20 ++++++ packages/nitro/src/runtime/entries/local.ts | 14 ++++ packages/nitro/src/runtime/entries/node.ts | 2 + packages/nitro/src/runtime/entries/server.ts | 18 +++++ .../src/runtime/entries/service-worker.ts | 39 ++++++++++ packages/nitro/src/runtime/entries/vercel.ts | 4 ++ packages/nitro/src/runtime/server/error.ts | 67 +++++++++++++++++ packages/nitro/src/runtime/server/index.ts | 23 ++++++ packages/nitro/src/runtime/server/static.ts | 63 ++++++++++++++++ packages/nitro/src/runtime/server/timing.ts | 22 ++++++ packages/nitro/src/runtime/types.d.ts | 6 ++ 21 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 packages/nitro/src/runtime/app/config.ts create mode 100644 packages/nitro/src/runtime/app/render.ts create mode 100644 packages/nitro/src/runtime/app/sigma.client.js create mode 100644 packages/nitro/src/runtime/app/vue2.basic.ts create mode 100644 packages/nitro/src/runtime/app/vue2.ts create mode 100644 packages/nitro/src/runtime/app/vue3.ts create mode 100644 packages/nitro/src/runtime/entries/azure.ts create mode 100644 packages/nitro/src/runtime/entries/cli.ts create mode 100644 packages/nitro/src/runtime/entries/cloudflare.ts create mode 100644 packages/nitro/src/runtime/entries/lambda.ts create mode 100644 packages/nitro/src/runtime/entries/local.ts create mode 100644 packages/nitro/src/runtime/entries/node.ts create mode 100644 packages/nitro/src/runtime/entries/server.ts create mode 100644 packages/nitro/src/runtime/entries/service-worker.ts create mode 100644 packages/nitro/src/runtime/entries/vercel.ts create mode 100644 packages/nitro/src/runtime/server/error.ts create mode 100644 packages/nitro/src/runtime/server/index.ts create mode 100644 packages/nitro/src/runtime/server/static.ts create mode 100644 packages/nitro/src/runtime/server/timing.ts create mode 100644 packages/nitro/src/runtime/types.d.ts diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index e0a917a95a..1827ecdbea 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -106,7 +106,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S } }, _internal: { - runtimeDir: resolve(__dirname, '../runtime'), + runtimeDir: resolve(__dirname, './runtime'), hooks: new Hookable() } } diff --git a/packages/nitro/src/runtime/app/config.ts b/packages/nitro/src/runtime/app/config.ts new file mode 100644 index 0000000000..a98105f3d4 --- /dev/null +++ b/packages/nitro/src/runtime/app/config.ts @@ -0,0 +1,19 @@ +import destr from 'destr' + +const runtimeConfig = process.env.RUNTIME_CONFIG + +for (const type of ['private', 'public']) { + for (const key in runtimeConfig[type]) { + runtimeConfig[type][key] = destr(process.env[key] || runtimeConfig[type][key]) + } +} + +const $config = global.$config = { + ...runtimeConfig.public, + ...runtimeConfig.private +} + +export default { + public: runtimeConfig.public, + private: $config +} diff --git a/packages/nitro/src/runtime/app/render.ts b/packages/nitro/src/runtime/app/render.ts new file mode 100644 index 0000000000..1c7552bd5f --- /dev/null +++ b/packages/nitro/src/runtime/app/render.ts @@ -0,0 +1,71 @@ +import { createRenderer } from 'vue-bundle-renderer' +import devalue from '@nuxt/devalue' +import config from './config' +import { renderToString } from '~renderer' +import server from '~build/dist/server/server' +import clientManifest from '~build/dist/server/client.manifest.json' +import htmlTemplate from '~build/views/document.template.js' + +const renderer = createRenderer(server, { + clientManifest, + renderToString +}) + +const STATIC_ASSETS_BASE = process.env.NUXT_STATIC_BASE + '/' + process.env.NUXT_STATIC_VERSION +const PAYLOAD_JS = '/payload.js' + +export async function renderMiddleware (req, res) { + let url = req.url + + // payload.json request detection + let isPayloadReq = false + if (url.startsWith(STATIC_ASSETS_BASE) && url.endsWith(PAYLOAD_JS)) { + isPayloadReq = true + url = url.substr(STATIC_ASSETS_BASE.length, url.length - STATIC_ASSETS_BASE.length - PAYLOAD_JS.length) + } + + const ssrContext = { + url, + runtimeConfig: { + public: config.public, + private: config.private + }, + ...(req.context || {}) + } + const rendered = await renderer.renderToString(ssrContext) + const payload = ssrContext.nuxt /* nuxt 2 */ || ssrContext.payload /* nuxt 3 */ + + if (process.env.NUXT_FULL_STATIC) { + payload.staticAssetsBase = STATIC_ASSETS_BASE + } + + let data + if (isPayloadReq) { + data = renderPayload(payload, url) + res.setHeader('Content-Type', 'text/javascript;charset=UTF-8') + } else { + data = renderHTML(payload, rendered, ssrContext) + res.setHeader('Content-Type', 'text/html;charset=UTF-8') + } + + const error = ssrContext.nuxt && ssrContext.nuxt.error + res.statusCode = error ? error.statusCode : 200 + res.end(data, 'utf-8') +} + +function renderHTML (payload, rendered, ssrContext) { + const state = `` + const _html = rendered.html + + return htmlTemplate({ + HTML_ATTRS: '', + HEAD_ATTRS: '', + BODY_ATTRS: '', + HEAD: rendered.renderResourceHints() + rendered.renderStyles() + (ssrContext.styles || ''), + APP: _html + state + rendered.renderScripts() + }) +} + +function renderPayload (payload, url) { + return `__NUXT_JSONP__("${url}", ${devalue(payload)})` +} diff --git a/packages/nitro/src/runtime/app/sigma.client.js b/packages/nitro/src/runtime/app/sigma.client.js new file mode 100644 index 0000000000..4212c21438 --- /dev/null +++ b/packages/nitro/src/runtime/app/sigma.client.js @@ -0,0 +1,7 @@ +import { $fetch } from 'ohmyfetch' + +global.process = global.process || {}; + +(function () { const o = Date.now(); const t = () => Date.now() - o; global.process.hrtime = global.process.hrtime || ((o) => { const e = Math.floor(0.001 * (Date.now() - t())); const a = 0.001 * t(); let l = Math.floor(a) + e; let n = Math.floor(a % 1 * 1e9); return o && (l -= o[0], n -= o[1], n < 0 && (l--, n += 1e9)), [l, n] }) })() + +global.$fetch = $fetch diff --git a/packages/nitro/src/runtime/app/vue2.basic.ts b/packages/nitro/src/runtime/app/vue2.basic.ts new file mode 100644 index 0000000000..cdae5c872c --- /dev/null +++ b/packages/nitro/src/runtime/app/vue2.basic.ts @@ -0,0 +1,12 @@ +import _renderToString from 'vue-server-renderer/basic' + +export function renderToString (component, context) { + return new Promise((resolve, reject) => { + _renderToString(component, context, (err, result) => { + if (err) { + return reject(err) + } + return resolve(result) + }) + }) +} diff --git a/packages/nitro/src/runtime/app/vue2.ts b/packages/nitro/src/runtime/app/vue2.ts new file mode 100644 index 0000000000..7c03d09c0d --- /dev/null +++ b/packages/nitro/src/runtime/app/vue2.ts @@ -0,0 +1,14 @@ +import { createRenderer } from '~vueServerRenderer' + +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/app/vue3.ts b/packages/nitro/src/runtime/app/vue3.ts new file mode 100644 index 0000000000..0d6b6c4190 --- /dev/null +++ b/packages/nitro/src/runtime/app/vue3.ts @@ -0,0 +1 @@ +export { renderToString } from '@vue/server-renderer' diff --git a/packages/nitro/src/runtime/entries/azure.ts b/packages/nitro/src/runtime/entries/azure.ts new file mode 100644 index 0000000000..eb309aa7f3 --- /dev/null +++ b/packages/nitro/src/runtime/entries/azure.ts @@ -0,0 +1,19 @@ +import '~polyfill' +import { localCall } from '../server' + +export default async function handle (context, req) { + const url = '/' + (req.params.url || '') + + const { body, status, statusText, headers } = await localCall({ + url, + headers: req.headers, + method: req.method, + body: req.body + }) + + context.res = { + status, + headers, + body: body ? body.toString() : statusText + } +} diff --git a/packages/nitro/src/runtime/entries/cli.ts b/packages/nitro/src/runtime/entries/cli.ts new file mode 100644 index 0000000000..f412abf5bf --- /dev/null +++ b/packages/nitro/src/runtime/entries/cli.ts @@ -0,0 +1,23 @@ +import '~polyfill' +import { localCall } from '../server/call' + +async function cli () { + const url = process.argv[2] || '/' + const debug = (label, ...args) => console.debug(`> ${label}:`, ...args) + const r = await localCall({ url }) + + debug('URL', url) + debug('StatusCode', r.status) + debug('StatusMessage', r.statusText) + for (const header of r.headers.entries()) { + debug(header[0], header[1]) + } + console.log('\n', r.body.toString()) +} + +if (require.main === module) { + cli().catch((err) => { + console.error(err) + process.exit(1) + }) +} diff --git a/packages/nitro/src/runtime/entries/cloudflare.ts b/packages/nitro/src/runtime/entries/cloudflare.ts new file mode 100644 index 0000000000..cd38d749fd --- /dev/null +++ b/packages/nitro/src/runtime/entries/cloudflare.ts @@ -0,0 +1,46 @@ +import '~polyfill' +import { getAssetFromKV } from '@cloudflare/kv-asset-handler' +import { localCall } from '../server' + +const PUBLIC_PATH = process.env.PUBLIC_PATH // Default: /_nuxt/ + +addEventListener('fetch', (event) => { + event.respondWith(handleEvent(event)) +}) + +async function handleEvent (event) { + try { + return await getAssetFromKV(event, { cacheControl: assetsCacheControl }) + } catch (_err) { + // Ignore + } + + const url = new URL(event.request.url) + + const r = await localCall({ + event, + url: url.pathname, + host: url.hostname, + protocol: url.protocol, + headers: event.request.headers, + method: event.request.method, + redirect: event.request.redirect, + body: event.request.body + }) + + return new Response(r.body, { + headers: r.headers, + status: r.status, + statusText: r.statusText + }) +} + +function assetsCacheControl (request) { + if (request.url.includes(PUBLIC_PATH) /* TODO: Check with routerBase */) { + return { + browserTTL: 31536000, + edgeTTL: 31536000 + } + } + return {} +} diff --git a/packages/nitro/src/runtime/entries/lambda.ts b/packages/nitro/src/runtime/entries/lambda.ts new file mode 100644 index 0000000000..41973392a8 --- /dev/null +++ b/packages/nitro/src/runtime/entries/lambda.ts @@ -0,0 +1,20 @@ +import '~polyfill' +import { localCall } from '../server' + +export async function handler (event, context) { + const r = await localCall({ + event, + url: event.path, + context, + headers: event.headers, + method: event.httpMethod, + query: event.queryStringParameters, + body: event.body // TODO: handle event.isBase64Encoded + }) + + return { + statusCode: r.status, + headers: r.headers, + body: r.body.toString() + } +} diff --git a/packages/nitro/src/runtime/entries/local.ts b/packages/nitro/src/runtime/entries/local.ts new file mode 100644 index 0000000000..7386fb5f39 --- /dev/null +++ b/packages/nitro/src/runtime/entries/local.ts @@ -0,0 +1,14 @@ +import '~polyfill' +import { Server } from 'http' +import { parentPort } from 'worker_threads' +import type { AddressInfo } from 'net' +import { handle } from '../server' + +const server = new Server(handle) + +const netServer = server.listen(0, () => { + parentPort.postMessage({ + event: 'listen', + port: (netServer.address() as AddressInfo).port + }) +}) diff --git a/packages/nitro/src/runtime/entries/node.ts b/packages/nitro/src/runtime/entries/node.ts new file mode 100644 index 0000000000..5646685d25 --- /dev/null +++ b/packages/nitro/src/runtime/entries/node.ts @@ -0,0 +1,2 @@ +import '~polyfill' +export * from '../server' diff --git a/packages/nitro/src/runtime/entries/server.ts b/packages/nitro/src/runtime/entries/server.ts new file mode 100644 index 0000000000..301c872964 --- /dev/null +++ b/packages/nitro/src/runtime/entries/server.ts @@ -0,0 +1,18 @@ +import '~polyfill' +import { Server } from 'http' +import { handle } from '../server' + +const server = new Server(handle) + +const port = process.env.NUXT_PORT || process.env.PORT || 3000 +const host = process.env.NUXT_HOST || process.env.HOST || 'localhost' + +server.listen(port, host, (err) => { + if (err) { + console.error(err) + process.exit(1) + } + console.log(`Listening on http://${host}:${port}`) +}) + +export default {} diff --git a/packages/nitro/src/runtime/entries/service-worker.ts b/packages/nitro/src/runtime/entries/service-worker.ts new file mode 100644 index 0000000000..c23486b653 --- /dev/null +++ b/packages/nitro/src/runtime/entries/service-worker.ts @@ -0,0 +1,39 @@ +import '~polyfill' +import { localCall } from '../server' + +addEventListener('fetch', (event: any) => { + const url = new URL(event.request.url) + + if (url.pathname.includes('.') /* is file */) { + return + } + + event.respondWith(handleEvent(url, event)) +}) + +async function handleEvent (url, event) { + const r = await localCall({ + event, + url: url.pathname, + host: url.hostname, + protocol: url.protocol, + headers: event.request.headers, + method: event.request.method, + redirect: event.request.redirect, + body: event.request.body + }) + + return new Response(r.body, { + headers: r.headers, + status: r.status, + statusText: r.statusText + }) +} + +self.addEventListener('install', () => { + self.skipWaiting() +}) + +self.addEventListener('activate', (event) => { + event.waitUntil(self.clients.claim()) +}) diff --git a/packages/nitro/src/runtime/entries/vercel.ts b/packages/nitro/src/runtime/entries/vercel.ts new file mode 100644 index 0000000000..3967889b40 --- /dev/null +++ b/packages/nitro/src/runtime/entries/vercel.ts @@ -0,0 +1,4 @@ +import '~polyfill' +import { handle } from '../server' + +export default handle diff --git a/packages/nitro/src/runtime/server/error.ts b/packages/nitro/src/runtime/server/error.ts new file mode 100644 index 0000000000..b01bf18998 --- /dev/null +++ b/packages/nitro/src/runtime/server/error.ts @@ -0,0 +1,67 @@ +// import ansiHTML from 'ansi-html' +const cwd = process.cwd() + +// TODO: Handle process.env.DEBUG +export function handleError (error, req, res) { + const stack = (error.stack || '') + .split('\n') + .splice(1) + .filter(line => line.includes('at ')) + .map((line) => { + const text = line + .replace(cwd + '/', './') + .replace('webpack:/', '') + .replace('.vue', '.js') // TODO: Support sourcemap + .trim() + return { + text, + internal: (line.includes('node_modules') && !line.includes('.cache')) || + line.includes('internal') || + line.includes('new Promise') + } + }) + + console.error(error.message + '\n' + stack.map(l => ' ' + l.text).join(' \n')) + + const html = ` + + + + + Nuxt Error + + + +
+
${req.method} ${req.url}

+

${error.toString()}

+
${stack.map(i =>
+        `${i.text}`
+  ).join('\n')
+    }
+
+ + +` + + res.statusCode = error.statusCode || 500 + res.statusMessage = error.statusMessage || 'Invernal Error' + res.end(html) +} diff --git a/packages/nitro/src/runtime/server/index.ts b/packages/nitro/src/runtime/server/index.ts new file mode 100644 index 0000000000..c42384a1b3 --- /dev/null +++ b/packages/nitro/src/runtime/server/index.ts @@ -0,0 +1,23 @@ +import '../app/config' +import { createApp, useBase } from 'h3' +import { createFetch } from 'ohmyfetch' +import destr from 'destr' +import { createCall, createFetch as createLocalFetch } from '@nuxt/un/runtime/fetch' +import { timingMiddleware } from './timing' +import { handleError } from './error' +import serverMiddleware from '~serverMiddleware' + +const app = createApp({ + debug: destr(process.env.DEBUG), + onError: handleError +}) + +app.use(timingMiddleware) +app.use(serverMiddleware) +app.use(() => import('../app/render').then(e => e.renderMiddleware), { lazy: true }) + +export const stack = app.stack +export const handle = useBase(process.env.ROUTER_BASE, app) +export const localCall = createCall(handle) +export const localFetch = createLocalFetch(localCall, global.fetch) +export const $fetch = global.$fetch = createFetch({ fetch: localFetch }) diff --git a/packages/nitro/src/runtime/server/static.ts b/packages/nitro/src/runtime/server/static.ts new file mode 100644 index 0000000000..c1ef0b935f --- /dev/null +++ b/packages/nitro/src/runtime/server/static.ts @@ -0,0 +1,63 @@ +import { sendError } from 'h3' +import { getAsset, readAsset } from '~static' + +const METHODS = ['HEAD', 'GET'] +const PUBLIC_PATH = process.env.PUBLIC_PATH // Default: /_nuxt/ +const TWO_DAYS = 2 * 60 * 60 * 24 + +// eslint-disable-next-line +export default async function serveStatic(req, res) { + if (!METHODS.includes(req.method)) { + return + } + + let id = req.url.split('?')[0] + if (id.startsWith('/')) { + id = id.substr(1) + } + if (id.endsWith('/')) { + id = id.substr(0, id.length - 1) + } + + const asset = getAsset(id) || getAsset(id = id + '/index.html') + + if (!asset) { + if (id.startsWith(PUBLIC_PATH)) { + sendError(res, 'Asset not found: ' + id, false, 404) + } + return + } + + const ifNotMatch = req.headers['if-none-match'] === asset.etag + if (ifNotMatch) { + res.statusCode = 304 + return res.end('Not Modified (etag)') + } + + const ifModifiedSinceH = req.headers['if-modified-since'] + if (ifModifiedSinceH && asset.mtime) { + if (new Date(ifModifiedSinceH) >= new Date(asset.mtime)) { + res.statusCode = 304 + return res.end('Not Modified (mtime)') + } + } + + if (asset.type) { + res.setHeader('Content-Type', asset.type) + } + + if (asset.etag) { + res.setHeader('ETag', asset.etag) + } + + if (asset.mtime) { + res.setHeader('Last-Modified', asset.mtime) + } + + if (id.startsWith(PUBLIC_PATH)) { + res.setHeader('Cache-Control', `max-age=${TWO_DAYS}, immutable`) + } + + const contents = await readAsset(id) + return res.end(contents) +} diff --git a/packages/nitro/src/runtime/server/timing.ts b/packages/nitro/src/runtime/server/timing.ts new file mode 100644 index 0000000000..6754a302bb --- /dev/null +++ b/packages/nitro/src/runtime/server/timing.ts @@ -0,0 +1,22 @@ +export const globalTiming = global.__timing__ || { + start: () => 0, + end: () => 0, + metrics: [] +} + +// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server-Timing +export function timingMiddleware (_req, res, next) { + const start = globalTiming.start() + + const _end = res.end + res.end = (data, encoding, callback) => { + const metrics = [['Generate', globalTiming.end(start)], ...globalTiming.metrics] + const serverTiming = metrics.map(m => `-;dur=${m[1]};desc="${encodeURIComponent(m[0])}"`).join(', ') + if (!res.headersSent) { + res.setHeader('Server-Timing', serverTiming) + } + _end.call(res, data, encoding, callback) + } + + next() +} diff --git a/packages/nitro/src/runtime/types.d.ts b/packages/nitro/src/runtime/types.d.ts new file mode 100644 index 0000000000..902e786658 --- /dev/null +++ b/packages/nitro/src/runtime/types.d.ts @@ -0,0 +1,6 @@ +declare module NodeJS { + interface Global { + __timing__: any + $config: any + } +} From 9e9b20ef90057c8fbc47a7e1e6803670b975bfc2 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 18 Jan 2021 12:42:00 +0100 Subject: [PATCH 187/227] fix: bring back nuxt3 support --- packages/nitro/src/context.ts | 2 ++ packages/nitro/src/rollup/config.ts | 6 +++--- packages/nitro/src/runtime/app/render.ts | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index 1827ecdbea..b3d6c9df2f 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -38,6 +38,7 @@ export interface SigmaContext { publicDir: string } _nuxt: { + majorVersion: number dev: boolean rootDir: string srcDir: string @@ -88,6 +89,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S publicDir: '{{ output.dir }}/public' }, _nuxt: { + majorVersion: nuxtOptions._majorVersion || 2, dev: nuxtOptions.dev, rootDir: nuxtOptions.rootDir, srcDir: nuxtOptions.srcDir, diff --git a/packages/nitro/src/rollup/config.ts b/packages/nitro/src/rollup/config.ts index 4723ba03ea..324c2ca8a4 100644 --- a/packages/nitro/src/rollup/config.ts +++ b/packages/nitro/src/rollup/config.ts @@ -159,13 +159,13 @@ export const getRollupConfig = (sigmaContext: SigmaContext) => { })) // https://github.com/rollup/plugins/tree/master/packages/alias - const renderer = sigmaContext.renderer || 'vue2' - const vueServerRenderer = 'vue-server-renderer/' + (sigmaContext._nuxt.dev ? 'build.dev.js' : 'build.prod.js') + const renderer = sigmaContext.renderer || (sigmaContext._nuxt.majorVersion === 3 ? 'vue3' : 'vue2') + const vue2ServerRenderer = 'vue-server-renderer/' + (sigmaContext._nuxt.dev ? 'build.dev.js' : 'build.prod.js') rollupConfig.plugins.push(alias({ entries: { '~runtime': sigmaContext._internal.runtimeDir, '~renderer': require.resolve(resolve(sigmaContext._internal.runtimeDir, 'app', renderer)), - '~vueServerRenderer': vueServerRenderer, + '~vueServerRenderer': vue2ServerRenderer, '~build': sigmaContext._nuxt.buildDir, ...env.alias } diff --git a/packages/nitro/src/runtime/app/render.ts b/packages/nitro/src/runtime/app/render.ts index 1c7552bd5f..80fa655dd4 100644 --- a/packages/nitro/src/runtime/app/render.ts +++ b/packages/nitro/src/runtime/app/render.ts @@ -33,7 +33,8 @@ export async function renderMiddleware (req, res) { ...(req.context || {}) } const rendered = await renderer.renderToString(ssrContext) - const payload = ssrContext.nuxt /* nuxt 2 */ || ssrContext.payload /* nuxt 3 */ + // TODO: nuxt3 should not reuse `nuxt` property for different purpose! + const payload = ssrContext.payload /* nuxt 3 */ || ssrContext.nuxt /* nuxt 2 */ if (process.env.NUXT_FULL_STATIC) { payload.staticAssetsBase = STATIC_ASSETS_BASE From fa5d0e04f9de188fca7bb6c127d21e35b798ca04 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Mon, 18 Jan 2021 12:47:25 +0100 Subject: [PATCH 188/227] chore: fix runtime typescript errors --- packages/nitro/src/runtime/app/config.ts | 2 +- packages/nitro/src/runtime/app/render.ts | 4 ++++ packages/nitro/src/runtime/app/vue2.ts | 1 + packages/nitro/src/runtime/app/vue3.ts | 1 + packages/nitro/src/runtime/entries/cli.ts | 3 ++- packages/nitro/src/runtime/entries/cloudflare.ts | 3 ++- packages/nitro/src/runtime/entries/server.ts | 10 ++++++---- packages/nitro/src/runtime/entries/service-worker.ts | 1 + packages/nitro/src/runtime/server/index.ts | 1 + packages/nitro/src/runtime/server/static.ts | 8 ++++++-- 10 files changed, 25 insertions(+), 9 deletions(-) diff --git a/packages/nitro/src/runtime/app/config.ts b/packages/nitro/src/runtime/app/config.ts index a98105f3d4..b026f824ea 100644 --- a/packages/nitro/src/runtime/app/config.ts +++ b/packages/nitro/src/runtime/app/config.ts @@ -1,6 +1,6 @@ import destr from 'destr' -const runtimeConfig = process.env.RUNTIME_CONFIG +const runtimeConfig = process.env.RUNTIME_CONFIG as any for (const type of ['private', 'public']) { for (const key in runtimeConfig[type]) { diff --git a/packages/nitro/src/runtime/app/render.ts b/packages/nitro/src/runtime/app/render.ts index 80fa655dd4..151cee3c65 100644 --- a/packages/nitro/src/runtime/app/render.ts +++ b/packages/nitro/src/runtime/app/render.ts @@ -1,9 +1,13 @@ import { createRenderer } from 'vue-bundle-renderer' import devalue from '@nuxt/devalue' import config from './config' +// @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, { diff --git a/packages/nitro/src/runtime/app/vue2.ts b/packages/nitro/src/runtime/app/vue2.ts index 7c03d09c0d..0de42f4c57 100644 --- a/packages/nitro/src/runtime/app/vue2.ts +++ b/packages/nitro/src/runtime/app/vue2.ts @@ -1,3 +1,4 @@ +// @ts-ignore import { createRenderer } from '~vueServerRenderer' const _renderer = createRenderer({}) diff --git a/packages/nitro/src/runtime/app/vue3.ts b/packages/nitro/src/runtime/app/vue3.ts index 0d6b6c4190..f3fd7daa59 100644 --- a/packages/nitro/src/runtime/app/vue3.ts +++ b/packages/nitro/src/runtime/app/vue3.ts @@ -1 +1,2 @@ +// @ts-ignore export { renderToString } from '@vue/server-renderer' diff --git a/packages/nitro/src/runtime/entries/cli.ts b/packages/nitro/src/runtime/entries/cli.ts index f412abf5bf..91d3141266 100644 --- a/packages/nitro/src/runtime/entries/cli.ts +++ b/packages/nitro/src/runtime/entries/cli.ts @@ -1,5 +1,5 @@ import '~polyfill' -import { localCall } from '../server/call' +import { localCall } from '../server' async function cli () { const url = process.argv[2] || '/' @@ -9,6 +9,7 @@ async function cli () { debug('URL', url) debug('StatusCode', r.status) debug('StatusMessage', r.statusText) + // @ts-ignore for (const header of r.headers.entries()) { debug(header[0], header[1]) } diff --git a/packages/nitro/src/runtime/entries/cloudflare.ts b/packages/nitro/src/runtime/entries/cloudflare.ts index cd38d749fd..1658fb8bf0 100644 --- a/packages/nitro/src/runtime/entries/cloudflare.ts +++ b/packages/nitro/src/runtime/entries/cloudflare.ts @@ -4,7 +4,7 @@ import { localCall } from '../server' const PUBLIC_PATH = process.env.PUBLIC_PATH // Default: /_nuxt/ -addEventListener('fetch', (event) => { +addEventListener('fetch', (event: any) => { event.respondWith(handleEvent(event)) }) @@ -29,6 +29,7 @@ async function handleEvent (event) { }) return new Response(r.body, { + // @ts-ignore headers: r.headers, status: r.status, statusText: r.statusText diff --git a/packages/nitro/src/runtime/entries/server.ts b/packages/nitro/src/runtime/entries/server.ts index 301c872964..a03ce951e7 100644 --- a/packages/nitro/src/runtime/entries/server.ts +++ b/packages/nitro/src/runtime/entries/server.ts @@ -1,18 +1,20 @@ import '~polyfill' import { Server } from 'http' +import destr from 'destr' import { handle } from '../server' const server = new Server(handle) -const port = process.env.NUXT_PORT || process.env.PORT || 3000 -const host = process.env.NUXT_HOST || process.env.HOST || 'localhost' +const port = (destr(process.env.NUXT_PORT || process.env.PORT) || 3000) as number +const hostname = process.env.NUXT_HOST || process.env.HOST || 'localhost' -server.listen(port, host, (err) => { +// @ts-ignore +server.listen(port, hostname, (err) => { if (err) { console.error(err) process.exit(1) } - console.log(`Listening on http://${host}:${port}`) + console.log(`Listening on http://${hostname}:${port}`) }) export default {} diff --git a/packages/nitro/src/runtime/entries/service-worker.ts b/packages/nitro/src/runtime/entries/service-worker.ts index c23486b653..6db71038cc 100644 --- a/packages/nitro/src/runtime/entries/service-worker.ts +++ b/packages/nitro/src/runtime/entries/service-worker.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import '~polyfill' import { localCall } from '../server' diff --git a/packages/nitro/src/runtime/server/index.ts b/packages/nitro/src/runtime/server/index.ts index c42384a1b3..67714eac9c 100644 --- a/packages/nitro/src/runtime/server/index.ts +++ b/packages/nitro/src/runtime/server/index.ts @@ -5,6 +5,7 @@ import destr from 'destr' import { createCall, createFetch as createLocalFetch } from '@nuxt/un/runtime/fetch' import { timingMiddleware } from './timing' import { handleError } from './error' +// @ts-ignore import serverMiddleware from '~serverMiddleware' const app = createApp({ diff --git a/packages/nitro/src/runtime/server/static.ts b/packages/nitro/src/runtime/server/static.ts index c1ef0b935f..cf639430c7 100644 --- a/packages/nitro/src/runtime/server/static.ts +++ b/packages/nitro/src/runtime/server/static.ts @@ -1,4 +1,5 @@ -import { sendError } from 'h3' +import { createError } from 'h3' +// @ts-ignore import { getAsset, readAsset } from '~static' const METHODS = ['HEAD', 'GET'] @@ -23,7 +24,10 @@ export default async function serveStatic(req, res) { if (!asset) { if (id.startsWith(PUBLIC_PATH)) { - sendError(res, 'Asset not found: ' + id, false, 404) + throw createError({ + message: 'Asset not found: ' + id, + statusCode: 404 + }) } return } From 0675191cba1866ad839451f53539e46bd803ff28 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 20 Jan 2021 15:34:00 +0100 Subject: [PATCH 189/227] fix: disable external tracing for local preset --- packages/nitro/src/presets/local.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/presets/local.ts b/packages/nitro/src/presets/local.ts index c00f2a1280..86827bbdeb 100644 --- a/packages/nitro/src/presets/local.ts +++ b/packages/nitro/src/presets/local.ts @@ -8,7 +8,9 @@ export const local: SigmaPreset = extendPreset(node, { serverDir: '{{ _nuxt.buildDir }}/sigma' }, minify: false, - externals: true, + externals: { + trace: false + }, inlineChunks: true, timing: false, sourceMap: true From cc4a32c024e86d64b78ac92de320aa8aea7e4fe2 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 20 Jan 2021 15:37:21 +0100 Subject: [PATCH 190/227] chore: hide generated logs --- packages/nitro/src/utils/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/utils/index.ts b/packages/nitro/src/utils/index.ts index d2b0cf9701..c5b15c0664 100644 --- a/packages/nitro/src/utils/index.ts +++ b/packages/nitro/src/utils/index.ts @@ -44,10 +44,12 @@ export function tryImport (dir: string, path: string) { } catch (_err) { } } -export async function writeFile (file, contents) { +export async function writeFile (file, contents, log = false) { await fse.mkdirp(dirname(file)) await fse.writeFile(file, contents, 'utf-8') - consola.info('Generated', prettyPath(file)) + if (log) { + consola.info('Generated', prettyPath(file)) + } } export function resolvePath (sigmaContext: SigmaInput, path: string | ((sigmaContext) => string), resolveBase: string = ''): string { From fd0be27f0c04a8891b15c9dbb217fafe36cb88e8 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 20 Jan 2021 16:00:14 +0100 Subject: [PATCH 191/227] fix: static asset handling with leading slash --- packages/nitro/src/rollup/plugins/static.ts | 2 +- packages/nitro/src/runtime/server/static.ts | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/nitro/src/rollup/plugins/static.ts b/packages/nitro/src/rollup/plugins/static.ts index 095416be40..a23487040c 100644 --- a/packages/nitro/src/rollup/plugins/static.ts +++ b/packages/nitro/src/rollup/plugins/static.ts @@ -19,7 +19,7 @@ export function staticAssets (context: SigmaContext) { const etag = createEtag(readFileSync(fullPath)) const stat = statSync(fullPath) - assets[id] = { + assets['/' + id] = { type, etag, mtime: stat.mtime.toJSON(), diff --git a/packages/nitro/src/runtime/server/static.ts b/packages/nitro/src/runtime/server/static.ts index cf639430c7..b802a0c6ab 100644 --- a/packages/nitro/src/runtime/server/static.ts +++ b/packages/nitro/src/runtime/server/static.ts @@ -1,4 +1,5 @@ import { createError } from 'h3' +import { withoutTrailingSlash, withLeadingSlash, parseURL } from 'ufo' // @ts-ignore import { getAsset, readAsset } from '~static' @@ -12,15 +13,18 @@ export default async function serveStatic(req, res) { return } - let id = req.url.split('?')[0] - if (id.startsWith('/')) { - id = id.substr(1) - } - if (id.endsWith('/')) { - id = id.substr(0, id.length - 1) - } + let id = withLeadingSlash(withoutTrailingSlash(parseURL(req.url).pathname)) + let asset = getAsset(id) - const asset = getAsset(id) || getAsset(id = id + '/index.html') + // Try index.html + if (!asset) { + const _id = id + '/index.html' + const _asset = getAsset(_id) + if (_asset) { + asset = _asset + id = _id + } + } if (!asset) { if (id.startsWith(PUBLIC_PATH)) { From 387fa4a278c5df50ef23cfd9e1e003e396a9c090 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 20 Jan 2021 16:42:42 +0100 Subject: [PATCH 192/227] fix: 404 handling for static assets --- packages/nitro/src/runtime/server/static.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/runtime/server/static.ts b/packages/nitro/src/runtime/server/static.ts index b802a0c6ab..c99886610a 100644 --- a/packages/nitro/src/runtime/server/static.ts +++ b/packages/nitro/src/runtime/server/static.ts @@ -29,7 +29,7 @@ export default async function serveStatic(req, res) { if (!asset) { if (id.startsWith(PUBLIC_PATH)) { throw createError({ - message: 'Asset not found: ' + id, + statusMessage: 'Cannot find static asset ' + id, statusCode: 404 }) } From 6e9be0eece336c28ce259d4463dda0c443675fb9 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Wed, 20 Jan 2021 20:13:28 +0100 Subject: [PATCH 193/227] feat: support ssrContext.head Co-Authored-By: Daniel Roe --- packages/nitro/src/runtime/app/render.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/nitro/src/runtime/app/render.ts b/packages/nitro/src/runtime/app/render.ts index 151cee3c65..af2c479b1f 100644 --- a/packages/nitro/src/runtime/app/render.ts +++ b/packages/nitro/src/runtime/app/render.ts @@ -62,11 +62,15 @@ function renderHTML (payload, rendered, ssrContext) { const state = `` const _html = rendered.html + const { htmlAttrs = '', bodyAttrs = '', headTags = '', headAttrs = '' } = + (ssrContext.head && ssrContext.head()) || {} + return htmlTemplate({ - HTML_ATTRS: '', - HEAD_ATTRS: '', - BODY_ATTRS: '', - HEAD: rendered.renderResourceHints() + rendered.renderStyles() + (ssrContext.styles || ''), + HTML_ATTRS: htmlAttrs, + HEAD_ATTRS: headAttrs, + BODY_ATTRS: bodyAttrs, + HEAD: headTags + + rendered.renderResourceHints() + rendered.renderStyles() + (ssrContext.styles || ''), APP: _html + state + rendered.renderScripts() }) } From 2186d953d0f828cbda1cd6960646ce6c9d5bbc49 Mon Sep 17 00:00:00 2001 From: "Xin Du (Clark)" Date: Wed, 20 Jan 2021 22:08:54 +0000 Subject: [PATCH 194/227] fix: update documentPath with updated buildDir (#70) --- packages/nitro/src/module/nuxt2.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 7669c623d5..449f62f13f 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -13,8 +13,10 @@ export default function (nuxt, moduleContainer) { } nuxt.options.build.transpile = nuxt.options.build.transpile || [] nuxt.options.build.transpile.push(nuxt.options.buildDir) - nuxt.options.appTemplatePath = nuxt.options.appTemplatePath - .replace(oldBuildDir, nuxt.options.buildDir) + for (const pathKey of ['appTemplatePath', 'documentPath']) { + nuxt.options[pathKey] = nuxt.options[pathKey] + .replace(oldBuildDir, nuxt.options.buildDir) + } // Create contexts const sigmaContext = getsigmaContext(nuxt.options, nuxt.options.sigma || {}) From f4e15196b20f9929c28c51c996819b63375675e3 Mon Sep 17 00:00:00 2001 From: "Xin Du (Clark)" Date: Wed, 20 Jan 2021 22:09:22 +0000 Subject: [PATCH 195/227] fix error message in rollup and server (#72) --- packages/nitro/src/build.ts | 2 +- packages/nitro/src/runtime/server/error.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index 2c40a808ad..d663d2429b 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -64,7 +64,7 @@ async function _build (sigmaContext: SigmaContext) { spinner.start('Building server...') const build = await rollup(sigmaContext.rollupConfig).catch((error) => { - spinner.fail('Rollup error: ' + error.messsage) + spinner.fail('Rollup error: ' + error.message) throw error }) diff --git a/packages/nitro/src/runtime/server/error.ts b/packages/nitro/src/runtime/server/error.ts index b01bf18998..155325d125 100644 --- a/packages/nitro/src/runtime/server/error.ts +++ b/packages/nitro/src/runtime/server/error.ts @@ -62,6 +62,6 @@ export function handleError (error, req, res) { ` res.statusCode = error.statusCode || 500 - res.statusMessage = error.statusMessage || 'Invernal Error' + res.statusMessage = error.statusMessage || 'Internal Error' res.end(html) } From 0ebab89014376a4d983f1636a1db99a35f69374e Mon Sep 17 00:00:00 2001 From: "Xin Du (Clark)" Date: Thu, 21 Jan 2021 00:58:43 +0000 Subject: [PATCH 196/227] update getSigmaContext name (#73) --- packages/nitro/src/context.ts | 2 +- packages/nitro/src/module/nuxt2.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index b3d6c9df2f..faa2bc1338 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -64,7 +64,7 @@ export interface SigmaInput extends DeepPartial {} export type SigmaPreset = SigmaInput | ((input: SigmaInput) => SigmaInput) -export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): SigmaContext { +export function getSigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): SigmaContext { const defaults: SigmaContext = { timing: true, inlineChunks: true, diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 449f62f13f..77259be301 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -1,7 +1,7 @@ import fetch from 'node-fetch' import { resolve } from 'upath' import { build, generate, prepare } from '../build' -import { getsigmaContext, SigmaContext } from '../context' +import { getSigmaContext, SigmaContext } from '../context' import { createDevServer } from '../server' import wpfs from '../utils/wpfs' @@ -19,8 +19,8 @@ export default function (nuxt, moduleContainer) { } // Create contexts - const sigmaContext = getsigmaContext(nuxt.options, nuxt.options.sigma || {}) - const sigmaDevContext = getsigmaContext(nuxt.options, { preset: 'local' }) + const sigmaContext = getSigmaContext(nuxt.options, nuxt.options.sigma || {}) + const sigmaDevContext = getSigmaContext(nuxt.options, { preset: 'local' }) // Connect hooks nuxt.addHooks(sigmaContext.nuxtHooks) From a6936ff8c6683174b1cef7df3f52f0d917d63907 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 21 Jan 2021 14:07:48 +0100 Subject: [PATCH 197/227] fix: default value for template path --- packages/nitro/src/module/nuxt2.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/module/nuxt2.ts index 77259be301..07f14eecda 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/module/nuxt2.ts @@ -13,8 +13,9 @@ export default function (nuxt, moduleContainer) { } nuxt.options.build.transpile = nuxt.options.build.transpile || [] nuxt.options.build.transpile.push(nuxt.options.buildDir) + for (const pathKey of ['appTemplatePath', 'documentPath']) { - nuxt.options[pathKey] = nuxt.options[pathKey] + nuxt.options[pathKey] = (nuxt.options[pathKey] || '') .replace(oldBuildDir, nuxt.options.buildDir) } From 0b886cf57ff2f55c693507d343c28e4979aa7b7d Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 21 Jan 2021 14:21:33 +0100 Subject: [PATCH 198/227] feat: serve-placeholder --- packages/nitro/src/server.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index 70bfd90041..20936f61ee 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -5,6 +5,7 @@ import debounce from 'debounce' import chokidar from 'chokidar' import { listen, Listener } from 'listhen' import serveStatic from 'serve-static' +import servePlaceholder from 'serve-placeholder' import { createProxy } from 'http-proxy' import { stat } from 'fs-extra' import type { SigmaContext } from './context' @@ -68,6 +69,10 @@ export function createDevServer (sigmaContext: SigmaContext) { return next() }) + // serve placeholder 404 assets instead of hitting SSR + app.use(sigmaContext._nuxt.publicPath, servePlaceholder()) + app.use(sigmaContext._nuxt.routerBase, servePlaceholder({ skipUnknown: true })) + // SSR Proxy const proxy = createProxy() app.use((req, res) => { From 4f09b514f121730c6754984743da9c13ed46d9e3 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 21 Jan 2021 15:46:05 +0100 Subject: [PATCH 199/227] fix: _interopDefault potential cjs files --- packages/nitro/src/runtime/app/render.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/nitro/src/runtime/app/render.ts b/packages/nitro/src/runtime/app/render.ts index af2c479b1f..1920715a38 100644 --- a/packages/nitro/src/runtime/app/render.ts +++ b/packages/nitro/src/runtime/app/render.ts @@ -4,14 +4,16 @@ import config from './config' // @ts-ignore import { renderToString } from '~renderer' // @ts-ignore -import server from '~build/dist/server/server' +import createApp 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, +function _interopDefault (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e } } + +const renderer = createRenderer(_interopDefault(createApp), { + clientManifest: _interopDefault(clientManifest), renderToString }) From d94aec4841eab634f4014712dc9194bda0729dcc Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Thu, 21 Jan 2021 15:49:34 +0100 Subject: [PATCH 200/227] fix: fix _interopDefault implementation --- packages/nitro/src/runtime/app/render.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nitro/src/runtime/app/render.ts b/packages/nitro/src/runtime/app/render.ts index 1920715a38..644d294134 100644 --- a/packages/nitro/src/runtime/app/render.ts +++ b/packages/nitro/src/runtime/app/render.ts @@ -10,7 +10,7 @@ import clientManifest from '~build/dist/server/client.manifest.json' // @ts-ignore import htmlTemplate from '~build/views/document.template.js' -function _interopDefault (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e } } +function _interopDefault (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e } const renderer = createRenderer(_interopDefault(createApp), { clientManifest: _interopDefault(clientManifest), From 41951c8862fd7c7fa96d996cd486b8bf83f846f3 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 22 Jan 2021 20:53:40 +0100 Subject: [PATCH 201/227] refactor: move nuxt2 plugin to compat --- .../nitro/src/{module/nuxt2.ts => compat.ts} | 65 +++++-------------- packages/nitro/src/index.ts | 11 ++-- packages/nitro/src/middleware.ts | 29 +++++++++ packages/nitro/src/server.ts | 50 +++++++------- packages/nitro/src/utils/wpfs.ts | 2 +- 5 files changed, 81 insertions(+), 76 deletions(-) rename packages/nitro/src/{module/nuxt2.ts => compat.ts} (63%) create mode 100644 packages/nitro/src/middleware.ts diff --git a/packages/nitro/src/module/nuxt2.ts b/packages/nitro/src/compat.ts similarity index 63% rename from packages/nitro/src/module/nuxt2.ts rename to packages/nitro/src/compat.ts index 07f14eecda..a573bf46c0 100644 --- a/packages/nitro/src/module/nuxt2.ts +++ b/packages/nitro/src/compat.ts @@ -1,23 +1,17 @@ import fetch from 'node-fetch' import { resolve } from 'upath' -import { build, generate, prepare } from '../build' -import { getSigmaContext, SigmaContext } from '../context' -import { createDevServer } from '../server' -import wpfs from '../utils/wpfs' +import { build, generate, prepare } from './build' +import { getSigmaContext, SigmaContext } from './context' +import { createDevServer } from './server' +import { wpfs } from './utils/wpfs' +import { resolveMiddleware } from './middleware' -export default function (nuxt, moduleContainer) { - // Build in node_modules/.cache/nuxt - const oldBuildDir = nuxt.options.buildDir - if (!nuxt.options.dev) { - nuxt.options.buildDir = resolve(nuxt.options.rootDir, 'node_modules/.cache/nuxt') - } - nuxt.options.build.transpile = nuxt.options.build.transpile || [] - nuxt.options.build.transpile.push(nuxt.options.buildDir) +export default function nuxt2CompatModule () { + const { nuxt } = this - for (const pathKey of ['appTemplatePath', 'documentPath']) { - nuxt.options[pathKey] = (nuxt.options[pathKey] || '') - .replace(oldBuildDir, nuxt.options.buildDir) - } + // Disable loading-screen + nuxt.options.build.loadingScreen = false + nuxt.options.build.indicator = false // Create contexts const sigmaContext = getSigmaContext(nuxt.options, nuxt.options.sigma || {}) @@ -45,41 +39,18 @@ export default function (nuxt, moduleContainer) { } // Sigma client plugin - moduleContainer.addPlugin({ + this.addPlugin({ fileName: 'sigma.client.js', src: resolve(sigmaContext._internal.runtimeDir, 'app/sigma.client.js') }) - // serverMiddleware bridge - // TODO: render:setupMiddleware hook - // TODO: support m.prefix and m.route + // Resolve middleware nuxt.hook('modules:done', () => { - const unsupported = [] - for (let m of nuxt.options.serverMiddleware) { - if (typeof m === 'string') { m = { handler: m } } - const route = m.path || m.route || '/' - let handle = m.handler || m.handle - if (typeof handle !== 'string' || typeof route !== 'string') { - if (route === '/_loading') { - nuxt.server.setLoadingMiddleware(handle) - continue - } - // Temporary hide for @nuxt/pwa module - if (route === '/_nuxt/' && process.env.NODE_ENV === 'development') { - continue - } - unsupported.push(m) - continue - } - handle = nuxt.resolver.resolvePath(handle) - sigmaContext.middleware.push({ ...m, route, handle }) - sigmaDevContext.middleware.push({ ...m, route, handle }) - } - nuxt.options.serverMiddleware = [...unsupported] - if (unsupported.length) { - console.warn('[sigma] Unsupported Server middleware used: \n', ...unsupported) - console.info('Supported format is `{ path: string, handler: string }` and handler should export `(req, res) => {}`') - } + const { middleware, legacyMiddleware } = + resolveMiddleware(nuxt.options.serverMiddleware, nuxt.resolver.resolvePath) + nuxt.server.setLegacyMiddleware(legacyMiddleware) + sigmaContext.middleware.push(...middleware) + sigmaDevContext.middleware.push(...middleware) }) // nuxt build/dev @@ -154,7 +125,7 @@ function createNuxt2DevServer (sigmaContext: SigmaContext) { renderRoute, listen, serverMiddlewarePaths () { return [] }, - ready () {} + ready () { } } } diff --git a/packages/nitro/src/index.ts b/packages/nitro/src/index.ts index a66a35c2fb..5fb5ca1103 100644 --- a/packages/nitro/src/index.ts +++ b/packages/nitro/src/index.ts @@ -1,7 +1,6 @@ -import nuxt2 from './module/nuxt2' +export * from './build' +export * from './context' +export * from './middleware' +export * from './server' export * from './types' - -export default function () { - const { nuxt } = this - return nuxt2(nuxt, this) -} +export { wpfs } from './utils/wpfs' diff --git a/packages/nitro/src/middleware.ts b/packages/nitro/src/middleware.ts new file mode 100644 index 0000000000..84178c5342 --- /dev/null +++ b/packages/nitro/src/middleware.ts @@ -0,0 +1,29 @@ +export interface Middleware { + handle: string + route: string +} + +export function resolveMiddleware (serverMiddleware: any[], resolvePath: (string) => string) { + const middleware: Middleware[] = [] + const legacyMiddleware: Middleware[] = [] + + for (let m of serverMiddleware) { + if (typeof m === 'string') { 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 { + middleware.push({ + ...m, + handle: resolvePath(handle), + route + }) + } + } + + return { + middleware, + legacyMiddleware + } +} diff --git a/packages/nitro/src/server.ts b/packages/nitro/src/server.ts index 20936f61ee..38243a0bca 100644 --- a/packages/nitro/src/server.ts +++ b/packages/nitro/src/server.ts @@ -1,5 +1,5 @@ import { Worker } from 'worker_threads' -import connect from 'connect' +import { createApp } from 'h3' import { resolve } from 'upath' import debounce from 'debounce' import chokidar from 'chokidar' @@ -48,26 +48,17 @@ export function createDevServer (sigmaContext: SigmaContext) { } // App - const app = connect() + const app = createApp() // _nuxt and static app.use(sigmaContext._nuxt.publicPath, serveStatic(resolve(sigmaContext._nuxt.buildDir, 'dist/client'))) app.use(sigmaContext._nuxt.routerBase, serveStatic(resolve(sigmaContext._nuxt.staticDir))) - // Dev Middleware - let loadingMiddleware, devMiddleware - const setLoadingMiddleware = (m) => { loadingMiddleware = m } - const setDevMiddleware = (m) => { devMiddleware = m } - app.use((req, res, next) => { - if (loadingMiddleware && req.url.startsWith('/_loading')) { - req.url = req.url.replace('/_loading', '') - return loadingMiddleware(req, res) - } - if (devMiddleware) { - return devMiddleware(req, res, next) - } - return next() - }) + // Dynamic Middlwware + const legacyMiddleware = createDynamicMiddleware() + const devMiddleware = createDynamicMiddleware() + app.use(legacyMiddleware.middleware) + app.use(devMiddleware.middleware) // serve placeholder 404 assets instead of hitting SSR app.use(sigmaContext._nuxt.publicPath, servePlaceholder()) @@ -80,10 +71,6 @@ export function createDevServer (sigmaContext: SigmaContext) { proxy.web(req, res, { target: workerAddress }, (_err) => { // console.error('[proxy]', err) }) - } else if (loadingMiddleware) { - // TODO:serverIndex method is not exposed - // loadingMiddleware(req, res) - sigmaContext._internal.hooks.callHook('renderLoading', req, res) } else { res.end('Worker not ready!') } @@ -131,7 +118,26 @@ export function createDevServer (sigmaContext: SigmaContext) { listen: _listen, close, watch, - setLoadingMiddleware, - setDevMiddleware + setLegacyMiddleware: legacyMiddleware.set, + setDevMiddleware: devMiddleware.set + } +} + +function createDynamicMiddleware () { + let middleware + return { + set: (input) => { + if (!Array.isArray(input)) { + middleware = input + return + } + const app = require('connect')() + for (const m of input) { + app.use(m.path || m.route || '/', m.handler || m.handle) + } + middleware = app + }, + middleware: (req, res, next) => + middleware ? middleware(req, res, next) : next() } } diff --git a/packages/nitro/src/utils/wpfs.ts b/packages/nitro/src/utils/wpfs.ts index 8636ac8567..ed033735df 100644 --- a/packages/nitro/src/utils/wpfs.ts +++ b/packages/nitro/src/utils/wpfs.ts @@ -1,7 +1,7 @@ import { join } from 'upath' import fsExtra from 'fs-extra' -export default { +export const wpfs = { ...fsExtra, join } From 5248905dd72be2d6e70c555a106da03573334ca1 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Fri, 22 Jan 2021 20:55:59 +0100 Subject: [PATCH 202/227] refactor: rebrand to nitro --- packages/nitro/src/build.ts | 62 ++++++------ packages/nitro/src/compat.ts | 66 ++++++------- packages/nitro/src/context.ts | 26 ++--- packages/nitro/src/presets/azure.ts | 8 +- packages/nitro/src/presets/browser.ts | 10 +- packages/nitro/src/presets/cli.ts | 6 +- packages/nitro/src/presets/cloudflare.ts | 6 +- packages/nitro/src/presets/lambda.ts | 4 +- packages/nitro/src/presets/local.ts | 6 +- packages/nitro/src/presets/netlify.ts | 4 +- packages/nitro/src/presets/node.ts | 4 +- packages/nitro/src/presets/server.ts | 6 +- packages/nitro/src/presets/vercel.ts | 8 +- packages/nitro/src/presets/worker.ts | 6 +- packages/nitro/src/rollup/config.ts | 96 +++++++++---------- packages/nitro/src/rollup/plugins/static.ts | 4 +- .../app/{sigma.client.js => nitro.client.js} | 0 packages/nitro/src/server.ts | 20 ++-- packages/nitro/src/utils/index.ts | 12 +-- 19 files changed, 177 insertions(+), 177 deletions(-) rename packages/nitro/src/runtime/app/{sigma.client.js => nitro.client.js} (100%) diff --git a/packages/nitro/src/build.ts b/packages/nitro/src/build.ts index d663d2429b..37161a602e 100644 --- a/packages/nitro/src/build.ts +++ b/packages/nitro/src/build.ts @@ -6,19 +6,19 @@ import { readFile, emptyDir, copy } from 'fs-extra' import { printFSTree } from './utils/tree' import { getRollupConfig } from './rollup/config' import { hl, prettyPath, serializeTemplate, writeFile, isDirectory } from './utils' -import { SigmaContext } from './context' +import { NitroContext } from './context' -export async function prepare (sigmaContext: SigmaContext) { - consola.info(`Sigma preset is ${hl(sigmaContext.preset)}`) +export async function prepare (nitroContext: NitroContext) { + consola.info(`Nitro preset is ${hl(nitroContext.preset)}`) - await cleanupDir(sigmaContext.output.dir) + await cleanupDir(nitroContext.output.dir) - if (!sigmaContext.output.publicDir.startsWith(sigmaContext.output.dir)) { - await cleanupDir(sigmaContext.output.publicDir) + if (!nitroContext.output.publicDir.startsWith(nitroContext.output.dir)) { + await cleanupDir(nitroContext.output.publicDir) } - if (!sigmaContext.output.serverDir.startsWith(sigmaContext.output.dir)) { - await cleanupDir(sigmaContext.output.serverDir) + if (!nitroContext.output.serverDir.startsWith(nitroContext.output.dir)) { + await cleanupDir(nitroContext.output.serverDir) } } @@ -27,63 +27,63 @@ async function cleanupDir (dir: string) { await emptyDir(dir) } -export async function generate (sigmaContext: SigmaContext) { +export async function generate (nitroContext: NitroContext) { const spinner = ora() spinner.start('Generating public...') - const clientDist = resolve(sigmaContext._nuxt.buildDir, 'dist/client') + const clientDist = resolve(nitroContext._nuxt.buildDir, 'dist/client') if (await isDirectory(clientDist)) { - await copy(clientDist, join(sigmaContext.output.publicDir, sigmaContext._nuxt.publicPath)) + await copy(clientDist, join(nitroContext.output.publicDir, nitroContext._nuxt.publicPath)) } - const staticDir = resolve(sigmaContext._nuxt.srcDir, sigmaContext._nuxt.staticDir) + const staticDir = resolve(nitroContext._nuxt.srcDir, nitroContext._nuxt.staticDir) if (await isDirectory(staticDir)) { - await copy(staticDir, sigmaContext.output.publicDir) + await copy(staticDir, nitroContext.output.publicDir) } - spinner.succeed('Generated public ' + prettyPath(sigmaContext.output.publicDir)) + spinner.succeed('Generated public ' + prettyPath(nitroContext.output.publicDir)) } -export async function build (sigmaContext: SigmaContext) { +export async function build (nitroContext: NitroContext) { // Compile html template - const htmlSrc = resolve(sigmaContext._nuxt.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`) + const htmlSrc = resolve(nitroContext._nuxt.buildDir, `views/${{ 2: 'app', 3: 'document' }[2]}.template.html`) const htmlTemplate = { src: htmlSrc, contents: '', dst: '', compiled: '' } htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.') htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8') htmlTemplate.compiled = 'module.exports = ' + serializeTemplate(htmlTemplate.contents) - await sigmaContext._internal.hooks.callHook('sigma:template:document', htmlTemplate) + await nitroContext._internal.hooks.callHook('nitro:template:document', htmlTemplate) await writeFile(htmlTemplate.dst, htmlTemplate.compiled) - sigmaContext.rollupConfig = getRollupConfig(sigmaContext) - await sigmaContext._internal.hooks.callHook('sigma:rollup:before', sigmaContext) - return sigmaContext._nuxt.dev ? _watch(sigmaContext) : _build(sigmaContext) + nitroContext.rollupConfig = getRollupConfig(nitroContext) + await nitroContext._internal.hooks.callHook('nitro:rollup:before', nitroContext) + return nitroContext._nuxt.dev ? _watch(nitroContext) : _build(nitroContext) } -async function _build (sigmaContext: SigmaContext) { +async function _build (nitroContext: NitroContext) { const spinner = ora() spinner.start('Building server...') - const build = await rollup(sigmaContext.rollupConfig).catch((error) => { + const build = await rollup(nitroContext.rollupConfig).catch((error) => { spinner.fail('Rollup error: ' + error.message) throw error }) spinner.start('Writing server bundle...') - await build.write(sigmaContext.rollupConfig.output) + await build.write(nitroContext.rollupConfig.output) spinner.succeed('Server built') - await printFSTree(sigmaContext.output.serverDir) - await sigmaContext._internal.hooks.callHook('sigma:compiled', sigmaContext) + await printFSTree(nitroContext.output.serverDir) + await nitroContext._internal.hooks.callHook('nitro:compiled', nitroContext) return { - entry: resolve(sigmaContext.rollupConfig.output.dir, sigmaContext.rollupConfig.output.entryFileNames) + entry: resolve(nitroContext.rollupConfig.output.dir, nitroContext.rollupConfig.output.entryFileNames) } } -function _watch (sigmaContext: SigmaContext) { +function _watch (nitroContext: NitroContext) { const spinner = ora() - const watcher = rollupWatch(sigmaContext.rollupConfig) + const watcher = rollupWatch(nitroContext.rollupConfig) let start @@ -96,13 +96,13 @@ function _watch (sigmaContext: SigmaContext) { // Building an individual bundle case 'BUNDLE_START': start = Date.now() - spinner.start('Building Sigma...') + spinner.start('Building Nitro...') return // Finished building all bundles case 'END': - sigmaContext._internal.hooks.callHook('sigma:compiled', sigmaContext) - return spinner.succeed(`Sigma built in ${Date.now() - start} ms`) + nitroContext._internal.hooks.callHook('nitro:compiled', nitroContext) + return spinner.succeed(`Nitro built in ${Date.now() - start} ms`) // Encountered an error while bundling case 'ERROR': diff --git a/packages/nitro/src/compat.ts b/packages/nitro/src/compat.ts index a573bf46c0..e6a5c9a56c 100644 --- a/packages/nitro/src/compat.ts +++ b/packages/nitro/src/compat.ts @@ -1,7 +1,7 @@ import fetch from 'node-fetch' import { resolve } from 'upath' import { build, generate, prepare } from './build' -import { getSigmaContext, SigmaContext } from './context' +import { getNitroContext, NitroContext } from './context' import { createDevServer } from './server' import { wpfs } from './utils/wpfs' import { resolveMiddleware } from './middleware' @@ -14,20 +14,20 @@ export default function nuxt2CompatModule () { nuxt.options.build.indicator = false // Create contexts - const sigmaContext = getSigmaContext(nuxt.options, nuxt.options.sigma || {}) - const sigmaDevContext = getSigmaContext(nuxt.options, { preset: 'local' }) + const nitroContext = getNitroContext(nuxt.options, nuxt.options.nitro || {}) + const nitroDevContext = getNitroContext(nuxt.options, { preset: 'local' }) // Connect hooks - nuxt.addHooks(sigmaContext.nuxtHooks) - nuxt.hook('close', () => sigmaContext._internal.hooks.callHook('close')) + nuxt.addHooks(nitroContext.nuxtHooks) + nuxt.hook('close', () => nitroContext._internal.hooks.callHook('close')) - nuxt.addHooks(sigmaDevContext.nuxtHooks) - nuxt.hook('close', () => sigmaDevContext._internal.hooks.callHook('close')) - sigmaDevContext._internal.hooks.hook('renderLoading', + nuxt.addHooks(nitroDevContext.nuxtHooks) + nuxt.hook('close', () => nitroDevContext._internal.hooks.callHook('close')) + nitroDevContext._internal.hooks.hook('renderLoading', (req, res) => nuxt.callHook('server:nuxt:renderLoading', req, res)) - // Expose process.env.SIGMA_PRESET - nuxt.options.env.SIGMA_PRESET = sigmaContext.preset + // Expose process.env.NITRO_PRESET + nuxt.options.env.NITRO_PRESET = nitroContext.preset // .ts is supported for serverMiddleware nuxt.options.extensions.push('ts') @@ -35,13 +35,13 @@ export default function nuxt2CompatModule () { // Replace nuxt server if (nuxt.server) { nuxt.server.__closed = true - nuxt.server = createNuxt2DevServer(sigmaDevContext) + nuxt.server = createNuxt2DevServer(nitroDevContext) } - // Sigma client plugin + // Nitro client plugin this.addPlugin({ - fileName: 'sigma.client.js', - src: resolve(sigmaContext._internal.runtimeDir, 'app/sigma.client.js') + fileName: 'nitro.client.js', + src: resolve(nitroContext._internal.runtimeDir, 'app/nitro.client.js') }) // Resolve middleware @@ -49,8 +49,8 @@ export default function nuxt2CompatModule () { const { middleware, legacyMiddleware } = resolveMiddleware(nuxt.options.serverMiddleware, nuxt.resolver.resolvePath) nuxt.server.setLegacyMiddleware(legacyMiddleware) - sigmaContext.middleware.push(...middleware) - sigmaDevContext.middleware.push(...middleware) + nitroContext.middleware.push(...middleware) + nitroDevContext.middleware.push(...middleware) }) // nuxt build/dev @@ -58,47 +58,47 @@ export default function nuxt2CompatModule () { nuxt.options.build.standalone = false nuxt.hook('build:done', async () => { if (nuxt.options.dev) { - await build(sigmaDevContext) - } else if (!sigmaContext._nuxt.isStatic) { - await prepare(sigmaContext) - await generate(sigmaContext) - await build(sigmaContext) + await build(nitroDevContext) + } else if (!nitroContext._nuxt.isStatic) { + await prepare(nitroContext) + await generate(nitroContext) + await build(nitroContext) } }) // nude dev if (nuxt.options.dev) { - sigmaDevContext._internal.hooks.hook('sigma:compiled', () => { nuxt.server.watch() }) + nitroDevContext._internal.hooks.hook('nitro:compiled', () => { nuxt.server.watch() }) nuxt.hook('build:compile', ({ compiler }) => { compiler.outputFileSystem = wpfs }) nuxt.hook('server:devMiddleware', (m) => { nuxt.server.setDevMiddleware(m) }) } // nuxt generate - nuxt.options.generate.dir = sigmaContext.output.publicDir + nuxt.options.generate.dir = nitroContext.output.publicDir nuxt.options.generate.manifest = false nuxt.hook('generate:cache:ignore', (ignore: string[]) => { - ignore.push(sigmaContext.output.dir) - ignore.push(sigmaContext.output.serverDir) - if (sigmaContext.output.publicDir) { - ignore.push(sigmaContext.output.publicDir) + ignore.push(nitroContext.output.dir) + ignore.push(nitroContext.output.serverDir) + if (nitroContext.output.publicDir) { + ignore.push(nitroContext.output.publicDir) } - ignore.push(...sigmaContext.ignore) + ignore.push(...nitroContext.ignore) }) nuxt.hook('generate:before', async () => { - await prepare(sigmaContext) + await prepare(nitroContext) }) nuxt.hook('generate:extendRoutes', async () => { - await build(sigmaDevContext) + await build(nitroDevContext) await nuxt.server.reload() }) nuxt.hook('generate:done', async () => { await nuxt.server.close() - await build(sigmaContext) + await build(nitroContext) }) } -function createNuxt2DevServer (sigmaContext: SigmaContext) { - const server = createDevServer(sigmaContext) +function createNuxt2DevServer (nitroContext: NitroContext) { + const server = createDevServer(nitroContext) const listeners = [] async function listen (port) { diff --git a/packages/nitro/src/context.ts b/packages/nitro/src/context.ts index faa2bc1338..efcf184ada 100644 --- a/packages/nitro/src/context.ts +++ b/packages/nitro/src/context.ts @@ -14,7 +14,7 @@ export interface ServerMiddleware { promisify?: boolean // Default is true } -export interface SigmaContext { +export interface NitroContext { timing: boolean inlineChunks: boolean minify: boolean @@ -60,12 +60,12 @@ export interface SigmaContext { type DeepPartial = { [P in keyof T]?: DeepPartial } -export interface SigmaInput extends DeepPartial {} +export interface NitroInput extends DeepPartial {} -export type SigmaPreset = SigmaInput | ((input: SigmaInput) => SigmaInput) +export type NitroPreset = NitroInput | ((input: NitroInput) => NitroInput) -export function getSigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): SigmaContext { - const defaults: SigmaContext = { +export function getNitroContext (nuxtOptions: NuxtOptions, input: NitroInput): NitroContext { + const defaults: NitroContext = { timing: true, inlineChunks: true, minify: true, @@ -113,7 +113,7 @@ export function getSigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S } } - defaults.preset = input.preset || process.env.SIGMA_PRESET || detectTarget() || 'server' + defaults.preset = input.preset || process.env.NITRO_PRESET || detectTarget() || 'server' let presetDefaults = PRESETS[defaults.preset] || tryImport(nuxtOptions.rootDir, defaults.preset) if (!presetDefaults) { throw new Error('Cannot resolve preset: ' + defaults.preset) @@ -123,16 +123,16 @@ export function getSigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S const _presetInput = defu(input, defaults) // @ts-ignore const _preset = extendPreset(input, presetDefaults)(_presetInput) - const sigmaContext: SigmaContext = defu(input, _preset, defaults) as any + const nitroContext: NitroContext = defu(input, _preset, defaults) as any - sigmaContext.output.dir = resolvePath(sigmaContext, sigmaContext.output.dir) - sigmaContext.output.publicDir = resolvePath(sigmaContext, sigmaContext.output.publicDir) - sigmaContext.output.serverDir = resolvePath(sigmaContext, sigmaContext.output.serverDir) + nitroContext.output.dir = resolvePath(nitroContext, nitroContext.output.dir) + nitroContext.output.publicDir = resolvePath(nitroContext, nitroContext.output.publicDir) + nitroContext.output.serverDir = resolvePath(nitroContext, nitroContext.output.serverDir) - sigmaContext._internal.hooks.addHooks(sigmaContext.hooks) + nitroContext._internal.hooks.addHooks(nitroContext.hooks) - // console.log(sigmaContext) + // console.log(nitroContext) // process.exit(1) - return sigmaContext + return nitroContext } diff --git a/packages/nitro/src/presets/azure.ts b/packages/nitro/src/presets/azure.ts index e69e28c23f..eb4eb41f1c 100644 --- a/packages/nitro/src/presets/azure.ts +++ b/packages/nitro/src/presets/azure.ts @@ -3,14 +3,14 @@ import consola from 'consola' import { createWriteStream } from 'fs-extra' import { join, resolve } from 'upath' import { prettyPath, writeFile } from '../utils' -import { SigmaPreset, SigmaContext } from '../context' +import { NitroPreset, NitroContext } from '../context' -export const azure: SigmaPreset = { +export const azure: NitroPreset = { inlineChunks: false, serveStatic: true, entry: '{{ _internal.runtimeDir }}/entries/azure', hooks: { - async 'sigma:compiled' (ctx: SigmaContext) { + async 'nitro:compiled' (ctx: NitroContext) { await writeRoutes(ctx) } } @@ -31,7 +31,7 @@ function zipDirectory (dir: string, outfile: string): Promise { }) } -async function writeRoutes ({ output: { dir, serverDir } }: SigmaContext) { +async function writeRoutes ({ output: { dir, serverDir } }: NitroContext) { const host = { version: '2.0', extensions: { http: { routePrefix: '' } } diff --git a/packages/nitro/src/presets/browser.ts b/packages/nitro/src/presets/browser.ts index 5e262ad882..1c77ef032f 100644 --- a/packages/nitro/src/presets/browser.ts +++ b/packages/nitro/src/presets/browser.ts @@ -2,10 +2,10 @@ import { writeFile } from 'fs-extra' import { resolve } from 'upath' import consola from 'consola' import { extendPreset, prettyPath } from '../utils' -import { SigmaPreset, SigmaContext, SigmaInput } from '../context' +import { NitroPreset, NitroContext, NitroInput } from '../context' import { worker } from './worker' -export const browser: SigmaPreset = extendPreset(worker, (input: SigmaInput) => { +export const browser: NitroPreset = extendPreset(worker, (input: NitroInput) => { const routerBase = input._nuxt.routerBase const script = `