mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-18 02:21:13 +00:00
feat: Reduce initial memory spike at server startup (no-changelog) (#4735)
* feat: Reduce initial memory spike at server startup (no-changelog) This changes the frontend types generation to generate less garbage for the GC to collect. * switch to stream pipelines for writing all the static files and, move all static file generation before the server starts
This commit is contained in:
committed by
GitHub
parent
540f6e0abd
commit
aac207a947
@@ -6,10 +6,17 @@
|
||||
/* eslint-disable no-console */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
import path from 'path';
|
||||
import { mkdir } from 'fs/promises';
|
||||
import { createReadStream, createWriteStream, existsSync } from 'fs';
|
||||
import localtunnel from 'localtunnel';
|
||||
import { BinaryDataManager, TUNNEL_SUBDOMAIN_ENV, UserSettings } from 'n8n-core';
|
||||
import { Command, flags } from '@oclif/command';
|
||||
import Redis from 'ioredis';
|
||||
import stream from 'stream';
|
||||
import replaceStream from 'replacestream';
|
||||
import { promisify } from 'util';
|
||||
import glob from 'fast-glob';
|
||||
|
||||
import { IDataObject, LoggerProxy, sleep } from 'n8n-workflow';
|
||||
import { createHash } from 'crypto';
|
||||
@@ -34,9 +41,12 @@ import { getLogger } from '@/Logger';
|
||||
import { getAllInstalledPackages } from '@/CommunityNodes/packageModel';
|
||||
import { initErrorHandling } from '@/ErrorReporting';
|
||||
import * as CrashJournal from '@/CrashJournal';
|
||||
import { createPostHogLoadingScript } from '@/telemetry/scripts';
|
||||
import { EDITOR_UI_DIST_DIR, GENERATED_STATIC_DIR } from '@/constants';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires
|
||||
const open = require('open');
|
||||
const pipeline = promisify(stream.pipeline);
|
||||
|
||||
let activeWorkflowRunner: ActiveWorkflowRunner.ActiveWorkflowRunner | undefined;
|
||||
let processExitCode = 0;
|
||||
@@ -152,6 +162,60 @@ export class Start extends Command {
|
||||
exit();
|
||||
}
|
||||
|
||||
static async generateStaticAssets() {
|
||||
// Read the index file and replace the path placeholder
|
||||
const n8nPath = config.getEnv('path');
|
||||
const hooksUrls = config.getEnv('externalFrontendHooksUrls');
|
||||
|
||||
let scriptsString = '';
|
||||
if (hooksUrls) {
|
||||
scriptsString = hooksUrls.split(';').reduce((acc, curr) => {
|
||||
return `${acc}<script src="${curr}"></script>`;
|
||||
}, '');
|
||||
}
|
||||
|
||||
if (config.getEnv('diagnostics.enabled')) {
|
||||
const phLoadingScript = createPostHogLoadingScript({
|
||||
apiKey: config.getEnv('diagnostics.config.posthog.apiKey'),
|
||||
apiHost: config.getEnv('diagnostics.config.posthog.apiHost'),
|
||||
autocapture: false,
|
||||
disableSessionRecording: config.getEnv(
|
||||
'diagnostics.config.posthog.disableSessionRecording',
|
||||
),
|
||||
debug: config.getEnv('logs.level') === 'debug',
|
||||
});
|
||||
|
||||
scriptsString += phLoadingScript;
|
||||
}
|
||||
|
||||
const closingTitleTag = '</title>';
|
||||
const compileFile = async (fileName: string) => {
|
||||
const filePath = path.join(EDITOR_UI_DIST_DIR, fileName);
|
||||
if (/(index\.html)|.*\.(js|css)/.test(filePath) && existsSync(filePath)) {
|
||||
const destFile = path.join(GENERATED_STATIC_DIR, fileName);
|
||||
await mkdir(path.dirname(destFile), { recursive: true });
|
||||
const streams = [
|
||||
createReadStream(filePath, 'utf-8'),
|
||||
replaceStream('/{{BASE_PATH}}/', n8nPath, { ignoreCase: false }),
|
||||
replaceStream('/static/', n8nPath + 'static/', { ignoreCase: false }),
|
||||
];
|
||||
if (filePath.endsWith('index.html')) {
|
||||
streams.push(
|
||||
replaceStream(closingTitleTag, closingTitleTag + scriptsString, {
|
||||
ignoreCase: false,
|
||||
}),
|
||||
);
|
||||
}
|
||||
streams.push(createWriteStream(destFile, 'utf-8'));
|
||||
return pipeline(streams);
|
||||
}
|
||||
};
|
||||
|
||||
await compileFile('index.html');
|
||||
const files = await glob('**/*.{css,js}', { cwd: EDITOR_UI_DIST_DIR });
|
||||
await Promise.all(files.map(compileFile));
|
||||
}
|
||||
|
||||
async run() {
|
||||
// Make sure that n8n shuts down gracefully if possible
|
||||
process.once('SIGTERM', Start.stopProcess);
|
||||
@@ -200,6 +264,10 @@ export class Start extends Command {
|
||||
);
|
||||
}
|
||||
|
||||
if (!config.getEnv('endpoints.disableUi')) {
|
||||
await Start.generateStaticAssets();
|
||||
}
|
||||
|
||||
// Load all node and credential types
|
||||
const loadNodesAndCredentials = LoadNodesAndCredentials();
|
||||
await loadNodesAndCredentials.init();
|
||||
|
||||
Reference in New Issue
Block a user