-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit fad271f
Showing
10 changed files
with
406 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
Magento Google Pagespeed Optimization Extension | ||
=============================================== | ||
|
||
This extension should help, to fulfill the requirements of the tool [Google PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/). | ||
|
||
Current features | ||
---------------- | ||
|
||
1. Move every Javascript tag (head & inline) to the bottom. ({stripped_html}{js}</body></html>) | ||
* including conditional js units (<!--[if lt IE 7]>{multiple js tags}<![endif]-->) | ||
* including external js tags | ||
* including "inline" js tags | ||
2. Move every CSS (head & inline) to the bottom. ({stripped_html}{css}</body></html>) | ||
* including conditional css units (<!--[if lt IE 7]>{multiple css tags}<![endif]-->) | ||
* including external css tags | ||
* including inline css tags | ||
|
||
How it works ? | ||
------------ | ||
|
||
Simple parse the final html stream on the event "controller_front_send_response_before". | ||
|
||
What about performance/paring time ? | ||
------------------------------ | ||
|
||
On our local hardware the html parsing requires a maximum of 8 milliseconds. | ||
|
||
|
||
Requirements from PageSpeed Insights and planned Features | ||
--------------------------------------------------------- | ||
|
||
1. ~~[Eliminate render-blocking JavaScript and CSS in above-the-fold content](https://developers.google.com/speed/docs/insights/BlockingJS)~~ (feature 1 & 2) | ||
2. [Prioritize visible content](https://developers.google.com/speed/docs/insights/PrioritizeVisibleContent) | ||
|
||
Requirements from PageSpeed Insights which are covered by 3rd party extensions | ||
------------------------------------------------------------------------------ | ||
|
||
1. [Minify CSS](https://developers.google.com/speed/docs/insights/MinifyResources) | ||
2. [Minify JavaScript](https://developers.google.com/speed/docs/insights/MinifyResources) | ||
* Both are covered by [Speedster Advanced by Fooman](http://www.magentocommerce.com/magento-connect/speedster-advanced-by-fooman.html) (note: that we have no experience with this extension, but Fooman seems to be a good guy.) | ||
3. [Optimize images](https://developers.google.com/speed/docs/insights/OptimizeImages) | ||
* [Image Optimization](http://www.magentocommerce.com/magento-connect/image-optimization.html)(note: no experience too.) | ||
4. [Minify HTML](https://developers.google.com/speed/docs/insights/MinifyResources)~~ | ||
* Based primary on [Minify CSS](https://developers.google.com/speed/docs/insights/MinifyResources) and [Minify JavaScript](https://developers.google.com/speed/docs/insights/MinifyResources). | ||
|
||
Requirements from PageSpeed Insights which are covered by your server admin :) | ||
------------------------------------------------------------------------------ | ||
|
||
1. [Enable compression](https://developers.google.com/speed/docs/insights/EnableCompression) | ||
2. [Avoid landing page redirects](https://developers.google.com/speed/docs/insights/AvoidRedirects) | ||
3. [Leverage browser caching](https://developers.google.com/speed/docs/insights/LeverageBrowserCaching) | ||
4. [Reduce server response time](https://developers.google.com/speed/docs/insights/Server) | ||
|
||
[Goal]: http://www.mediarox.de/goal.png | ||
|
||
Notices | ||
------ | ||
1. There is also a great tool called [PageSpeed Module](https://developers.google.com/speed/pagespeed/module) | ||
for common webservers like apache and nginx. If you have the opportunity: Use it, but read the manual. | ||
2. Test before use. There are also "great" things like multiple "</body>" tags, that will crash the party. | ||
3. Front Page Cache: Test it. Look that our event "controller_front_send_response_before" is called before | ||
your FPC-Extension starts to observe. | ||
|
||
|
||
Developer | ||
--------- | ||
Steven Fritzsche [@de_mediarox](https://twitter.com/de_mediarox) | ||
|
||
Licence | ||
------- | ||
[OSL - Open Software Licence 3.0](http://opensource.org/licenses/osl-3.0.php) | ||
|
||
Copyright | ||
--------- | ||
(c) 2015 Steven Fritzsche <sfritzsche@mediarox.de> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
/** | ||
* @package Pagespeed_Css | ||
* @copyright Copyright (c) 2015 mediarox UG (haftungsbeschraenkt) (http://www.mediarox.de) | ||
* @author Steven Fritzsche <sfritzsche@mediarox.de> | ||
*/ | ||
|
||
/** | ||
* Standard helper | ||
*/ | ||
class Pagespeed_Css_Helper_Data extends Mage_Core_Helper_Abstract | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?php | ||
/** | ||
* @package Pagespeed_Css | ||
* @copyright Copyright (c) 2015 mediarox UG (haftungsbeschraenkt) (http://www.mediarox.de) | ||
* @author Steven Fritzsche <sfritzsche@mediarox.de> | ||
*/ | ||
|
||
/** | ||
* Standard observer class | ||
*/ | ||
class Pagespeed_Css_Model_Observer | ||
{ | ||
/** | ||
* Move every Css (head & inline) to the bottom. ({stripped_html}{css}</body></html>) | ||
* | ||
* Step 1: Load needed data. | ||
* Step 2: Return if no </body> is found in html. | ||
* Step 3: Search and replace conditional css units. (example: <!--[if lt IE 7]>{multiple css tags}<![endif]-->) | ||
* Step 4: Search and replace external css tags. (link-tags must xhtml-compliant closed by "/>") | ||
* Step 5: Search and replace inline css tags. | ||
* Step 6: Return if no css is found. | ||
* Step 7: Remove blank lines from html. | ||
* Step 8: Recalculating </body> position, insert css groups right before body ends and set response. | ||
* Final order: | ||
* 1. stripped html | ||
* 2. conditional css tags | ||
* 3. external css tags | ||
* 3. inline css tags | ||
* 4. </body></html> | ||
* | ||
* @param Varien_Event_Observer $observer | ||
*/ | ||
public function parseCssToBottom(Varien_Event_Observer $observer) | ||
{ | ||
//$timeStart = microtime(true); | ||
|
||
// Step 1 | ||
$response = $observer->getFront()->getResponse(); | ||
$html = $response->getBody(); | ||
|
||
// Step 2 | ||
$closedBodyPosition = strpos($html, '</body>'); | ||
if (false === $closedBodyPosition) return; | ||
|
||
// Step 3 | ||
$conditionalCssTags = ''; | ||
$conditionalCssPattern = '#\<\!--\[if[^\>]*>\s*<link[^>]*type\="text\/css"[^>]*/>\s*<\!\[endif\]-->#isUm'; | ||
$conditionalCssHits = preg_match_all($conditionalCssPattern, $html, $conditionalMatches); | ||
|
||
if((bool)$conditionalCssHits) { | ||
$conditionalCssTags = implode('', $conditionalMatches[0]); | ||
$html = preg_replace($conditionalCssPattern, '' , $html); | ||
} | ||
|
||
// Step 4 | ||
$externalCssTags = ''; | ||
$externalCssPattern = '#<link[^>]*type\=["\']text\/css["\'][^>]*/>#isUm'; | ||
$externalCssHits = preg_match_all($externalCssPattern, $html, $externalMatches); | ||
|
||
if((bool)$externalCssHits) { | ||
$externalCssTags = implode('', $externalMatches[0]); | ||
$html = preg_replace($externalCssPattern, '' , $html); | ||
} | ||
|
||
// Step 5 | ||
$inlineCssTags = ''; | ||
$inlineCssPattern = '#<style.*</style>#isUm'; | ||
$inlineCssHits = preg_match_all($inlineCssPattern, $html, $inlineMatches); | ||
|
||
if((bool)$inlineCssHits) { | ||
$inlineCssTags = implode('', $inlineMatches[0]); | ||
$html = preg_replace($inlineCssPattern, '' , $html); | ||
} | ||
|
||
// Step 6 | ||
$overallCssHit = ((bool)$conditionalCssHits || (bool)$externalCssHits || (bool)$inlineCssHits); | ||
if(!$overallCssHit) return; | ||
|
||
// Step 7 | ||
$html = preg_replace('/^\h*\v+/m', '', $html); | ||
|
||
// Step 8 | ||
$closedBodyPosition = strpos($html, '</body>'); | ||
$css = $conditionalCssTags . $externalCssTags . $inlineCssTags; | ||
$html = substr_replace($html, $css, $closedBodyPosition, 0); | ||
$response->setBody($html); | ||
|
||
//Mage::log('parseCssToBottom ' . round(((microtime(true) - $timeStart) * 1000)) . ' ms'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?xml version="1.0"?> | ||
<!-- | ||
/** | ||
* @package Pagespeed_Css | ||
* @copyright Copyright (c) 2015 mediarox UG (haftungsbeschraenkt) (http://www.mediarox.de) | ||
* @author Steven Fritzsche <sfritzsche@mediarox.de> | ||
*/ | ||
--> | ||
<config> | ||
<modules> | ||
<Pagespeed_Css> | ||
<version>0.0.0.1</version> | ||
</Pagespeed_Css> | ||
</modules> | ||
<frontend> | ||
<events> | ||
|
||
<!-- | ||
Event before response send to browser | ||
--> | ||
<controller_front_send_response_before> | ||
<observers> | ||
<pagespeed_css_response_before> | ||
<type>singleton</type> | ||
<class>pagespeed_css/observer</class> | ||
<method>parseCssToBottom</method> | ||
</pagespeed_css_response_before> | ||
</observers> | ||
</controller_front_send_response_before> | ||
|
||
</events> | ||
</frontend> | ||
<global> | ||
|
||
<!-- | ||
default class declarations | ||
--> | ||
<models> | ||
<pagespeed_css> | ||
<class>Pagespeed_Css_Model</class> | ||
</pagespeed_css> | ||
</models> | ||
<helpers> | ||
<pagespeed_css> | ||
<class>Pagespeed_Css_Helper</class> | ||
</pagespeed_css> | ||
</helpers> | ||
|
||
</global> | ||
|
||
</config> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
/** | ||
* @package Pagespeed_Js | ||
* @copyright Copyright (c) 2015 mediarox UG (haftungsbeschraenkt) (http://www.mediarox.de) | ||
* @author Steven Fritzsche <sfritzsche@mediarox.de> | ||
*/ | ||
|
||
/** | ||
* Standard helper | ||
*/ | ||
class Pagespeed_Js_Helper_Data extends Mage_Core_Helper_Abstract | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php | ||
/** | ||
* @package Pagespeed_Js | ||
* @copyright Copyright (c) 2015 mediarox UG (haftungsbeschraenkt) (http://www.mediarox.de) | ||
* @author Steven Fritzsche <sfritzsche@mediarox.de> | ||
*/ | ||
|
||
/** | ||
* Standard observer class | ||
*/ | ||
class Pagespeed_Js_Model_Observer | ||
{ | ||
/** | ||
* Move every JS (head & inline) to the bottom. ({stripped_html}{js}</body></html>) | ||
* | ||
* Step 1: Load needed data. | ||
* Step 2: Return if no </body> is found in html. | ||
* Step 3: Search and replace conditional js units. (example: <!--[if lt IE 7]>{multiple js tags}<![endif]-->) | ||
* Step 4: Search and replace normal js tags. | ||
* Step 5: Return if no js is found. | ||
* Step 6: Remove blank lines from html. | ||
* Step 7: Recalculating </body> position, insert js groups right before body ends and set response. | ||
* Final order: | ||
* 1. stripped html | ||
* 2. conditional js tags | ||
* 3. normal js tags | ||
* 4. </body></html> | ||
* | ||
* @param Varien_Event_Observer $observer | ||
*/ | ||
public function parseJsToBottom(Varien_Event_Observer $observer) | ||
{ | ||
//$timeStart = microtime(true); | ||
|
||
// Step 1 | ||
$response = $observer->getFront()->getResponse(); | ||
$html = $response->getBody(); | ||
|
||
// Step 2 | ||
$closedBodyPosition = strpos($html, '</body>'); | ||
if($closedBodyPosition === false) return; | ||
|
||
// Step 3 | ||
$conditionalJsTags = ''; | ||
$conditionalJsPattern = '#\<\!--\[if[^\>]*>\s*<script.*</script>\s*<\!\[endif\]-->#isUm'; | ||
$conditionalJsHits = preg_match_all($conditionalJsPattern, $html, $conditionalMatches); | ||
|
||
if((bool)$conditionalJsHits) { | ||
$conditionalJsTags = implode('', $conditionalMatches[0]); | ||
$html = preg_replace($conditionalJsPattern, '' , $html); | ||
} | ||
|
||
// Step 4 | ||
$jsTags = ''; | ||
$jsPattern = '#<script.*</script>#isUm'; | ||
$jsHits = preg_match_all($jsPattern, $html, $matches); | ||
|
||
if((bool)$jsHits) { | ||
$jsTags = implode('', $matches[0]); | ||
$html = preg_replace($jsPattern, '' , $html); | ||
} | ||
|
||
// Step 5 | ||
$overallJsHit = ((bool)$conditionalJsHits || (bool)$jsHits); | ||
if(!$overallJsHit) return; | ||
|
||
// Step 6 | ||
$html = preg_replace('/^\h*\v+/m', '', $html); | ||
|
||
// Step 7 | ||
$closedBodyPosition = strpos($html, '</body>'); | ||
$html = substr_replace($html, $conditionalJsTags . $jsTags, $closedBodyPosition, 0); | ||
$response->setBody($html); | ||
|
||
//Mage::log('parseJsToBottom ' . round(((microtime(true) - $timeStart) * 1000)) . ' ms'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?xml version="1.0"?> | ||
<!-- | ||
/** | ||
* @package Pagespeed_Js | ||
* @copyright Copyright (c) 2015 mediarox UG (haftungsbeschraenkt) (http://www.mediarox.de) | ||
* @author Steven Fritzsche <sfritzsche@mediarox.de> | ||
*/ | ||
--> | ||
<config> | ||
<modules> | ||
<Pagespeed_Js> | ||
<version>0.0.0.1</version> | ||
</Pagespeed_Js> | ||
</modules> | ||
<frontend> | ||
<events> | ||
|
||
<!-- | ||
Event before response send to browser | ||
--> | ||
<controller_front_send_response_before> | ||
<observers> | ||
<pagespeed_js_response_before> | ||
<type>singleton</type> | ||
<class>pagespeed_js/observer</class> | ||
<method>parseJsToBottom</method> | ||
</pagespeed_js_response_before> | ||
</observers> | ||
</controller_front_send_response_before> | ||
|
||
</events> | ||
</frontend> | ||
<global> | ||
|
||
<!-- | ||
default class declarations | ||
--> | ||
<models> | ||
<pagespeed_js> | ||
<class>Pagespeed_Js_Model</class> | ||
</pagespeed_js> | ||
</models> | ||
<helpers> | ||
<pagespeed_js> | ||
<class>Pagespeed_Js_Helper</class> | ||
</pagespeed_js> | ||
</helpers> | ||
|
||
</global> | ||
|
||
</config> |
Oops, something went wrong.