/
buildHandler.js
156 lines (140 loc) · 4.24 KB
/
buildHandler.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import fs from 'fs'
import path from 'path'
import execa from 'execa'
import { Listr } from 'listr2'
import rimraf from 'rimraf'
import terminalLink from 'terminal-link'
import { buildApi } from '@redwoodjs/internal/dist/build/api'
import { loadAndValidateSdls } from '@redwoodjs/internal/dist/validateSchema'
import { detectPrerenderRoutes } from '@redwoodjs/prerender/detection'
import { timedTelemetry, errorTelemetry } from '@redwoodjs/telemetry'
import { getPaths } from '../lib'
import c from '../lib/colors'
import { generatePrismaCommand } from '../lib/generatePrismaClient'
export const handler = async ({
side = ['api', 'web'],
verbose = false,
performance = false,
stats = false,
prisma = true,
prerender,
}) => {
const rwjsPaths = getPaths()
if (performance) {
console.log('Measuring Web Build Performance...')
execa.sync(
`yarn cross-env NODE_ENV=production webpack --config ${require.resolve(
'@redwoodjs/core/config/webpack.perf.js'
)}`,
{ stdio: 'inherit', shell: true, cwd: rwjsPaths.web.base }
)
// We do not want to continue building...
return
}
if (stats) {
console.log('Building Web Stats...')
execa.sync(
`yarn cross-env NODE_ENV=production webpack --config ${require.resolve(
'@redwoodjs/core/config/webpack.stats.js'
)}`,
{ stdio: 'inherit', shell: true, cwd: rwjsPaths.web.base }
)
// We do not want to continue building...
return
}
const prerenderRoutes =
prerender && side.includes('web') ? detectPrerenderRoutes() : []
const shouldGeneratePrismaClient =
prisma && (side.includes('api') || prerenderRoutes.length > 0)
const tasks = [
shouldGeneratePrismaClient && {
title: 'Generating Prisma Client...',
task: () => {
const { cmd, args } = generatePrismaCommand(rwjsPaths.api.dbSchema)
return execa(cmd, args, {
stdio: verbose ? 'inherit' : 'pipe',
shell: true,
cwd: rwjsPaths.api.base,
})
},
},
side.includes('api') && {
title: 'Verifying graphql schema...',
task: loadAndValidateSdls,
},
side.includes('api') && {
title: 'Building API...',
task: () => {
const { errors, warnings } = buildApi()
if (errors.length) {
console.error(errors)
}
if (warnings.length) {
console.warn(warnings)
}
},
},
side.includes('web') && {
// Clean web
title: 'Cleaning Web...',
task: () => {
rimraf.sync(rwjsPaths.web.dist)
},
},
side.includes('web') && {
title: 'Building Web...',
task: async () => {
await execa(
`yarn cross-env NODE_ENV=production webpack --config ${require.resolve(
'@redwoodjs/core/config/webpack.production.js'
)}`,
{
stdio: verbose ? 'inherit' : 'pipe',
shell: true,
cwd: rwjsPaths.web.base,
}
)
console.log('Creating 200.html...')
const indexHtmlPath = path.join(getPaths().web.dist, 'index.html')
fs.copyFileSync(
indexHtmlPath,
path.join(getPaths().web.dist, '200.html')
)
},
},
].filter(Boolean)
const triggerPrerender = async () => {
console.log('Starting prerendering...')
if (prerenderRoutes.length === 0) {
console.log(
`You have not marked any routes to "prerender" in your ${terminalLink(
'Routes',
'file://' + rwjsPaths.web.routes
)}.`
)
}
// Running a separate process here, otherwise it wouldn't pick up the
// generated Prisma Client due to require module caching
await execa('yarn rw prerender', {
stdio: 'inherit',
shell: true,
cwd: rwjsPaths.web.base,
})
}
const jobs = new Listr(tasks, {
renderer: verbose && 'verbose',
})
try {
await timedTelemetry(process.argv, { type: 'build' }, async () => {
await jobs.run()
if (side.includes('web') && prerender) {
// This step is outside Listr so that it prints clearer, complete messages
await triggerPrerender()
}
})
} catch (e) {
console.log(c.error(e.message))
errorTelemetry(process.argv, e.message)
process.exit(1)
}
}