Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Continue builds on errors and adjust error throwing point #21

Merged
merged 1 commit into from
Jan 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Continue builds on errors and adjust error throwing point
Improve site building errors and reliability

Watch also doesn't crash as often so thats good.
  • Loading branch information
bcomnes committed Jan 13, 2022
commit 6b24e750ed481a6dfba6af12236148336b9e47ec
2 changes: 2 additions & 0 deletions bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,12 @@ async function run () {
}

if (!argv.watch) {
// TODO: handle warning and error output
const results = await siteup.build()
console.log(results)
console.log('done')
} else {
// TODO: handle watch data event or something... maybe like a async iterator?
const initialResults = await siteup.watch()
console.log(initialResults)
}
Expand Down
639 changes: 377 additions & 262 deletions dependencygraph.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 15 additions & 8 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,18 @@ export class Siteup {
}

async watch () {
// TODO: expose events and stuff to the caller instead.
if (this.watching) throw new Error('Already watching.')
const results = await watchBuild(this._src, this._dest, this.opts)

let report

try {
report = await watchBuild(this._src, this._dest, this.opts)
console.log('Initial JS, CSS and Page Build Complete')
} catch (err) {
console.error(err)
if (err.report) report = err.report
}

this._cpxWatcher = cpx.watch(getCopyGlob(this._src), this._dest, { ignore: this.opts.ignore })

Expand All @@ -60,7 +70,6 @@ export class Siteup {
console.log(`Copy error: ${err.message}`)
})

console.log(this.opts.ignore)
const ig = ignore().add(this.opts.ignore)

const anymatch = name => ig.ignores(relname(this._src, name))
Expand All @@ -70,27 +79,25 @@ export class Siteup {
persistent: true
})

console.log(watcher)

this._watcher = watcher

await once(watcher, 'ready')

watcher.on('add', path => {
console.log(`File ${path} has been added`)
watchBuild(this._src, this._dest, this.opts)
watchBuild(this._src, this._dest, this.opts).then(() => console.log('Site Rebuilt')).catch(console.error)
})
watcher.on('change', path => {
console.log(`File ${path} has been changed`)
watchBuild(this._src, this._dest, this.opts)
watchBuild(this._src, this._dest, this.opts).then(() => console.log('Site Rebuilt')).catch(console.error)
})
watcher.on('unlink', path => {
console.log(`File ${path} has been removed`)
// await build(this.src, this.dest)
watchBuild(this._src, this._dest, this.opts).then(() => console.log('Site Rebuilt')).catch(console.error)
})
watcher.on('error', console.error)

return results
return report
}

