abc-team / ABC

Assets build center
5 stars 0 forks source link

关于CSS模块的多页面共用 #4

Closed neekey closed 11 years ago

neekey commented 11 years ago

不管是QuickPage还是SagePage(SinglePage由于其简单性,不大有这方面的问题),都存在一个CSS多页面共用的问题。

我们有util来解决JS组件多页面共用的问题,但是CSS貌似还没有一个公用的机制或者说是考虑。

SafePage

我们先来看看SafePage的设置(大体就是KISSY Pie的思路)

page1/
| ----- 1.0/
| ----- | ----- page/
| ----- | ----- | ----- page1.js
| ----- | ----- | ----- page1.css
| ----- | ----- | ----- page1.less
| ----- | ----- | ----- mods/
| ----- | ----- | ----- | ----- mods1.js
| ----- | ----- | ----- | ----- mods2.js
| ----- | ----- | ----- | ----- mods1.css
| ----- | ----- | ----- | ----- mods2.css
| ----- | ----- | ----- | ----- ...
| ----- 2.0/
| ----- ...
| ----- 20120203/
| ----- | ----- page/
| ----- | ----- | ----- page1.js(minify concat)
| ----- | ----- | ----- page1.css(minify concat)
| ----- 20120204/
| ----- ...
page2/

SafePage在具体page中没有额外将JS/CSS等目录做分离,而是并行放置,这在CSS文件模块划分力度比价小的情况下OK,但是当CSS模块较多,又和较多的JS文件混合,其实会有些乱...上面是题外话...恩恩,那么可以看到SafePage的设计貌似也是没有给出一个多页面共享CSS模块的机制。

QuickPage

首先QuickPage的特点是高位的包配置,而所谓的source这块的目录结构其实还没有深入讨论过,之前的:

---quickPage-------------------
init/
| ----- page1.js
| ----- page2.js
| ----- ...
| ----- page1.css
| ----- page2.css
| ----- ...
mods/
| ----- page1/
| ----- | ----- mod1.js
| ----- | ----- mod1.css
| ----- | ----- ...
| ----- page2/
| ----- ...
release/
| ----- 20120102/

的结构其实是针对亚城那边的结构来设定,其实不怎么典型,而且可以看到page1.js,page2.js这样并行放置是不合理的,因为不同页面的复杂度会有很大差别。

所以抛开这块,我们重新设计一下QuickPage部分的source目录:

quickPage
    // 所有的页面源文件
    ├ pages
        ├ page1
            // 根据几个大版本分割的版本目录
            ├ v1
            ├ v2
                // 脚本
                ├ js
         ├ page2
            // 根据几个大版本分割的版本目录
            ├ v1
            ├ v2
                // 脚本
                ├ js

上面的source部分的设计和SafePage类似,各page分离,也无法解决跨页面共享CSS模块的问题。

那么如果调整目录划分维度是不是可以解决这个问题?

quickPage
    // 所有的页面源文件
    ├ source
        ├ v1
            ├ js
                ├ page1
                    ├ index.js
                    ├ _mods_a.js
                    ├ _mods_b.js
                ├ page2
                    ├ index.js
            ├ less    
                ├ common
                    ├ button.less
                    ├ icon.less
                ├ page1
                    ├ index.less
                    ├ _mods_a.less
                ├ page2
                    ├ index.less

首先将assets type这一维度往上提,在每一个type中再做page的划分,另外去掉了page唯独下面的大版本号的划分,而是将版本放在最上方。通过这样的方式可以实现跨页面共享CSS模块的目的,但是带来的问题是:

目前运营平台这边(除了正在使用KISSY Pie的项目外),实质上都是采用上述的目录结构。

大家考虑下这个问题

daxingplay commented 11 years ago

css和js一样的,都可以放到utils目录下,这样就可以解决跨页面引用的问题了。

本身,很多时候,util的一个东西都会配合一个相应的样式。比如dialog,有dialog.js,理论上就应该有dialog.css,那么我个人建议都放在utils下,并且我个人觉得最佳实践就是这两个文件命名保持一致,这样,别人看到dialog.css就应该会想到他是dialog.css的样式。

对于引用,css combo就可以实现,写相对目录上去就可以了~我以前做二手的时候就这么用过。

再补充一点,css combo的模块和js模块稍微有些区别,毕竟是用原生的语法解决的,所以他本身不关心page和包,无论你的css在哪里,只要路径写对,就能引用到:)

daxingplay commented 11 years ago

对于你说分目录的问题,我觉得在page下的目录其实是你自己决定的。我们工具其实并不关心你page下的目录是叫mod还是叫module还是叫mokuai,还是叫任何其他你喜欢的名字。本身你在模块定义的时候都已经把这层目录写进去了,任何打包工具都不关心这层目录,所以你想把js和css分开放在不同的目录肯定是可以的。

只是我个人觉得,和刚才的reply一样,还是拿dialog举例,放在一起看起来比较方便,容易修改。如果你觉得文件太多,你可以细分mod这个目录嘛。

neekey commented 11 years ago

@daxingplay 嗯,可能我的意思没有明确。

你这边说的dialog组件放在util中,其可能包含两个文件:dialog.js以及dialog.css,那么我们在js中会

KISSY.add(function(){
    ...
}, { requires: [ 'utils/dialog' ] } );

