mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-04 01:01:41 +09:00
CSS/JS파일을 Optimizer 클래스를 통해 하나의 단일파일로 묶어서 출력하도록 출력 부분 수정
git-svn-id: http://xe-core.googlecode.com/svn/sandbox@2661 201d5d3c-b55e-5fd7-737f-ddc643e51545
This commit is contained in:
parent
6f15d2f388
commit
4ce386b736
6 changed files with 185 additions and 25 deletions
|
|
@ -121,6 +121,15 @@
|
|||
// 상대 경로 설정
|
||||
$this->path = $this->getRequestUri();
|
||||
|
||||
// 기본 JS/CSS 등록
|
||||
$this->addJsFile("./common/js/x.js");
|
||||
$this->addJsFile("./common/js/common.js");
|
||||
$this->addJsFile("./common/js/xml_handler.js");
|
||||
$this->addJsFile("./common/js/xml_js_filter.js");
|
||||
$this->addCSSFile("./common/css/default.css");
|
||||
$this->addCSSFile("./common/css/button.css");
|
||||
if(Context::get('module')=='admin' || strpos(Context::get('act'),'Admin')>0) $this->addCssFile("./modules/admin/tpl/css/admin.css");
|
||||
|
||||
// rewrite module때문에 javascript에서 location.href 문제 해결을 위해 직접 실제 경로 설정
|
||||
if($_SERVER['REQUEST_METHOD'] == 'GET') {
|
||||
if($this->get_vars) {
|
||||
|
|
@ -676,6 +685,8 @@
|
|||
**/
|
||||
function _addJsFile($file) {
|
||||
if(in_array($file, $this->js_files)) return;
|
||||
|
||||
if(!eregi("^http:\/\/",$file)) $file = str_replace(realpath("."), ".", realpath($file));
|
||||
$this->js_files[] = $file;
|
||||
}
|
||||
|
||||
|
|
@ -691,7 +702,9 @@
|
|||
* @brief js file 목록을 return
|
||||
**/
|
||||
function _getJsFile() {
|
||||
return $this->js_files;
|
||||
require_once("./classes/optimizer/Optimizer.class.php");
|
||||
$oOptimizer = new Optimizer();
|
||||
return $oOptimizer->getOptimizedFiles($this->js_files, "js");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -707,6 +720,8 @@
|
|||
**/
|
||||
function _addCSSFile($file) {
|
||||
if(in_array($file, $this->css_files)) return;
|
||||
|
||||
if(!eregi("^http:\/\/",$file)) $file = str_replace(realpath("."), ".", realpath($file));
|
||||
$this->css_files[] = $file;
|
||||
}
|
||||
|
||||
|
|
@ -722,7 +737,9 @@
|
|||
* @brief CSS file 목록 return
|
||||
**/
|
||||
function _getCSSFile() {
|
||||
return $this->css_files;
|
||||
require_once("./classes/optimizer/Optimizer.class.php");
|
||||
$oOptimizer = new Optimizer();
|
||||
return $oOptimizer->getOptimizedFiles($this->css_files, "css");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -923,5 +940,18 @@
|
|||
return WidgetHandler::execute($widget, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief gzip encoding 여부 체크
|
||||
**/
|
||||
function isGzEnabled() {
|
||||
if(
|
||||
(defined('__OB_GZHANDLER_ENABLE__') && __OB_GZHANDLER_ENABLE__ == 1) &&
|
||||
strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')!==false &&
|
||||
function_exists('ob_gzhandler') &&
|
||||
extension_loaded('zlib')
|
||||
) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
|
|
|||
|
|
@ -22,12 +22,7 @@
|
|||
function printContent(&$oModule) {
|
||||
|
||||
// gzip encoding 지원 여부 체크
|
||||
if(
|
||||
(defined('__OB_GZHANDLER_ENABLE__') && __OB_GZHANDLER_ENABLE__ == 1) &&
|
||||
strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')!==false &&
|
||||
function_exists('ob_gzhandler') &&
|
||||
extension_loaded('zlib')
|
||||
) $this->gz_enabled = true;
|
||||
$this->gz_enabled = Context::isGzEnabled();
|
||||
|
||||
// header 출력
|
||||
$this->_printHeader();
|
||||
|
|
|
|||
144
classes/optimizer/Optimizer.class.php
Normal file
144
classes/optimizer/Optimizer.class.php
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
/**
|
||||
* @class Optimizer
|
||||
* @author zero (zero@nzeo.com)
|
||||
* @brief JS/CSS파일등을 특정한 규칙에 맞게 하나의 파일로 만들어서 client에서 가져갈 수 있도록 성능향상을 지원하는 클래스
|
||||
*
|
||||
* 일단 내부적인 코드가 아무리 튜닝이 되어도 모듈/애드온/위젯/에디터컴포넌트등 각 요소들의 JS/CSs파일들을 잘라서 호출하는 구조이기에
|
||||
* 사용자의 브라우저에서는 최소 10이상의 파일을 별도로 서버에 요청을 하게 된다.
|
||||
* 이를 방지하기 위해서 서버내의 로컬 파일일 경우 하나로 묶어서 클라이언트에서 가져갈 수 있도록 하여 그 효과를 증대시킴.
|
||||
**/
|
||||
|
||||
class Optimizer {
|
||||
|
||||
var $cache_path = "./files/cache/optimized/";
|
||||
|
||||
/**
|
||||
* @brief optimizer에서 캐싱파일을 저장할 곳을 찾아서 없으면 만듬
|
||||
**/
|
||||
function Optimizer() {
|
||||
if(!is_dir($this->cache_path)) {
|
||||
FileHandler::makeDir($this->cache_path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief optimize 대상 파일을 받아서 처리 후 optimize 된 파일이름을 return
|
||||
**/
|
||||
function getOptimizedFiles($source_files, $type = "js") {
|
||||
$file_count = count($source_files);
|
||||
for($i=0;$i<$file_count;$i++) {
|
||||
$file = trim($source_files[$i]);
|
||||
if(!$file) continue;
|
||||
if(eregi("^http:\/\/",$file)) $files[] = $file;
|
||||
else $targets[] = $file;
|
||||
}
|
||||
|
||||
if(!count($targets)) return $files;
|
||||
|
||||
$hashed_filename = $this->getHashFilename($targets);
|
||||
|
||||
$filename = sprintf("%s%s.%s.php", $this->cache_path, $hashed_filename, $type);
|
||||
|
||||
$this->doOptimizedFile($filename, $targets, $type);
|
||||
|
||||
$files[] = $filename;
|
||||
|
||||
return $files;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief optimize는 대상 파일을 \n로 연결후 md5 hashing하여 파일이름의 중복을 피함
|
||||
**/
|
||||
function getHashFilename($files) {
|
||||
$buff = implode("\n", $files);
|
||||
return md5($buff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 이미 저장된 캐시 파일과의 시간등을 검사하여 새로 캐싱해야 할지를 체크
|
||||
**/
|
||||
function doOptimizedFile($filename, $targets, $type) {
|
||||
if(!file_exists($filename)) return $this->makeOptimizedFile($filename, $targets, $type);
|
||||
|
||||
$file_count = count($targets);
|
||||
|
||||
$mtime = filemtime($filename);
|
||||
for($i=0;$i<$file_count;$i++) {
|
||||
if($mtime < filemtime($targets[$i])) return $this->makeOptimizedFile($filename, $targets, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief css나 js파일을 묶어서 하나의 파일로 만들고 gzip 압축이나 헤더등을 통제하기 위해서 php파일을 별도로 만들어서 진행함
|
||||
**/
|
||||
function makeOptimizedFile($filename, $targets, $type) {
|
||||
/**
|
||||
* 실제 css나 js의 내용을 합친 것을 구함
|
||||
**/
|
||||
// 대상 파일의 내용을 구해오고 css 파일일 경우 url()내의 경로를 변경
|
||||
$file_count = count($targets);
|
||||
for($i=0;$i<$file_count;$i++) {
|
||||
$file = $targets[$i];
|
||||
$str = FileHandler::readFile($file);
|
||||
|
||||
// css 일경우 background:url() 변경
|
||||
if($type == "css") $str = $this->replaceCssPath($file, $str);
|
||||
|
||||
$content_buff .= $str."\n";
|
||||
}
|
||||
if(Context::isGzEnabled()) $content_buff = ob_gzhandler($content_buff, 5);
|
||||
$content_file = eregi_replace("\.php$","",$filename);
|
||||
$content_filename = str_replace($this->cache_path, '', $content_file);
|
||||
|
||||
FileHandler::writeFile($content_file, $content_buff);
|
||||
|
||||
/**
|
||||
* 압축을 지원하고 캐시 타임을 제대로 이용하기 위한 헤더 파일 구함
|
||||
**/
|
||||
// php의 헤더파일 생성
|
||||
$modified_time = gmdate("D, d M Y H:i:s");
|
||||
|
||||
// gzip 압축 체크
|
||||
if(Context::isGzEnabled()) $gzip_header = 'header("Content-Encoding: gzip");';
|
||||
|
||||
// 확장자별 content-type 체크
|
||||
if($type == 'css') $content_type = 'text/css';
|
||||
elseif($type == 'js') $content_type = 'text/javascript';
|
||||
|
||||
$header_buff = <<<EndOfBuff
|
||||
<?php
|
||||
header("Content-Type: {$content_type}; charset=UTF-8");
|
||||
//header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
|
||||
header("Last-Modified: {$modified_time} GMT");
|
||||
//header("Cache-Control: no-store, no-cache, must-revalidate");
|
||||
//header("Cache-Control: post-check=0, pre-check=0", false);
|
||||
//header("Pragma: no-cache");
|
||||
{$gzip_header}
|
||||
if(@file_exists("{$content_filename}")) {
|
||||
@fpassthru(fopen("{$content_filename}", "rb"));
|
||||
}
|
||||
exit();
|
||||
?>
|
||||
EndOfBuff;
|
||||
|
||||
FileHandler::writeFile($filename, $header_buff);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief css의 경우 import/ background 등의 속성에서 사용되는 url내의 경로를 변경시켜줌
|
||||
**/
|
||||
function replaceCssPath($file, $str) {
|
||||
$this->tmp_css_path = Context::getRequestUri().ereg_replace("^\.\/","",dirname($file))."/";
|
||||
$str = preg_replace_callback('!url\(("|\'){0,1}([^\)]+)("|\'){0,1}\)!is', array($this, '_replaceCssPath'), $str);
|
||||
return $str;
|
||||
}
|
||||
|
||||
function _replaceCssPath($matches) {
|
||||
if(eregi("^http",$matches[2])) return $matches[0];
|
||||
return sprintf('url(%s)', $this->tmp_css_path.$matches[2]);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
{@ $js_files = Context::getJsFile() }{@ $css_files = Context::getCssFile() }<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html lang="{Context::getLangType()}" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
|
|
@ -9,16 +9,9 @@
|
|||
<!--@end--><!--@if($layout->author)--><meta name="layout_maker" content="{$layout_info->author->name} ({$layout_info->author->homepage})" />
|
||||
<!--@end--><meta http-equiv="imagetoolbar" content="no" />
|
||||
<title>{Context::getBrowserTitle()}</title>
|
||||
<script type="text/javascript" src="./common/js/x.js?rnd={time()}"></script>
|
||||
<script type="text/javascript" src="./common/js/common.js?rnd={time()}"></script>
|
||||
<script type="text/javascript" src="./common/js/xml_handler.js?rnd={time()}"></script>
|
||||
<script type="text/javascript" src="./common/js/xml_js_filter.js?rnd={time()}"></script>
|
||||
<!--@foreach(Context::getJsFile() as $key => $js_file)--><script type="text/javascript" src="{$js_file}?rnd={time()}"></script>
|
||||
<!--@foreach($js_files as $key => $js_file)--><script type="text/javascript" src="{$js_file}"></script>
|
||||
<!--@end--><!--@foreach($css_files as $key => $css_file)--><link rel="stylesheet" href="{$css_file}" type="text/css" />
|
||||
<!--@end--><!--@if($rss_url)--><link rel="alternate" type="application/rss+xml" title="RSS 2.0" href="{$rss_url}" />
|
||||
<!--@end--><link rel="stylesheet" href="./common/css/default.css?rnd={time()}" type="text/css" />
|
||||
<link rel="stylesheet" href="./common/css/button.css?rnd={time()}" type="text/css" />
|
||||
<!--@foreach(Context::getCssFile() as $key => $css_file)--><link rel="stylesheet" href="{$css_file}?rnd={time()}" type="text/css" />
|
||||
<!--@end--><!--@if($module=='admin' || strpos($act,'Admin')>0)--><link rel="stylesheet" href="./modules/admin/tpl/css/admin.css?rnd={time()}" type="text/css" />
|
||||
<!--@end--><script type="text/javascript">//<![CDATA[
|
||||
var current_url = "{$current_url}";
|
||||
var request_uri = "{$request_uri}";
|
||||
|
|
@ -32,8 +25,6 @@
|
|||
<body>
|
||||
{$zbxe_final_content}
|
||||
|
||||
{Context::getHtmlFooter()}
|
||||
|
||||
<div id="waitingforserverresponse" style="visibility:hidden"></div>
|
||||
<div id="fororiginalimagearea" style="visibility:hidden">
|
||||
<div id="fororiginalimageareabg">
|
||||
|
|
@ -43,5 +34,7 @@
|
|||
</div>
|
||||
<div id="membermenuarea"></div>
|
||||
|
||||
{Context::getHtmlFooter()}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<!--%import("css/popup.css")-->
|
||||
<!--%import("../../modules/admin/tpl/css/admin.css")-->
|
||||
<div id="popup_content">{$content}</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
/**
|
||||
* 에디터에서 사용하는 iframe, textarea의 prefix
|
||||
**/
|
||||
var iframe_id = 'editor_iframe_'; ///< 에디터로 사용하는 iframe의 prefix
|
||||
var textarea_id = 'editor_textarea_'; ///< 에디터의 html편집 모드에서 사용하는 textarea의 prefix
|
||||
var editor_mode = new Array(); ///<< 에디터의 html편집 모드 flag 세팅 변수
|
||||
var _editorSyncList = new Array(); ///< 에디터와 form 동기화를 위한 동기화 대상 목록
|
||||
var _autoSaveObj = {fo_obj:null, editor_sequence:0, title:'', content:'', locked:false} ///< 자동저장을 위한 정보를 가진 object
|
||||
|
|
@ -26,13 +24,13 @@ xAddEventListener(window, 'load', _editorSync); ///< 에디터의 동기화를
|
|||
|
||||
// editor_sequence값에 해당하는 iframe의 object를 return
|
||||
function editorGetIFrame(editor_sequence) {
|
||||
var obj_id = iframe_id + editor_sequence;
|
||||
var obj_id = 'editor_iframe_'+ editor_sequence;
|
||||
return xGetElementById(obj_id);
|
||||
}
|
||||
|
||||
// editor_sequence값에 해당하는 textarea object를 return
|
||||
function editorGetTextArea(editor_sequence) {
|
||||
var obj_id = textarea_id + editor_sequence;
|
||||
var obj_id = 'editor_textarea_' + editor_sequence;
|
||||
return xGetElementById(obj_id);
|
||||
}
|
||||
|
||||
|
|
@ -830,4 +828,3 @@ function closeEditorInfo(editor_sequence) {
|
|||
expire.setTime(expire.getTime()+ (7000 * 24 * 3600000));
|
||||
xSetCookie('EditorInfo', '1', expire);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue