mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-29 17:07:22 +00:00
feat: dynamic-require rollup plugin
This commit is contained in:
parent
ec8468635b
commit
cbae59a88b
46
packages/nitro/src/dynamic-require.ts
Normal file
46
packages/nitro/src/dynamic-require.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { resolve } from 'path'
|
||||||
|
import globby, { GlobbyOptions } from 'globby'
|
||||||
|
|
||||||
|
const PLUGIN_NAME = 'dynamic-require'
|
||||||
|
const HELPER_DYNAMIC = `\0${PLUGIN_NAME}.js`
|
||||||
|
const DYNAMIC_REQUIRE_RE = /require\("\.\/" \+/g
|
||||||
|
|
||||||
|
function CJSTemplate ({ imports }) {
|
||||||
|
return `${imports.map(i => `import ${i.name} from '${i.import}'`).join('\n')}
|
||||||
|
const dynamicChunks = {
|
||||||
|
${imports.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function dynamicRequire(id) {
|
||||||
|
return dynamicChunks[id];
|
||||||
|
};`
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Options {
|
||||||
|
dir: string,
|
||||||
|
globbyOptions: GlobbyOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function dynamicRequire ({ dir, globbyOptions }: Options) {
|
||||||
|
return {
|
||||||
|
name: PLUGIN_NAME,
|
||||||
|
transform (code, _id) {
|
||||||
|
return code.replace(DYNAMIC_REQUIRE_RE, `require('${HELPER_DYNAMIC}')(`)
|
||||||
|
},
|
||||||
|
resolveId (id) {
|
||||||
|
return id === HELPER_DYNAMIC ? id : null
|
||||||
|
},
|
||||||
|
async load (id) {
|
||||||
|
if (id === HELPER_DYNAMIC) {
|
||||||
|
const files = await globby('**/*.js', { cwd: dir, absolute: false, ...globbyOptions })
|
||||||
|
const imports = files.map(id => ({
|
||||||
|
id,
|
||||||
|
import: resolve(dir, id),
|
||||||
|
name: id.replace(/[\\/.]/g, '_')
|
||||||
|
}))
|
||||||
|
return CJSTemplate({ imports })
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,44 +0,0 @@
|
|||||||
import { join } from 'path'
|
|
||||||
import globby from 'globby'
|
|
||||||
|
|
||||||
export async function createDynamicImporter (cwd: string) {
|
|
||||||
const assets = await globby('**/*.js', { cwd, absolute: false })
|
|
||||||
const chunkInfo = {}
|
|
||||||
for (const asset of assets) {
|
|
||||||
const { id, ids, modules } = require(join(cwd, asset))
|
|
||||||
if ((id || ids) && modules) {
|
|
||||||
chunkInfo[asset] = { id, ids, modules: Object.keys(modules) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (syncImport, asyncImport) => genRequireDynamic(chunkInfo, syncImport, asyncImport)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function genRequireDynamic (chunkInfo, syncImport, asyncImport) {
|
|
||||||
return `\nconst _dynamic_chunks = ${JSON.stringify(chunkInfo, null, 2)};
|
|
||||||
function requireDynamic (chunkId) {
|
|
||||||
const chunk = _dynamic_chunks[chunkId]
|
|
||||||
|
|
||||||
if (!chunk) {
|
|
||||||
return ${syncImport}
|
|
||||||
}
|
|
||||||
|
|
||||||
const promise = ${asyncImport}
|
|
||||||
|
|
||||||
if (Array.isArray(chunk.modules)) {
|
|
||||||
const modules = {}
|
|
||||||
for (const id of chunk.modules) {
|
|
||||||
modules[id] = function (module, _exports, _require) {
|
|
||||||
module.exports = promise.then(chunk => {
|
|
||||||
const asyncModule = { exports: {}, require: _require }
|
|
||||||
chunk.modules[id](asyncModule, asyncModule.exports, asyncModule.require)
|
|
||||||
return asyncModule.exports
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chunk.modules = modules
|
|
||||||
}
|
|
||||||
|
|
||||||
return chunk
|
|
||||||
};`
|
|
||||||
}
|
|
@ -9,7 +9,6 @@ import gzipSize from 'gzip-size'
|
|||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import { getRollupConfig } from './rollup.config'
|
import { getRollupConfig } from './rollup.config'
|
||||||
import { tryImport, hl, prettyPath } from './utils'
|
import { tryImport, hl, prettyPath } from './utils'
|
||||||
import { createDynamicImporter } from './dynamic'
|
|
||||||
|
|
||||||
async function main () {
|
async function main () {
|
||||||
const rootDir = resolve(process.cwd(), process.argv[2] || '.')
|
const rootDir = resolve(process.cwd(), process.argv[2] || '.')
|
||||||
@ -20,8 +19,6 @@ async function main () {
|
|||||||
buildDir: '',
|
buildDir: '',
|
||||||
targets: [],
|
targets: [],
|
||||||
nuxt: 2,
|
nuxt: 2,
|
||||||
importSync: "require('../server/' + chunkId)",
|
|
||||||
importAsync: "Promise.resolve(require('../server/' + chunkId))",
|
|
||||||
target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null,
|
target: process.argv[3] && process.argv[3][0] !== '-' ? process.argv[3] : null,
|
||||||
minify: process.argv.includes('--minify') ? true : null,
|
minify: process.argv.includes('--minify') ? true : null,
|
||||||
analyze: process.argv.includes('--analyze') ? true : null,
|
analyze: process.argv.includes('--analyze') ? true : null,
|
||||||
@ -49,10 +46,6 @@ async function main () {
|
|||||||
await writeFile(htmlTemplateFileJS, htmlTemplateCompiled)
|
await writeFile(htmlTemplateFileJS, htmlTemplateCompiled)
|
||||||
consola.info('Generated', prettyPath(htmlTemplateFileJS))
|
consola.info('Generated', prettyPath(htmlTemplateFileJS))
|
||||||
|
|
||||||
// Collect dynamic chunks
|
|
||||||
consola.info('Collecting dynamic chunks...')
|
|
||||||
const dynamicImporter = await createDynamicImporter(resolve(config.buildDir, 'dist/server'))
|
|
||||||
|
|
||||||
// Bundle for each target
|
// Bundle for each target
|
||||||
for (let target of config.targets) {
|
for (let target of config.targets) {
|
||||||
if (typeof target === 'string') {
|
if (typeof target === 'string') {
|
||||||
@ -69,8 +62,7 @@ async function main () {
|
|||||||
const ctx: any = defu(
|
const ctx: any = defu(
|
||||||
target,
|
target,
|
||||||
config,
|
config,
|
||||||
tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target),
|
tryImport(__dirname, `./targets/${target.target}`) || tryImport(config.rootDir, target.target)
|
||||||
{ dynamicImporter }
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const hooks = new Hookable()
|
const hooks = new Hookable()
|
||||||
|
@ -9,6 +9,7 @@ import json from '@rollup/plugin-json'
|
|||||||
import replace from '@rollup/plugin-replace'
|
import replace from '@rollup/plugin-replace'
|
||||||
import analyze from 'rollup-plugin-analyzer'
|
import analyze from 'rollup-plugin-analyzer'
|
||||||
import ts from 'rollup-plugin-ts'
|
import ts from 'rollup-plugin-ts'
|
||||||
|
import dynamicRequire from './dynamic-require'
|
||||||
|
|
||||||
export type RollupConfig = InputOptions & { output: OutputOptions }
|
export type RollupConfig = InputOptions & { output: OutputOptions }
|
||||||
|
|
||||||
@ -66,13 +67,15 @@ export const getRollupConfig = (config) => {
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// Dynamic Importer
|
// Dynamic Require Support
|
||||||
if (config.dynamicImporter) {
|
options.plugins.push(dynamicRequire({
|
||||||
options.output.intro += config.dynamicImporter(config.importSync, config.importAsync)
|
dir: path.resolve(config.buildDir, 'dist/server'),
|
||||||
} else {
|
globbyOptions: {
|
||||||
options.output.intro += `const requireDynamic = (chunkId) => ${config.importSync}`
|
ignore: [
|
||||||
|
'server.js'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
options.plugins.push(replace({ values: { 'require("./" +': 'requireDynamic(' }, delimiters: ['', ''] }))
|
}))
|
||||||
|
|
||||||
// https://github.com/rollup/plugins/tree/master/packages/alias
|
// https://github.com/rollup/plugins/tree/master/packages/alias
|
||||||
options.plugins.push(alias({
|
options.plugins.push(alias({
|
||||||
|
Loading…
Reference in New Issue
Block a user