/
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:

  1. 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
  2. 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
  3. add "AssetResolver::add($asset_name, array $configuration)" method to dynamic asset adding from events below
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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
  9. on deploy we'll build all asset caches according to "assets.json" files
  10. 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.

Related Discussions

Related Tasks