引入:
上文中我们已经提到了如果设置了css_fast_load=1,会进入Minifier Filter之后,对minifyCss方法进行调用,而如果设置css_fast_load=0,那么就算进入Minifier Filter,也不会对minifyCss方法进行调用。我们这片文章的重点是研究这个方法。
调试分析:
从这里可以看出,从宏观上,这个方法先会去读取原始迷你化之前的css文件(比如我们的platform-In-theme/css/main.css)文件,
然后调用aggregateCss()方法来递归的聚合css,这个方法是递归方法,会递归的吧多个资源文件合并到一个文件中。我们来看下它的实现:
public static String aggregateCss(String dir, String content) throws IOException { StringBuilder sb = new StringBuilder(content.length()); int pos = 0; while (true) { int commentX = content.indexOf(_CSS_COMMENT_BEGIN, pos); int commentY = content.indexOf( _CSS_COMMENT_END, commentX + _CSS_COMMENT_BEGIN.length()); int importX = content.indexOf(_CSS_IMPORT_BEGIN, pos); int importY = content.indexOf( _CSS_IMPORT_END, importX + _CSS_IMPORT_BEGIN.length()); if ((importX == -1) || (importY == -1)) { sb.append(content.substring(pos, content.length())); break; } else if ((commentX != -1) && (commentY != -1) && (commentX < importX) && (commentY > importX)) { commentY += _CSS_COMMENT_END.length(); sb.append(content.substring(pos, commentY)); pos = commentY; } else { sb.append(content.substring(pos, importX)); String importFileName = content.substring( importX + _CSS_IMPORT_BEGIN.length(), importY); String importFullFileName = dir.concat(StringPool.SLASH).concat( importFileName); String importContent = FileUtil.read(importFullFileName); if (importContent == null) { if (_log.isWarnEnabled()) { _log.warn( "File " + importFullFileName + " does not exist"); } importContent = StringPool.BLANK; } String importDir = StringPool.BLANK; int slashPos = importFileName.lastIndexOf(CharPool.SLASH); if (slashPos != -1) { importDir = StringPool.SLASH.concat( importFileName.substring(0, slashPos + 1)); } importContent = aggregateCss(dir + importDir, importContent); int importDepth = StringUtil.count( importFileName, StringPool.SLASH); // LEP-7540 String relativePath = StringPool.BLANK; for (int i = 0; i < importDepth; i++) { relativePath += "../"; } importContent = StringUtil.replace( importContent, new String[] { "url('" + relativePath, "url(\"" + relativePath, "url(" + relativePath }, new String[] { "url('[$TEMP_RELATIVE_PATH$]", "url(\"[$TEMP_RELATIVE_PATH$]", "url([$TEMP_RELATIVE_PATH$]" }); importContent = StringUtil.replace( importContent, "[$TEMP_RELATIVE_PATH$]", StringPool.BLANK); sb.append(importContent); pos = importY + _CSS_IMPORT_END.length(); } } return sb.toString(); }
从上面可以看出,它先会先把所有的@import url()这种外部导入的文件递归的导入,合并为一个大的css文件:
然后调用重载的minifyCss()方法,吧刚才产生的合并后的content,以及这个目标文件的真实路径作为入参传递进去:
然后调用DynamicCSSUtil的parseSass方法,吧这个合并的css文件中的全部Sass语法解析掉,成为一个普通的大的css文件。
紧接着,它会调用如下代码:
If(!browserId.equals(BrowserSniffer.BROWSER_ID_IE) Matcher matcher= _pattern.matcher(content); Content=matcher. replaceAll(StringPool.BLANK); }
这段代码是消除ie的负面css影响。
然后再调用私有的重载的minifyCss方法,这是利用YuiCompressor的CssCompressor对于刚才的大的css文件进行压缩,变为小的css文件。最后结果放入输出流。
压缩前的css文件:
压缩后的css文件:
对比下,发现注释被去掉了,一些该合并的被合并了,尺寸被大大缩小了
最后吧这个结果放入ServletOutputStream中,我们和最终返回到页面上的比较,发现是完全一致的。
总结:
从以上简单的分析中我们可以有以下结论:
(1)minifyCss会先把所有的@import url()外部进入的css文件递归插入。
(2)其次,它会吧插入完的大的css文件中利用parseSass()方法去除其中的sass标记,还原为普通css文件。
(3)再次它会消除ie的特殊行为。
(4)最后它会用yui-compressor对于这个css文件进行压缩,包括合并相似样式,去除注解,去除空白等。