/
Asset Management v3 [5.3.0-B1]
Asset Management v3 [5.3.0-B1]
We've made several attempts to deal with assets (e.g. JS/CSS files) management in past.
First Attempt
Use JS/CSS files as is.
- Pros:
- no coding needed because all just works
- cache invalidation is done by browser itself on JS/CSS file change
- Cons:
- slows down page load, because JS/CSS files can't be loaded in parallel
Second Attempt (current)
Create ad-hoc file groups via <inp2:m_Compress/>
tag.
- Pros:
- network friendly, because all resources are combined into large files
- combined resource files can be minified
- combined filename contains CRC of it's contents to auto-invalidate by browser on content change
- Cons:
- combine resource files are huge
- single resource change would invalidate combine file, which needs to be redownloaded from scratch
- no way to determine which old combined files needs to be deleted because we only have new combined filename
- ad-hoc combined file creation - no way to pre-compile resources at deployment
Solution
Idea:
- each module has "
/modules/<module-name>/install/assets.json
" file - each theme has: "
/themes/<theme-name>/_install/assets.json
" file (one theme can have several files for each module sub-folder, e.g. "/themes/<theme-name>/in-link/_install/assets.json
") example contents of "assets.json" file (all path are relative to theme/module):
{ "example-package.js": { "engine": "yui", "files": [ "assets/js/lib/enquire.js", "assets/js/lib/slick.js" ] }, "example-package.css": { "files": [ "assets/css/style.css" ] } }
- the asset content can be specified in these forms (all exception "@refrerence" are already supported by "m_Compress" tag):
- "
path/to/asset.ext
" - asset within module, where "assets.json" is located - "
{module_path}/path/to/asset.ext
" - asset from each module - other formats supported by "m_Compress" tag currently
- "
@reference
" format - asset name, defined in any of "assets.json" files
- "
Plan:
- modify "MinifyHelper::CompressScriptTag" method (powers "m_Compress" tag) to have 4 modes (current behavior to always recreate asset in debug mode stays):
- "auto" - if asset file is missing, then create it and return it's url (as now, by default)
- "require" - if asset file is missing, then throw an exception otherwise immediately return it's url (don't even try to create it)
- "force" - always create asset file regardless of the fact, that it might already be present
- create "AssetResolver" class that will:
- when invoked from Front-End handle assets from all front-end themes; when invoked from admin console handle its assets
- collect data from "
assets.json
" files
- add "AssetResolver::add($asset_name, array $configuration)" method to dynamic asset adding from events below
- have "AssetResolver::resolve($asset_name)" method, that will:
- call "
adm:OnResolveAssets
" event to allow dynamic asset adding - iterate through asset configuration and resolve all asset references (in "@reference" format)
- cache resolved asset configuration somewhere under /system/cache/assets/ folder (not cached in debug mode & reset when cached assets are reset)
- return it
- call "
- have "AssetResolver::dump($asset_name)" method that would:
- call "resolve" method to get asset configuration
- call the "
MinifyHelper::CompressScriptTag
" with that data + mode=force (see above) to produce actual asset
- have "AssetResolver::url($asset_name)" method, that would:
- call "resolve" method to get asset configuration
- call the "
MinifyHelper::CompressScriptTag
" with that data + mode=require (see above) to get url of the asset
- have "AssetResolver::dumpAll()" method, that would:
- iterate through all registered assets (somehow don't call "adm:OnResolveAssets" event multiple times)
- call "dump" method on each of them
- create
<inp2:m_Asset name="..."/>
tag, that will:- be used as alternative to the
<inp2:m_Compress .../>
tag - call "AssetResolver::url" method for given asset name
- be used as alternative to the
- on deploy we'll build all asset caches according to "
assets.json
" files - add the "
asset:compile
" command to compile assets manually
P.S.
Assetic can also compile LESS/SASS into CSS and minify JS using YUI compressor or Google Closure Compiler. So we no longer need to setup tricky tasks for PhpStorm or commit compiled CSS anymore.