Drupal, meet Assetic

Preview:

DESCRIPTION

Drupal 8 leverages Assetic for managing Javascript and CSS assets. This library abstracts the headaches of integrating with the burgeoning universe of asset pre-processors and optimization tools available to the modern developer. The lead developer of Assetic will give a tour of the library and discuss the current state of the project, its strengths, and its weaknesses, and also touch on the future: Assetic 2.0.

Citation preview

assetic

@kriswallsmith

things are pretty good

things could be better

problems

solutions

past

present

future

kriswallsmith/assetic

inspired by python’s webassetshttp://github.com/miracle2k/webassets

2,500+ stars

400+ forks

2.4 million installs

the team• kriswallsmith

• stof

• schmittjoh

• everzet

• 88 other contributors

boring

css

javascript

such assetsso wait

wow

model the problem

assets

images stylesheets javascripts

• path • last modified • content

an object-oriented api

interface AssetInterface!{! function getContent();! function getSourceRoot();! function getSourcePath();! function getTargetPath();! function getLastModified();!!

// ...!}

interface AssetInterface!{! // ...!!

function load();! function dump();!!

// ...!}

implementations

• StringAsset

• FileAsset

• HttpAsset

use Assetic\Asset\StringAsset;!!

$a = new StringAsset('alert("hi!")');!$a->load();!echo $a->dump();

use Assetic\Asset\StringAsset;!!

$a = new StringAsset('alert("hi!")');!$a->load();!echo $a->dump();

use Assetic\Asset\StringAsset;!!

$a = new StringAsset('alert("hi!")');!!

echo $a->dump();

use Assetic\Asset\FileAsset;!!

$a = new FileAsset('/path/to/hi.js');!!

echo $a->dump();

use Assetic\Asset\HttpAsset;!!

$a = new HttpAsset('//example.com/hi.js');!!

echo $a->dump();

special implementations

• AssetCollection

• GlobAsset

• AssetCache

• AssetReference

use Assetic\Asset\AssetCollection;!use Assetic\Asset\FileAsset;!use Assetic\Asset\StringAsset;!!

$a = new AssetCollection(array(! new StringAsset('// (c) me'),! new FileAsset('/path/to/main.js'),!));!!

echo $a->dump();

use Assetic\Asset\GlobAsset;!!

$a = new GlobAsset('/path/to/js/*.js');!!

echo $a->dump();

use Assetic\Asset\AssetCache;!use Assetic\Asset\HttpAsset;!use Assetic\Cache\ApcCache;!!

$a = new AssetCache(! new HttpAsset(‘//example.com/hi.js'),! new ApcCache()!);!!

echo $a->dump();

use Assetic\Asset\AssetReference;!use Assetic\Asset\StringAsset;!use Assetic\AssetManager;!!

$am = new AssetManager();!$am->set('hi', new StringAsset('...'));!!

$a = new AssetReference($am, 'hi');!!

echo $a->dump();

slow

fewer requests

smaller responses

tools

• CssEmbed

• Google Closure

• jpegoptim

• jpegtran

• JSMin

• JSqueeze

• optipng

• PhpCssEmbed

• pngout

• UglifyCSS

• UglifyJS

• YUI Compressor

tedious

more tools

• CoffeeScript

• Compass

• Dart

• Less

• Lessphp

• Packager

• Roole

• SASS

• Scssphp

• Sprockets

• Stylus

• TypeScript

model the problem

use Assetic\Asset\AssetInterface as Asset;!!

interface FilterInterface!{! function filterLoad(Asset $asset);! function filterDump(Asset $asset);!}

var myVariable var _a

dumpload

coffeescript javascript

load javascript

• CoffeeScriptFilter

• DartFilter

• EmberPrecompileFilter

• HandlebarsFilter

• PackagerFilter

• SprocketsFilter

• TypeScriptFilter

load css• CompassFilter

• CssImportFilter

• GssFilter

• LessFilter

• LessphpFilter

• PhpCssEmbedFilter

• RooleFilter

• Sass\SassFilter

• Sass\ScssFilter

• ScssphpFilter

• StylusFilter

dump javascript• Google\CompilerApiFilter

• Google\CompilerJarFilter

• JSMinFilter

• JSMinPlusFilter

• JSqueezeFilter

• PackerFilter

• UglifyJsFilter

• UglifyJs2Filter

• Yui\JsCompressorFilter

dump css• CssEmbedFilter

• CssMinFilter

• CssRewriteFilter

• UglifyCssFilter

• Yui\CssCompressorFilter

dump images

• JpegoptimFilter

• JpegtranFilter

• OptiPngFilter

• PngoutFilter

use Assetic\Filter\FilterInterface;!!

interface AssetInterface!{! function ensureFilter(! FilterInterface $filter);!!

// ...!}

use Assetic\Asset\FileAsset;!use Assetic\Filter\CoffeeScriptFilter;!use Assetic\Filter\UglifyJs2Filter;!!

$a = new FileAsset('/path/to/app.coffee');!$a->ensureFilter(new CoffeeScriptFilter());!$a->ensureFilter(new UglifyJs2Filter());!!

echo $a->dump();

use Assetic\Asset\FileAsset;!use Assetic\Filter\CoffeeScriptFilter;!use Assetic\Filter\UglifyJs2Filter;!!

$a = new FileAsset(! '/path/to/app.coffee',! array(! new CoffeeScriptFilter(),! new UglifyJs2Filter(),! )!);

serve

# /path/to/web/js/app.php!!

$a = new FileAsset('/path/to/app.coffee');!$a->ensureFilter(new CoffeeScriptFilter());!$a->ensureFilter(new UglifyJs2Filter());!!

header('Content-Type: text/javascript');!echo $a->dump();

# /path/to/web/js/app.php!!

use Assetic\Asset\AssetCache;!use Assetic\Cache\ApcCache;!!

// ...!!

$a = new AssetCache($a, new ApcCache());!!

header('Content-Type: text/javascript');!echo $a->dump();

flat

use Assetic\Asset\FileAsset;!use Assetic\AssetManager;!use Assetic\AssetWriter;!!

$a = new FileAsset('/path/to/app.js');!$a->setTargetPath('js/app.js');!!

$am = new AssetManager();!$am->set('app_js', $a);!!

$writer = new AssetWriter('/path/to/web');!$writer->writeManagerAssets($am);

reference

<script src="/js/app.php"></script>

<script src="/js/app.js"></script>

<script src="<?= asset('app_js') ?>"></script>

template as configuration

<script src="<?=! assetic_javascripts(! array('js/app.coffee'),! array('coffee', 'uglifyjs2'),! array('output' => 'js/app.js')! )!?>"></script>

use Assetic\Filter\CoffeeScriptFilter;!use Assetic\FilterManager;!!

$fm = new FilterManager();!$fm->set(! 'coffee',! new CoffeeScriptFilter()!);

use Assetic\Factory\AssetFactory;!!

$factory = new AssetFactory('/www');!$factory->setFilterManager($fm);

use ...\Loader\FunctionCallsFormulaLoader;!use ...\Resource\DirectoryResource;!!

$ldr = new FunctionCallsFormulaLoader();!$rsc = new DirectoryResource(! '/path/to/views',! '/\.php$/'!);

use Assetic\Factory\LazyAssetManager;!!

$am = new LazyAssetManager($factory);!$am->setLoader('php', $ldr);!$am->addResource($rsc, 'php');

detect

includesreferences

while (true) {! foreach ($am->getNames() as $name) {! // ...! }!!

sleep(1);!}

push

henrikbjorn/lurker

use Lurker\ResourceWatcher;!!

$watcher = new ResourceWatcher();!$watcher->track('twig', '/path/to/views');!$watcher->addListener('twig', function($e) {! // ...!});!!

$watcher->start();

respond

_colors.sass

foreach ($am->getNames() as $name) {! $asset = $am->get($name);! // ...!!

if ($match) {! // ...! }!}

graph

profile.sass

_colors.sass background.gif

home.sass

includes

includes

references

references

included by

included byreferenced by

referenced by

nodes

edges

profile.sass

_colors.sass background.gif

home.sass

includes

includes

references

references

included by

included byreferenced by

referenced by

profile.sass

_colors.sass background.gif

home.sass

includes

includes

references

references

included by

included byreferenced by

referenced by

profile.sass

_colors.sass background.gif

home.sass

includes

includes

references

references

included by

included byreferenced by

referenced by

use Assetic\Asset\HttpAsset;!!

$a = new HttpAsset('//example.com/hi.js');

• proxy

• authentication

• errors

• ssl

• mock

• test

• logging

• profiling

• curl

• guzzle

represent

separate

• load

• filter

• reflection

• optimization

maintain

~40 filters

ping

opinion

• engines

• javascript optimizer

• css optimizer

• jpeg optimizer

• png optimizer

sponsor

follow@kriswallsmith

hire

• workshops

• architecture

• audits

• performance

• symfony

• phpunit

• twig

• doctrine

questions?

kris.wallsmith@gmail.com

Recommended