mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-29 09:02:03 +00:00
feat: support dynamic chunks, lazy middleware and cjs target
This commit is contained in:
parent
e3609b6d8a
commit
1e34041e8d
@ -5,24 +5,27 @@ import Hookable from 'hookable'
|
|||||||
import prettyBytes from 'pretty-bytes'
|
import prettyBytes from 'pretty-bytes'
|
||||||
import gzipSize from 'gzip-size'
|
import gzipSize from 'gzip-size'
|
||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import { readFile } from 'fs-extra'
|
import { readFile, emptyDir } from 'fs-extra'
|
||||||
import { getRollupConfig } from './rollup/config'
|
import { getRollupConfig } from './rollup/config'
|
||||||
import { hl, prettyPath, serializeTemplate, writeFile } from './utils'
|
import { hl, prettyPath, serializeTemplate, writeFile } from './utils'
|
||||||
import { SLSOptions } from './config'
|
import { SLSOptions } from './config'
|
||||||
|
|
||||||
export async function build (options: SLSOptions) {
|
export async function build (options: SLSOptions) {
|
||||||
console.log('\n')
|
|
||||||
consola.info(`Generating bundle for ${hl(options.target)}`)
|
consola.info(`Generating bundle for ${hl(options.target)}`)
|
||||||
|
|
||||||
const hooks = new Hookable()
|
const hooks = new Hookable()
|
||||||
hooks.addHooks(options.hooks)
|
hooks.addHooks(options.hooks)
|
||||||
|
|
||||||
|
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(options.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 = serializeTemplate(htmlTemplate.contents)
|
htmlTemplate.compiled = 'module.exports = ' + serializeTemplate(htmlTemplate.contents)
|
||||||
await hooks.callHook('template:document', htmlTemplate)
|
await hooks.callHook('template:document', htmlTemplate)
|
||||||
await writeFile(htmlTemplate.dst, htmlTemplate.compiled)
|
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 { output } = await build.write(options.rollupConfig.output as OutputOptions)
|
||||||
const size = prettyBytes(output[0].code.length)
|
const size = prettyBytes(output[0].code.length)
|
||||||
const zSize = prettyBytes(await gzipSize(output[0].code))
|
const zSize = prettyBytes(await gzipSize(output[0].code))
|
||||||
consola.success('Generated', prettyPath((options.rollupConfig.output as any).file),
|
consola.success('Generated bundle in', prettyPath(options.targetDir), chalk.gray(`(Size: ${size} Gzip: ${zSize})`))
|
||||||
chalk.gray(`(Size: ${size} Gzip: ${zSize})`)
|
|
||||||
)
|
|
||||||
|
|
||||||
await hooks.callHook('done', options)
|
await hooks.callHook('done', options)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entry: options.rollupConfig.output.file
|
entry: resolve(options.rollupConfig.output.dir, options.rollupConfig.output.entryFileNames)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ export interface Nuxt extends Hookable{
|
|||||||
export interface ServerMiddleware {
|
export interface ServerMiddleware {
|
||||||
route: string
|
route: string
|
||||||
handle: string
|
handle: string
|
||||||
|
lazy?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SLSOptions {
|
export interface SLSOptions {
|
||||||
@ -34,11 +35,13 @@ export interface SLSOptions {
|
|||||||
node: false | true
|
node: false | true
|
||||||
target: string
|
target: string
|
||||||
minify: boolean
|
minify: boolean
|
||||||
|
externals: boolean
|
||||||
rollupConfig?: any
|
rollupConfig?: any
|
||||||
logStartup: boolean
|
logStartup: boolean
|
||||||
inlineChunks: boolean
|
inlineChunks: boolean
|
||||||
renderer: string
|
renderer: string
|
||||||
analyze: boolean
|
analyze: boolean
|
||||||
|
cleanTargetDir: boolean
|
||||||
|
|
||||||
runtimeDir: string
|
runtimeDir: string
|
||||||
slsDir: string
|
slsDir: string
|
||||||
@ -72,6 +75,8 @@ export function getoptions (nuxtOptions: Nuxt['options'], serverless: SLSConfig)
|
|||||||
logStartup: true,
|
logStartup: true,
|
||||||
inlineChunks: true,
|
inlineChunks: true,
|
||||||
minify: false,
|
minify: false,
|
||||||
|
externals: false,
|
||||||
|
cleanTargetDir: true,
|
||||||
|
|
||||||
runtimeDir: resolve(__dirname, '../runtime'),
|
runtimeDir: resolve(__dirname, '../runtime'),
|
||||||
slsDir: '{{ rootDir }}/.nuxt/serverless',
|
slsDir: '{{ rootDir }}/.nuxt/serverless',
|
||||||
|
@ -13,9 +13,7 @@ export default <Module> function slsModule () {
|
|||||||
const options = getoptions(nuxt.options, nuxt.options.serverless || {})
|
const options = getoptions(nuxt.options, nuxt.options.serverless || {})
|
||||||
|
|
||||||
// Tune webpack config
|
// Tune webpack config
|
||||||
if (options.minify !== false) {
|
nuxt.options.build._minifyServer = options.minify !== false
|
||||||
nuxt.options.build._minifyServer = true
|
|
||||||
}
|
|
||||||
nuxt.options.build.standalone = true
|
nuxt.options.build.standalone = true
|
||||||
|
|
||||||
// Tune generator
|
// Tune generator
|
||||||
@ -46,7 +44,7 @@ export default <Module> function slsModule () {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
options.serverMiddleware.push({ route, handle })
|
options.serverMiddleware.push({ ...m, route, handle })
|
||||||
}
|
}
|
||||||
if (unsupported.length) {
|
if (unsupported.length) {
|
||||||
console.warn('[serverless] Unsupported Server middleware used: ', unsupported)
|
console.warn('[serverless] Unsupported Server middleware used: ', unsupported)
|
||||||
@ -72,12 +70,16 @@ export default <Module> function slsModule () {
|
|||||||
})
|
})
|
||||||
|
|
||||||
nuxt.hook('generate:before', async () => {
|
nuxt.hook('generate:before', async () => {
|
||||||
|
console.info('Building light version for `nuxt generate`')
|
||||||
const { entry } = await build(getoptions(nuxt.options, {
|
const { entry } = await build(getoptions(nuxt.options, {
|
||||||
target: 'node',
|
target: 'cjs',
|
||||||
serverMiddleware: options.serverMiddleware
|
serverMiddleware: options.serverMiddleware
|
||||||
}))
|
}))
|
||||||
|
console.info('Loading lambda')
|
||||||
require(entry)
|
require(entry)
|
||||||
})
|
})
|
||||||
|
|
||||||
nuxt.hook('generate:done', () => build(options))
|
nuxt.hook('generate:done', async () => {
|
||||||
|
await build(options)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Module from 'module'
|
import Module from 'module'
|
||||||
import { basename, dirname, extname, resolve } from 'path'
|
import { join, resolve } from 'path'
|
||||||
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'
|
||||||
@ -13,23 +13,18 @@ import analyze from 'rollup-plugin-analyzer'
|
|||||||
|
|
||||||
import hasha from 'hasha'
|
import hasha from 'hasha'
|
||||||
import { SLSOptions } from '../config'
|
import { SLSOptions } from '../config'
|
||||||
import { resolvePath } from '../utils'
|
import { resolvePath, MODULE_DIR } from '../utils'
|
||||||
import dynamicRequire from './dynamic-require'
|
import { dynamicRequire } from './dynamic-require'
|
||||||
|
import { externals } from './externals'
|
||||||
|
|
||||||
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 }
|
export type RollupConfig = InputOptions & { output: OutputOptions }
|
||||||
|
|
||||||
export const getRollupConfig = (config: SLSOptions) => {
|
export const getRollupConfig = (options: SLSOptions) => {
|
||||||
const providedDeps = [
|
|
||||||
'@nuxt/devalue',
|
|
||||||
'vue-bundle-renderer',
|
|
||||||
'@cloudflare/kv-asset-handler'
|
|
||||||
]
|
|
||||||
|
|
||||||
const extensions: string[] = ['.ts', '.mjs', '.js', '.json', '.node']
|
const extensions: string[] = ['.ts', '.mjs', '.js', '.json', '.node']
|
||||||
|
|
||||||
const external: string[] = []
|
const external: InputOptions['external'] = []
|
||||||
|
|
||||||
const injects:{ [key: string]: string| string[] } = {}
|
const injects:{ [key: string]: string| string[] } = {}
|
||||||
|
|
||||||
@ -53,7 +48,10 @@ export const getRollupConfig = (config: SLSOptions) => {
|
|||||||
'@vue/compiler-ssr'
|
'@vue/compiler-ssr'
|
||||||
]))
|
]))
|
||||||
|
|
||||||
if (config.node === false) {
|
// Uses eval
|
||||||
|
aliases.depd = '~mocks/custom/depd'
|
||||||
|
|
||||||
|
if (options.node === false) {
|
||||||
// Globals
|
// Globals
|
||||||
// injects.Buffer = ['buffer', 'Buffer'] <-- TODO: Make it opt-in
|
// injects.Buffer = ['buffer', 'Buffer'] <-- TODO: Make it opt-in
|
||||||
injects.process = '~mocks/node/process'
|
injects.process = '~mocks/node/process'
|
||||||
@ -73,7 +71,6 @@ export const getRollupConfig = (config: SLSOptions) => {
|
|||||||
|
|
||||||
// Custom
|
// Custom
|
||||||
'node-fetch': '~mocks/custom/node-fetch',
|
'node-fetch': '~mocks/custom/node-fetch',
|
||||||
depd: '~mocks/custom/depd',
|
|
||||||
etag: '~mocks/generic/noop',
|
etag: '~mocks/generic/noop',
|
||||||
|
|
||||||
// Express
|
// Express
|
||||||
@ -91,13 +88,15 @@ export const getRollupConfig = (config: SLSOptions) => {
|
|||||||
external.push(...Module.builtinModules)
|
external.push(...Module.builtinModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
const outFile = resolve(config.targetDir, config.outName)
|
const rollupConfig: RollupConfig = {
|
||||||
|
input: resolvePath(options, options.entry),
|
||||||
const options: RollupConfig = {
|
|
||||||
input: resolvePath(config, config.entry),
|
|
||||||
output: {
|
output: {
|
||||||
file: outFile,
|
dir: options.targetDir,
|
||||||
|
entryFileNames: options.outName,
|
||||||
|
chunkFileNames: 'chunks/_[name].js',
|
||||||
|
inlineDynamicImports: options.inlineChunks,
|
||||||
format: 'cjs',
|
format: 'cjs',
|
||||||
|
exports: 'auto',
|
||||||
intro: '',
|
intro: '',
|
||||||
outro: '',
|
outro: '',
|
||||||
preferConst: true
|
preferConst: true
|
||||||
@ -106,31 +105,32 @@ export const getRollupConfig = (config: SLSOptions) => {
|
|||||||
plugins: []
|
plugins: []
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.logStartup) {
|
if (options.logStartup) {
|
||||||
options.output.intro += 'global._startTime = global.process.hrtime();'
|
rollupConfig.output.intro += 'global._startTime = global.process.hrtime();'
|
||||||
// eslint-disable-next-line no-template-curly-in-string
|
// 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(), "") : "<entry>"})`);'
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/rollup/plugins/tree/master/packages/replace
|
// https://github.com/rollup/plugins/tree/master/packages/replace
|
||||||
options.plugins.push(replace({
|
rollupConfig.plugins.push(replace({
|
||||||
values: {
|
values: {
|
||||||
'process.env.NODE_ENV': '"production"',
|
'process.env.NODE_ENV': '"production"',
|
||||||
'typeof window': '"undefined"',
|
'typeof window': '"undefined"',
|
||||||
'process.env.ROUTER_BASE': JSON.stringify(config.routerBase),
|
'process.env.ROUTER_BASE': JSON.stringify(options.routerBase),
|
||||||
'process.env.PUBLIC_PATH': JSON.stringify(config.publicPath),
|
'process.env.PUBLIC_PATH': JSON.stringify(options.publicPath),
|
||||||
'process.env.NUXT_STATIC_BASE': JSON.stringify(config.staticAssets.base),
|
'process.env.NUXT_STATIC_BASE': JSON.stringify(options.staticAssets.base),
|
||||||
'process.env.NUXT_STATIC_VERSION': JSON.stringify(config.staticAssets.version),
|
'process.env.NUXT_STATIC_VERSION': JSON.stringify(options.staticAssets.version),
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
'process.env.NUXT_FULL_STATIC': config.fullStatic
|
'process.env.NUXT_FULL_STATIC': options.fullStatic
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Dynamic Require Support
|
// Dynamic Require Support
|
||||||
options.plugins.push(dynamicRequire({
|
rollupConfig.plugins.push(dynamicRequire({
|
||||||
dir: resolve(config.buildDir, 'dist/server'),
|
dir: resolve(options.buildDir, 'dist/server'),
|
||||||
outDir: (config.node === false || config.inlineChunks) ? undefined : dirname(outFile),
|
inline: options.node === false || options.inlineChunks,
|
||||||
chunksDir: '_' + basename(outFile, extname(outFile)),
|
outDir: join(options.targetDir, 'chunks'),
|
||||||
|
prefix: './',
|
||||||
globbyOptions: {
|
globbyOptions: {
|
||||||
ignore: [
|
ignore: [
|
||||||
'server.js'
|
'server.js'
|
||||||
@ -140,7 +140,7 @@ export const getRollupConfig = (config: SLSOptions) => {
|
|||||||
|
|
||||||
// https://github.com/rollup/plugins/tree/master/packages/replace
|
// https://github.com/rollup/plugins/tree/master/packages/replace
|
||||||
// TODO: better fix for node-fetch issue
|
// TODO: better fix for node-fetch issue
|
||||||
options.plugins.push(replace({
|
rollupConfig.plugins.push(replace({
|
||||||
delimiters: ['', ''],
|
delimiters: ['', ''],
|
||||||
values: {
|
values: {
|
||||||
'require(\'encoding\')': '{}'
|
'require(\'encoding\')': '{}'
|
||||||
@ -149,59 +149,77 @@ export const getRollupConfig = (config: SLSOptions) => {
|
|||||||
|
|
||||||
// Provide serverMiddleware
|
// Provide serverMiddleware
|
||||||
const getImportId = p => '_' + hasha(p).substr(0, 6)
|
const getImportId = p => '_' + hasha(p).substr(0, 6)
|
||||||
options.plugins.push(virtual({
|
rollupConfig.plugins.push(virtual({
|
||||||
'~serverMiddleware': `
|
'~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 [
|
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
|
// https://github.com/rollup/plugins/tree/master/packages/alias
|
||||||
const renderer = config.renderer || 'vue2'
|
const renderer = options.renderer || 'vue2'
|
||||||
options.plugins.push(alias({
|
rollupConfig.plugins.push(alias({
|
||||||
entries: {
|
entries: {
|
||||||
'~runtime': config.runtimeDir,
|
'~runtime': options.runtimeDir,
|
||||||
'~mocks': resolve(config.runtimeDir, 'mocks'),
|
'~mocks': resolve(options.runtimeDir, 'mocks'),
|
||||||
'~renderer': require.resolve(resolve(config.runtimeDir, 'ssr', renderer)),
|
'~renderer': require.resolve(resolve(options.runtimeDir, 'ssr', renderer)),
|
||||||
'~build': config.buildDir,
|
'~build': options.buildDir,
|
||||||
'~mock': require.resolve(resolve(config.runtimeDir, 'mocks/generic')),
|
'~mock': require.resolve(resolve(options.runtimeDir, 'mocks/generic')),
|
||||||
...providedDeps.reduce((p, c) => ({ ...p, [c]: require.resolve(c) }), {}),
|
|
||||||
...aliases
|
...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
|
// https://github.com/rollup/plugins/tree/master/packages/node-resolve
|
||||||
options.plugins.push(nodeResolve({
|
rollupConfig.plugins.push(nodeResolve({
|
||||||
extensions,
|
extensions,
|
||||||
preferBuiltins: true,
|
preferBuiltins: true,
|
||||||
rootDir: config.rootDir,
|
rootDir: options.rootDir,
|
||||||
// https://www.npmjs.com/package/resolve
|
// 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)
|
mainFields: ['main'] // Force resolve CJS (@vue/runtime-core ssrUtils)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||||
options.plugins.push(commonjs({
|
rollupConfig.plugins.push(commonjs({
|
||||||
extensions: extensions.filter(ext => ext !== '.json')
|
extensions: extensions.filter(ext => ext !== '.json')
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// https://github.com/rollup/plugins/tree/master/packages/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
|
// 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
|
// https://github.com/doesdev/rollup-plugin-analyzer
|
||||||
options.plugins.push(analyze())
|
rollupConfig.plugins.push(analyze())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.minify !== false) {
|
if (options.minify !== false) {
|
||||||
options.plugins.push(terser())
|
rollupConfig.plugins.push(terser())
|
||||||
}
|
}
|
||||||
|
|
||||||
return options
|
return rollupConfig
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { basename, resolve, dirname } from 'path'
|
import { resolve, dirname } from 'path'
|
||||||
import globby, { GlobbyOptions } from 'globby'
|
import globby, { GlobbyOptions } from 'globby'
|
||||||
import { copyFile, mkdirp } from 'fs-extra'
|
import { copyFile, mkdirp } from 'fs-extra'
|
||||||
|
|
||||||
@ -6,43 +6,26 @@ const PLUGIN_NAME = 'dynamic-require'
|
|||||||
const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js`
|
const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js`
|
||||||
const DYNAMIC_REQUIRE_RE = /require\("\.\/" ?\+/g
|
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 {
|
interface Options {
|
||||||
dir: string
|
dir: string
|
||||||
|
inline: boolean
|
||||||
globbyOptions: GlobbyOptions
|
globbyOptions: GlobbyOptions
|
||||||
outDir?: string
|
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 {
|
return {
|
||||||
name: PLUGIN_NAME,
|
name: PLUGIN_NAME,
|
||||||
transform (code: string, _id: string) {
|
transform (code: string, _id: string) {
|
||||||
@ -51,30 +34,60 @@ export default function dynamicRequire ({ dir, globbyOptions, outDir, chunksDir
|
|||||||
resolveId (id: string) {
|
resolveId (id: string) {
|
||||||
return id === HELPER_DYNAMIC ? id : null
|
return id === HELPER_DYNAMIC ? id : null
|
||||||
},
|
},
|
||||||
async load (id: string) {
|
async load (_id: string) {
|
||||||
if (id === HELPER_DYNAMIC) {
|
if (_id !== HELPER_DYNAMIC) {
|
||||||
const files = await globby('**/*.js', { cwd: dir, absolute: false, ...globbyOptions })
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const imports = files.map(id => ({
|
// Scan chunks
|
||||||
|
const files = await globby('**/*.js', { cwd: dir, absolute: false, ...globbyOptions })
|
||||||
|
const chunks = files.map(id => ({
|
||||||
id,
|
id,
|
||||||
import: resolve(dir, id),
|
src: resolve(dir, id).replace(/\\/g, '/'),
|
||||||
|
out: prefix + id,
|
||||||
name: '_' + id.replace(/[\\/.]/g, '_')
|
name: '_' + id.replace(/[\\/.]/g, '_')
|
||||||
}))
|
}))
|
||||||
|
|
||||||
if (!outDir) {
|
// Inline mode
|
||||||
return TMPL_ESM_INLINE({ imports })
|
if (inline) {
|
||||||
|
return TMPL_ESM_INLINE({ chunks, prefix })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write chunks
|
// Write chunks
|
||||||
chunksDir = chunksDir || basename(dir)
|
await Promise.all(chunks.map(async (chunk) => {
|
||||||
await Promise.all(imports.map(async (i) => {
|
const dst = resolve(outDir, prefix + chunk.id)
|
||||||
const dst = resolve(outDir, chunksDir, i.id)
|
|
||||||
await mkdirp(dirname(dst))
|
await mkdirp(dirname(dst))
|
||||||
await copyFile(i.import, dst)
|
await copyFile(chunk.src, dst)
|
||||||
}))
|
}))
|
||||||
return TMPL_CJS_LAZY({ chunksDir, imports })
|
|
||||||
}
|
return TMPL_CJS_LAZY({ chunks, prefix })
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
// };`
|
||||||
|
// }
|
||||||
|
24
packages/nitro/src/rollup/externals.ts
Normal file
24
packages/nitro/src/rollup/externals.ts
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,6 +18,7 @@ if ('serviceWorker' in navigator) {
|
|||||||
entry: '{{ runtimeDir }}/targets/service-worker',
|
entry: '{{ runtimeDir }}/targets/service-worker',
|
||||||
targetDir: '{{ publicDir }}',
|
targetDir: '{{ publicDir }}',
|
||||||
outName: '_nuxt.js',
|
outName: '_nuxt.js',
|
||||||
|
cleanTargetDir: false,
|
||||||
nuxtHooks: {
|
nuxtHooks: {
|
||||||
'vue-renderer:ssr:templateParams' (params) {
|
'vue-renderer:ssr:templateParams' (params) {
|
||||||
params.APP += script
|
params.APP += script
|
||||||
|
10
packages/nitro/src/targets/cjs.ts
Normal file
10
packages/nitro/src/targets/cjs.ts
Normal file
@ -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
|
||||||
|
})
|
@ -3,5 +3,6 @@ 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 './vercel'
|
export * from './vercel'
|
||||||
export * from './worker'
|
export * from './worker'
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
|
|
||||||
import { relative } from 'path'
|
|
||||||
import consola from 'consola'
|
|
||||||
import { SLSTarget } from '../config'
|
import { SLSTarget } from '../config'
|
||||||
|
|
||||||
export const lambda: SLSTarget = {
|
export const lambda: SLSTarget = {
|
||||||
entry: '{{ runtimeDir }}/targets/lambda',
|
entry: '{{ runtimeDir }}/targets/lambda',
|
||||||
outName: '_nuxt.js',
|
outName: '_nuxt.js',
|
||||||
inlineChunks: false,
|
inlineChunks: false
|
||||||
hooks: {
|
|
||||||
'done' ({ rollupConfig }) {
|
|
||||||
const entry = relative(process.cwd(), rollupConfig.output.file).replace(/\.js$/, '')
|
|
||||||
consola.info(`Ready to deploy lambda: \`${entry}\``)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,7 @@
|
|||||||
import { relative } from 'path'
|
|
||||||
import consola from 'consola'
|
|
||||||
import { SLSTarget } from '../config'
|
import { SLSTarget } from '../config'
|
||||||
|
|
||||||
export const node: SLSTarget = {
|
export const node: SLSTarget = {
|
||||||
entry: '{{ runtimeDir }}/targets/node',
|
entry: '{{ runtimeDir }}/targets/node',
|
||||||
outName: 'index.js',
|
outName: 'index.js',
|
||||||
inlineChunks: false,
|
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]\``)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import Hookable from 'hookable'
|
|||||||
import consola from 'consola'
|
import consola from 'consola'
|
||||||
import { SLSOptions, UnresolvedPath, SLSTarget, SLSTargetFn, SLSConfig } from './config'
|
import { SLSOptions, UnresolvedPath, SLSTarget, SLSTargetFn, SLSConfig } from './config'
|
||||||
|
|
||||||
|
export const MODULE_DIR = resolve(__dirname, '..')
|
||||||
|
|
||||||
export function hl (str: string) {
|
export function hl (str: string) {
|
||||||
return '`' + str + '`'
|
return '`' + str + '`'
|
||||||
}
|
}
|
||||||
@ -21,7 +23,7 @@ export function compileTemplate (contents: string) {
|
|||||||
|
|
||||||
export function serializeTemplate (contents: string) {
|
export function serializeTemplate (contents: string) {
|
||||||
// eslint-disable-next-line no-template-curly-in-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) {
|
export function jitiImport (dir: string, path: string) {
|
||||||
@ -80,3 +82,22 @@ export function extendTarget (base: SLSTarget, target: SLSTarget): SLSTargetFn {
|
|||||||
}, target, base)
|
}, 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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user