diff --git a/package.json b/package.json index fcd62064ef11..bf9dcc17df50 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "markdown-it-emoji": "^1.4.0", "markdown-it-table-of-contents": "^0.4.4", "minimist": "^1.2.5", + "ora": "^5.1.0", "prismjs": "^1.20.0", "slash": "^3.0.0", "vite": "^1.0.0-rc.9", diff --git a/src/node/build/build.ts b/src/node/build/build.ts index f46d556c2def..b452a6417eee 100644 --- a/src/node/build/build.ts +++ b/src/node/build/build.ts @@ -1,9 +1,10 @@ import fs from 'fs-extra' -import { bundle } from './bundle' +import { bundle, okMark, failMark } from './bundle' import { BuildConfig as ViteBuildOptions } from 'vite' import { resolveConfig } from '../config' import { renderPage } from './render' import { OutputChunk, OutputAsset } from 'rollup' +import ora from 'ora' export type BuildOptions = Pick< Partial, @@ -16,41 +17,54 @@ export type BuildOptions = Pick< export async function build(buildOptions: BuildOptions = {}) { process.env.NODE_ENV = 'production' const siteConfig = await resolveConfig(buildOptions.root) + try { const [clientResult, , pageToHashMap] = await bundle( siteConfig, buildOptions ) - console.log('rendering pages...') - - const appChunk = clientResult.assets.find( - (chunk) => - chunk.type === 'chunk' && chunk.fileName.match(/^app\.\w+\.js$/) - ) as OutputChunk - - const cssChunk = clientResult.assets.find( - (chunk) => chunk.type === 'asset' && chunk.fileName.endsWith('.css') - ) as OutputAsset - - // We embed the hash map string into each page directly so that it doesn't - // alter the main chunk's hash on every build. It's also embedded as a - // string and JSON.parsed from the client because it's faster than embedding - // as JS object literal. - const hashMapStirng = JSON.stringify(JSON.stringify(pageToHashMap)) - - for (const page of siteConfig.pages) { - await renderPage( - siteConfig, - page, - clientResult, - appChunk, - cssChunk, - pageToHashMap, - hashMapStirng - ) + + const spinner = ora() + spinner.start('rendering pages...') + + try { + const appChunk = clientResult.assets.find( + (chunk) => + chunk.type === 'chunk' && chunk.fileName.match(/^app\.\w+\.js$/) + ) as OutputChunk + + const cssChunk = clientResult.assets.find( + (chunk) => chunk.type === 'asset' && chunk.fileName.endsWith('.css') + ) as OutputAsset + + // We embed the hash map string into each page directly so that it doesn't + // alter the main chunk's hash on every build. It's also embedded as a + // string and JSON.parsed from the client because it's faster than embedding + // as JS object literal. + const hashMapStirng = JSON.stringify(JSON.stringify(pageToHashMap)) + + for (const page of siteConfig.pages) { + await renderPage( + siteConfig, + page, + clientResult, + appChunk, + cssChunk, + pageToHashMap, + hashMapStirng + ) + } + } catch (e) { + spinner.stopAndPersist({ + symbol: failMark + }) + throw e } + spinner.stopAndPersist({ + symbol: okMark + }) } finally { await fs.remove(siteConfig.tempDir) } - console.log('done.') + console.log('✨ done.') } diff --git a/src/node/build/bundle.ts b/src/node/build/bundle.ts index fab681de1c43..0506ec2ad2a9 100644 --- a/src/node/build/bundle.ts +++ b/src/node/build/bundle.ts @@ -12,6 +12,10 @@ import { BuildConfig as ViteBuildOptions, BuildResult } from 'vite' +import ora from 'ora' + +export const okMark = '\x1b[32m✓\x1b[0m' +export const failMark = '\x1b[31m✖\x1b[0m' const hashRE = /\.(\w+)\.js$/ const staticInjectMarkerRE = /\b(const _hoisted_\d+ = \/\*#__PURE__\*\/createStaticVNode)\("(.*)", (\d+)\)/g @@ -143,14 +147,37 @@ export async function bundle( minify: !process.env.DEBUG } - console.log('building client bundle...') - const clientResult = await build(viteOptions) + let clientResult, serverResult - console.log('building server bundle...') + const spinner = ora() + spinner.start('building client bundle...') + try { + clientResult = await build(viteOptions) + } catch (e) { + spinner.stopAndPersist({ + symbol: failMark + }) + throw e + } + spinner.stopAndPersist({ + symbol: okMark + }) + + spinner.start('building server bundle...') isClientBuild = false - const serverResult = await ssrBuild({ - ...viteOptions, - outDir: config.tempDir + try { + serverResult = await ssrBuild({ + ...viteOptions, + outDir: config.tempDir + }) + } catch (e) { + spinner.stopAndPersist({ + symbol: failMark + }) + throw e + } + spinner.stopAndPersist({ + symbol: okMark }) return [clientResult[0], serverResult[0], pageToHashMap]