mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-26 13:19:34 +07:00
refactor: Extract renderer URL and protocol management into dedicated manager (#11208)
* feat: Add static export modifier for Electron, refactor route variant constants, and simplify renderer file path resolution. * refactor: Extract renderer URL and protocol management into a dedicated `RendererUrlManager` and update `App` to utilize it. Signed-off-by: Innei <tukon479@gmail.com> * feat: Implement Electron app locale management and i18n initialization based on stored settings. Signed-off-by: Innei <tukon479@gmail.com> --------- Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
@@ -5,12 +5,14 @@ import { modifyAppCode } from './appCode.mjs';
|
||||
import { cleanUpCode } from './cleanUp.mjs';
|
||||
import { modifyNextConfig } from './nextConfig.mjs';
|
||||
import { modifyRoutes } from './routes.mjs';
|
||||
import { modifyStaticExport } from './staticExport.mjs';
|
||||
import { isDirectRun, runStandalone } from './utils.mjs';
|
||||
|
||||
export const modifySourceForElectron = async (TEMP_DIR: string) => {
|
||||
await modifyNextConfig(TEMP_DIR);
|
||||
await modifyAppCode(TEMP_DIR);
|
||||
await modifyRoutes(TEMP_DIR);
|
||||
await modifyStaticExport(TEMP_DIR);
|
||||
await cleanUpCode(TEMP_DIR);
|
||||
};
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ export const modifyNextConfig = async (TEMP_DIR: string) => {
|
||||
|
||||
console.log(` Processing ${path.relative(TEMP_DIR, nextConfigPath)}...`);
|
||||
await updateFile({
|
||||
assertAfter: (code) => /output\s*:\s*["']export["']/.test(code) && !/withPWA\s*\(/.test(code),
|
||||
filePath: nextConfigPath,
|
||||
name: 'modifyNextConfig',
|
||||
transformer: (code) => {
|
||||
@@ -147,7 +148,6 @@ export const modifyNextConfig = async (TEMP_DIR: string) => {
|
||||
|
||||
return newCode;
|
||||
},
|
||||
assertAfter: (code) => /output\s*:\s*['"]export['"]/.test(code) && !/withPWA\s*\(/.test(code),
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
174
scripts/electronWorkflow/modifiers/staticExport.mts
Normal file
174
scripts/electronWorkflow/modifiers/staticExport.mts
Normal file
@@ -0,0 +1,174 @@
|
||||
import { Lang, parse } from '@ast-grep/napi';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'node:path';
|
||||
|
||||
import { isDirectRun, runStandalone, updateFile } from './utils.mjs';
|
||||
|
||||
/**
|
||||
* Remove the URL rewrite logic from the proxy middleware.
|
||||
* For Electron static export, we don't need URL rewriting since pages are pre-rendered.
|
||||
*/
|
||||
const removeUrlRewriteLogic = (code: string): string => {
|
||||
const ast = parse(Lang.TypeScript, code);
|
||||
const root = ast.root();
|
||||
const edits: Array<{ end: number; start: number; text: string }> = [];
|
||||
|
||||
// Find the defaultMiddleware arrow function
|
||||
const defaultMiddleware = root.find({
|
||||
rule: {
|
||||
pattern: 'const defaultMiddleware = ($REQ) => { $$$ }',
|
||||
},
|
||||
});
|
||||
|
||||
if (!defaultMiddleware) {
|
||||
console.warn(' ⚠️ defaultMiddleware not found, skipping URL rewrite removal');
|
||||
return code;
|
||||
}
|
||||
|
||||
// Replace the entire defaultMiddleware function with a simplified version
|
||||
// that just returns NextResponse.next() for non-API routes
|
||||
const range = defaultMiddleware.range();
|
||||
|
||||
const simplifiedMiddleware = `const defaultMiddleware = (request: NextRequest) => {
|
||||
const url = new URL(request.url);
|
||||
logDefault('Processing request: %s %s', request.method, request.url);
|
||||
|
||||
// skip all api requests
|
||||
if (backendApiEndpoints.some((path) => url.pathname.startsWith(path))) {
|
||||
logDefault('Skipping API request: %s', url.pathname);
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
return NextResponse.next();
|
||||
}`;
|
||||
|
||||
edits.push({ end: range.end.index, start: range.start.index, text: simplifiedMiddleware });
|
||||
|
||||
// Apply edits
|
||||
if (edits.length === 0) return code;
|
||||
|
||||
edits.sort((a, b) => b.start - a.start);
|
||||
let result = code;
|
||||
for (const edit of edits) {
|
||||
result = result.slice(0, edit.start) + edit.text + result.slice(edit.end);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
const assertUrlRewriteRemoved = (code: string): boolean =>
|
||||
// Ensure the URL rewrite related code is removed
|
||||
!/NextResponse\.rewrite\(/.test(code) &&
|
||||
!/RouteVariants\.serializeVariants/.test(code) &&
|
||||
!/url\.pathname = nextPathname/.test(code);
|
||||
|
||||
/**
|
||||
* Rename [variants] directories to (variants) under src/app
|
||||
*/
|
||||
const renameVariantsDirectories = async (TEMP_DIR: string): Promise<void> => {
|
||||
const srcAppPath = path.join(TEMP_DIR, 'src', 'app');
|
||||
|
||||
// Recursively find and rename [variants] directories
|
||||
const renameRecursively = async (dir: string): Promise<void> => {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
const oldPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.name === '[variants]') {
|
||||
const newPath = path.join(dir, '(variants)');
|
||||
|
||||
// If (variants) already exists, remove it first
|
||||
if (await fs.pathExists(newPath)) {
|
||||
console.log(` Removing existing: ${path.relative(TEMP_DIR, newPath)}`);
|
||||
await fs.remove(newPath);
|
||||
}
|
||||
|
||||
console.log(
|
||||
` Renaming: ${path.relative(TEMP_DIR, oldPath)} -> ${path.relative(TEMP_DIR, newPath)}`,
|
||||
);
|
||||
await fs.rename(oldPath, newPath);
|
||||
// Continue searching in the renamed directory
|
||||
await renameRecursively(newPath);
|
||||
} else {
|
||||
// Continue searching in subdirectories
|
||||
await renameRecursively(oldPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await renameRecursively(srcAppPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Update all imports that reference [variants] to use (variants)
|
||||
*/
|
||||
const updateVariantsImports = async (TEMP_DIR: string): Promise<void> => {
|
||||
const srcPath = path.join(TEMP_DIR, 'src');
|
||||
|
||||
// Pattern to match imports containing [variants]
|
||||
const variantsImportPattern = /(\[variants])/g;
|
||||
|
||||
const processFile = async (filePath: string): Promise<void> => {
|
||||
const content = await fs.readFile(filePath, 'utf8');
|
||||
|
||||
if (!content.includes('[variants]')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updated = content.replaceAll('[variants]', '(variants)');
|
||||
|
||||
if (updated !== content) {
|
||||
console.log(` Updated imports: ${path.relative(TEMP_DIR, filePath)}`);
|
||||
await fs.writeFile(filePath, updated);
|
||||
}
|
||||
};
|
||||
|
||||
const processDirectory = async (dir: string): Promise<void> => {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// Skip node_modules and other non-source directories
|
||||
if (entry.name === 'node_modules' || entry.name === '.git') {
|
||||
continue;
|
||||
}
|
||||
await processDirectory(fullPath);
|
||||
} else if (entry.isFile() && /\.(ts|tsx|js|jsx|mts|mjs)$/.test(entry.name)) {
|
||||
await processFile(fullPath);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
await processDirectory(srcPath);
|
||||
};
|
||||
|
||||
export const modifyStaticExport = async (TEMP_DIR: string): Promise<void> => {
|
||||
// 1. Remove URL rewrite logic from define-config.ts
|
||||
const defineConfigPath = path.join(TEMP_DIR, 'src', 'libs', 'next', 'proxy', 'define-config.ts');
|
||||
console.log(' Processing src/libs/next/proxy/define-config.ts...');
|
||||
await updateFile({
|
||||
assertAfter: assertUrlRewriteRemoved,
|
||||
filePath: defineConfigPath,
|
||||
name: 'modifyStaticExport:removeUrlRewrite',
|
||||
transformer: removeUrlRewriteLogic,
|
||||
});
|
||||
|
||||
// 2. Rename [variants] directories to (variants)
|
||||
console.log(' Renaming [variants] directories to (variants)...');
|
||||
await renameVariantsDirectories(TEMP_DIR);
|
||||
|
||||
// 3. Update all imports referencing [variants]
|
||||
console.log(' Updating imports referencing [variants]...');
|
||||
await updateVariantsImports(TEMP_DIR);
|
||||
};
|
||||
|
||||
if (isDirectRun(import.meta.url)) {
|
||||
await runStandalone('modifyStaticExport', modifyStaticExport, [
|
||||
{ lang: Lang.TypeScript, path: 'src/libs/next/proxy/define-config.ts' },
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user