Compare commits

...

2 Commits

Author SHA1 Message Date
Paul Popus
fbc47d624b add support in dev mode for https dev using pnpm dev:https 2025-04-11 21:55:52 +01:00
Paul Popus
2e1a63e291 fix: add protocol checks for HMR in getPayload 2025-04-11 21:55:13 +01:00
4 changed files with 50 additions and 12 deletions

2
.gitignore vendored
View File

@@ -15,7 +15,7 @@ test-results
/migrations
.localstack
.turbo
dev-certs
meta_client.json
meta_server.json
meta_index.json

View File

@@ -61,10 +61,12 @@
"clean:build:allowtgz": "node ./scripts/delete-recursively.js 'media/' '**/dist/' '**/.cache/' '**/.next/' '**/.turbo/' '**/tsconfig.tsbuildinfo' '**/meta_*.json'",
"clean:cache": "node ./scripts/delete-recursively.js node_modules/.cache! packages/payload/node_modules/.cache! .next/*",
"dev": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts",
"dev:generate-certs": "mkdir test/dev-certs && openssl req -x509 -newkey rsa:2048 -nodes -keyout ./test/dev-certs/localhost-key.pem -out ./test/dev-certs/localhost-cert.pem -days 365 -subj '/CN=localhost'",
"dev:generate-db-schema": "pnpm runts ./test/generateDatabaseSchema.ts",
"dev:generate-graphql-schema": "pnpm runts ./test/generateGraphQLSchema.ts",
"dev:generate-importmap": "pnpm runts ./test/generateImportMap.ts",
"dev:generate-types": "pnpm runts ./test/generateTypes.ts",
"dev:https": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts --experimental-https",
"dev:postgres": "cross-env PAYLOAD_DATABASE=postgres pnpm runts ./test/dev.ts",
"dev:prod": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts --prod",
"dev:prod:memorydb": "cross-env NODE_OPTIONS=--no-deprecation tsx ./test/dev.ts --prod --start-memory-db",

View File

@@ -927,6 +927,10 @@ export const getPayload = async (
process.env.DISABLE_PAYLOAD_HMR !== 'true'
) {
try {
const hasHTTPS =
process.argv.includes('--experimental-https') ??
process.env.__NEXT_ASSET_PREFIX?.includes('https:')
const protocol = hasHTTPS ? 'wss' : 'ws'
const port = process.env.PORT || '3000'
const path = '/_next/webpack-hmr'
@@ -934,7 +938,7 @@ export const getPayload = async (
const prefix = process.env.__NEXT_ASSET_PREFIX ?? ''
cached.ws = new WebSocket(
process.env.PAYLOAD_HMR_URL_OVERRIDE ?? `ws://localhost:${port}${prefix}${path}`,
process.env.PAYLOAD_HMR_URL_OVERRIDE ?? `${protocol}://localhost:${port}${prefix}${path}`,
)
cached.ws.onmessage = (event) => {

View File

@@ -1,12 +1,15 @@
import nextEnvImport from '@next/env'
import chalk from 'chalk'
import { createServer } from 'http'
import { readFileSync } from 'fs'
import { createServer as createServerHTTP } from 'http'
import { createServer as createServerHTTPS } from 'https'
import minimist from 'minimist'
import nextImport from 'next'
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import open from 'open'
import { join } from 'path'
import { loadEnv } from 'payload/node'
import { parse } from 'url'
@@ -32,11 +35,25 @@ if (shouldStartMemoryDB) {
process.env.START_MEMORY_DB = 'true'
}
const https = process.argv.includes('--experimental-https')
loadEnv()
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
let httpsOptions = {}
if (https) {
const key = readFileSync(join(dirname, 'dev-certs', 'localhost-key.pem'))
const cert = readFileSync(join(dirname, 'dev-certs', 'localhost-cert.pem'))
httpsOptions = {
key,
cert,
}
}
const {
_: [_testSuiteArg = '_community'],
...args
@@ -83,7 +100,7 @@ if (args.o) {
const findOpenPort = (startPort: number): Promise<number> => {
return new Promise((resolve, reject) => {
const server = createServer()
const server = https ? createServerHTTPS() : createServerHTTP()
server.listen(startPort, () => {
console.log(`✓ Running on port ${startPort}`)
server.close(() => resolve(startPort))
@@ -97,6 +114,7 @@ const findOpenPort = (startPort: number): Promise<number> => {
})
}
const protocol = https ? 'https' : 'http'
const port = process.env.PORT ? Number(process.env.PORT) : 3000
const availablePort = await findOpenPort(port)
@@ -111,6 +129,11 @@ const app = nextImport({
hostname: 'localhost',
port: availablePort,
dir: rootDir,
...(https
? {
experimentalHttpsServer: httpsOptions,
}
: {}),
})
const handle = app.getRequestHandler()
@@ -120,20 +143,29 @@ let resolveServer: () => void
const serverPromise = new Promise<void>((res) => (resolveServer = res))
void app.prepare().then(() => {
createServer(async (req, res) => {
const parsedUrl = parse(req.url || '', true)
await handle(req, res, parsedUrl)
}).listen(availablePort, () => {
resolveServer()
})
if (https) {
createServerHTTPS(httpsOptions, async (req, res) => {
const parsedUrl = parse(req.url || '', true)
await handle(req, res, parsedUrl)
}).listen(availablePort, () => {
resolveServer()
})
} else {
createServerHTTP(async (req, res) => {
const parsedUrl = parse(req.url || '', true)
await handle(req, res, parsedUrl)
}).listen(availablePort, () => {
resolveServer()
})
}
})
await serverPromise
process.env.PAYLOAD_DROP_DATABASE = process.env.PAYLOAD_DROP_DATABASE === 'false' ? 'false' : 'true'
// fetch the admin url to force a render
void fetch(`http://localhost:${availablePort}${adminRoute}`)
void fetch(`http://localhost:${availablePort}/api/access`)
void fetch(`${protocol}://localhost:${availablePort}${adminRoute}`)
void fetch(`${protocol}://localhost:${availablePort}/api/access`)
// This ensures that the next-server process is killed when this process is killed and doesn't linger around.
process.on('SIGINT', () => {
if (child) {