-
Notifications
You must be signed in to change notification settings - Fork 0
/
start.mjs
88 lines (80 loc) · 2.65 KB
/
start.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import http from 'http'
import esbuild from 'esbuild'
import { existsSync } from 'fs'
import { join } from 'path'
// https://github.com/evanw/esbuild/pull/2816
const liveReload = `
new EventSource('/esbuild').addEventListener('change', e => {
const { added, removed, updated } = JSON.parse(e.data)
if (!added.length && !removed.length && updated.length === 1) {
for (const link of document.getElementsByTagName("link")) {
const url = new URL(link.href)
if (url.host === location.host && url.pathname === updated[0]) {
const next = link.cloneNode()
next.href = updated[0] + '?' + Math.random().toString(36).slice(2)
next.onload = () => link.remove()
link.parentNode.insertBefore(next, link.nextSibling)
return
}
}
}
location.reload()
})
`
async function streamToString(stream) {
const chunks = [];
for await (const chunk of stream) chunks.push(Buffer.from(chunk));
return Buffer.concat(chunks).toString("utf-8");
}
export async function start(esbuildConfig, devConfig = { host: 'localhost', port: 3000 }) {
esbuildConfig.plugins = esbuildConfig.plugins || [];
esbuildConfig.plugins.push({
name: 'notify',
setup(build) {
build.onEnd(result => {
if (result.errors.length == 0) console.log('sucessfully built')
})
}
});
const context = await esbuild.context(esbuildConfig)
await context.watch()
// https://esbuild.github.io/api/#serve-proxy
const servedir = esbuildConfig.outdir
const host = devConfig.host
const port = devConfig.port + 1
await context.serve({ port, servedir })
http.createServer((req, res) => {
var path = req.url;
if (!existsSync(join(servedir, path))) {
if (existsSync(join(servedir, `${path.substring(1)}.html`))) path += '.html';
}
const options = {
hostname: host,
port,
path,
method: req.method,
headers: req.headers,
}
const proxyReq = http.request(options, async proxyRes => {
if (proxyRes.statusCode === 404) {
res.writeHead(404, { 'Content-Type': 'text/html' })
res.end('<h1>A custom 404 page</h1>')
return
}
const contentType = proxyRes.headers?.['content-type']
if (contentType && contentType.includes('text/html')) {
const resp = (await streamToString(proxyRes)).replace('</body>', `<script>${liveReload}</script></body>`)
const buffer = Buffer.from(resp, 'utf8')
proxyRes.headers['content-length'] = buffer.length
res.writeHead(proxyRes.statusCode, proxyRes.headers)
res.write(resp)
res.end()
} else {
res.writeHead(proxyRes.statusCode, proxyRes.headers)
proxyRes.pipe(res, { end: true })
}
})
req.pipe(proxyReq, { end: true })
}).listen(devConfig.port)
console.log(`serving on http://${host}:${devConfig.port}`)
}