feat: switch to server in dev & prod
This commit is contained in:
parent
6cf343d623
commit
1c2c374ada
@ -5,7 +5,8 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "remix vite:build && vite build",
|
||||
"dev": "remix vite:dev",
|
||||
"dev": "node server/dev.mjs",
|
||||
"start": "node build/headplane/server.js",
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -43,6 +44,7 @@
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-typescript": "^7.26.0",
|
||||
"@remix-run/dev": "^2.15.0",
|
||||
"@remix-run/route-config": "^2.15.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
|
||||
@ -110,6 +110,9 @@ importers:
|
||||
specifier: ^3.23.8
|
||||
version: 3.23.8
|
||||
devDependencies:
|
||||
'@babel/preset-typescript':
|
||||
specifier: ^7.26.0
|
||||
version: 7.26.0(@babel/core@7.26.0)
|
||||
'@remix-run/dev':
|
||||
specifier: ^2.15.0
|
||||
version: 2.15.0(@remix-run/react@2.15.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(typescript@5.7.2))(@types/node@22.10.1)(typescript@5.7.2)(vite@6.0.3(@types/node@22.10.1)(jiti@1.21.6)(yaml@2.6.1))
|
||||
|
||||
33
server/dev.mjs
Normal file
33
server/dev.mjs
Normal file
@ -0,0 +1,33 @@
|
||||
// This is a polyglot entrypoint for Headplane when running in development
|
||||
// It does some silly magic to load the vite config, set some globals that
|
||||
// are required to function, and create the vite development server.
|
||||
import { createServer } from 'vite'
|
||||
import { env, exit } from 'node:process'
|
||||
import { log } from './utils.mjs'
|
||||
|
||||
log('DEVX', 'INFO', 'This script is only intended for development')
|
||||
env.NODE_ENV = 'development'
|
||||
|
||||
// The production entrypoint uses a global called "PREFIX" to determine
|
||||
// what route the application is being served at and a global called "BUILD"
|
||||
// to determine the Remix handler. We need to set these globals here so that
|
||||
// the development server can function correctly and override the production
|
||||
// values.
|
||||
|
||||
log('DEVX', 'INFO', 'Creating Vite Development Server')
|
||||
const server = await createServer({
|
||||
server: {
|
||||
middlewareMode: true
|
||||
}
|
||||
})
|
||||
|
||||
// This entrypoint is defined in the documentation to load the server
|
||||
const build = await server.ssrLoadModule('virtual:remix/server-build')
|
||||
|
||||
// We already handle this logic in the Vite configuration
|
||||
global.PREFIX = server.config.base.slice(0, -1)
|
||||
global.BUILD = build
|
||||
global.MODE = 'development'
|
||||
global.MIDDLEWARE = server.middlewares
|
||||
|
||||
await import('./prod.mjs')
|
||||
56
server.mjs → server/prod.mjs
Executable file → Normal file
56
server.mjs → server/prod.mjs
Executable file → Normal file
@ -9,30 +9,16 @@ import { createReadStream, existsSync, statSync } from 'node:fs'
|
||||
import { createServer } from 'node:http'
|
||||
import { join, resolve } from 'node:path'
|
||||
import { env } from 'node:process'
|
||||
import { log } from './utils.mjs'
|
||||
|
||||
function log(level, message) {
|
||||
const date = new Date().toISOString()
|
||||
console.log(`${date} (${level}) [SRVX] ${message}`)
|
||||
}
|
||||
|
||||
log('INFO', `Running with Node.js ${process.versions.node}`)
|
||||
log('SRVX', 'INFO', `Running with Node.js ${process.versions.node}`)
|
||||
|
||||
try {
|
||||
await access('./node_modules/@remix-run', constants.F_OK | constants.R_OK)
|
||||
log('INFO', 'Found node_modules dependencies')
|
||||
log('SRVX', 'INFO', 'Found node_modules dependencies')
|
||||
} catch (error) {
|
||||
log('ERROR', 'No node_modules found. Please run `pnpm install` first')
|
||||
log('ERROR', error)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
try {
|
||||
await access('./build/server', constants.F_OK | constants.R_OK)
|
||||
log('INFO', 'Found build directory')
|
||||
} catch (error) {
|
||||
const date = new Date().toISOString()
|
||||
log('ERROR', 'No build directory found. Please run `pnpm build` first')
|
||||
log('ERROR', error)
|
||||
log('SRVX', 'ERROR', 'No node_modules found. Please run `pnpm install`')
|
||||
log('SRVX', 'ERROR', error)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@ -46,16 +32,36 @@ const { default: mime } = await import('mime')
|
||||
const port = env.PORT || 3000
|
||||
const host = env.HOST || '0.0.0.0'
|
||||
const buildPath = env.BUILD_PATH || './build'
|
||||
|
||||
// Because this is a dynamic import without an easily discernable path
|
||||
// we gain the "deoptimization" we want so that Vite doesn't bundle this
|
||||
const build = await import(resolve(join(buildPath, 'server', 'index.js')))
|
||||
const baseDir = resolve(join(buildPath, 'client'))
|
||||
|
||||
const handler = remixRequestHandler(build, 'production')
|
||||
if (!global.BUILD) {
|
||||
try {
|
||||
await access(join(buildPath, 'server'), constants.F_OK | constants.R_OK)
|
||||
log('SRVX', 'INFO', 'Found build directory')
|
||||
} catch (error) {
|
||||
const date = new Date().toISOString()
|
||||
log('SRVX', 'ERROR', 'No build found. Please run `pnpm build`')
|
||||
log('SRVX', 'ERROR', error)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Because this is a dynamic import without an easily discernable path
|
||||
// we gain the "deoptimization" we want so that Vite doesn't bundle this
|
||||
const build = await import(resolve(join(buildPath, 'server', 'index.js')))
|
||||
global.BUILD = build
|
||||
global.MODE = 'production'
|
||||
}
|
||||
|
||||
const handler = remixRequestHandler(global.BUILD, global.MODE)
|
||||
const http = createServer(async (req, res) => {
|
||||
const url = new URL(`http://${req.headers.host}${req.url}`)
|
||||
|
||||
if (global.MIDDLEWARE) {
|
||||
await new Promise(resolve => {
|
||||
global.MIDDLEWARE(req, res, resolve)
|
||||
})
|
||||
}
|
||||
|
||||
if (!url.pathname.startsWith(PREFIX)) {
|
||||
res.writeHead(404)
|
||||
res.end()
|
||||
@ -155,5 +161,5 @@ const http = createServer(async (req, res) => {
|
||||
})
|
||||
|
||||
http.listen(port, host, () => {
|
||||
log('INFO', `Running on ${host}:${port}`)
|
||||
log('SRVX', 'INFO', `Running on ${host}:${port}`)
|
||||
})
|
||||
4
server/utils.mjs
Normal file
4
server/utils.mjs
Normal file
@ -0,0 +1,4 @@
|
||||
export function log(topic, level, message) {
|
||||
const date = new Date().toISOString()
|
||||
console.log(`${date} (${level}) [${topic}] ${message}`)
|
||||
}
|
||||
@ -17,15 +17,18 @@ if (!version) {
|
||||
|
||||
export default defineConfig(({ isSsrBuild }) => {
|
||||
// If we have the Headplane entry we build it as a single
|
||||
// server.mjs file that is built for production server bundle
|
||||
// server/prod.mjs file that is built for production server bundle
|
||||
// We know the remix invoked command is vite:build
|
||||
if (!process.argv.includes('vite:build') && !process.argv.includes('vite:dev')) {
|
||||
if (
|
||||
process.env.NODE_ENV !== 'development'
|
||||
&& !process.argv.includes('vite:build')
|
||||
) {
|
||||
return {
|
||||
build: {
|
||||
minify: false,
|
||||
target: 'esnext',
|
||||
rollupOptions: {
|
||||
input: './server.mjs',
|
||||
input: './server/prod.mjs',
|
||||
output: {
|
||||
entryFileNames: 'server.js',
|
||||
dir: 'build/headplane',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user