Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions .changeset/solid-pigs-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@hyperdx/app': patch
---

Transition the local development server from Webpack to Turbopack to
significantly improve build performance and hot-reloading speed.
52 changes: 25 additions & 27 deletions packages/app/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,50 +31,48 @@ const nextConfig = {
},
// External packages to prevent bundling issues (moved from experimental in Next.js 15+)
// https://github.com/open-telemetry/opentelemetry-js/issues/4297#issuecomment-2285070503
//
// `serverExternalPackages` is bundler-agnostic: it applies to both Webpack
// (production `build`) and Turbopack (local `dev`), so the server-bundle
// externalization below stays consistent across both bundlers.
serverExternalPackages: [
'@opentelemetry/instrumentation',
'@opentelemetry/sdk-node',
'@opentelemetry/auto-instrumentations-node',
'@hyperdx/node-opentelemetry',
'@hyperdx/instrumentation-sentry-node',
// Outside of Vercel preview deployments, the `/api/[...all]` catch-all
// proxies to a separately-deployed API service and never imports the
// `@hyperdx/api` package at runtime. Keep it (and its subpaths) external
// so server bundles do not pull in passport-saml, mongoose, AWS SDK, etc.
// This must stay external under both Webpack and Turbopack; otherwise the
// Turbopack dev server would attempt to bundle the entire `@hyperdx/api`
// dependency tree (slow startup / module-resolution errors).
...(process.env.HDX_PREVIEW_INLINE_API !== 'true' ? ['@hyperdx/api'] : []),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

When I run this branch locally, I get this error. It's still trying to compile the require('@hyperdx/api/build/serverless'); path for me locally I believe.

Are you getting that?

],
typescript: {
tsconfigPath: 'tsconfig.build.json',
},
// NOTE: Using Webpack instead of Turbopack (Next.js 16 default)
// Reason: Turbopack has CSS module parsing issues with nested :global syntax
// used in styles/SearchPage.module.scss and other SCSS files.
// The --webpack flag is added to dev and build scripts in package.json.
// TODO: Re-evaluate when Turbopack CSS module support improves
// Ignore otel pkgs warnings
// NOTE: `dev`/`dev:local` run on Turbopack (Next.js 16 default) while
// `build`/`build:clickhouse` run on Webpack (the `--webpack` flag in
// package.json). The split exists because Turbopack historically had CSS
// module parsing issues with nested :global syntax used in
// styles/SearchPage.module.scss and other SCSS files; dev tolerates this
// while production builds stay on the known-good Webpack path. Because the
// two bundlers can diverge (CSS modules, loaders, module resolution), prefer
// bundler-agnostic config (e.g. `serverExternalPackages` above) over the
// Webpack-only `webpack` callback below, which Turbopack silently ignores.
// TODO: Collapse onto a single bundler once Turbopack CSS module support and
// build parity are confirmed.
//
// Ignore otel pkgs warnings (Webpack-only; harmless to skip under Turbopack)
// https://github.com/open-telemetry/opentelemetry-js/issues/4173#issuecomment-1822938936
webpack: (
config,
{ buildId, dev, isServer, defaultLoaders, nextRuntime, webpack },
) => {
if (isServer) {
config.ignoreWarnings = [{ module: /opentelemetry/ }];

// Outside of Vercel preview deployments, the `/api/[...all]` catch-all
// proxies to a separately-deployed API service and never imports the
// `@hyperdx/api` package at runtime. Mark it (and its subpaths) as a
// CommonJS external so production app builds (Docker fullstack image,
// standalone Next output) stay byte-for-byte equivalent to today and
// do not pull in passport-saml, mongoose, AWS SDK, etc.
if (process.env.HDX_PREVIEW_INLINE_API !== 'true') {
config.externals = [
...(config.externals ?? []),
({ request }, callback) => {
if (
request === '@hyperdx/api' ||
request?.startsWith?.('@hyperdx/api/')
) {
return callback(null, `commonjs ${request}`);
}
return callback();
},
];
}
}
return config;
},
Expand Down
5 changes: 3 additions & 2 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
"engines": {
"node": ">=22.16.0"
},
"//bundler": "dev/dev:local run on Turbopack for fast local iteration; build/build:clickhouse run on Webpack (--webpack) for production parity. The two bundlers can diverge on CSS Modules/loaders/module resolution, so build failures may not reproduce in dev. See next.config.mjs for rationale.",
"scripts": {
"dev": "npx dotenv -e .env.development -- next dev --webpack",
"dev:local": "NEXT_PUBLIC_IS_LOCAL_MODE=true npx dotenv -e .env.development -- next dev --webpack",
"dev": "npx dotenv -e .env.development -- next dev --turbopack",
"dev:local": "NEXT_PUBLIC_IS_LOCAL_MODE=true npx dotenv -e .env.development -- next dev --turbopack",
"build": "next build --webpack",
"build:clickhouse": "NEXT_PUBLIC_THEME=clickstack NEXT_PUBLIC_IS_LOCAL_MODE=true NEXT_PUBLIC_CLICKHOUSE_BUILD=true next build --webpack && node scripts/prepare-clickhouse-build-export.js",
"run:clickhouse": "test -d out && npx rimraf tmp && mkdir tmp && cp -r out tmp/clickstack && echo 'visit http://localhost:3000/clickstack to start' && npx serve tmp -l 3000 || echo 'run build:clickhouse first'",
Expand Down
36 changes: 17 additions & 19 deletions packages/app/styles/SearchPage.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,26 @@
overflow: hidden;
z-index: 3; // higher z-index to be above other elements

:global {
.mantine-TextInput-wrapper {
background-color: transparent;
}
:global(.mantine-TextInput-wrapper) {
background-color: transparent;
}

.mantine-TextInput-input {
height: 20px;
min-height: 20px;
background-color: transparent;
color: var(--color-text-secondary);
font-size: var(--mantine-font-size-xs);
:global(.mantine-TextInput-input) {
height: 20px;
min-height: 20px;
background-color: transparent;
color: var(--color-text-secondary);
font-size: var(--mantine-font-size-xs);
}

&::placeholder {
color: var(--color-text-muted);
font-weight: bold;
}
:global(.mantine-TextInput-input::placeholder) {
color: var(--color-text-muted);
font-weight: bold;
}

&:focus {
border: none;
outline: none;
}
}
:global(.mantine-TextInput-input:focus) {
border: none;
outline: none;
}
}

Expand Down
Loading