-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ref(nextjs): Use loader to set
RewriteFrames
helper value (#5445)
In order to work, in the nextjs SDK our server-side `RewriteFrames` integration needs to know the name of the directory into which the app is built. While that information is readily available at build time, it isn't at runtime, so we adjust the webpack config to inject a global variable with the correct value in before the the injected `Sentry.init()` call from `sentry.server.config.js` wherever we inject that `Sentry.init(). Currently, this is done by creating a temporary file with the relevant code and adding it to the relevant pages' `entry` value along with `sentry.server.config.js`. This works, but has its downsides[1], and is a fair amount of machinery just to add a single line of code. This injects the same line of code using a loader, which is really just a transformation function for the code from matching files. In this case, we're modifying `sentry.server.config.js` itself, so that by the time it's added to various pages' entry points, it already contains the relevant code. Since we don't know what the value will be ahead of time, there's a template, which the loader then populates before injecting the new code. _But how is that any less machinery?_, you might ask. _All of that, still for just one line of code?_ Honestly, it's not. But in the quest to improve parameterization of transactions names, we're going to be adding a loader in any case. Adding the `RewriteFrames` value thus provides the perfect proof of concept, precisely because it's so simple, letting us get the loader working separate from all of the other changes that work will entail. Notes: - I moved setting the default value for `distDir` from retrieval-of-the-value time to storage-of-the-value time, because using a loader necessarily stringifies everything, meaning `undefined` was turning into the string `'undefined'`, preventing the default from getting picked up. - There are a few scattered lines of unrelated changes, artifacts of the fact that I ended up unpacking a few values at the top of the new webpack function. [1] #4813
- Loading branch information
1 parent
fc7682c
commit 57c964a
Showing
7 changed files
with
154 additions
and
81 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,47 @@ | ||
import { makeBaseNPMConfig, makeNPMConfigVariants } from '../../rollup/index.js'; | ||
|
||
export default makeNPMConfigVariants( | ||
makeBaseNPMConfig({ | ||
// We need to include `instrumentServer.ts` separately because it's only conditionally required, and so rollup | ||
// doesn't automatically include it when calculating the module dependency tree. | ||
entrypoints: ['src/index.server.ts', 'src/index.client.ts', 'src/utils/instrumentServer.ts'], | ||
// prevent this nextjs code from ending up in our built package (this doesn't happen automatially because the name | ||
// doesn't match an SDK dependency) | ||
packageSpecificConfig: { external: ['next/router'] }, | ||
}), | ||
); | ||
export default [ | ||
...makeNPMConfigVariants( | ||
makeBaseNPMConfig({ | ||
// We need to include `instrumentServer.ts` separately because it's only conditionally required, and so rollup | ||
// doesn't automatically include it when calculating the module dependency tree. | ||
entrypoints: ['src/index.server.ts', 'src/index.client.ts', 'src/utils/instrumentServer.ts'], | ||
|
||
// prevent this internal nextjs code from ending up in our built package (this doesn't happen automatially because | ||
// the name doesn't match an SDK dependency) | ||
packageSpecificConfig: { external: ['next/router'] }, | ||
}), | ||
), | ||
...makeNPMConfigVariants( | ||
makeBaseNPMConfig({ | ||
entrypoints: ['src/config/prefixLoaderTemplate.ts'], | ||
|
||
packageSpecificConfig: { | ||
output: { | ||
// preserve the original file structure (i.e., so that everything is still relative to `src`) | ||
entryFileNames: 'config/[name].js', | ||
|
||
// this is going to be add-on code, so it doesn't need the trappings of a full module (and in fact actively | ||
// shouldn't have them, lest they muck with the module to which we're adding it) | ||
sourcemap: false, | ||
esModule: false, | ||
}, | ||
}, | ||
}), | ||
), | ||
...makeNPMConfigVariants( | ||
makeBaseNPMConfig({ | ||
entrypoints: ['src/config/prefixLoader.ts'], | ||
|
||
packageSpecificConfig: { | ||
output: { | ||
// make it so Rollup calms down about the fact that we're doing `export { loader as default }` | ||
exports: 'default', | ||
|
||
// preserve the original file structure (i.e., so that everything is still relative to `src`) | ||
entryFileNames: 'config/[name].js', | ||
}, | ||
}, | ||
}), | ||
), | ||
]; |
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,34 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
|
||
type LoaderOptions = { | ||
distDir: string; | ||
}; | ||
// TODO Use real webpack types | ||
type LoaderThis = { | ||
// Webpack 4 | ||
query?: LoaderOptions; | ||
// Webpack 5 | ||
getOptions?: () => LoaderOptions; | ||
addDependency: (filepath: string) => void; | ||
}; | ||
|
||
/** | ||
* Inject templated code into the beginning of a module. | ||
*/ | ||
function prefixLoader(this: LoaderThis, userCode: string): string { | ||
// We know one or the other will be defined, depending on the version of webpack being used | ||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | ||
const { distDir } = this.getOptions ? this.getOptions() : this.query!; | ||
|
||
const templatePath = path.resolve(__dirname, 'prefixLoaderTemplate.js'); | ||
this.addDependency(templatePath); | ||
|
||
// Fill in the placeholder | ||
let templateCode = fs.readFileSync(templatePath).toString(); | ||
templateCode = templateCode.replace('__DIST_DIR__', distDir); | ||
|
||
return `${templateCode}\n${userCode}`; | ||
} | ||
|
||
export { prefixLoader as default }; |
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,5 @@ | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any | ||
(global as any).__rewriteFramesDistDir__ = '__DIST_DIR__'; | ||
|
||
// We need this to make this file an ESM module, which TS requires when using `isolatedModules`. | ||
export {}; |
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
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