diff --git a/conf/default.conf.php b/conf/default.conf.php index 5759262487..977230ead1 100644 --- a/conf/default.conf.php +++ b/conf/default.conf.php @@ -789,6 +789,10 @@ return array( // settings are the defaults.) 'celerity.force-disk-reads' => false, + // Minify static resources by removing whitespace and comments. You should + // enable this in production, but disable it in development. + 'celerity.minify' => false, + // You can respond to various application events by installing listeners, // which will receive callbacks when interesting things occur. Specify a list // of classes which extend PhabricatorEventListener here. diff --git a/conf/development.conf.php b/conf/development.conf.php index 963e6a88b2..425afda13a 100644 --- a/conf/development.conf.php +++ b/conf/development.conf.php @@ -22,5 +22,6 @@ return array( 'celerity.force-disk-reads' => true, 'phabricator.show-stack-traces' => true, 'phabricator.show-error-callout' => true, + 'celerity.minify' => false, ) + phabricator_read_config_file('default'); diff --git a/scripts/fpm/warmup.php b/scripts/fpm/warmup.php index f4744d1991..ad0d80c6a4 100644 --- a/scripts/fpm/warmup.php +++ b/scripts/fpm/warmup.php @@ -48,6 +48,9 @@ function __warmup__() { $loader = new PhutilSymbolLoader(); $loader->selectAndLoadSymbols(); + // Force load of the Celerity map. + CelerityResourceMap::getInstance(); + define('__WARMUP__', true); } diff --git a/src/infrastructure/celerity/controller/CelerityResourceController.php b/src/infrastructure/celerity/controller/CelerityResourceController.php index 6c1f081404..fac5a3c9fe 100644 --- a/src/infrastructure/celerity/controller/CelerityResourceController.php +++ b/src/infrastructure/celerity/controller/CelerityResourceController.php @@ -81,6 +81,7 @@ final class CelerityResourceController extends AphrontController { } $response = new AphrontFileResponse(); + $data = $this->minifyData($data, $type); $response->setContent($data); switch ($type) { case 'css': @@ -101,4 +102,42 @@ final class CelerityResourceController extends AphrontController { return $response; } + private function minifyData($data, $type) { + if (!PhabricatorEnv::getEnvConfig('celerity.minify')) { + return $data; + } + + switch ($type) { + case 'css': + // Remove comments. + $data = preg_replace('@/\*.*?\*/@s', '', $data); + // Remove whitespace around symbols. + $data = preg_replace('@\s*([{}:;,])\s+@', '\1', $data); + // Remove unnecessary semicolons. + $data = preg_replace('@;}@', '}', $data); + // Replace #rrggbb with #rgb when possible. + $data = preg_replace( + '@#([a-f0-9])\1([a-f0-9])\2([a-f0-9])\3@i', + '#\1\2\3', + $data); + $data = trim($data); + break; + case 'js': + $root = dirname(phutil_get_library_root('phabricator')); + $bin = $root.'/externals/javelin/support/jsxmin/jsxmin'; + + if (@file_exists($bin)) { + $future = new ExecFuture("{$bin} __DEV__:0"); + $future->write($data); + list($err, $result) = $future->resolve(); + if (!$err) { + $data = $result; + } + } + break; + } + + return $data; + } + } diff --git a/src/infrastructure/celerity/controller/__init__.php b/src/infrastructure/celerity/controller/__init__.php index 11f5f8028b..9a0bd830fc 100644 --- a/src/infrastructure/celerity/controller/__init__.php +++ b/src/infrastructure/celerity/controller/__init__.php @@ -14,6 +14,7 @@ phutil_require_module('phabricator', 'infrastructure/celerity/map'); phutil_require_module('phabricator', 'infrastructure/env'); phutil_require_module('phutil', 'filesystem'); +phutil_require_module('phutil', 'future/exec'); phutil_require_module('phutil', 'moduleutils');