async stopWatching () {
Expand Down
51 changes: 34 additions & 17 deletions lib/build-css/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import postcssNesting from 'postcss-nesting'
* @param {[type]} siteData [description]
* @return {[type]} [description]
*/
export async function buildCss (src, dest, siteData) {
export async function buildCss (src, dest, siteData, opts) {
const styles = []

if (siteData.globalStyle) styles.push(siteData.globalStyle)
Expand All @@ -22,23 +22,40 @@ export async function buildCss (src, dest, siteData) {
if (page.pageStyle) styles.push(page.pageStyle)
}

const results = []
const results = {
type: 'css',
success: [],
errors: [],
warnings: []
}

for (const style of styles) {
const css = await readFile(style.filepath)
const targetPath = join(dest, style.relname)
const result = await postcss([
postcssImport,
postcssUrl({
url: 'copy',
useHash: true,
assetsPath: 'assets'
}),
postcssNesting,
autoprefixer
]).process(css, { from: style.filepath, to: targetPath })
await writeFile(targetPath, result.css)
if (result.map) await writeFile(targetPath + '.map', result.map.toString())
results.push(result)
try {
const css = await readFile(style.filepath)
const targetPath = join(dest, style.relname)
const result = await postcss([
postcssImport,
postcssUrl({
url: 'copy',
useHash: true,
assetsPath: 'assets'
}),
postcssNesting,
autoprefixer
]).process(css, { from: style.filepath, to: targetPath })
await writeFile(targetPath, result.css)
if (result.map) {
await writeFile(targetPath + '.map', result.map.toString())
delete result.map
}
delete result.css
results.success.push(result)
} catch (err) {
const buildError = new Error('Error building css', { cause: err })
buildError.style = style
results.errors.push(buildError)
}
}

return results
}
24 changes: 20 additions & 4 deletions lib/build-js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ import esbuild from 'esbuild'
* @param {[type]} siteData [description]
* @return {[type]} [description]
*/
export async function buildJs (src, dest, siteData) {
export async function buildJs (src, dest, siteData, opts) {
const entryPoints = []
if (siteData.globalClient) entryPoints.push(join(src, siteData.globalClient.relname))

for (const page of siteData.pages) {
if (page.clientBundle) entryPoints.push(join(src, page.clientBundle.relname))
}

const results = await esbuild.build({
const buildOpts = {
entryPoints: entryPoints,
logLevel: 'silent',
bundle: true,
write: true,
format: 'esm',
Expand All @@ -27,7 +28,22 @@ export async function buildJs (src, dest, siteData) {
target: [
'es2020'
]
})
}

return results
try {
// esbuild returns { errors:[], warnings: [] } already
const report = await esbuild.build(buildOpts)
return { ...report, buildOpts, type: 'js' }
} catch (err) {
const results = {
type: 'js',
errors: [],
warnings: [],
buildOpts
}
const buildError = new Error('Error building JS clients', { cause: err })
buildError.buildOpts = buildOpts
results.errors.push(buildError)
return results
}
}
101 changes: 76 additions & 25 deletions lib/build-pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,47 +12,98 @@ const __dirname = desm(import.meta.url)
export { pageBuilders }

/**
* Page builder glue. Most of the magic happens in the builders
* Page builder glue. Most of the magic happens in the builders.
* @param {[type]} src [description]
* @param {[type]} dest [description]
* @param {[type]} siteData [description]
* @return {[type]} [description]
*/
export async function buildPages (src, dest, siteData) {
export function buildPages (src, dest, siteData, opts) {
return new Promise((resolve, reject) => {
const worker = new Worker(join(__dirname, 'worker.js'), {
workerData: { src, dest, siteData }
})

worker.once('message', results => {
if (results.errors.length > 0) {
// Put the errorData on the error to be consistent with the rest of the builders.
results.errors = results.errors.map(({ error, errorData }) => {
for (const [key, val] of Object.entries(errorData)) {
error[key] = val
}
return error
})
}
resolve(results)
})
worker.once('error', reject)
worker.once('exit', (code) => {
if (code !== 0) { reject(new Error(`Worker stopped with exit code ${code}`)) }
})
})
}

/**
* Directly build pages. Normally you run this in a worker.
* @param {[type]} src [description]
* @param {[type]} dest [description]
* @param {[type]} siteData [description]
* @return {[type]} [description]
*/
export async function buildPagesDirect (src, dest, siteData) {
const results = {
type: 'page',
success: [],
errors: [],
warnings: []
}

const [
globalVars,
rootLayout
] = await Promise.all([
] = await Promise.allSettled([
resolveVars(siteData?.globalVars?.filepath),
resolveLayout(siteData?.rootLayout?.filepath)
])

const results = []
if (globalVars.status === 'rejected') {
results.errors.push(new Error('Encountered an error when resolving globalVars', {
cause: globalVars.reason
}))
}

if (rootLayout.status === 'rejected') {
results.errors.push(new Error('Encountered an error when resolving rootLayout', {
cause: rootLayout.reason
}))
}

if (results.errors.length > 0) return results // Return early, these will all fail.

for (const page of siteData.pages) {
const builder = pageBuilders[page.type]
// This should never happen
if (!builder) throw new Error(`Can't build ${page.path}. unimplemented type ${page.type}`)
try {
const builder = pageBuilders[page.type]
// This should never happen
if (!builder) throw new Error(`Can't build ${page.path}. unimplemented type ${page.type}`)

globalVars.styles = siteData.globalStyle ? ['/global.css'] : []
globalVars.scripts = siteData.globalClient ? ['/global.client.js'] : []
// Supplement global vars with some global styles and clients
globalVars.value.styles = siteData.globalStyle ? ['/global.css'] : []
globalVars.value.scripts = siteData.globalClient ? ['/global.client.js'] : []

const result = await builder({ src, dest, page, globalVars, rootLayout })
results.push(result)
const result = await builder({
src,
dest,
page,
globalVars: globalVars.value,
rootLayout: rootLayout.value
})
results.success.push(result)
} catch (err) {
const buildError = new Error('Error building page', { cause: err })
// I can't put stuff on the error, the worker swallows it for some reason.
results.errors.push({ error: buildError, errorData: { page } })
}
}

return results
}

export function buildPagesInWorker (src, dest, siteData) {
return new Promise((resolve, reject) => {
const worker = new Worker(join(__dirname, 'worker.js'), {
workerData: { src, dest, siteData }
})

worker.once('message', resolve)
worker.once('error', reject)
worker.once('exit', (code) => {
if (code !== 0) { reject(new Error(`Worker stopped with exit code ${code}`)) }
})
})
}
4 changes: 2 additions & 2 deletions lib/build-pages/worker.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { parentPort, workerData } from 'worker_threads'
import { buildPages } from './index.js'
import { buildPagesDirect } from './index.js'

async function run () {
const { src, dest, siteData } = workerData
const results = await buildPages(src, dest, siteData)
const results = await buildPagesDirect(src, dest, siteData)
parentPort.postMessage(results)
}

Expand Down
22 changes: 20 additions & 2 deletions lib/build-static/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,24 @@ export function getCopyGlob (src) {
/**
* run CPX2 on src folder
*/
export async function buildStatic (src, dest, opts = {}) {
return await copy(getCopyGlob(src), dest, { ignore: opts.ignore })
export async function buildStatic (src, dest, siteData, opts = {}) {
const results = {
type: 'static',
report: null,
errors: [],
warnings: []
}

const args = [getCopyGlob(src), dest, { ignore: opts.ignore }]

try {
const report = await copy(...args)
results.report = report
} catch (err) {
const buildError = new Error('Error copying static files', { cause: err })
buildError.staticArgs = args
results.errors.push(buildError)
}

return results
}
Loading