Deduplicate CDN assets by URL in bundle compiler
Unify CDN asset collection between dev and prod modes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -132,19 +132,9 @@ class Prod_Build_Command extends Command
|
||||
if (!$this->option('skip-laravel-cache')) {
|
||||
$this->line('[3/3] Building Laravel caches...');
|
||||
|
||||
passthru('php artisan config:cache 2>/dev/null', $exit_code);
|
||||
passthru('php artisan optimize:cache 2>/dev/null', $exit_code);
|
||||
if ($exit_code === 0) {
|
||||
$this->line(' Config cached');
|
||||
}
|
||||
|
||||
passthru('php artisan route:cache 2>/dev/null', $exit_code);
|
||||
if ($exit_code === 0) {
|
||||
$this->line(' Routes cached');
|
||||
}
|
||||
|
||||
passthru('php artisan view:cache 2>/dev/null', $exit_code);
|
||||
if ($exit_code === 0) {
|
||||
$this->line(' Views cached');
|
||||
$this->line(' Laravel caches built');
|
||||
}
|
||||
} else {
|
||||
$this->line('[3/3] Skipping Laravel caches (--skip-laravel-cache)');
|
||||
|
||||
@@ -463,9 +463,14 @@ class BundleCompiler
|
||||
'app_css_bundle_path' => !empty($app_css_files) ? basename($app_css_files[0]) : null,
|
||||
];
|
||||
|
||||
// Also resolve CDN assets - they're served separately via /_vendor/ URLs
|
||||
// We need to resolve the bundle includes to get CDN asset definitions
|
||||
$this->_resolve_cdn_assets_only();
|
||||
// Resolve CDN assets using the same code path as dev mode
|
||||
// This ensures directory scanning, nested bundles, etc. all work the same
|
||||
// File collection happens but we ignore it since we use cached bundles
|
||||
$bundle_fqcn = $this->_get_bundle_fqcn($this->bundle_name);
|
||||
$this->resolved_includes[$bundle_fqcn] = true;
|
||||
$this->root_bundle_class = $bundle_fqcn;
|
||||
$this->_process_required_bundles();
|
||||
$this->_resolve_bundle($bundle_fqcn);
|
||||
|
||||
if (!empty($this->cdn_assets['js'])) {
|
||||
$result['cdn_js'] = $this->_prepare_cdn_assets($this->cdn_assets['js'], 'js');
|
||||
@@ -479,81 +484,6 @@ class BundleCompiler
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve only CDN assets without full bundle compilation
|
||||
*
|
||||
* Used when serving from production cache to get CDN asset URLs
|
||||
* without re-resolving and re-compiling all bundle files.
|
||||
*/
|
||||
protected function _resolve_cdn_assets_only(): void
|
||||
{
|
||||
// Process required bundles first (they may have CDN assets)
|
||||
$required_bundles = config('rsx.required_bundles', []);
|
||||
$bundle_aliases = config('rsx.bundle_aliases', []);
|
||||
|
||||
foreach ($required_bundles as $alias) {
|
||||
if (isset($bundle_aliases[$alias])) {
|
||||
$this->_collect_cdn_assets_from_include($bundle_aliases[$alias]);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the bundle's own CDN assets
|
||||
$fqcn = $this->_get_bundle_fqcn($this->bundle_name);
|
||||
$definition = $fqcn::define();
|
||||
|
||||
// Add CDN assets from the bundle definition (same format as main resolution)
|
||||
if (!empty($definition['cdn_assets'])) {
|
||||
if (!empty($definition['cdn_assets']['js'])) {
|
||||
$this->cdn_assets['js'] = array_merge($this->cdn_assets['js'], $definition['cdn_assets']['js']);
|
||||
}
|
||||
if (!empty($definition['cdn_assets']['css'])) {
|
||||
$this->cdn_assets['css'] = array_merge($this->cdn_assets['css'], $definition['cdn_assets']['css']);
|
||||
}
|
||||
}
|
||||
|
||||
// Also check for Asset Bundle includes that may have CDN assets
|
||||
foreach ($definition['include'] ?? [] as $include) {
|
||||
$this->_collect_cdn_assets_from_include($include);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect CDN assets from a bundle include without full resolution
|
||||
*/
|
||||
protected function _collect_cdn_assets_from_include($include): void
|
||||
{
|
||||
// Handle config array format (from bundle aliases like jquery, lodash)
|
||||
if (is_array($include) && isset($include['cdn'])) {
|
||||
foreach ($include['cdn'] as $cdn_item) {
|
||||
// Determine type from URL extension
|
||||
$url = $cdn_item['url'] ?? '';
|
||||
$type = str_ends_with($url, '.css') ? 'css' : 'js';
|
||||
$this->cdn_assets[$type][] = $cdn_item;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle class name includes (could be Asset Bundles with CDN assets)
|
||||
// Normalize FQCN to simple name for manifest lookup (manifest stores simple names)
|
||||
if (is_string($include)) {
|
||||
$simple_name = Manifest::_normalize_class_name($include);
|
||||
if (isset(Manifest::$data['data']['php_classes'][$simple_name])) {
|
||||
if (Manifest::php_is_subclass_of($simple_name, 'Rsx_Asset_Bundle_Abstract')) {
|
||||
$asset_def = $include::define();
|
||||
if (!empty($asset_def['cdn_assets'])) {
|
||||
if (!empty($asset_def['cdn_assets']['js'])) {
|
||||
$this->cdn_assets['js'] = array_merge($this->cdn_assets['js'], $asset_def['cdn_assets']['js']);
|
||||
}
|
||||
if (!empty($asset_def['cdn_assets']['css'])) {
|
||||
$this->cdn_assets['css'] = array_merge($this->cdn_assets['css'], $asset_def['cdn_assets']['css']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process required bundles (jquery, lodash, jqhtml)
|
||||
*/
|
||||
@@ -2459,18 +2389,27 @@ implode("\n", array_map(fn ($f) => ' - ' . str_replace(base_path() . '/', '',
|
||||
*/
|
||||
protected function _prepare_cdn_assets(array $assets, string $type): array
|
||||
{
|
||||
// In development mode, return as-is (use CDN URLs directly)
|
||||
// Deduplicate by URL (same asset may be included via multiple bundles)
|
||||
$seen_urls = [];
|
||||
$deduplicated = [];
|
||||
foreach ($assets as $asset) {
|
||||
$url = $asset['url'] ?? '';
|
||||
if (empty($url) || isset($seen_urls[$url])) {
|
||||
continue;
|
||||
}
|
||||
$seen_urls[$url] = true;
|
||||
$deduplicated[] = $asset;
|
||||
}
|
||||
|
||||
// In development mode, return deduplicated (use CDN URLs directly)
|
||||
if (!$this->is_production) {
|
||||
return $assets;
|
||||
return $deduplicated;
|
||||
}
|
||||
|
||||
// In production-like modes, ensure cached and add filename
|
||||
$prepared = [];
|
||||
foreach ($assets as $asset) {
|
||||
$url = $asset['url'] ?? '';
|
||||
if (empty($url)) {
|
||||
continue;
|
||||
}
|
||||
foreach ($deduplicated as $asset) {
|
||||
$url = $asset['url'];
|
||||
|
||||
// Ensure the asset is cached (downloads if not already)
|
||||
Cdn_Cache::get($url, $type);
|
||||
|
||||
Reference in New Issue
Block a user