那么在JS层面打包的时候会打入dialog.js的内容,但是dialog.css文件可能是动态引入的。

那么我换成button.less这样一个通用组件来看:

其实是希望能在各page的层面@import进来编译,如在page1/less/index.less中我希望能使用这个模块,我该怎么做?`@import "../../../../utils/button.less" ?

neekey commented 11 years ago

@daxingplay 会涉及到目录的设计,说白了,就是引用路径距离的问题,之前的思路是最顶层是page,所以他们子目录中的assets之间的距离是比较远的,所以想把asset type这个维度上提,来缩短引用距离

frontwindysky commented 11 years ago

assets-type这个维度如果放在page之上,内聚性不好,做一个需求要跨好大的距离去找js和css,就这一条当初讨论的时候就否定掉的,另外之前kissypie没有按assets-type来额外增加一个维度,是因为a.js和a.css及时放在一起相对来说比较清晰,文件名对应好,那么他们的位置基本上按照文件夹的排序是在一起的,两种文件的图标和后缀不一样也很容易区分,所以就放在一起好了

daxingplay commented 11 years ago

@neekey 我觉得这个引用路径距离是不可避免的问题。既然你的主文件(入口文件)不在这个目录下,想引用到更上层目录下的其他文件,肯定是要写一些../上去。对于js,kissy通过包配置的形式解决这个问题,相当于给这么多的../赋予了一个变量,那么在less里面,你也可以这么做吧?虽然我不是很清楚less是否支持这个。对于动态引用,kissy 1.3已经去掉了对fullpath的支持,我觉得把这个css文件打包到主文件也没啥太大问题吧?如果你用css combo,可以和less一样,直接import进来。

neekey commented 11 years ago

@daxingplay 距离不可避免,是长度的问题。上面举的例子,正常的如KP的目录,引用路径是

@Import "../../../../utils/button"

我觉得这个长度是不可接受而且可读性非常差的。然后通过目录变换,是为了让它可以达到

@import "../common/button"

其实想解决的就是这个问题。

然后不是针对less,我知道css combo是可以做的,SASS也一样,所以题设是“CSS 模块"。

要么要是能在util中也提供一套类似js的包的css模块机制,比如我可以写成

@import "utils/button.less"

这样倒是可以。

我上面提到的目录方案,只是个人的一个意见。发这个issue的初衷还是想要指出,在这个问题上,之前我们的讨论都还没有覆盖到,所以希望听听大家的意见

neekey commented 11 years ago

@frontwindysky 嗯,这个问题是顺带提一下,我的观点是数量少,混合到一起OK,但是多的时候都是裸堆着会很乱。不过这个问题如 @daxingplay 观点,不做目录限制,用户自然会根据实际需求自己做组织。这点是赞成的。这个问题是题外话.... 这个讨论还是集中到CSS 模块的跨页面服用上来吧

maxbbn commented 11 years ago

这个问题我之前也想过, 我们可以优化下CssCombo来解决这个问题,比如可以指定下Path

cssCombo.setPath('utils', 'path/to/utils');

CSS 里面 就可以通过

@import('utils/mod1.css');

来引用utils下面的css

maxbbn commented 11 years ago

lessc 里面就可以设置paths 和 rootPath

https://github.com/cloudhead/less.js/blob/master/bin/lessc#L15

neekey commented 11 years ago

@maxbbn 嗯,可能还是实现一种机制会比较靠谱,你说的这块紫英的CSS Combo 在js实现层面应该好解决路径问题,lessc看来也可以,那我觉得主流的这两种已经OK

其他的如SASS 我这边看看有没有相应配置

neekey commented 11 years ago

SASS 可以通过指定--load-path 来添加一个用于查找的路径: http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import

做了下尝试,可行:

dir/
 | ----- subDir/
 | ----- | ----- test.scss
 | ----- | ----- mod.scss
 | ----- | ----- sibDir
 | ----- | ----- | ----- base.scss
sibDir/
 | ----- base.scss
 | ----- common.scss

针对test.scss文件进行编译,命令为:

$ sass test.scss test.css --load-path ~/Dropbox/nodejs/app/sassPathTest/`

先把几个文件的内容列一下:

sibDir/common.scss:

body{ color: red; }

sibDir/base.scss:

a { color: red; }

dir/subDir/mod.scss:

div { color: yellow; }

dir/subDir/sibDir/base.scss:

a { color: yellow; }

这边的测试文件特地举出了下面几种情景:

OK,下面对几种情况进行测试:

首先,引入了外部模块和内部模块:

test.scss

@import "sibDir/common";
@import "mod";

test.css:

body{ color: red; }
div { color: yellow; }

然后我们将test.scss修改为:

@import "sibDir/common";
@import "sibDir/base"
@import "mod";

test.css:

body{ color: red; }
a { color: yellow }
div { color: yellow; }

总结

所以SASS的--load-path还是比较OK的,其原则基本上是

另外--load-path可以多次指定,也就说可以指定多个Additional search directories.

那么应该能达到的效果是:

neekey commented 11 years ago

@daxingplay @maxbbn 我重新开一个 https://github.com/abc-team/ABC/issues/8 ,我们把 CSS 模块迁入到utils中的方案放到那里讨论。