Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ref(nextjs): Extract
isBuild
into an exported function (#5444)
In nextjs hooks which run both during build- and runtime (like `getStaticProps`, which mostly is a build-time function, but will run at runtime[1] if revalidation is turned on) it's sometimes helpful to know which you're in, and there's no official way to do that that I've been able to find. In our case, we need to know which phase we're in because by the time pages get loaded in order to be rendered during build, they already have a `Sentry.init()` call baked in, causing the SDK to run. Since certain operations can only happen at runtime, we have logic in `index.server.ts` to detect the current phase. This pulls that logic into a utility function, so that it can be exported. (Ultimately this is a selfish change, as I'd like to be able to use `isBuild` in my test apps, but I figure it's a harmless addition which might help other developers, too.) [1] https://nextjs.org/docs/basic-features/data-fetching/get-static-props#when-does-getstaticprops-run
- Loading branch information
1 parent
43ace49
commit db9ab7c
Showing
3 changed files
with
76 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* Decide if the currently running process is part of the build phase or happening at runtime. | ||
*/ | ||
export function isBuild(): boolean { | ||
// During build, the main process is invoked by | ||
// `node next build` | ||
// and child processes are invoked as | ||
// `node <path>/node_modules/.../jest-worker/processChild.js`. | ||
// The former is (obviously) easy to recognize, but the latter could happen at runtime as well. Fortunately, the main | ||
// process hits this file before any of the child processes do, so we're able to set an env variable which the child | ||
// processes can then check. During runtime, the main process is invoked as | ||
// `node next start` | ||
// or | ||
// `node /var/runtime/index.js`, | ||
// so we never drop into the `if` in the first place. | ||
if (process.argv.includes('build') || process.env.SENTRY_BUILD_PHASE) { | ||
process.env.SENTRY_BUILD_PHASE = 'true'; | ||
return true; | ||
} | ||
|
||
return false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { isBuild } from '../../src/utils/isBuild'; | ||
|
||
let originalEnv: typeof process.env; | ||
let originalArgv: typeof process.argv; | ||
|
||
function assertNoMagicValues(): void { | ||
if (Object.keys(process.env).includes('SENTRY_BUILD_PHASE') || process.argv.includes('build')) { | ||
throw new Error('Not starting test with a clean setup'); | ||
} | ||
} | ||
|
||
describe('isBuild()', () => { | ||
beforeEach(() => { | ||
assertNoMagicValues(); | ||
originalEnv = { ...process.env }; | ||
originalArgv = [...process.argv]; | ||
}); | ||
|
||
afterEach(() => { | ||
process.env = originalEnv; | ||
process.argv = originalArgv; | ||
assertNoMagicValues(); | ||
}); | ||
|
||
it("detects 'build' in argv", () => { | ||
// the result of calling `next build` | ||
process.argv = ['/abs/path/to/node', '/abs/path/to/nextjs/excecutable', 'build']; | ||
expect(isBuild()).toBe(true); | ||
}); | ||
|
||
it("sets env var when 'build' in argv", () => { | ||
// the result of calling `next build` | ||
process.argv = ['/abs/path/to/node', '/abs/path/to/nextjs/excecutable', 'build']; | ||
isBuild(); | ||
expect(Object.keys(process.env).includes('SENTRY_BUILD_PHASE')).toBe(true); | ||
}); | ||
|
||
it("does not set env var when 'build' not in argv", () => { | ||
isBuild(); | ||
expect(Object.keys(process.env).includes('SENTRY_BUILD_PHASE')).toBe(false); | ||
}); | ||
|
||
it('detects env var', () => { | ||
process.env.SENTRY_BUILD_PHASE = 'true'; | ||
expect(isBuild()).toBe(true); | ||
}); | ||
|
||
it("returns false when 'build' not in `argv` and env var not present", () => { | ||
expect(isBuild()).toBe(false); | ||
}); | ||
}); |