@posthog/nextjs-config
Version:
NextJS configuration helper for Posthog 🦔
86 lines (85 loc) • 4.53 kB
JavaScript
import { PosthogWebpackPlugin, resolveConfig } from "@posthog/webpack-plugin";
import { hasCompilerHook, isTurbopackEnabled, processSourceMaps } from "./utils.mjs";
import { stripDanglingSourceMapComments } from "./strip-sourcemap-comments.mjs";
const INVOCATION_TIMEOUT_MS = 5000;
function withPostHogConfig(userNextConfig, posthogConfig) {
const resolvedConfig = resolveConfig(posthogConfig);
const sourceMapEnabled = resolvedConfig.sourcemaps.enabled;
const isCompilerHookSupported = hasCompilerHook();
const turbopackEnabled = isTurbopackEnabled();
if (turbopackEnabled && !isCompilerHookSupported) console.warn('[@posthog/nextjs-config] Turbopack support is only available with next version >= 15.4.1');
let invoked = false;
const nextConfigFn = async (phase, param)=>{
let { defaultConfig } = param;
invoked = true;
const { webpack: userWebPackConfig, compiler: userCompilerConfig, distDir, ...userConfig } = await resolveUserConfig(userNextConfig, phase, defaultConfig);
const nextConfig = {
...userConfig,
distDir,
webpack: withWebpackConfig(userWebPackConfig, resolvedConfig),
compiler: withCompilerConfig(userCompilerConfig, resolvedConfig)
};
if (turbopackEnabled && sourceMapEnabled) nextConfig.productionBrowserSourceMaps = true;
return nextConfig;
};
if ('function' == typeof setTimeout) {
var _timer_unref;
const timer = setTimeout(()=>{
if (!invoked) console.warn("[@posthog/nextjs-config] withPostHogConfig was loaded but Next.js never invoked the config function it returns. This usually means another config wrapper (e.g. withNextIntl, withSentryConfig) is wrapping withPostHogConfig and producing a plain object that drops the PostHog hooks. Move withPostHogConfig(...) to be the OUTERMOST wrapper in next.config.js so source maps upload and other build hooks run. See https://github.com/PostHog/posthog-js/issues/3572");
}, INVOCATION_TIMEOUT_MS);
null == (_timer_unref = timer.unref) || _timer_unref.call(timer);
}
return nextConfigFn;
}
function resolveUserConfig(userNextConfig, phase, defaultConfig) {
if ('function' == typeof userNextConfig) {
const maybePromise = userNextConfig(phase, {
defaultConfig
});
if (maybePromise instanceof Promise) return maybePromise;
return Promise.resolve(maybePromise);
}
if ('object' == typeof userNextConfig) return Promise.resolve(userNextConfig);
throw new Error('Invalid user config');
}
function withWebpackConfig(userWebpackConfig, posthogConfig) {
const defaultWebpackConfig = userWebpackConfig || ((config)=>config);
const sourceMapEnabled = posthogConfig.sourcemaps.enabled;
const turbopackEnabled = isTurbopackEnabled();
return (config, options)=>{
const webpackConfig = defaultWebpackConfig(config, options);
const isServer = options.isServer;
if (sourceMapEnabled) {
if (!turbopackEnabled) {
webpackConfig.plugins = webpackConfig.plugins || [];
let currentConfig = posthogConfig;
if (isServer) currentConfig = {
...posthogConfig,
sourcemaps: {
...posthogConfig.sourcemaps,
deleteAfterUpload: false
}
};
webpackConfig.plugins.push(new PosthogWebpackPlugin(currentConfig, true));
}
}
return webpackConfig;
};
}
function withCompilerConfig(userCompilerConfig, posthogConfig) {
const sourceMapEnabled = posthogConfig.sourcemaps.enabled;
const turbopackEnabled = isTurbopackEnabled();
if (sourceMapEnabled && turbopackEnabled && hasCompilerHook()) {
const newConfig = userCompilerConfig || {};
const userCompilerHook = null == userCompilerConfig ? void 0 : userCompilerConfig.runAfterProductionCompile;
newConfig.runAfterProductionCompile = async (config)=>{
await (null == userCompilerHook ? void 0 : userCompilerHook(config));
console.debug('Processing source maps from compilation hook...');
await processSourceMaps(posthogConfig, config.distDir);
if (posthogConfig.sourcemaps.deleteAfterUpload) await stripDanglingSourceMapComments(config.distDir);
};
return newConfig;
}
return userCompilerConfig;
}
export { withPostHogConfig };