UNPKG

6.7 kBJavaScriptView Raw
1#! /usr/bin/env node
2'use strict'
3
4let log = null
5
6const fs = require('fs-extra')
7const path = require('path')
8const exit = require('exit')
9const onExit = require('exit-hook')
10const React = require('react')
11
12const rolaCompiler = require('@rola/compiler')
13const rolaStatic = require('@rola/static')
14const { getConfig, createDocument } = require('@rola/util')
15
16const createServer = require('./util/createServer.js')
17const createConfig = require('./util/createConfig.js')
18
19const cwd = process.cwd()
20
21const pkg = require('./package.json')
22const userPkg = require(path.join(cwd, './package.json'))
23
24const PORT = process.env.PORT || 3000
25const prog = require('commander')
26 .version(pkg.version)
27
28process.env.ROLA_VERSION = pkg.version
29
30let clientEntry
31let serverEntry
32
33try {
34 clientEntry = require.resolve(path.join(cwd, 'client.js'))
35} catch (e) {}
36
37try {
38 serverEntry = require.resolve(path.join(cwd, 'server.js'))
39} catch (e) {}
40
41/**
42 * clean up outdir
43 */
44fs.removeSync(path.join(cwd, 'build'))
45
46/**
47 * remove temp dir on exit
48 */
49onExit(() => {
50 fs.removeSync(path.join(cwd, '.rola'))
51})
52
53let server
54
55function serve () {
56 if (!server) {
57 server = createServer({
58 file: path.join(cwd, '/build/server.js'),
59 port: PORT
60 })
61
62 server.init()
63
64 log({ server: [ PORT ] })
65
66 onExit(() => {
67 server && server.close()
68 })
69 }
70}
71
72function createGenerator (config, plugins) {
73 const generator = rolaStatic({
74 env: config.env,
75 alias: config.alias,
76 presets: config.presets,
77 plugins
78 })
79
80 generator.on('rendered', pages => {
81 log({ static: pages })
82 // TODO clear logs?
83 server && server.update()
84 })
85 generator.on('warn', e => {
86 log(state => ({
87 warn: state.warn.concat(e)
88 }))
89 })
90 generator.on('error', e => {
91 log(state => ({
92 error: state.error.concat(e)
93 }))
94 })
95
96 return generator
97}
98
99function createServerProps ({ presets }) {
100 const context = {
101 name: userPkg.name,
102 version: userPkg.version
103 }
104
105 const tags = createDocument({
106 context,
107 plugins: presets
108 })
109
110 const props = {
111 context,
112 tags
113 }
114
115 fs.outputFileSync(
116 path.join(cwd, '.rola', 'props.js'),
117 `module.exports = ${JSON.stringify(props, null, ' ')}`
118 )
119}
120
121prog
122 .command('build')
123 .action(async () => {
124 log({ actions: [ 'build' ] })
125
126 const { plugins, ...config } = getConfig()
127
128 for (let key in (config.env || {})) {
129 process.env[key] = config.env[key]
130 }
131
132 const configs = []
133
134 if (clientEntry) configs.push(createConfig({
135 entry: clientEntry,
136 env: config.env,
137 alias: config.alias,
138 presets: config.presets
139 }))
140
141 if (serverEntry) configs.push(createConfig({
142 entry: serverEntry,
143 env: config.env,
144 alias: config.alias,
145 presets: config.presets
146 }))
147
148 createServerProps({
149 presets: [
150 ...config.presets,
151 (clientEntry ? {
152 createDocument ({ context }) {
153 return {
154 body: `<script src='/client.js?v${context.version}'></script>`
155 }
156 }
157 } : {})
158 ]
159 })
160
161 async function done () {
162 /**
163 * for api requests, if needed
164 */
165 if (serverEntry) serve()
166
167 await createGenerator(config, plugins).render('/static', '/build/assets')
168
169 exit()
170 }
171
172 if (configs.length) {
173 let allstats = []
174 const compiler = rolaCompiler(configs)
175
176 compiler.on('error', e => {
177 log(state => ({
178 error: state.error.concat(e)
179 }))
180 })
181
182 compiler.on('warn', e => {
183 log(state => ({
184 warn: state.warn.concat(e)
185 }))
186 })
187
188 compiler.on('stats', async stats => {
189 stats.map(_stats => {
190 const server = _stats.assets.reduce((bool, asset) => {
191 if (/server/.test(asset.name)) bool = true
192 return bool
193 }, false)
194
195 if (server) {
196 allstats[1] = _stats
197 } else {
198 allstats[0] = _stats
199 }
200 })
201
202 log({
203 actions: [],
204 stats: allstats
205 })
206
207 done()
208 })
209
210 compiler.build()
211 } else {
212 done()
213 }
214 })
215
216prog
217 .command('watch')
218 .action(async () => {
219 log({ actions: [ 'watch' ] })
220
221 const { plugins, ...config } = getConfig()
222
223 for (let key in (config.env || {})) {
224 process.env[key] = config.env[key]
225 }
226
227 let compiled = false
228 const configs = []
229
230 if (clientEntry) configs.push(createConfig({
231 entry: clientEntry,
232 env: config.env,
233 alias: config.alias,
234 banner: require('./util/clientReloader.js')(PORT),
235 presets: config.presets
236 }))
237
238 if (serverEntry) configs.push(createConfig({
239 entry: serverEntry,
240 env: config.env,
241 alias: config.alias,
242 presets: config.presets
243 }))
244
245 let allstats = []
246
247 createServerProps({
248 presets: [
249 ...config.presets,
250 (clientEntry ? {
251 createDocument ({ context }) {
252 return {
253 body: `<script src='/client.js?v${context.version}'></script>`
254 }
255 }
256 } : {})
257 ]
258 })
259
260 if (configs.length) {
261 const compiler = rolaCompiler(configs)
262
263 compiler.on('error', e => {
264 log(state => ({
265 error: state.error.concat(e)
266 }))
267 })
268
269 compiler.on('warn', e => {
270 log(state => ({
271 warn: state.warn.concat(e)
272 }))
273 })
274
275 compiler.on('stats', stats => {
276 // TODO
277 // use the errors/warnings on stats objects
278 // to keep track on pertinent warnings
279 stats.map(_stats => {
280 const isServer = _stats.assets.reduce((bool, asset) => {
281 if (/server/.test(asset.name)) bool = true
282 return bool
283 }, false)
284
285 if (isServer) {
286 allstats[1] = _stats
287 } else {
288 allstats[0] = _stats
289 }
290 })
291
292 server && server.update()
293
294 serve()
295
296 if (!compiled) {
297 createGenerator(config, plugins).watch('/static', '/build/assets')
298
299 compiled = true
300 }
301
302 /**
303 * reset logs
304 */
305 log({
306 error: [],
307 warn: [],
308 log: [],
309 stats: allstats
310 })
311 })
312
313 compiler.watch()
314 } else {
315 serve()
316 createGenerator(config, plugins).watch('/static', '/build/assets')
317 }
318 })
319
320if (!process.argv.slice(2).length) {
321 prog.outputHelp(txt => {
322 console.log(txt)
323 exit()
324 })
325} else {
326 /**
327 * fresh console
328 */
329 console.clear()
330
331 log = require('@rola/log')
332
333 log({ actions: [ 'initializing' ] })
334
335 prog.parse(process.argv)
336}