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:
co-authored by
Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
6d1fe32a39
commit
520e711ca6
@@ -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"),
|
||||
};
|
||||
+1
-1
@@ -85,7 +85,6 @@
|
||||
"HUBSPOT_CLIENT_SECRET",
|
||||
"IFFY_API_KEY",
|
||||
"INTEGRATION_TEST_MODE",
|
||||
"IS_E2E",
|
||||
"INTERCOM_SECRET",
|
||||
"INTERCOM_SECRET",
|
||||
"INSIGHTS_DATABASE_URL",
|
||||
@@ -108,6 +107,7 @@
|
||||
"NEXT_PUBLIC_FORMBRICKS_HOST_URL",
|
||||
"NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID",
|
||||
"NEXT_PUBLIC_HOSTED_CAL_FEATURES",
|
||||
"NEXT_PUBLIC_IS_E2E",
|
||||
"NEXT_PUBLIC_MINUTES_TO_BOOK",
|
||||
"NEXT_PUBLIC_ORG_SELF_SERVE_ENABLED",
|
||||
"NEXT_PUBLIC_SENDER_ID",
|
||||
|
||||
@@ -3066,6 +3066,32 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/exchange2013calendar@workspace:packages/app-store/exchange2013calendar":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@calcom/exchange2013calendar@workspace:packages/app-store/exchange2013calendar"
|
||||
dependencies:
|
||||
"@calcom/lib": "*"
|
||||
"@calcom/prisma": "*"
|
||||
"@calcom/types": "*"
|
||||
"@calcom/ui": "*"
|
||||
ews-javascript-api: ^0.11.0
|
||||
react-hook-form: ^7.43.3
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/exchange2016calendar@workspace:packages/app-store/exchange2016calendar":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@calcom/exchange2016calendar@workspace:packages/app-store/exchange2016calendar"
|
||||
dependencies:
|
||||
"@calcom/lib": "*"
|
||||
"@calcom/prisma": "*"
|
||||
"@calcom/types": "*"
|
||||
"@calcom/ui": "*"
|
||||
ews-javascript-api: ^0.11.0
|
||||
react-hook-form: ^7.43.3
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/exchangecalendar@workspace:packages/app-store/exchangecalendar":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@calcom/exchangecalendar@workspace:packages/app-store/exchangecalendar"
|
||||
|
||||
Reference in New Issue
Block a user