Skip to content

Commit

Permalink
chore(gatsby): remove other services
Browse files Browse the repository at this point in the history
  • Loading branch information
wardpeet committed May 16, 2022
1 parent 5d3bb53 commit 5a73c9b
Show file tree
Hide file tree
Showing 8 changed files with 11 additions and 401 deletions.
2 changes: 1 addition & 1 deletion packages/gatsby-plugin-netlify-cms/src/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ exports.onCreateWebpackConfig = (
messages: [
`Netlify CMS is running at ${
program.https ? `https://` : `http://`
}${program.host}:${program.proxyPort}/${publicPathClean}/`,
}${program.host}:${program.port}/${publicPathClean}/`,
],
},
}),
Expand Down
252 changes: 8 additions & 244 deletions packages/gatsby/src/commands/develop.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,15 @@
// NOTE(@mxstbr): Do not use the reporter in this file, as that has side-effects on import which break structured logging
import path from "path"
import http from "http"
import https from "https"
import tmp from "tmp"
import { ChildProcess } from "child_process"
import execa from "execa"
import chokidar from "chokidar"
import getRandomPort from "detect-port"
import { detectPortInUseAndPrompt } from "../utils/detect-port-in-use-and-prompt"
import { Server as SocketIO } from "socket.io"
import fs from "fs-extra"
import onExit from "signal-exit"
import {
isCI,
slash,
createServiceLock,
getService,
updateInternalSiteMetadata,
UnlockFn,
uuid,
} from "gatsby-core-utils"
import { v4 } from "gatsby-core-utils/uuid"
import { slash } from "gatsby-core-utils/path"
import reporter from "gatsby-cli/lib/reporter"
import { getSslCert } from "../utils/get-ssl-cert"
import { IProxyControls, startDevelopProxy } from "../utils/develop-proxy"
import { IProgram, IDebugInfo } from "./types"
import { flush as telemetryFlush } from "gatsby-telemetry"

Expand All @@ -41,34 +28,6 @@ const requireUncached = (file: string): any => {
}
}

// Heuristics for gatsby-config.js, as not all changes to it require a full restart to take effect
const doesConfigChangeRequireRestart = (
lastConfig: Record<string, any>,
newConfig: Record<string, any>
): boolean => {
// Ignore changes to siteMetadata
const replacer = (_, v): string | void => {
if (typeof v === `function` || v instanceof RegExp) {
return v.toString()
} else {
return v
}
}

const oldConfigString = JSON.stringify(
{ ...lastConfig, siteMetadata: null },
replacer
)
const newConfigString = JSON.stringify(
{ ...newConfig, siteMetadata: null },
replacer
)

if (oldConfigString === newConfigString) return false

return true
}

// Return a user-supplied port otherwise the default Node.js debugging port
const getDebugPort = (port?: number): number => port ?? 9229

Expand Down Expand Up @@ -200,17 +159,14 @@ const REGEX_IP =

module.exports = async (program: IProgram): Promise<void> => {
global.__GATSBY = {
buildId: uuid.v4(),
buildId: v4(),
root: program.directory,
}

// In some cases, port can actually be a string. But our codebase is expecting it to be a number.
// So we want to early just force it to a number to ensure we always act on a correct type.
program.port = parseInt(program.port + ``, 10)
const developProcessPath = slash(require.resolve(`./develop-process`))
const telemetryServerPath = slash(
require.resolve(`../utils/telemetry-server`)
)

try {
program.port = await detectPortInUseAndPrompt(program.port)
Expand All @@ -224,27 +180,15 @@ module.exports = async (program: IProgram): Promise<void> => {

// Run the actual develop server on a random port, and the proxy on the program port
// which users will access
const proxyPort = program.port
const debugInfo = getDebugInfo(program)

const rootFile = (file: string): string => path.join(program.directory, file)

// Require gatsby-config.js before accessing process.env, to enable the user to change
// environment variables from the config file.
let lastConfig = requireUncached(rootFile(`gatsby-config`))

// INTERNAL_STATUS_PORT allows for setting the websocket port used for monitoring
// when the browser should prompt the user to restart the develop process.
// This port is randomized by default and in most cases should never be required to configure.
// It is exposed for environments where port access needs to be explicit, such as with Docker.
// As the port is meant for internal usage only, any attempt to interface with features
// it exposes via third-party software is not supported.
const [statusServerPort, developPort, telemetryServerPort] =
await Promise.all([
getRandomPort(process.env.INTERNAL_STATUS_PORT),
getRandomPort(),
getRandomPort(),
])
requireUncached(rootFile(`gatsby-config`))

const developPort = program.port

// In order to enable custom ssl, --cert-file --key-file and -https flags must all be
// used together
Expand Down Expand Up @@ -284,21 +228,12 @@ module.exports = async (program: IProgram): Promise<void> => {
}
}

// NOTE(@mxstbr): We need to start the develop proxy before the develop process to ensure
// codesandbox detects the right port to expose by default
const proxy = startDevelopProxy({
proxyPort: proxyPort,
targetPort: developPort,
program,
})

const developProcess = new ControllableScript(
`
const cmd = require(${JSON.stringify(developProcessPath)});
const args = ${JSON.stringify({
...program,
port: developPort,
proxyPort,
// Don't pass SSL options down to the develop process, it should always use HTTP
ssl: null,
debugInfo,
Expand All @@ -308,106 +243,17 @@ module.exports = async (program: IProgram): Promise<void> => {
debugInfo
)

const telemetryServerProcess = new ControllableScript(
`require(${JSON.stringify(telemetryServerPath)}).default(${JSON.stringify(
telemetryServerPort
)})`,
null
)

let unlocks: Array<UnlockFn | null> = []
if (!isCI()) {
const statusUnlock = await createServiceLock(
program.directory,
`developstatusserver`,
{
port: statusServerPort,
}
)
const developUnlock = await createServiceLock(
program.directory,
`developproxy`,
{
port: proxyPort,
}
)
const telemetryUnlock = await createServiceLock(
program.directory,
`telemetryserver`,
{
port: telemetryServerPort,
}
)
await updateInternalSiteMetadata({
name: program.sitePackageJson.name,
sitePath: program.directory,
pid: process.pid,
lastRun: Date.now(),
})

if (!statusUnlock || !developUnlock) {
const data = await getService(program.directory, `developproxy`)
const port = data?.port || 8000
console.error(
`Looks like develop for this site is already running, can you visit ${
program.ssl ? `https:` : `http:`
}//localhost:${port} ? If it is not, try again in five seconds!`
)
process.exit(1)
}

unlocks = unlocks.concat([statusUnlock, developUnlock, telemetryUnlock])
}

