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

Refactor cli serve command #8958

Merged
merged 5 commits into from
Jul 24, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
12 changes: 9 additions & 3 deletions packages/cli/src/commands/__tests__/serve.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,15 @@ jest.mock('fs', () => {
}
})

jest.mock('../serveHandler', () => {
jest.mock('../serveApiHandler', () => {
return {
...jest.requireActual('../serveHandler'),
...jest.requireActual('../serveApiHandler'),
apiServerHandler: jest.fn(),
}
})
jest.mock('../serveBothHandler', () => {
return {
...jest.requireActual('../serveBothHandler'),
bothServerHandler: jest.fn(),
}
})
Expand All @@ -54,7 +59,8 @@ import execa from 'execa'
import yargs from 'yargs'

import { builder } from '../serve'
import { apiServerHandler, bothServerHandler } from '../serveHandler'
import { apiServerHandler } from '../serveApiHandler'
import { bothServerHandler } from '../serveBothHandler'

describe('yarn rw serve', () => {
afterEach(() => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/deploy/flightcontrol.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers'
import { getConfig } from '@redwoodjs/project-config'

import { getPaths } from '../../lib'
import { apiServerHandler } from '../serveHandler'
import { apiServerHandler } from '../serveApiHandler'

export const command = 'flightcontrol <side>'
export const alias = 'fc'
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/commands/deploy/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers'
import { getConfig } from '@redwoodjs/project-config'

import { getPaths } from '../../lib'
import { apiServerHandler } from '../serveHandler'
import { apiServerHandler } from '../serveApiHandler'

export const command = 'render <side>'
export const description = 'Build, Migrate, and Serve command for Render deploy'
Expand Down
156 changes: 19 additions & 137 deletions packages/cli/src/commands/serve.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import fs from 'fs'
import path from 'path'

import chalk from 'chalk'
import execa from 'execa'
import terminalLink from 'terminal-link'

import { recordTelemetryAttributes } from '@redwoodjs/cli-helpers'

import { getPaths, getConfig } from '../lib'
import c from '../lib/colors'

import { webServerHandler, webSsrServerHandler } from './serveWebHandler'

export const command = 'serve [side]'
export const description = 'Run server for api or web in production'

Expand Down Expand Up @@ -43,99 +43,16 @@ export const builder = async (yargs) => {

// Run the experimental server file, if it exists, with web side also
if (hasExperimentalServerFile()) {
console.log(
[
separator,
`🧪 ${chalk.green('Experimental Feature')} 🧪`,
separator,
'Using the experimental API server file at api/dist/server.js',
separator,
].join('\n')
const { bothExperimentalServerFileHandler } = await import(
'./serveBothHandler.js'
)

if (getConfig().experimental?.rsc?.enabled) {
console.warn('')
console.warn('⚠️ Skipping Fastify web server ⚠️')
console.warn('⚠️ Using new RSC server instead ⚠️')
console.warn('')
await execa(
'node',
[
'--conditions react-server',
'./node_modules/@redwoodjs/vite/dist/runRscFeServer.js',
],
{
cwd: getPaths().base,
stdio: 'inherit',
shell: true,
}
)
} else if (getConfig().experimental?.streamingSsr?.enabled) {
console.warn('')
console.warn('⚠️ Skipping Fastify web server ⚠️')
console.warn('⚠️ Using new Streaming FE server instead ⚠️')
console.warn('')
await execa('yarn', ['rw-serve-fe'], {
cwd: getPaths().web.base,
stdio: 'inherit',
shell: true,
})
} else {
await execa(
'yarn',
['node', path.join('dist', 'server.js'), '--enable-web'],
{
cwd: getPaths().api.base,
stdio: 'inherit',
shell: true,
}
)
}
return
}

if (getConfig().experimental?.rsc?.enabled) {
const { apiServerHandler } = await import('./serveHandler.js')
// TODO (RSC) Allow specifying port, socket and apiRootPath
const apiPromise = apiServerHandler({
...argv,
port: 8911,
apiRootPath: '/',
})

// TODO (RSC) More gracefully handle Ctrl-C
const fePromise = execa(
'node',
[
'--conditions react-server',
'./node_modules/@redwoodjs/vite/dist/runRscFeServer.js',
],
{
cwd: getPaths().base,
stdio: 'inherit',
shell: true,
}
)

await Promise.all([apiPromise, fePromise])
await bothExperimentalServerFileHandler()
} else if (getConfig().experimental?.rsc?.enabled) {
const { bothRscServerHandler } = await import('./serveBothHandler.js')
await bothRscServerHandler(argv)
} else if (getConfig().experimental?.streamingSsr?.enabled) {
const { apiServerHandler } = await import('./serveHandler.js')
// TODO (STREAMING) Allow specifying port, socket and apiRootPath
const apiPromise = apiServerHandler({
...argv,
port: 8911,
apiRootPath: '/',
})

// TODO (STREAMING) More gracefully handle Ctrl-C
// Right now you get a big red error box when you kill the process
const fePromise = execa('yarn', ['rw-serve-fe'], {
cwd: getPaths().web.base,
stdio: 'inherit',
shell: true,
})

await Promise.all([apiPromise, fePromise])
const { bothSsrServerHandler } = await import('./serveBothHandler.js')
await bothSsrServerHandler(argv)
} else {
// Wanted to use the new web-server package here, but can't because
// of backwards compatibility reasons. With `bothServerHandler` both
Expand All @@ -144,7 +61,7 @@ export const builder = async (yargs) => {
// them on the same port, and so we lose backwards compatibility.
// TODO: Use @redwoodjs/web-server when we're ok with breaking
// backwards compatibility.
const { bothServerHandler } = await import('./serveHandler.js')
const { bothServerHandler } = await import('./serveBothHandler.js')
await bothServerHandler(argv)
}
},
Expand Down Expand Up @@ -179,25 +96,14 @@ export const builder = async (yargs) => {

// Run the experimental server file, if it exists, api side only
if (hasExperimentalServerFile()) {
console.log(
[
separator,
`🧪 ${chalk.green('Experimental Feature')} 🧪`,
separator,
'Using the experimental API server file at api/dist/server.js',
separator,
].join('\n')
const { apiExperimentalServerFileHandler } = await import(
'./serveApiHandler.js'
)
await execa('yarn', ['node', path.join('dist', 'server.js')], {
cwd: getPaths().api.base,
stdio: 'inherit',
shell: true,
})
return
await apiExperimentalServerFileHandler()
} else {
const { apiServerHandler } = await import('./serveApiHandler.js')
await apiServerHandler(argv)
}

const { apiServerHandler } = await import('./serveHandler.js')
await apiServerHandler(argv)
},
})
.command({
Expand Down Expand Up @@ -227,29 +133,9 @@ export const builder = async (yargs) => {
})

if (getConfig().experimental?.streamingSsr?.enabled) {
await execa('yarn', ['rw-serve-fe'], {
cwd: getPaths().web.base,
stdio: 'inherit',
shell: true,
})
await webSsrServerHandler()
} else {
await execa(
'yarn',
[
'rw-web-server',
'--port',
argv.port,
'--socket',
argv.socket,
'--api-host',
argv.apiHost,
],
{
cwd: getPaths().base,
stdio: 'inherit',
shell: true,
}
)
await webServerHandler(argv)
}
},
})
Expand Down Expand Up @@ -312,10 +198,6 @@ export const builder = async (yargs) => {
)
}

const separator = chalk.hex('#ff845e')(
'------------------------------------------------------------------'
)

// We'll clean this up later, but for now note that this function is
// duplicated between this package and @redwoodjs/fastify
// to avoid importing @redwoodjs/fastify when the CLI starts.
Expand Down
89 changes: 89 additions & 0 deletions packages/cli/src/commands/serveApiHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import path from 'path'

import chalk from 'chalk'
import execa from 'execa'

import { createFastifyInstance, redwoodFastifyAPI } from '@redwoodjs/fastify'
import { getPaths } from '@redwoodjs/project-config'

export const apiExperimentalServerFileHandler = async () => {
logExperimentalHeader()

await execa('yarn', ['node', path.join('dist', 'server.js')], {
cwd: getPaths().api.base,
stdio: 'inherit',
shell: true,
})
return
}

export const apiServerHandler = async (options) => {
const { port, socket, apiRootPath } = options
const tsApiServer = Date.now()

console.log(chalk.dim.italic('Starting API Server...'))

const fastify = createFastifyInstance()

process.on('exit', () => {
fastify?.close()
})

await fastify.register(redwoodFastifyAPI, {
redwood: {
...options,
},
})

let listenOptions

if (socket) {
listenOptions = { path: socket }
} else {
listenOptions = {
port,
host: process.env.NODE_ENV === 'production' ? '0.0.0.0' : '::',
}
}

fastify.listen(listenOptions)

fastify.ready(() => {
fastify.log.trace(
{ custom: { ...fastify.initialConfig } },
'Fastify server configuration'
)
fastify.log.trace(`Registered plugins \n${fastify.printPlugins()}`)
console.log(chalk.italic.dim('Took ' + (Date.now() - tsApiServer) + ' ms'))

const on = socket
? socket
: chalk.magenta(`http://localhost:${port}${apiRootPath}`)

console.log(`API listening on ${on}`)
const graphqlEnd = chalk.magenta(`${apiRootPath}graphql`)
console.log(`GraphQL endpoint at ${graphqlEnd}`)

sendProcessReady()
})
}

function sendProcessReady() {
return process.send && process.send('ready')
}

const separator = chalk.hex('#ff845e')(
'------------------------------------------------------------------'
)

function logExperimentalHeader() {
console.log(
[
separator,
`🧪 ${chalk.green('Experimental Feature')} 🧪`,
separator,
'Using the experimental API server file at api/dist/server.js',
separator,
].join('\n')
)
}
Loading
Loading