引入:

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

调试分析:

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

然后调用aggregateCss()方法来递归的聚合css,这个方法是递归方法,会递归的吧多个资源文件合并到一个文件中。我们来看下它的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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文件。

紧接着,它会调用如下代码:

1
2
3
4
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文件进行压缩,包括合并相似样式,去除注解,去除空白等。

本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1284092,如需转载请自行联系原作者

Liferay 中Minifier Filter的minifyCss 奥秘窥探相关推荐

  1. Liferay Dynamic CSS Filter方法的研究 - 总体过程

    背景知识: 最近项目组遇到一个问题就是改了一个new theme之后导致某些css文件不起作用了,这也激起了我的好奇心,让我有机会去研究下Liferay Dynamic CSS Filter的原理. ...

  2. SpringBoot学习之路:09.Spring Boot中添加Filter应用

    2019独角兽企业重金招聘Python工程师标准>>> 上篇文章中说了SpringBoot中是如何使用servlet的,本文将讲解在SpringBoot中对过滤器Filter的实现 ...

  3. Java Web中的Filter和Interceptor的区别

    2019独角兽企业重金招聘Python工程师标准>>> 1.问题的来源 项目中使用了Filter,进行白名单的控制,同时使用了Filter进行了跨域请求的控制,使用了Intercep ...

  4. javaweb过滤器_JavaWeb技术(2):SpringMVC中的Filter

    Filter顾名思义就是过滤器,在JavaWeb体系中,他在服务端,卡在请求/响应与Servlet之间做一些操作: 过滤器相关的类的顶层接口如下,以下方法都由Web容器自动调用: package 你可 ...

  5. vue 中的el表达式_Vue中vue.filter()的使用方法介绍(过滤)

    本篇文章给大家带来的内容是关于Vue中vue.filter()的使用方法介绍(过滤),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. Vue过滤器 {{msg |msgFormat}} ...

  6. web.xml 中的filter

    Servlet API的2.3版本中最重要的一个新功能就是能够为servlet和JSP页面定义过滤器.过滤器提供了某些早期服务器所支持的非标准"servlet链接"的一种功能强大且 ...

  7. Python3中的 Filter的改变

    在python3中,filter处理之后,变成了一个可迭代对象,解决办法有2中: ① 切成python2 ② 在filter外面套一层list df = df.dropna() lines=df.co ...

  8. JS中 map, filter, some, every, forEach, for in, for of 用法总结

    for.for in和for of和forEach的区别:http://blog.sina.com.cn/s/blog_c112a2980102xqg9.html JS中 map, filter, s ...

  9. 数组中的filter方法_数组filter()方法以及JavaScript中的示例

    数组中的filter方法 JavaScript filter()方法 (JavaScript filter() method) filter() method is used to returns a ...

最新文章

  1. 项目管理ppt_「PPT」几近满分的项目管理PPT干货
  2. 60幅精美绝伦的绘景(Matte Paintings)作品欣赏(上篇)
  3. C语言实现斐波那契搜索Fibonacci search算法(附完整源码)
  4. element UI 单选框设置默认选中值
  5. 扩展CheckBoxList实现选中绑定
  6. ssl证书的生成与签名
  7. 巧用DBGrid控件的Sort属性实现“点击标题栏自动排序功能”。(改进版本)
  8. bootstrap 输入错误提示_网上体育用品商城(ssm,mysql,bootstrap,html,css)
  9. Linux拷贝分区内容,dd复制分区后目标分区的大小变成原分区了
  10. linux info命令详解,Linux info 命令简介
  11. 习题--答案--22/6/8
  12. 用《圣经》做训练数据集,达特茅斯学院完美打造语言风格转换工具
  13. 电影《失控玩家》:软件2.0,让游戏角色“觉醒”了?
  14. RK3399平台开发系列讲解(其他篇)1.31、 什么是虚拟化
  15. 牛客每日练习----あなたの蛙が帰っています,おみやげをまらいました,写真がとどいています
  16. MacOS使用conan
  17. 使用Requests库+re库爬取猫眼电影评分
  18. 遥感影像分类算法C++实现(一)
  19. 英国python工资_就业强势起薪高?英国BA硕士哪家强?!
  20. FGH60N60SMD 60A600V IGBT单管在工业逆变应用中的解决方案

热门文章

  1. xib加载的两种方式
  2. 大数据之-Hadoop3.x_MapReduce_二次排序案例---大数据之hadoop3.x工作笔记0116
  3. C++提高部分_C++普通函数与函数模板的区别---C++语言工作笔记084
  4. 持续集成部署Jenkins工作笔记0011---配置构建命令并手动执行一次构建
  5. 移动APP开发工作笔记002---Hbuilder js判断当前设备是安卓设备还是苹果设备
  6. Android零碎要点---eclipse两个小技巧
  7. Android学习笔记06---电话拨号器的制作:项目结构深化
  8. JPA学习笔记---JPA理解---第一个JPA程序
  9. resnet18 参数解读
  10. CSS样式重叠,前端显示的效果