feat: dynamic-require rollup plugin

This commit is contained in:
Pooya Parsa 2020-11-03 20:55:36 +01:00
parent ec8468635b
commit cbae59a88b
4 changed files with 57 additions and 60 deletions

View 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
}
}
}

View File

@ -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
};`
}

View File

@ -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()

View File

@ -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({