mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-14 01:53:55 +00:00
sigma (#36)
This commit is contained in:
parent
047761f8b7
commit
c06f09e9ab
@ -1,48 +1,97 @@
|
|||||||
import { resolve } from 'path'
|
import { resolve, join } from 'upath'
|
||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import { rollup } from 'rollup'
|
import { rollup, watch as rollupWatch } from 'rollup'
|
||||||
import Hookable from 'hookable'
|
import ora from 'ora'
|
||||||
import { readFile, emptyDir } from 'fs-extra'
|
import { readFile, emptyDir, copy } from 'fs-extra'
|
||||||
import { printFSTree } from './utils/tree'
|
import { printFSTree } from './utils/tree'
|
||||||
import { getRollupConfig } from './rollup/config'
|
import { getRollupConfig } from './rollup/config'
|
||||||
import { hl, serializeTemplate, writeFile } from './utils'
|
import { hl, serializeTemplate, writeFile } from './utils'
|
||||||
import { SLSOptions } from './config'
|
import { SigmaContext } from './context'
|
||||||
|
|
||||||
export async function build (options: SLSOptions) {
|
export async function build (sigmaContext: SigmaContext) {
|
||||||
consola.info(`Generating bundle for ${hl(options.target)}`)
|
consola.info(`Sigma preset is ${hl(sigmaContext.preset)}`)
|
||||||
|
|
||||||
const hooks = new Hookable()
|
// Cleanup output dir
|
||||||
hooks.addHooks(options.hooks)
|
await emptyDir(sigmaContext.output.dir)
|
||||||
|
|
||||||
if (options.cleanTargetDir) {
|
|
||||||
await emptyDir(options.targetDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile html template
|
// 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: '' }
|
const htmlTemplate = { src: htmlSrc, contents: '', dst: '', compiled: '' }
|
||||||
htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.')
|
htmlTemplate.dst = htmlTemplate.src.replace(/.html$/, '.js').replace('app.', 'document.')
|
||||||
htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8')
|
htmlTemplate.contents = await readFile(htmlTemplate.src, 'utf-8')
|
||||||
htmlTemplate.compiled = 'module.exports = ' + serializeTemplate(htmlTemplate.contents)
|
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)
|
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) => {
|
await sigmaContext._internal.hooks.callHook('sigma:rollup:before', sigmaContext)
|
||||||
error.message = '[serverless] Rollup Error: ' + error.message
|
|
||||||
|
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
|
throw error
|
||||||
})
|
})
|
||||||
|
|
||||||
await build.write(options.rollupConfig.output)
|
spinner.start('Wrting Sigma bundle...')
|
||||||
|
await build.write(sigmaContext.rollupConfig.output)
|
||||||
|
|
||||||
await printFSTree(options.targetDir)
|
spinner.succeed('Sigma built')
|
||||||
|
await printFSTree(sigmaContext.output.serverDir)
|
||||||
await hooks.callHook('done', options)
|
await sigmaContext._internal.hooks.callHook('sigma:compiled', sigmaContext)
|
||||||
|
|
||||||
return {
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -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<Partial<SLSOptions>, '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
|
|
||||||
}
|
|
110
packages/nitro/src/context.ts
Normal file
110
packages/nitro/src/context.ts
Normal file
@ -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<SigmaContext> {}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
@ -1,85 +1,6 @@
|
|||||||
import type { Module } from '@nuxt/types'
|
import nuxt2 from './module/nuxt2'
|
||||||
import { build } from './build'
|
|
||||||
import { getoptions } from './config'
|
|
||||||
|
|
||||||
export default <Module> function slsModule () {
|
export default function () {
|
||||||
const { nuxt } = this
|
const { nuxt } = this
|
||||||
|
return nuxt2(nuxt)
|
||||||
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)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
126
packages/nitro/src/module/nuxt2.ts
Normal file
126
packages/nitro/src/module/nuxt2.ts
Normal file
@ -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('&')
|
||||||
|
}
|
40
packages/nitro/src/presets/browser.ts
Normal file
40
packages/nitro/src/presets/browser.ts
Normal file
@ -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 = `<script>
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
window.addEventListener('load', function () {
|
||||||
|
navigator.serviceWorker.register('${input._nuxt.routerBase}index.js');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>`
|
||||||
|
|
||||||
|
return <SigmaInput> {
|
||||||
|
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('</body>', script + '</body>')
|
||||||
|
},
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
15
packages/nitro/src/presets/cli.ts
Normal file
15
packages/nitro/src/presets/cli.ts
Normal file
@ -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]`')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
19
packages/nitro/src/presets/cloudflare.ts
Normal file
19
packages/nitro/src/presets/cloudflare.ts
Normal file
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
11
packages/nitro/src/presets/dev.ts
Normal file
11
packages/nitro/src/presets/dev.ts
Normal file
@ -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
|
||||||
|
})
|
@ -3,6 +3,8 @@ export * from './cloudflare'
|
|||||||
export * from './lambda'
|
export * from './lambda'
|
||||||
export * from './netlify'
|
export * from './netlify'
|
||||||
export * from './node'
|
export * from './node'
|
||||||
export * from './cjs'
|
export * from './dev'
|
||||||
|
export * from './server'
|
||||||
|
export * from './cli'
|
||||||
export * from './vercel'
|
export * from './vercel'
|
||||||
export * from './worker'
|
export * from './worker'
|
7
packages/nitro/src/presets/lambda.ts
Normal file
7
packages/nitro/src/presets/lambda.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
import { SigmaPreset } from '../context'
|
||||||
|
|
||||||
|
export const lambda: SigmaPreset = {
|
||||||
|
entry: '{{ _internal.runtimeDir }}/entries/lambda',
|
||||||
|
inlineChunks: false
|
||||||
|
}
|
10
packages/nitro/src/presets/netlify.ts
Normal file
10
packages/nitro/src/presets/netlify.ts
Normal file
@ -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'
|
||||||
|
]
|
||||||
|
})
|
6
packages/nitro/src/presets/node.ts
Normal file
6
packages/nitro/src/presets/node.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { SigmaPreset } from '../context'
|
||||||
|
|
||||||
|
export const node: SigmaPreset = {
|
||||||
|
entry: '{{ _internal.runtimeDir }}/entries/node',
|
||||||
|
inlineChunks: false
|
||||||
|
}
|
16
packages/nitro/src/presets/server.ts
Normal file
16
packages/nitro/src/presets/server.ts
Normal file
@ -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)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
48
packages/nitro/src/presets/vercel.ts
Normal file
48
packages/nitro/src/presets/vercel.ts
Normal file
@ -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))
|
||||||
|
}
|
11
packages/nitro/src/presets/worker.ts
Normal file
11
packages/nitro/src/presets/worker.ts
Normal file
@ -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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import Module from 'module'
|
import Module from 'module'
|
||||||
import { dirname, join, relative, resolve } from 'path'
|
import { dirname, join, relative, resolve } from 'upath'
|
||||||
import { InputOptions, OutputOptions } from 'rollup'
|
import { InputOptions, OutputOptions } from 'rollup'
|
||||||
import { terser } from 'rollup-plugin-terser'
|
import { terser } from 'rollup-plugin-terser'
|
||||||
import commonjs from '@rollup/plugin-commonjs'
|
import commonjs from '@rollup/plugin-commonjs'
|
||||||
@ -10,110 +10,64 @@ import replace from '@rollup/plugin-replace'
|
|||||||
import virtual from '@rollup/plugin-virtual'
|
import virtual from '@rollup/plugin-virtual'
|
||||||
import inject from '@rollup/plugin-inject'
|
import inject from '@rollup/plugin-inject'
|
||||||
import analyze from 'rollup-plugin-analyzer'
|
import analyze from 'rollup-plugin-analyzer'
|
||||||
|
import * as un from '@nuxt/un'
|
||||||
|
|
||||||
import hasha from 'hasha'
|
import hasha from 'hasha'
|
||||||
import { SLSOptions } from '../config'
|
import { SigmaContext } from '../context'
|
||||||
import { resolvePath, MODULE_DIR } from '../utils'
|
import { resolvePath, MODULE_DIR } from '../utils'
|
||||||
|
|
||||||
import { dynamicRequire } from './dynamic-require'
|
import { dynamicRequire } from './dynamic-require'
|
||||||
import { externals } from './externals'
|
import { externals } from './externals'
|
||||||
import { timing } from './timing'
|
import { timing } from './timing'
|
||||||
|
|
||||||
const mapArrToVal = (val, arr) => arr.reduce((p, c) => ({ ...p, [c]: val }), {})
|
|
||||||
|
|
||||||
export type RollupConfig = InputOptions & { output: OutputOptions }
|
export type RollupConfig = InputOptions & { output: OutputOptions }
|
||||||
|
|
||||||
export const getRollupConfig = (options: SLSOptions) => {
|
export const getRollupConfig = (sigmaContext: SigmaContext) => {
|
||||||
const extensions: string[] = ['.ts', '.mjs', '.js', '.json', '.node']
|
const extensions: string[] = ['.ts', '.js', '.json', '.node']
|
||||||
|
|
||||||
const external: InputOptions['external'] = []
|
const external: InputOptions['external'] = []
|
||||||
|
|
||||||
const injects:{ [key: string]: string| string[] } = {}
|
const presets = []
|
||||||
|
|
||||||
const aliases: { [key: string]: string } = {}
|
if (sigmaContext.node === false) {
|
||||||
|
presets.push(un.nodeless)
|
||||||
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'
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
|
presets.push(un.node)
|
||||||
external.push(...Module.builtinModules)
|
external.push(...Module.builtinModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
const chunksDirName = join(dirname(options.outName), 'chunks')
|
const env = un.env(...presets, {
|
||||||
const serverDir = join(options.buildDir, 'dist/server')
|
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 = {
|
const rollupConfig: RollupConfig = {
|
||||||
input: resolvePath(options, options.entry),
|
input: resolvePath(sigmaContext, sigmaContext.entry),
|
||||||
output: {
|
output: {
|
||||||
dir: options.targetDir,
|
dir: sigmaContext.output.serverDir,
|
||||||
entryFileNames: options.outName,
|
entryFileNames: 'index.js',
|
||||||
chunkFileNames (chunkInfo) {
|
chunkFileNames (chunkInfo) {
|
||||||
let prefix = ''
|
let prefix = ''
|
||||||
const modules = Object.keys(chunkInfo.modules)
|
const modules = Object.keys(chunkInfo.modules)
|
||||||
const lastModule = modules[modules.length - 1]
|
const lastModule = modules[modules.length - 1]
|
||||||
if (lastModule.startsWith(serverDir)) {
|
if (lastModule.startsWith(buildServerDir)) {
|
||||||
prefix = join('ssr', relative(serverDir, dirname(lastModule)))
|
prefix = join('app', relative(buildServerDir, dirname(lastModule)))
|
||||||
} else if (lastModule.startsWith(options.buildDir)) {
|
} else if (lastModule.startsWith(runtimeAppDir)) {
|
||||||
prefix = 'ssr'
|
prefix = 'app'
|
||||||
} else if (lastModule.startsWith(options.runtimeDir)) {
|
} else if (lastModule.startsWith(sigmaContext._nuxt.buildDir)) {
|
||||||
prefix = 'runtime'
|
prefix = 'nuxt'
|
||||||
} else if (!prefix && options.serverMiddleware.find(m => lastModule.startsWith(m.handle))) {
|
} else if (lastModule.startsWith(sigmaContext._internal.runtimeDir)) {
|
||||||
|
prefix = 'sigma'
|
||||||
|
} else if (!prefix && sigmaContext.middleware.find(m => lastModule.startsWith(m.handle))) {
|
||||||
prefix = 'middleware'
|
prefix = 'middleware'
|
||||||
}
|
}
|
||||||
return join(chunksDirName, prefix, '[name].js')
|
return join('chunks', prefix, '[name].js')
|
||||||
},
|
},
|
||||||
inlineDynamicImports: options.inlineChunks,
|
inlineDynamicImports: sigmaContext.inlineChunks,
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
exports: 'auto',
|
exports: 'auto',
|
||||||
intro: '',
|
intro: '',
|
||||||
@ -124,28 +78,28 @@ export const getRollupConfig = (options: SLSOptions) => {
|
|||||||
plugins: []
|
plugins: []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.timing) {
|
if (sigmaContext.timing) {
|
||||||
rollupConfig.plugins.push(timing())
|
rollupConfig.plugins.push(timing())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/rollup/plugins/tree/master/packages/replace
|
// https://github.com/rollup/plugins/tree/master/packages/replace
|
||||||
rollupConfig.plugins.push(replace({
|
rollupConfig.plugins.push(replace({
|
||||||
values: {
|
values: {
|
||||||
'process.env.NODE_ENV': '"production"',
|
'process.env.NODE_ENV': sigmaContext._nuxt.dev ? '"development"' : '"production"',
|
||||||
'typeof window': '"undefined"',
|
'typeof window': '"undefined"',
|
||||||
'process.env.ROUTER_BASE': JSON.stringify(options.routerBase),
|
'process.env.ROUTER_BASE': JSON.stringify(sigmaContext._nuxt.routerBase),
|
||||||
'process.env.PUBLIC_PATH': JSON.stringify(options.publicPath),
|
'process.env.PUBLIC_PATH': JSON.stringify(sigmaContext._nuxt.publicPath),
|
||||||
'process.env.NUXT_STATIC_BASE': JSON.stringify(options.staticAssets.base),
|
'process.env.NUXT_STATIC_BASE': JSON.stringify(sigmaContext._nuxt.staticAssets.base),
|
||||||
'process.env.NUXT_STATIC_VERSION': JSON.stringify(options.staticAssets.version),
|
'process.env.NUXT_STATIC_VERSION': JSON.stringify(sigmaContext._nuxt.staticAssets.version),
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
'process.env.NUXT_FULL_STATIC': options.fullStatic
|
'process.env.NUXT_FULL_STATIC': sigmaContext.fullStatic
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Dynamic Require Support
|
// Dynamic Require Support
|
||||||
rollupConfig.plugins.push(dynamicRequire({
|
rollupConfig.plugins.push(dynamicRequire({
|
||||||
dir: resolve(options.buildDir, 'dist/server'),
|
dir: resolve(sigmaContext._nuxt.buildDir, 'dist/server'),
|
||||||
inline: options.node === false || options.inlineChunks,
|
inline: sigmaContext.node === false || sigmaContext.inlineChunks,
|
||||||
globbyOptions: {
|
globbyOptions: {
|
||||||
ignore: [
|
ignore: [
|
||||||
'server.js'
|
'server.js'
|
||||||
@ -166,36 +120,39 @@ export const getRollupConfig = (options: SLSOptions) => {
|
|||||||
const getImportId = p => '_' + hasha(p).substr(0, 6)
|
const getImportId = p => '_' + hasha(p).substr(0, 6)
|
||||||
rollupConfig.plugins.push(virtual({
|
rollupConfig.plugins.push(virtual({
|
||||||
'~serverMiddleware': `
|
'~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 [
|
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
|
// https://github.com/rollup/plugins/tree/master/packages/alias
|
||||||
const renderer = options.renderer || 'vue2'
|
const renderer = sigmaContext.renderer || 'vue2'
|
||||||
rollupConfig.plugins.push(alias({
|
rollupConfig.plugins.push(alias({
|
||||||
entries: {
|
entries: {
|
||||||
'~runtime': options.runtimeDir,
|
'~runtime': sigmaContext._internal.runtimeDir,
|
||||||
'~mocks': resolve(options.runtimeDir, 'mocks'),
|
'~renderer': require.resolve(resolve(sigmaContext._internal.runtimeDir, 'app', renderer)),
|
||||||
'~renderer': require.resolve(resolve(options.runtimeDir, 'ssr', renderer)),
|
'~build': sigmaContext._nuxt.buildDir,
|
||||||
'~build': options.buildDir,
|
...env.alias
|
||||||
'~mock': require.resolve(resolve(options.runtimeDir, 'mocks/generic')),
|
|
||||||
...aliases
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// External Plugin
|
// External Plugin
|
||||||
if (options.externals) {
|
if (sigmaContext.externals) {
|
||||||
rollupConfig.plugins.push(externals({
|
rollupConfig.plugins.push(externals({
|
||||||
relativeTo: options.targetDir,
|
relativeTo: sigmaContext.output.serverDir,
|
||||||
include: [
|
include: [
|
||||||
options.runtimeDir,
|
sigmaContext._internal.runtimeDir,
|
||||||
...options.serverMiddleware.map(m => m.handle)
|
...sigmaContext.middleware.map(m => m.handle)
|
||||||
]
|
]
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -204,12 +161,12 @@ export const getRollupConfig = (options: SLSOptions) => {
|
|||||||
rollupConfig.plugins.push(nodeResolve({
|
rollupConfig.plugins.push(nodeResolve({
|
||||||
extensions,
|
extensions,
|
||||||
preferBuiltins: true,
|
preferBuiltins: true,
|
||||||
rootDir: options.rootDir,
|
rootDir: sigmaContext._nuxt.rootDir,
|
||||||
// https://www.npmjs.com/package/resolve
|
// https://www.npmjs.com/package/resolve
|
||||||
customResolveOptions: {
|
customResolveOptions: {
|
||||||
basedir: options.rootDir,
|
basedir: sigmaContext._nuxt.rootDir,
|
||||||
paths: [
|
paths: [
|
||||||
resolve(options.rootDir, 'node_modukes'),
|
resolve(sigmaContext._nuxt.rootDir, 'node_modules'),
|
||||||
resolve(MODULE_DIR, 'node_modules')
|
resolve(MODULE_DIR, 'node_modules')
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -225,16 +182,16 @@ export const getRollupConfig = (options: SLSOptions) => {
|
|||||||
rollupConfig.plugins.push(json())
|
rollupConfig.plugins.push(json())
|
||||||
|
|
||||||
// https://github.com/rollup/plugins/tree/master/packages/inject
|
// 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
|
// https://github.com/doesdev/rollup-plugin-analyzer
|
||||||
rollupConfig.plugins.push(analyze())
|
rollupConfig.plugins.push(analyze())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/TrySound/rollup-plugin-terser
|
// https://github.com/TrySound/rollup-plugin-terser
|
||||||
// https://github.com/terser/terser#minify-options
|
// https://github.com/terser/terser#minify-sigmaContext
|
||||||
if (options.minify !== false) {
|
if (sigmaContext.minify) {
|
||||||
rollupConfig.plugins.push(terser({
|
rollupConfig.plugins.push(terser({
|
||||||
mangle: {
|
mangle: {
|
||||||
keep_fnames: true,
|
keep_fnames: true,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { resolve } from 'path'
|
import { resolve } from 'upath'
|
||||||
import globby, { GlobbyOptions } from 'globby'
|
import globby, { GlobbyOptions } from 'globby'
|
||||||
import type { Plugin } from 'rollup'
|
import type { Plugin } from 'rollup'
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { isAbsolute, relative } from 'path'
|
import { isAbsolute, relative } from 'upath'
|
||||||
|
|
||||||
export function externals ({ include = [], relativeTo }) {
|
export function externals ({ include = [], relativeTo }) {
|
||||||
return {
|
return {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { extname } from 'path'
|
import { extname } from 'upath'
|
||||||
import type { Plugin, RenderedChunk } from 'rollup'
|
import type { Plugin, RenderedChunk } from 'rollup'
|
||||||
|
|
||||||
export interface Options { }
|
export interface Options { }
|
||||||
@ -20,7 +20,7 @@ const end = s => { const d = hrtime(s); return ((d[0] * 1e9) + d[1]) / 1e6; };
|
|||||||
const _s = {};
|
const _s = {};
|
||||||
const metrics = [];
|
const metrics = [];
|
||||||
const logStart = id => { _s[id] = hrtime(); };
|
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 };
|
${TIMING} = { hrtime, start, end, metrics, logStart, logEnd };
|
||||||
`)
|
`)
|
||||||
|
|
||||||
@ -30,7 +30,8 @@ export function timing (_opts: Options = {}): Plugin {
|
|||||||
renderChunk (code, chunk: RenderedChunk) {
|
renderChunk (code, chunk: RenderedChunk) {
|
||||||
let name = chunk.fileName || ''
|
let name = chunk.fileName || ''
|
||||||
name = name.replace(extname(name), '')
|
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}');`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
137
packages/nitro/src/server.ts
Normal file
137
packages/nitro/src/server.ts
Normal file
@ -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<Server>((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
|
||||||
|
}
|
||||||
|
}
|
@ -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 = `<script>
|
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
window.addEventListener('load', function () {
|
|
||||||
navigator.serviceWorker.register('${options.routerBase}_nuxt.js');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</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('</body>', script + '</body>')
|
|
||||||
},
|
|
||||||
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)}\``)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
@ -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
|
|
||||||
})
|
|
@ -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`')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
import { SLSTarget } from '../config'
|
|
||||||
|
|
||||||
export const lambda: SLSTarget = {
|
|
||||||
entry: '{{ runtimeDir }}/targets/lambda',
|
|
||||||
outName: '_nuxt.js',
|
|
||||||
inlineChunks: false
|
|
||||||
}
|
|
@ -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'
|
|
||||||
]
|
|
||||||
})
|
|
@ -1,8 +0,0 @@
|
|||||||
import { SLSTarget } from '../config'
|
|
||||||
|
|
||||||
export const node: SLSTarget = {
|
|
||||||
entry: '{{ runtimeDir }}/targets/node',
|
|
||||||
outName: 'index.js',
|
|
||||||
inlineChunks: false,
|
|
||||||
minify: true
|
|
||||||
}
|
|
@ -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))
|
|
||||||
}
|
|
@ -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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +1,17 @@
|
|||||||
import { relative, dirname, resolve } from 'path'
|
import { relative, dirname, resolve } from 'upath'
|
||||||
import fse from 'fs-extra'
|
import fse from 'fs-extra'
|
||||||
import jiti from 'jiti'
|
import jiti from 'jiti'
|
||||||
import defu from 'defu'
|
import defu from 'defu'
|
||||||
import Hookable from 'hookable'
|
import Hookable from 'hookable'
|
||||||
import consola from 'consola'
|
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 const MODULE_DIR = resolve(__dirname, '..')
|
||||||
|
|
||||||
export function hl (str: string) {
|
export function hl (str: string) {
|
||||||
return '`' + str + '`'
|
return chalk.cyan(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function prettyPath (p: string, highlight = true) {
|
export function prettyPath (p: string, highlight = true) {
|
||||||
@ -18,7 +20,13 @@ export function prettyPath (p: string, highlight = true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function compileTemplate (contents: string) {
|
export function compileTemplate (contents: string) {
|
||||||
return (params: Record<string, any>) => contents.replace(/{{ ?(\w+) ?}}/g, (_, match) => params[match] || '')
|
return (params: Record<string, any>) => 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) {
|
export function serializeTemplate (contents: string) {
|
||||||
@ -42,16 +50,16 @@ export async function writeFile (file, contents) {
|
|||||||
consola.info('Generated', prettyPath(file))
|
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') {
|
if (typeof path === 'function') {
|
||||||
path = path(options)
|
path = path(sigmaContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof path !== 'string') {
|
if (typeof path !== 'string') {
|
||||||
throw new TypeError('Invalid path: ' + path)
|
throw new TypeError('Invalid path: ' + path)
|
||||||
}
|
}
|
||||||
|
|
||||||
path = compileTemplate(path)(options)
|
path = compileTemplate(path)(sigmaContext)
|
||||||
|
|
||||||
return resolve(resolveBase, path)
|
return resolve(resolveBase, path)
|
||||||
}
|
}
|
||||||
@ -64,22 +72,19 @@ export function detectTarget () {
|
|||||||
if (process.env.NOW_BUILDER) {
|
if (process.env.NOW_BUILDER) {
|
||||||
return 'vercel'
|
return 'vercel'
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'node'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extendTarget (base: SLSTarget, target: SLSTarget): SLSTargetFn {
|
export function extendPreset (base: SigmaPreset, preset: SigmaPreset): SigmaPreset {
|
||||||
return (config: SLSConfig) => {
|
return (config: SigmaInput) => {
|
||||||
if (typeof target === 'function') {
|
if (typeof preset === 'function') {
|
||||||
target = target(config)
|
preset = preset(config)
|
||||||
}
|
}
|
||||||
if (typeof base === 'function') {
|
if (typeof base === 'function') {
|
||||||
base = base(config)
|
base = base(config)
|
||||||
}
|
}
|
||||||
return defu({
|
return defu({
|
||||||
hooks: Hookable.mergeHooks(base.hooks, target.hooks),
|
hooks: Hookable.mergeHooks(base.hooks, preset.hooks)
|
||||||
nuxtHooks: Hookable.mergeHooks(base.nuxtHooks as any, target.nuxtHooks as any)
|
}, preset, base)
|
||||||
}, target, base)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { resolve, dirname, relative } from 'path'
|
import { resolve, dirname, relative } from 'upath'
|
||||||
import globby from 'globby'
|
import globby from 'globby'
|
||||||
import prettyBytes from 'pretty-bytes'
|
import prettyBytes from 'pretty-bytes'
|
||||||
import gzipSize from 'gzip-size'
|
import gzipSize from 'gzip-size'
|
||||||
@ -30,5 +30,5 @@ export async function printFSTree (dir) {
|
|||||||
totalGzip += item.gzip
|
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`)
|
||||||
}
|
}
|
||||||
|
7
packages/nitro/src/utils/wpfs.ts
Normal file
7
packages/nitro/src/utils/wpfs.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { join } from 'upath'
|
||||||
|
import fsExtra from 'fs-extra'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
...fsExtra,
|
||||||
|
join
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user