Skip to content

Commit

Permalink
feat: serveStatic (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 authored Nov 28, 2020
1 parent 7742014 commit af42712
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 75 deletions.
2 changes: 2 additions & 0 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface SigmaContext {
preset: string
rollupConfig?: any
renderer: string
serveStatic: boolean
middleware: ServerMiddleware[]
hooks: configHooksT
nuxtHooks: configHooksT
Expand Down Expand Up @@ -72,6 +73,7 @@ export function getsigmaContext (nuxtOptions: NuxtOptions, input: SigmaInput): S
preset: undefined,
rollupConfig: undefined,
renderer: undefined,
serveStatic: false,
middleware: [],
ignore: [],
env: {},
Expand Down
49 changes: 3 additions & 46 deletions src/presets/azure.ts
Original file line number Diff line number Diff line change
@@ -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<string, string>)

return {
files,
metadata
}
}

function zipDirectory (dir: string, outfile: string): Promise<undefined> {
const archive = archiver('zip', { zlib: { level: 9 } })
const stream = createWriteStream(outfile)
Expand Down
3 changes: 2 additions & 1 deletion src/presets/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
44 changes: 17 additions & 27 deletions src/rollup/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }

Expand Down Expand Up @@ -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\')': '{}'
}
}))

// 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')}
// Static
if (sigmaContext.serveStatic) {
rollupConfig.plugins.push(staticAssets(sigmaContext))
}

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({
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/rollup/esbuild.ts → src/rollup/plugins/esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export type Options = {
}
}

export default (options: Options = {}): Plugin => {
export function esbuild (options: Options = {}): Plugin {
let target: string | string[]

const loaders = {
Expand Down
File renamed without changes.
21 changes: 21 additions & 0 deletions src/rollup/plugins/middleware.ts
Original file line number Diff line number Diff line change
@@ -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
`
})
}
47 changes: 47 additions & 0 deletions src/rollup/plugins/static.ts
Original file line number Diff line number Diff line change
@@ -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<string, { type: string, etag: string, mtime: string, path: string }> = {}

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]
}
`
})
}
File renamed without changes.

0 comments on commit af42712

Please sign in to comment.