const statusServer = program.ssl
? https.createServer(program.ssl)
: http.createServer()
statusServer.listen(statusServerPort)

const io = new SocketIO(statusServer, {
// whitelist all (https://github.com/expressjs/cors#configuration-options)
cors: {
origin: true,
},
cookie: true,
})

const handleChildProcessIPC = (msg): void => {
if (msg.type === `HEARTBEAT`) return
if (process.send) {
// Forward IPC
process.send(msg)
}

io.emit(`structured-log`, msg)

if (
msg.type === `LOG_ACTION` &&
msg.action.type === `SET_STATUS` &&
msg.action.payload === `SUCCESS`
) {
proxy.serveSite()
}
}

io.on(`connection`, socket => {
socket.on(`develop:restart`, async respond => {
isRestarting = true
proxy.serveRestartingScreen()
// respond() responds to the client, which in our case prompts it to reload the page to show the restarting screen
if (respond) respond(`develop:is-starting`)
await developProcess.stop()
developProcess.start()
developProcess.onMessage(handleChildProcessIPC)
isRestarting = false
})
})

developProcess.start()
developProcess.onMessage(handleChildProcessIPC)

telemetryServerProcess.start()

// Plugins can call `process.exit` which would be sent to `develop-process` (child process)
// This needs to be propagated back to the parent process
developProcess.onExit(
Expand Down Expand Up @@ -440,58 +286,10 @@ module.exports = async (program: IProgram): Promise<void> => {
}
)

const files = [
rootFile(`gatsby-config.js`),
rootFile(`gatsby-node.js`),
rootFile(`gatsby-config.ts`),
rootFile(`gatsby-node.ts`),
]
const GATSBY_CONFIG_REGEX = /^gatsby-config\.[jt]s$/
let watcher: chokidar.FSWatcher

if (!isCI()) {
watcher = chokidar.watch(files).on(`change`, filePath => {
const file = path.basename(filePath)

if (file.match(GATSBY_CONFIG_REGEX)) {
const newConfig = requireUncached(rootFile(`gatsby-config`))

if (!doesConfigChangeRequireRestart(lastConfig, newConfig)) {
lastConfig = newConfig
return
}

lastConfig = newConfig
}

console.warn(
`develop process needs to be restarted to apply the changes to ${file}`
)
io.emit(`structured-log`, {
type: `LOG_ACTION`,
action: {
type: `DEVELOP`,
payload: `RESTART_REQUIRED`,
dirtyFile: file,
},
})
})
}

// route ipc messaging to the original develop process
process.on(`message`, msg => {
developProcess.send(msg)
})

process.on(`SIGINT`, async () => {
await shutdownServices(
{
developProcess,
telemetryServerProcess,
unlocks,
statusServer,
proxy,
watcher,
},
`SIGINT`
)
Expand All @@ -503,11 +301,6 @@ module.exports = async (program: IProgram): Promise<void> => {
await shutdownServices(
{
developProcess,
telemetryServerProcess,
unlocks,
statusServer,
proxy,
watcher,
},
`SIGTERM`
)
Expand All @@ -519,55 +312,26 @@ module.exports = async (program: IProgram): Promise<void> => {
shutdownServices(
{
developProcess,
telemetryServerProcess,
unlocks,
statusServer,
proxy,
watcher,
},
signal as NodeJS.Signals
)
})
}

interface IShutdownServicesOptions {
statusServer: https.Server | http.Server
developProcess: ControllableScript
proxy: IProxyControls
unlocks: Array<UnlockFn | null>
watcher: chokidar.FSWatcher
telemetryServerProcess: ControllableScript
}

function shutdownServices(
{
statusServer,
developProcess,
proxy,
unlocks,
watcher,
telemetryServerProcess,
}: IShutdownServicesOptions,
{ developProcess }: IShutdownServicesOptions,
signal: NodeJS.Signals
): Promise<void> {
try {
telemetryFlush()
} catch (e) {
// nop
}
const services = [
developProcess.stop(signal),
telemetryServerProcess.stop(),
watcher?.close(),
new Promise(resolve => statusServer.close(resolve)),
new Promise(resolve => proxy.server.close(resolve)),
]

unlocks.forEach(unlock => {
if (unlock) {
services.push(unlock())
}
})
const services = [developProcess.stop(signal)]

return Promise.all(services)
.catch(() => {})
Expand Down
1 change: 0 additions & 1 deletion packages/gatsby/src/commands/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export interface IProgram {
open: boolean
openTracingConfigFile: string
port: number
proxyPort: number
host: string
report: Reporter
[`cert-file`]?: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ exports.sourceNodes = ({
siteMetadata: {
...configCopy.siteMetadata,
},
port: program.proxyPort,
port: program.port,
host: program.host,
...configCopy,
}
Expand Down
Loading

0 comments on commit 5a73c9b

Please sign in to comment.