UNPKG

@platform/react.ssr

Version:

A lightweight SSR (server-side-rendering) system for react apps bundled with ParcelJS and hosted on S3.

93 lines (92 loc) 3.21 kB
import { bundler } from '../bundler'; import { Config } from '../config'; import { cli, exec, fs, log, npm } from './common'; import * as push from './cmd.push'; export async function run(args = {}) { const config = args.config || (await Config.create()); const { endpoint } = config.s3; let manifest; await fs.ensureDir(config.builder.bundles); const pkgPath = await fs.ancestor(config.builder.bundles).first('package.json'); const pkg = npm.pkg(pkgPath); log.info.gray(fs.dirname(pkgPath)); log.info(); const version = args.version || (await npm.prompt.incrementVersion({ path: pkgPath, noChange: true, save: true })); const bundleDir = fs.resolve(fs.join(config.builder.bundles, version)); const isPush = args.push !== undefined ? args.push : (await cli.prompt.list({ message: 'push to S3', items: ['yes', 'no'] })) === 'yes'; if (isPush && !endpoint) { throw new Error(`The S3 endpoint has not been configured in [ssr.yml].`); } log.info(); const tasks = cli .tasks() .task('build', async (e) => execScript(pkg, e, 'build')) .task('bundle', async (e) => execScript(pkg, e, 'bundle')) .task('manifest', async (e) => { const entries = await getEntries(config); const res = await bundler.prepare({ bundleDir, entries, silent: true }); manifest = res.manifest; }); await tasks.run({ concurrent: false }); if (isPush) { await push.bundle({ config, version }); } else if (manifest) { bundler.log.bundle({ bundleDir, manifest }); } log.info(); } async function execScript(pkg, e, scriptName) { const exists = Boolean(pkg.scripts.bundle); if (!exists) { e.error(`Package.json does not have a "${scriptName}" script.`); return; } const cwd = pkg.dir; await exec.command(`yarn ${scriptName}`).run({ cwd, silent: true }); } const getRootDir = async (source) => { let path = ''; await fs.ancestor(source).walk(async (e) => { if ((await fs.readdir(e.dir)).includes('package.json')) { return e.stop(); } else { path = e.dir; } }); return path; }; const getEntries = async (config) => { let source = config.builder.entries; if (!source) { return []; } source = fs.resolve(source); const sourceRoot = await getRootDir(source); const sourcePath = source.substring(sourceRoot.length); const localRoot = fs.resolve(`tmp/${fs.basename(sourceRoot)}`); const localPath = fs.join(localRoot, sourcePath); await fs.ensureDir(fs.dirname(localRoot)); await fs.remove(localRoot); await fs.copy(sourceRoot, localRoot); const err = `Failed to load bundle entries at path: ${source}.`; try { const res = require(localPath); if (Array.isArray(res.default)) { return res.default; } log.error(`${err} Ensure the array is exported as the module default.`); return []; } catch (error) { log.error(`${err} ${error.message}`); return []; } finally { await fs.remove(fs.resolve('tmp')); } };