Author: chabotc
Date: Thu May 15 05:39:15 2008
New Revision: 656630
URL: http://svn.apache.org/viewvc?rev=656630&view=rev
Log:
Take 2 of javascript compression.
This time we're using a php port of jsmin.c, it has a slightly lower compression
ratio then yuicompressort, but the overhead of starting a java app in the
background
was way to high. This way it's actually quite functional and speedy.
All the compressed js is cached, so the first time a feature lib is called it
will
have a slight delay compared to normal (0.5 seconds on my box), but all
subsiquent
calls will be just as fast as before.
Using this method we save nearly 50% on the gadget html size
Added:
incubator/shindig/trunk/php/src/common/JsMin.php
Modified:
incubator/shindig/trunk/php/config.php
incubator/shindig/trunk/php/src/common/HttpServlet.php
incubator/shindig/trunk/php/src/common/RemoteContentRequest.php
incubator/shindig/trunk/php/src/gadgets/GadgetContext.php
incubator/shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php
incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php
incubator/shindig/trunk/php/src/gadgets/JsLibrary.php
incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php
Modified: incubator/shindig/trunk/php/config.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/config.php?rev=656630&r1=656629&r2=656630&view=diff
==============================================================================
--- incubator/shindig/trunk/php/config.php (original)
+++ incubator/shindig/trunk/php/config.php Thu May 15 05:39:15 2008
@@ -1,5 +1,24 @@
<?
/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+/*
* I really detest such config files to be honest, why put configuration in a
web document!
* But since PHP lacks a propper way to set application configurations, and
any other method
* would be horribly slow (db, xml, ini files etc), so ... here's our
config.php
@@ -20,10 +39,14 @@
'token_cipher_key' => 'INSECURE_DEFAULT_KEY',
'token_hmac_key' => 'INSECURE_DEFAULT_KEY',
+ // Compresses features javascript? can save upto 50% page size
+ 'compress_javascript' => true,
+
// Configurable CSS rules that are injected to the gadget page,
// be careful when adjusting these not to break most gadget's layouts :)
'gadget_css' => 'body,td,div,span,p{font-family:arial,sans-serif;} a
{color:#0000cc;}a:visited {color:#551a8b;}a:active {color:#ff0000;}body{margin:
0px;padding: 0px;background-color:white;}',
-
+ // 'gadget_css' => 'body,td,div,span,p{font-family:arial,sans-serif;}
body {background-color:#ffffff; font-family: arial, sans-serif; padding: 0px;
margin: 0px; font-size: 12px; color: #000000;}a, a:visited {color:
#3366CC;text-decoration: none; }a:hover {color: #3366CC; text-decoration:
underline;} input, select { border: 1px solid #bdc7d8;font-size: 11px;padding:
3px;}',
+
// The html / javascript samples use a plain text demo token,
// set this to false on anything resembling a real site
'allow_plaintext_token' => true,
@@ -43,7 +66,7 @@
// The data handlers for the social data, this is a list of class names
// seperated by a , For example:
- // 'handlers' => 'PartuzaHandler',
+ //'handlers' => 'PartuzaHandler',
// if the value is empty, the defaults used in the example above will
be used.
'handlers' => '',
@@ -82,8 +105,7 @@
/**
* Abstracts how to retrieve configuration values so we can replace the
- * not so pretty $config array some day.
- *
+ * not so pretty $shindigConfig array some day.
*/
class Config {
static function get($key)
Modified: incubator/shindig/trunk/php/src/common/HttpServlet.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/HttpServlet.php?rev=656630&r1=656629&r2=656630&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/HttpServlet.php (original)
+++ incubator/shindig/trunk/php/src/common/HttpServlet.php Thu May 15 05:39:15
2008
@@ -68,8 +68,8 @@
header("Expires: " . gmdate("D, d M Y H:i:s",
time() + $this->cacheTime) . " GMT");
// Obey browsers (or proxy's) request to send a
fresh copy if we recieve a no-cache pragma or cache-control request
if (! isset($_SERVER['HTTP_PRAGMA']) || !
strstr(strtolower($_SERVER['HTTP_PRAGMA']), 'no-cache') && (!
isset($_SERVER['HTTP_CACHE_CONTROL']) || !
strstr(strtolower($_SERVER['HTTP_CACHE_CONTROL']), 'no-cache'))) {
- // If the browser send us a E-TAG check
if it matches (sha1 sum of content), if so send a not modified header instead
of content
- $etag = sha1($content);
+ // If the browser send us a E-TAG check
if it matches (md5 sum of content), if so send a not modified header instead of
content
+ $etag = md5($content);
if
(isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] ==
$etag) {
header("ETag: \"$etag\"");
if ($this->lastModified) {
Added: incubator/shindig/trunk/php/src/common/JsMin.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/JsMin.php?rev=656630&view=auto
==============================================================================
--- incubator/shindig/trunk/php/src/common/JsMin.php (added)
+++ incubator/shindig/trunk/php/src/common/JsMin.php Thu May 15 05:39:15 2008
@@ -0,0 +1,290 @@
+<?php
+/**
+ * jsmin.php - PHP implementation of Douglas Crockford's JSMin.
+ *
+ * This is pretty much a direct port of jsmin.c to PHP with just a few
+ * PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
+ * outputs to stdout, this library accepts a string as input and returns
another
+ * string as output.
+ *
+ * PHP 5 or higher is required.
+ *
+ * Permission is hereby granted to use this version of the library under the
+ * same terms as jsmin.c, which has the following license:
+ *
+ * --
+ * Copyright (c) 2002 Douglas Crockford (www.crockford.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
copy of
+ * this software and associated documentation files (the "Software"), to deal
in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies
+ * of the Software, and to permit persons to whom the Software is furnished to
do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
all
+ * copies or substantial portions of the Software.
+ *
+ * The Software shall be used for Good, not Evil.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE
+ * SOFTWARE.
+ * --
+ *
+ * @package JSMin
+ * @author Ryan Grove <[EMAIL PROTECTED]>
+ * @copyright 2002 Douglas Crockford <[EMAIL PROTECTED]> (jsmin.c)
+ * @copyright 2008 Ryan Grove <[EMAIL PROTECTED]> (PHP port)
+ * @license http://opensource.org/licenses/mit-license.php MIT License
+ * @version 1.1.1 (2008-03-02)
+ * @link http://code.google.com/p/jsmin-php/
+ */
+
+class JsMinException extends Exception {}
+
+class JsMin {
+ const ORD_LF = 10;
+ const ORD_SPACE = 32;
+
+ protected $a = '';
+ protected $b = '';
+ protected $input = '';
+ protected $inputIndex = 0;
+ protected $inputLength = 0;
+ protected $lookAhead = null;
+ protected $output = '';
+
+ // -- Public Static Methods
--------------------------------------------------
+
+ public static function minify($js) {
+ $jsmin = new JsMin($js);
+ return $jsmin->min();
+ }
+
+ // -- Public Instance Methods
------------------------------------------------
+
+ public function __construct($input) {
+ $this->input = str_replace("\r\n", "\n", $input);
+ $this->inputLength = strlen($this->input);
+ }
+
+ // -- Protected Instance Methods
---------------------------------------------
+
+ protected function action($d) {
+ switch($d) {
+ case 1:
+ $this->output .= $this->a;
+
+ case 2:
+ $this->a = $this->b;
+
+ if ($this->a === "'" || $this->a === '"') {
+ for (;;) {
+ $this->output .= $this->a;
+ $this->a = $this->get();
+
+ if ($this->a === $this->b) {
+ break;
+ }
+
+ if (ord($this->a) <= self::ORD_LF) {
+ throw new JsMinException('Unterminated string literal.');
+ }
+
+ if ($this->a === '\\') {
+ $this->output .= $this->a;
+ $this->a = $this->get();
+ }
+ }
+ }
+
+ case 3:
+ $this->b = $this->next();
+
+ if ($this->b === '/' && (
+ $this->a === '(' || $this->a === ',' || $this->a === '=' ||
+ $this->a === ':' || $this->a === '[' || $this->a === '!' ||
+ $this->a === '&' || $this->a === '|' || $this->a === '?')) {
+
+ $this->output .= $this->a . $this->b;
+
+ for (;;) {
+ $this->a = $this->get();
+
+ if ($this->a === '/') {
+ break;
+ } elseif ($this->a === '\\') {
+ $this->output .= $this->a;
+ $this->a = $this->get();
+ } elseif (ord($this->a) <= self::ORD_LF) {
+ throw new JsMinException('Unterminated regular expression '.
+ 'literal.');
+ }
+
+ $this->output .= $this->a;
+ }
+
+ $this->b = $this->next();
+ }
+ }
+ }
+
+ protected function get() {
+ $c = $this->lookAhead;
+ $this->lookAhead = null;
+
+ if ($c === null) {
+ if ($this->inputIndex < $this->inputLength) {
+ $c = $this->input[$this->inputIndex];
+ $this->inputIndex += 1;
+ } else {
+ $c = null;
+ }
+ }
+
+ if ($c === "\r") {
+ return "\n";
+ }
+
+ if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
+ return $c;
+ }
+
+ return ' ';
+ }
+
+ protected function isAlphaNum($c) {
+ return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
+ }
+
+ protected function min() {
+ $this->a = "\n";
+ $this->action(3);
+
+ while ($this->a !== null) {
+ switch ($this->a) {
+ case ' ':
+ if ($this->isAlphaNum($this->b)) {
+ $this->action(1);
+ } else {
+ $this->action(2);
+ }
+ break;
+
+ case "\n":
+ switch ($this->b) {
+ case '{':
+ case '[':
+ case '(':
+ case '+':
+ case '-':
+ $this->action(1);
+ break;
+
+ case ' ':
+ $this->action(3);
+ break;
+
+ default:
+ if ($this->isAlphaNum($this->b)) {
+ $this->action(1);
+ }
+ else {
+ $this->action(2);
+ }
+ }
+ break;
+
+ default:
+ switch ($this->b) {
+ case ' ':
+ if ($this->isAlphaNum($this->a)) {
+ $this->action(1);
+ break;
+ }
+
+ $this->action(3);
+ break;
+
+ case "\n":
+ switch ($this->a) {
+ case '}':
+ case ']':
+ case ')':
+ case '+':
+ case '-':
+ case '"':
+ case "'":
+ $this->action(1);
+ break;
+
+ default:
+ if ($this->isAlphaNum($this->a)) {
+ $this->action(1);
+ }
+ else {
+ $this->action(3);
+ }
+ }
+ break;
+
+ default:
+ $this->action(1);
+ break;
+ }
+ }
+ }
+
+ return $this->output;
+ }
+
+ protected function next() {
+ $c = $this->get();
+
+ if ($c === '/') {
+ switch($this->peek()) {
+ case '/':
+ for (;;) {
+ $c = $this->get();
+
+ if (ord($c) <= self::ORD_LF) {
+ return $c;
+ }
+ }
+
+ case '*':
+ $this->get();
+
+ for (;;) {
+ switch($this->get()) {
+ case '*':
+ if ($this->peek() === '/') {
+ $this->get();
+ return ' ';
+ }
+ break;
+
+ case null:
+ throw new JsMinException('Unterminated comment.');
+ }
+ }
+
+ default:
+ return $c;
+ }
+ }
+
+ return $c;
+ }
+
+ protected function peek() {
+ $this->lookAhead = $this->get();
+ return $this->lookAhead;
+ }
+}
+
Modified: incubator/shindig/trunk/php/src/common/RemoteContentRequest.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/common/RemoteContentRequest.php?rev=656630&r1=656629&r2=656630&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/common/RemoteContentRequest.php (original)
+++ incubator/shindig/trunk/php/src/common/RemoteContentRequest.php Thu May 15
05:39:15 2008
@@ -39,10 +39,10 @@
}
// returns a hash code which identifies this request, used for caching
- // takes url and postbody into account for constructing the sha1
checksum
+ // takes url and postbody into account for constructing the md5 checksum
public function toHash()
{
- return sha1($this->url . $this->postBody);
+ return md5($this->url . $this->postBody);
}
public function getContentType()
Modified: incubator/shindig/trunk/php/src/gadgets/GadgetContext.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetContext.php?rev=656630&r1=656629&r2=656630&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetContext.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetContext.php Thu May 15
05:39:15 2008
@@ -149,9 +149,9 @@
{
// Profiling showed 40% of the processing time was spend in the
feature registry
// So by caching this and making it a one time initialization,
we almost double the performance
- if (! ($registry =
$this->getCache()->get(sha1(Config::get('features_path'))))) {
+ if (! ($registry =
$this->getCache()->get(md5(Config::get('features_path'))))) {
$registry = new
GadgetFeatureRegistry(Config::get('features_path'));
-
$this->getCache()->set(sha1(Config::get('features_path')), $registry);
+
$this->getCache()->set(md5(Config::get('features_path')), $registry);
}
return $registry;
}
Modified: incubator/shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php?rev=656630&r1=656629&r2=656630&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/GadgetFeatureRegistry.php Thu May
15 05:39:15 2008
@@ -22,11 +22,9 @@
private $features = array();
private $core = array();
private $coreDone = false;
- private $debug;
- public function __construct($featurePath, $debug = false)
+ public function __construct($featurePath)
{
- $this->debug = $debug;
$this->registerFeatures($featurePath);
}
@@ -36,7 +34,7 @@
return;
}
$coreDeps = array();
- $loader = new JsFeatureLoader($this->debug);
+ $loader = new JsFeatureLoader();
$jsFeatures = $loader->loadFeatures($featurePath, $this);
if (! $this->coreDone) {
foreach ($jsFeatures as $entry) {
Modified: incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php?rev=656630&r1=656629&r2=656630&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/JsFeatureLoader.php Thu May 15
05:39:15 2008
@@ -19,12 +19,6 @@
*/
class JsFeatureLoader {
- private $debug;
-
- public function __construct($debug)
- {
- $this->debug = $debug;
- }
public function loadFeatures($path, $registry)
{
Modified: incubator/shindig/trunk/php/src/gadgets/JsLibrary.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/JsLibrary.php?rev=656630&r1=656629&r2=656630&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/JsLibrary.php (original)
+++ incubator/shindig/trunk/php/src/gadgets/JsLibrary.php Thu May 15 05:39:15
2008
@@ -36,23 +36,23 @@
{
return $this->type;
}
-
- public function readfile()
- {
- // hack to bypass having the script in memory and dump it
directly to stdout
- if (!$this->loaded && $this->type == 'FILE') {
- readfile($this->content);
- echo "\n";
- } else {
- // a call to getContent was already made so we have it
in memory, just echo it then
- echo $this->content;
- }
- }
public function getContent()
{
if (!$this->loaded && $this->type == 'FILE') {
- $this->content = JsLibrary::loadData($this->content,
$this->type);
+ if (Config::get('compress_javascript')) {
+ $dataCache = Config::get('data_cache');
+ $dataCache = new $dataCache();
+ if (!($content =
$dataCache->get(md5($this->content)))) {
+ $content =
JSMin::minify(JsLibrary::loadData($this->content, $this->type));
+ $dataCache->set(md5($this->content),
$content);
+ $this->content = $content;
+ } else {
+ $this->content = $content;
+ }
+ } else {
+ $this->content =
JsLibrary::loadData($this->content, $this->type);
+ }
$this->loaded = true;
}
return $this->content;
Modified:
incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php?rev=656630&r1=656629&r2=656630&view=diff
==============================================================================
--- incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php
(original)
+++ incubator/shindig/trunk/php/src/gadgets/http/GadgetRenderingServlet.php Thu
May 15 05:39:15 2008
@@ -160,11 +160,11 @@
// servlet. We should probably inline external
JS as well.
$externJs .= sprintf($externFmt,
$library->getContent()) . "\n";
} else if ($type == 'INLINE') {
- $library->readfile();
+ echo $library->getContent();
} else {
// FILE or RESOURCE
if ($forcedLibs == null) {
- $library->readfile();
+ echo $library->getContent();
}
// otherwise it was already included by
config.forceJsLibs.
}