mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-03-23 17:56:31 +00:00
238 lines
6.5 KiB
JavaScript
238 lines
6.5 KiB
JavaScript
// Learn more https://docs.expo.io/guides/customizing-metro
|
||
const { getDefaultConfig } = require("expo/metro-config");
|
||
const path = require("node:path");
|
||
|
||
/** @type {import('expo/metro-config').MetroConfig} */
|
||
const config = getDefaultConfig(__dirname);
|
||
|
||
// =======================================================
|
||
// STREAMYFIN METRO CONFIG - PERFORMANCE OPTIMIZED 🚀
|
||
// =======================================================
|
||
// Advanced configuration for multi-platform Jellyfin client
|
||
// Optimized for media streaming, TV support, and Bun
|
||
// =======================================================
|
||
|
||
// HERMES + ADVANCED PERFORMANCE
|
||
// ==============================
|
||
config.transformer.hermesParser = true;
|
||
|
||
// CPU optimization (your existing setting)
|
||
const os = require("node:os");
|
||
config.maxWorkers = Math.max(1, os.cpus().length - 1);
|
||
|
||
// JAVASCRIPT OPTIMIZATION (Safe & Stable)
|
||
// ========================================
|
||
config.transformer = {
|
||
...config.transformer,
|
||
hermesParser: true,
|
||
|
||
// NEW: Inline requires for 15-30% startup improvement
|
||
inlineRequires: true,
|
||
|
||
// NEW: Minification optimized for streaming apps
|
||
minifierConfig: {
|
||
// Keep function names in dev for better debugging
|
||
keep_fnames: process.env.NODE_ENV === "development",
|
||
mangle: {
|
||
keep_fnames: process.env.NODE_ENV === "development",
|
||
// Optimize for Hermes bytecode
|
||
properties: false, // Safer for dynamic property access in streaming
|
||
},
|
||
// Compress optimized for media apps
|
||
compress: {
|
||
// Remove console logs in production
|
||
drop_console: process.env.NODE_ENV === "production",
|
||
// Keep class names for error reporting
|
||
keep_classnames: true,
|
||
// Preserve function names for performance profiling
|
||
keep_fnames: process.env.NODE_ENV === "development",
|
||
},
|
||
},
|
||
};
|
||
|
||
// RESOLVER OPTIMIZATIONS ENHANCED
|
||
// ===============================
|
||
config.resolver = {
|
||
...config.resolver,
|
||
|
||
// NEW: Package exports (stable in recent Metro)
|
||
unstable_enablePackageExports: true,
|
||
|
||
// ENHANCED: Extensions optimized for Streamyfin
|
||
assetExts: [
|
||
...config.resolver.assetExts,
|
||
// Video formats (enhanced for Jellyfin)
|
||
"mkv",
|
||
"mp4",
|
||
"avi",
|
||
"mov",
|
||
"wmv",
|
||
"flv",
|
||
"webm",
|
||
"m4v",
|
||
"mpg",
|
||
"mpeg",
|
||
// Audio formats
|
||
"mp3",
|
||
"wav",
|
||
"flac",
|
||
"aac",
|
||
"m4a",
|
||
"ogg",
|
||
"wma",
|
||
"opus",
|
||
// Subtitle files (complete for media)
|
||
"srt",
|
||
"vtt",
|
||
"ass",
|
||
"ssa",
|
||
"sub",
|
||
"idx",
|
||
"sbv",
|
||
"ttml",
|
||
// Database/Cache
|
||
"db",
|
||
"sqlite",
|
||
"realm",
|
||
"json5",
|
||
// Fonts (TV optimized)
|
||
"woff2",
|
||
"woff",
|
||
"eot",
|
||
"otf",
|
||
// Images (enhanced for thumbnails)
|
||
"avif",
|
||
"heic",
|
||
"heif", // Modern formats
|
||
],
|
||
|
||
sourceExts: [
|
||
...config.resolver.sourceExts,
|
||
"mjs",
|
||
"cjs", // Modern JS support
|
||
],
|
||
|
||
// NEW: Platform prioritization for performance
|
||
platforms: ["ios", "android", "native", "web", "tv"],
|
||
};
|
||
|
||
// SERIALIZER OPTIMIZATIONS (Production)
|
||
// ====================================
|
||
if (process.env.NODE_ENV === "production") {
|
||
config.serializer = {
|
||
...config.serializer,
|
||
|
||
// NEW: Module IDs optimized for caching
|
||
createModuleIdFactory: () => {
|
||
return (path) => {
|
||
// Shorter module IDs for smaller bundles
|
||
return require("node:crypto")
|
||
.createHash("sha1")
|
||
.update(path)
|
||
.digest("hex")
|
||
.substring(0, 8);
|
||
};
|
||
},
|
||
|
||
// NEW: Bundle pre-loading for streaming apps
|
||
getModulesRunBeforeMainModule: (_entryFilePath) => [
|
||
// Pre-load critical modules for faster TTI
|
||
require.resolve("react-native/Libraries/Core/InitializeCore"),
|
||
],
|
||
|
||
// Web bundle splitting (if applicable)
|
||
...(process.env.EXPO_PLATFORM === "web" && {
|
||
// Experimental code splitting for web
|
||
experimentalSerializerHook: () => {},
|
||
}),
|
||
};
|
||
}
|
||
|
||
// TV PLATFORM ENHANCEMENTS
|
||
// ========================
|
||
if (process.env?.EXPO_TV === "1") {
|
||
const originalSourceExts = config.resolver.sourceExts;
|
||
const tvSourceExts = [
|
||
...originalSourceExts.map((ext) => `tv.${ext}`),
|
||
...originalSourceExts,
|
||
];
|
||
config.resolver.sourceExts = tvSourceExts;
|
||
|
||
// NEW: TV-specific optimizations
|
||
config.transformer = {
|
||
...config.transformer,
|
||
// Optimize transforms for TV hardware
|
||
experimentalImportSupport: false, // Reduce complexity on TV
|
||
// Use legacy transformer for better TV compatibility
|
||
allowOptionalDependencies: true,
|
||
};
|
||
|
||
console.log("📺 TV platform optimized for Streamyfin");
|
||
console.log(`📁 TV extensions: ${tvSourceExts.slice(0, 6).join(", ")}...`);
|
||
}
|
||
|
||
// DEVELOPMENT ENHANCEMENTS
|
||
// ========================
|
||
if (process.env.NODE_ENV === "development") {
|
||
// NEW: Enhanced error reporting
|
||
config.reporter = {
|
||
update: (event) => {
|
||
if (event.type === "bundle_build_failed") {
|
||
console.error(
|
||
"🔴 Streamyfin Bundle Build Failed:",
|
||
event.error.message,
|
||
);
|
||
} else if (event.type === "bundle_build_done") {
|
||
console.log(
|
||
"✅ Streamyfin Bundle Ready:",
|
||
event.bundleDetails?.bundleSize || "Unknown size",
|
||
);
|
||
}
|
||
},
|
||
};
|
||
|
||
console.log("🚀 Streamyfin Metro Config - OPTIMIZED VERSION");
|
||
console.log(`📦 Workers: ${config.maxWorkers}`);
|
||
console.log(`🎯 Hermes: ${config.transformer.hermesParser}`);
|
||
console.log(`⚡ Inline requires: ${config.transformer.inlineRequires}`);
|
||
console.log(
|
||
`📺 TV support: ${process.env.EXPO_TV === "1" ? "ENABLED" : "DISABLED"}`,
|
||
);
|
||
}
|
||
|
||
// STREAMING APP SPECIFIC OPTIMIZATIONS
|
||
// ===================================
|
||
|
||
// NEW: Cache hints for better performance
|
||
if (typeof config.cacheStores === "undefined") {
|
||
// Only add if not causing issues
|
||
try {
|
||
const MetroCache = require("metro-cache");
|
||
config.cacheStores = [
|
||
new MetroCache.FileStore({
|
||
root: path.join(os.tmpdir(), "streamyfin-metro-cache"),
|
||
}),
|
||
];
|
||
} catch (_e) {
|
||
// Fallback: use default cache
|
||
console.log("ℹ️ Using default Metro cache (custom cache not available)");
|
||
}
|
||
}
|
||
|
||
// NEW: Network request optimizations for streaming
|
||
config.server = {
|
||
...config.server,
|
||
// Enhanced request handling for media assets
|
||
enhanceMiddleware: (middleware, _server) => {
|
||
// Add caching headers for static assets
|
||
return (req, res, next) => {
|
||
if (req.url?.match(/\.(mp4|mkv|jpg|jpeg|png|webp)$/)) {
|
||
res.setHeader("Cache-Control", "public, max-age=31536000");
|
||
}
|
||
return middleware(req, res, next);
|
||
};
|
||
},
|
||
};
|
||
|
||
module.exports = config;
|