-
Notifications
You must be signed in to change notification settings - Fork 87
/
Copy pathbuild.js
113 lines (97 loc) · 3.2 KB
/
build.js
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { cp, rm } from 'node:fs/promises'
import { resolve, join } from 'node:path'
import { build, context } from 'esbuild'
import { execaCommand } from 'execa'
import glob from 'fast-glob'
const OUT_DIR = 'dist'
await rm(OUT_DIR, { force: true, recursive: true })
const entryPointsESM = await glob('src/**/*.ts', { ignore: ['**/*.test.ts'] })
const entryPointsCJS = await glob('src/**/*.cts')
/**
*
* @param {string[]} entryPoints
* @param {'esm' | 'cjs'} format
* @param {boolean=} watch
* @returns
*/
async function bundle(entryPoints, format, watch) {
/** @type {import('esbuild').BuildOptions} */
const options = {
entryPoints,
entryNames: '[dir]/[name]',
bundle: true,
platform: 'node',
target: 'node18',
format,
external: ['next'], // don't try to bundle next
allowOverwrite: watch,
plugins: [
{
// runtime modules are all entrypoints, so importing them should mark them as external
// to avoid duplicating them in the bundle (which also can cause import path issues)
name: 'mark-runtime-modules-as-external',
setup(pluginBuild) {
pluginBuild.onResolve({ filter: /^\..*\.c?js$/ }, (args) => {
if (args.importer.includes(join('next-runtime', 'src'))) {
return { path: args.path, external: true }
}
})
},
},
],
}
if (format === 'esm') {
options.outdir = OUT_DIR
options.chunkNames = 'esm-chunks/[name]-[hash]'
options.splitting = true
options.banner = {
// this shim is needed for cjs modules that are imported in ESM :(
// explicitly use var as it might be already defined in some cases
js: `
var require = await (async () => {
var { createRequire } = await import("node:module");
return createRequire(import.meta.url);
})();
`,
}
} else {
options.outfile = entryPoints[0].replace('src', OUT_DIR).replace('cts', 'cjs')
}
if (!watch) {
return build(options)
}
const ctx = await context(options)
await ctx.watch()
process.on('SIGINT', () => {
ctx.dispose().then(() => {
// eslint-disable-next-line n/no-process-exit
process.exit()
})
})
}
export async function vendorDeno(dir) {
const vendorSource = resolve(join(dir, 'vendor.ts'))
const vendorDest = resolve(join(dir, 'vendor'))
try {
await execaCommand('deno --version')
} catch {
throw new Error('Could not check the version of Deno. Is it installed on your system?')
}
console.log(`🧹 Deleting '${vendorDest}'...`)
await rm(vendorDest, { force: true, recursive: true })
console.log(`📦 Vendoring Deno modules into '${vendorDest}'...`)
await execaCommand(`deno vendor ${vendorSource} --output=${vendorDest} --force`)
}
const args = new Set(process.argv.slice(2))
const watch = args.has('--watch') || args.has('-w')
await Promise.all([
vendorDeno('edge-runtime'),
bundle(entryPointsESM, 'esm', watch),
...entryPointsCJS.map((entry) => bundle([entry], 'cjs', watch)),
cp('src/build/templates', join(OUT_DIR, 'build/templates'), { recursive: true, force: true }),
])
if (watch) {
console.log('Starting compilation in watch mode...')
} else {
console.log('Finished building 🎉')
}