引入:

上文中我们已经提到了如果设置了css_fast_load=1,会进入Minifier Filter之后,对minifyCss方法进行调用,而如果设置css_fast_load=0,那么就算进入Minifier Filter,也不会对minifyCss方法进行调用。我们这片文章的重点是研究这个方法。


调试分析:

Liferay 中Minifier Filter的minifyCss 奥秘窥探_第1张图片

从这里可以看出,从宏观上,这个方法先会去读取原始迷你化之前的css文件(比如我们的platform-In-theme/css/main.css)文件,

Liferay 中Minifier Filter的minifyCss 奥秘窥探_第2张图片

然后调用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文件:

Liferay 中Minifier Filter的minifyCss 奥秘窥探_第3张图片


然后调用重载的minifyCss()方法,吧刚才产生的合并后的content,以及这个目标文件的真实路径作为入参传递进去:

Liferay 中Minifier Filter的minifyCss 奥秘窥探_第4张图片


然后调用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文件:

Liferay 中Minifier Filter的minifyCss 奥秘窥探_第5张图片

压缩后的css文件:

对比下,发现注释被去掉了,一些该合并的被合并了,尺寸被大大缩小了


最后吧这个结果放入ServletOutputStream中,我们和最终返回到页面上的比较,发现是完全一致的。

Liferay 中Minifier Filter的minifyCss 奥秘窥探_第6张图片



总结

从以上简单的分析中我们可以有以下结论:

(1)minifyCss会先把所有的@import url()外部进入的css文件递归插入。

(2)其次,它会吧插入完的大的css文件中利用parseSass()方法去除其中的sass标记,还原为普通css文件。

(3)再次它会消除ie的特殊行为。

(4)最后它会用yui-compressor对于这个css文件进行压缩,包括合并相似样式,去除注解,去除空白等。