perf: optimize analytics app imports to avoid loading entire app store (#23372)
* perf: optimize analytics app imports to avoid loading entire app store - Add analytics service generation to app-store-cli build process - Generate analytics.services.generated.ts with only analytics apps (dub) - Update getAnalytics.ts to use AnalyticsServiceMap instead of full appStore - Add NEXT_PUBLIC_IS_E2E to turbo.json globalEnv for generated files - Reduces import footprint from 100+ apps to only analytics apps with AnalyticsService - Follows same pattern as calendar services optimization from PR #22450 Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * Reorder cli output * fix: follow getCalendar pattern in getAnalytics and maintain alphabetical order in turbo.json - Remove unnecessary object wrapping in getAnalytics.ts to match getCalendar.ts pattern - Move NEXT_PUBLIC_IS_E2E to correct alphabetical position in turbo.json globalEnv - Address PR feedback from keithwillcode Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> * chore: update yarn.lock after analytics optimization changes Co-Authored-By: keith@cal.com <keithwillcode@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
6d1fe32a39
commit
520e711ca6
5 files changed
+82
-24
No files matched your search
@@ -378,12 +378,50 @@ function generateFiles() {
|
||||
calendarOutput.push(...calendarServices);
|
||||
}
|
||||
|
||||
const analyticsOutput = [];
|
||||
const analyticsServices = getExportedObject(
|
||||
"AnalyticsServiceMap",
|
||||
{
|
||||
importConfig: {
|
||||
fileToBeImported: "lib/AnalyticsService.ts",
|
||||
importName: "default",
|
||||
},
|
||||
lazyImport: true,
|
||||
},
|
||||
(app: App) => {
|
||||
const hasAnalyticsService = fs.existsSync(
|
||||
path.join(APP_STORE_PATH, app.path, "lib/AnalyticsService.ts")
|
||||
);
|
||||
return hasAnalyticsService;
|
||||
}
|
||||
);
|
||||
|
||||
const analyticsExportLineIndex = analyticsServices.findIndex((line) =>
|
||||
line.startsWith("export const AnalyticsServiceMap")
|
||||
);
|
||||
if (analyticsExportLineIndex !== -1) {
|
||||
const exportLine = analyticsServices[analyticsExportLineIndex];
|
||||
const objectContent = analyticsServices.slice(analyticsExportLineIndex + 1, -1);
|
||||
|
||||
analyticsOutput.push(
|
||||
exportLine.replace(
|
||||
"export const AnalyticsServiceMap = {",
|
||||
"export const AnalyticsServiceMap = process.env.NEXT_PUBLIC_IS_E2E ? {} : {"
|
||||
),
|
||||
...objectContent,
|
||||
"};"
|
||||
);
|
||||
} else {
|
||||
analyticsOutput.push(...analyticsServices);
|
||||
}
|
||||
|
||||
const banner = `/**
|
||||
This file is autogenerated using the command \`yarn app-store:build --watch\`.
|
||||
Don't modify this file manually.
|
||||
**/
|
||||
`;
|
||||
const filesToGenerate: [string, string[]][] = [
|
||||
["analytics.services.generated.ts", analyticsOutput],
|
||||
["apps.metadata.generated.ts", metadataOutput],
|
||||
["apps.server.generated.ts", serverOutput],
|
||||
["apps.browser.generated.tsx", browserOutput],
|
||||
|
||||
@@ -1,25 +1,11 @@
|
||||
import logger from "@calcom/lib/logger";
|
||||
import type { AnalyticsService, AnalyticsServiceClass } from "@calcom/types/AnalyticsService";
|
||||
import type { AnalyticsService } from "@calcom/types/AnalyticsService";
|
||||
import type { CredentialPayload } from "@calcom/types/Credential";
|
||||
|
||||
import appStore from "..";
|
||||
import { AnalyticsServiceMap } from "../analytics.services.generated";
|
||||
|
||||
const log = logger.getSubLogger({ prefix: ["AnalyticsManager"] });
|
||||
|
||||
interface AnalyticsApp {
|
||||
lib: {
|
||||
AnalyticsService: AnalyticsServiceClass;
|
||||
};
|
||||
}
|
||||
|
||||
const isAnalyticsService = (x: unknown): x is AnalyticsApp =>
|
||||
!!x &&
|
||||
typeof x === "object" &&
|
||||
"lib" in x &&
|
||||
typeof x.lib === "object" &&
|
||||
!!x.lib &&
|
||||
"AnalyticsService" in x.lib;
|
||||
|
||||
export const getAnalyticsService = async ({
|
||||
credential,
|
||||
}: {
|
||||
@@ -30,22 +16,21 @@ export const getAnalyticsService = async ({
|
||||
|
||||
const analyticsName = analyticsType.split("_")[0];
|
||||
|
||||
const analyticsAppImportFn = appStore[analyticsName as keyof typeof appStore];
|
||||
const analyticsAppImportFn = AnalyticsServiceMap[analyticsName as keyof typeof AnalyticsServiceMap];
|
||||
|
||||
if (!analyticsAppImportFn) {
|
||||
log.warn(`analytics app not implemented`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const analyticsApp = await analyticsAppImportFn();
|
||||
const analyticsApp = await analyticsAppImportFn;
|
||||
|
||||
if (!isAnalyticsService(analyticsApp)) {
|
||||
log.warn(`Analytics is not implemented`);
|
||||
const AnalyticsService = analyticsApp.default;
|
||||
|
||||
if (!AnalyticsService || typeof AnalyticsService !== "function") {
|
||||
log.warn(`analytics of type ${analyticsType} is not implemented`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const AnalyticsService = analyticsApp.lib.AnalyticsService;
|
||||
log.info("Got analyticsApp", AnalyticsService);
|
||||
|
||||
return new AnalyticsService(credential);
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
This file is autogenerated using the command `yarn app-store:build --watch`.
|
||||
Don't modify this file manually.
|
||||
**/
|
||||
export const AnalyticsServiceMap = process.env.NEXT_PUBLIC_IS_E2E
|
||||
? {}
|
||||
: {
|
||||
dub: import("./dub/lib/AnalyticsService"),
|
||||
};
|
||||
Reference in new issue
Block a user