Permalink
Browse files

perf(views): Allow serving assets directly from filesystem

BREAKING CHANGES:
Assets must have valid file extensions

We now cache assets by `"$viewtype/$view"`, not `md5("$viewtype|$view")`
which can result in conflicts between cacheable views that don't have
file extensions to disambiguate files from directories.

This requirement makes it possibile for us to serve assets
directly from disk for performance, instead of serving them through PHP.
Just create a symlink from /cache/ to /dataroot/views_simplecache/
and if your web server supports following symlinks, you'll get this benefit.

This also makes it much easier to explore the available cached resources
by navigating to dataroot/views_simplecache and browsing around.

Fixes #8381
  • Loading branch information...
ewinslow committed Jun 19, 2015
1 parent 13afe2e commit c4c5734d1706aca5545264e5b14fafc1ee7813db
View
@@ -2,12 +2,13 @@
/engine/settings.php
/.htaccess
/mod/*
-composer.lock
-composer.phar
+/composer.lock
+/composer.phar
+/cache
# Don't check in third party code
-node_modules
-vendor
+/node_modules
+/vendor
# don't ignore bundled plugins
!/mod/aalborg_theme/
View
@@ -83,6 +83,18 @@ It is recommended that you do this on your development platform if you are writi
This cache is automatically flushed when a plugin is enabled, disabled or reordered,
or when upgrade.php is executed.
+For best performance, you can also create a symlink from ``/cache/`` in your www
+root dir to the ``/views_simplecache/`` directory in the data directory you
+configured when you installed Elgg:
+
+.. code:: shell
+
+ cd /path/to/wwwroot/
+ ln -s /path/to/dataroot/views_simplecache/ cache
+
+If your webserver supports following symlinks, this will serve files straight off
+disk without booting up PHP each time.
+
System cache
------------
View
@@ -12,6 +12,23 @@ See the administrator guides for :doc:`how to upgrade a live site </admin/upgrad
From 1.x to 2.0
===============
+Cacheable views must have a file extension in their names
+---------------------------------------------------------
+
+This requirement makes it possibile for us to serve assets directly
+from disk for performance, instead of serving them through PHP.
+
+It also makes it much easier to explore the available cached resources
+by navigating to dataroot/views_simplecache and browsing around.
+
+ * Bad: ``my/cool/template``
+ * Good: ``my/cool/template.html``
+
+We now cache assets by ``"$viewtype/$view"``, not ``md5("$viewtype|$view")``,
+which can result in conflicts between cacheable views that don't have file extensions
+to disambiguate files from directories.
+
+
Dropped ``jquery-migrate`` and upgraded ``jquery`` to ^2.1.4
------------------------------------------------------------
View
@@ -73,10 +73,19 @@ Views as cacheable assets
=========================
As mentioned before, views can contain JS, CSS, or even images.
-Cacheable views *cannot* take any ``$vars`` parameters. They also must not change
-their output based on who is logged in, the time of day, etc. The simplest way
-to make sure your view meets the requirements for cacheable views is to just avoid
-using any PHP in them.
+
+Asset views must meet certain requirements:
+
+ * They *must not* take any ``$vars`` parameters
+ * They *must not* change their output based on global state like
+
+ * who is logged in
+ * the time of day
+
+ * They *must* contain a valid file extension
+
+ * Bad: ``my/cool/template``
+ * Good: ``my/cool/template.html``
For example, suppose you wanted to load some CSS on a page.
You could define a view ``mystyles.css``, which would look like so:
@@ -72,10 +72,12 @@ public function handleRequest($path) {
$viewtype = $request['viewtype'];
$contentType = $this->getContentType($view);
- if (!empty($contentType)) {
- header("Content-Type: $contentType", true);
+ if (empty($contentType)) {
+ $this->send403("Asset must have a valid file extension");
}
+ header("Content-Type: $contentType", true);
+
// this may/may not have to connect to the DB
$this->setupSimplecache();
@@ -85,7 +87,7 @@ public function handleRequest($path) {
$this->application->bootCore();
if (!\_elgg_is_view_cacheable($view)) {
- $this->send403();
+ $this->send403("Requested view is not an asset");
} else {
echo $this->renderView($view, $viewtype);
}
@@ -100,30 +102,30 @@ public function handleRequest($path) {
exit;
}
- $filename = $config->getVolatile('dataroot') . 'views_simplecache/' . md5("$viewtype|$view");
- if (file_exists($filename)) {
- $this->sendCacheHeaders($etag);
- readfile($filename);
- exit;
- }
-
$this->application->bootCore();
elgg_set_viewtype($viewtype);
if (!\_elgg_is_view_cacheable($view)) {
- $this->send403();
+ $this->send403("Requested view is not an asset");
}
- $cache_timestamp = (int)$config->get('lastcache');
+ $lastcache = (int)$config->get('lastcache');
+
+ $filename = $config->getVolatile('dataroot') . "views_simplecache/$lastcache/$viewtype/$view";
+ if (file_exists($filename)) {
+ $this->sendCacheHeaders($etag);
+ readfile($filename);
+ exit;
+ }
- if ($cache_timestamp == $ts) {
+ if ($lastcache == $ts) {
$this->sendCacheHeaders($etag);
$content = $this->getProcessedView($view, $viewtype);
- $dir_name = $config->getDataPath() . 'views_simplecache/';
+ $dir_name = dirname($filename);
if (!is_dir($dir_name)) {
- mkdir($dir_name, 0700);
+ mkdir($dir_name, 0700, true);
}
file_put_contents($filename, $content);
@@ -146,8 +146,7 @@ function disable() {
_elgg_services()->datalist->set('simplecache_enabled', 0);
_elgg_services()->config->set('simplecache_enabled', 0);
- // purge simple cache
- _elgg_rmdir(_elgg_services()->config->getDataPath() . "views_simplecache");
+ $this->invalidate();
}
}
@@ -158,7 +157,6 @@ function disable() {
* @return bool
*/
function invalidate() {
- _elgg_rmdir("{$this->CONFIG->dataroot}views_simplecache");
mkdir("{$this->CONFIG->dataroot}views_simplecache");
$time = time();
@@ -8,7 +8,7 @@
// Require is currently an Elgg shim. Convert it to a RequireJS config
?>
// <script>
-require = <?php echo json_encode($amdConfig); ?>;
+require = <?php echo json_encode($amdConfig, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); ?>;
<?php
// Note we don't process the require() queue yet because it may require('elgg')
@@ -33,4 +33,4 @@
}
?>
-define(<?php echo json_encode($translations); ?>);
+define(<?php echo json_encode($translations, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); ?>);

0 comments on commit c4c5734

Please sign in to comment.