feat: bundle node_modules into the server

This commit is contained in:
Aarnav Tale 2025-03-24 16:08:34 -04:00
parent cac64a6fbe
commit b8d22beb17
6 changed files with 21 additions and 27 deletions

View File

@ -9,15 +9,8 @@ RUN pnpm install --frozen-lockfile
COPY . . COPY . .
RUN pnpm run build RUN pnpm run build
RUN pnpm prune --prod
FROM node:22-alpine FROM node:22-alpine
WORKDIR /app WORKDIR /app
COPY --from=build /app/build /app/build COPY --from=build /app/build /app/build
COPY --from=build /app/node_modules /app/node_modules CMD [ "node", "./build/server/index.js" ]
RUN echo '{"type":"module"}' > /app/package.json
EXPOSE 3000
ENV NODE_ENV=production
ENV HOST=0.0.0.0
CMD [ "node", "./build/headplane/server.js" ]

View File

@ -1,7 +1,7 @@
import { Building2, House, Key } from 'lucide-react'; import { Building2, House, Key } from 'lucide-react';
import Card from '~/components/Card'; import Card from '~/components/Card';
import Link from '~/components/Link'; import Link from '~/components/Link';
import type { HeadplaneConfig } from '~server/context/parser'; import type { HeadplaneConfig } from '~/server/config/schema';
import CreateUser from '../dialogs/create-user'; import CreateUser from '../dialogs/create-user';
interface Props { interface Props {

View File

@ -1,5 +1,4 @@
import { constants, access } from 'node:fs/promises'; import { env, versions } from 'node:process';
import { env, exit, versions } from 'node:process';
import type { UpgradeWebSocket } from 'hono/ws'; import type { UpgradeWebSocket } from 'hono/ws';
import { createHonoServer } from 'react-router-hono-server/node'; import { createHonoServer } from 'react-router-hono-server/node';
import type { WebSocket } from 'ws'; import type { WebSocket } from 'ws';
@ -20,13 +19,6 @@ declare global {
// MARK: Side-Effects // MARK: Side-Effects
// This module contains a side-effect because everything running here // This module contains a side-effect because everything running here
// exists for the lifetime of the process, making it appropriate. // exists for the lifetime of the process, making it appropriate.
try {
await access('./node_modules/react-router', constants.F_OK | constants.R_OK);
} catch {
log.error('server', 'Cannot locate `node_modules`, please install them');
exit(1);
}
log.info('server', 'Running Node.js %s', versions.node); log.info('server', 'Running Node.js %s', versions.node);
configureLogger(env[envVariables.debugLog]); configureLogger(env[envVariables.debugLog]);
const config = await loadConfig( const config = await loadConfig(
@ -73,14 +65,18 @@ declare module 'react-router' {
interface AppLoadContext extends LoadContext {} interface AppLoadContext extends LoadContext {}
} }
export default await createHonoServer({ export default createHonoServer({
useWebSocket: true, useWebSocket: true,
overrideGlobalObjects: true, overrideGlobalObjects: true,
port: config.server.port, port: config.server.port,
hostname: config.server.host, hostname: config.server.host,
getLoadContext(c, { build, mode }) { // Only log in development mode
// This is the place where we can handle reverse proxy translation defaultLogger: import.meta.env.DEV,
getLoadContext() {
// TODO: This is the place where we can handle reverse proxy translation
// This is better than doing it in the OIDC client, since we can do it
// for all requests, not just OIDC ones.
return appLoadContext; return appLoadContext;
}, },

View File

@ -29,20 +29,17 @@ stdenv.mkDerivation (finalAttrs: {
buildPhase = '' buildPhase = ''
runHook preBuild runHook preBuild
pnpm build pnpm build
pnpm prune --prod
runHook postBuild runHook postBuild
''; '';
installPhase = '' installPhase = ''
runHook preInstall runHook preInstall
mkdir -p $out/{bin,share/headplane} mkdir -p $out/{bin,share/headplane}
cp -r {build,node_modules} $out/share/headplane/ cp -r build $out/share/headplane/
sed -i "s;$PWD;../..;" $out/share/headplane/build/headplane/server.js sed -i "s;$PWD;../..;" $out/share/headplane/build/server/index.js
makeWrapper ${lib.getExe nodejs_22} $out/bin/headplane \ makeWrapper ${lib.getExe nodejs_22} $out/bin/headplane \
--chdir $out/share/headplane \ --chdir $out/share/headplane \
--set BUILD_PATH $out/share/headplane/build \ --add-flags $out/share/headplane/build/server/index.js
--set NODE_ENV production \
--add-flags $out/share/headplane/build/headplane/server.js
runHook postInstall runHook postInstall
''; '';
}) })

View File

@ -3,4 +3,8 @@ import type { Config } from '@react-router/dev/config';
export default { export default {
basename: '/admin/', basename: '/admin/',
ssr: true, ssr: true,
future: {
unstable_optimizeDeps: true,
unstable_splitRouteModules: 'enforce',
},
} satisfies Config; } satisfies Config;

View File

@ -26,6 +26,10 @@ export default defineConfig({
plugins: [tailwindcss, autoprefixer], plugins: [tailwindcss, autoprefixer],
}, },
}, },
ssr: {
target: 'node',
noExternal: true,
},
define: { define: {
__VERSION__: JSON.stringify(version), __VERSION__: JSON.stringify(version),
__PREFIX__: JSON.stringify(prefix), __PREFIX__: JSON.stringify(prefix),