fex-team / fis

Front-end Integrated Solution - 前端集成解决方案, 最新版请进入 FIS3 https://github.com/fex-team/fis3
http://fis.baidu.com
MIT License
2.96k stars 654 forks source link

[草稿] 配置格式新尝试 #90

Open hefangshi opened 10 years ago

hefangshi commented 10 years ago

配置格式新尝试

目前想法还比较粗略,结果也不是特别满意,仅用于抛砖引玉

示例

前端项目构建

fis.when("**.(js|coffe)")
    //启动流程分支处理coffee
    .children("**.coffee")
    .parse({
      ext:"js"
    })
    .end()
    //启动流程分支处理modules下的文件
    .children(/^\/modules\/(.*).js$/)
    .id("$1")
    //包裹CommonJs规范
    .wrap()
    .end()
  .standard()
  //添加配置调用pack
  .pack({
    "/static/pkg/lib.js": 
       "/lib/mod.js",
       "/modules/jquery/**"
     ]
  })
  .optimize()
  .dest('/static/$&')

// lazy表示不会直接调用,而是通过其余流程启动
fis.lazy("**.tmpl")
  .attr('isHtmlLike', true)
  .standard()
  .parse()
  .attr('isJsLike', true)
  .dest(false)

流程外置

fis.lazy("**.coffee")
  .parse({
    ext:"js"
  })

fis.lazy(/^\/modules\/(.*).js$/)
  .id("$1")
  //包裹CommonJs规范
  .wrap()
  .end()

fis.when("**.(js|coffee)")
  //声明主流程名称
  .flow("script")
  .standard()
  //添加配置调用pack
  .pack({
    "/static/pkg/lib.js": 
       "/lib/mod.js",
       "/modules/jquery/**"
     ]
  })
  .optimize()
  .md5()
  .dest('/static/$&')

//通过for确定递归编译时使用哪个流程
fis.lazy("**.tmpl")
  .for("script")
  .attr('isHtmlLike', true)
  .standard()
  .parse()
  .attr('isJsLike', true)
  .dest(false)

//script流程进行递归编译时不会被调用
fis.lazy("**.tmpl")
  .parse({
    ext:"js"
  })
  .attr('isJsLike', true)
  .standard()

类库构建

fis.lazy("**.coffee")
  .parse({
    ext:"js"
  })

fis.when("somelib/**.(js|coffee)")
    .pack({
      "/pkg/lib.js": ["**.js"]
    })
    .children(/(\/pkg\/.*)\.js/i)
    .dest("$1.js")
    .optimize()
    .dest("$1.min.js")

总结

原则

fouber commented 10 years ago
  1. 贴一下fis-plus基于这个是什么样的配置
  2. 基于这个配置的fis-plus,用户使用过程中如何增加一个规范?(之前是fis.config.get('roadmap.path').unshif(...))
  3. 基于这个配置的fis-plus,用户使用过程中如何增加一个流程?(之前是fis.config.set('modules.postpackager', [ plugin_1, my_plugin, plugin_2 ]))
  4. csssprite是怎么配置的?
hefangshi commented 10 years ago

实现一个fis-plus的配置后果然有一些新的看法,不过还是把我的实现贴出来吧,只实现了主要部分,压缩部分需要包装一下处理压缩开关。

fis-plus配置

fis.when("**.tpl")
    .extlang()
    .standard()
    .smartyxss()
    .htmlcompress()
    .dest("/template/${namespace}/$&");

fis.on(/^\/widget\/(.*\.tpl)$/i)
    .attr('isMod', true)
    .url('${namespace}/widget/$1');

fis.on(/^\/page\/(.+\.tpl)$/i)
    .attr({
        isMod: true,
        extras: {
            isPage: true
        }
    });

fis.when(/^\/widget\/(.*\.js)$/i)
    .attr('isMod', true)
    .standard()
    .jswrapper({
        type: 'amd'
    })
    .requireasync()
    .uglifyjs()
    .dest("${statics}/${namespace}$&");

fis.when(/^\/widget\/(.*\.css)$/i)
    .standard()
    .cleancss()
    .dest("${statics}/${namespace}$&");

fis.on("**.tmpl")
    .attr('isHtmlLike', true)
    .standard()
    .bdtmpl({
        LEFT_DELIMITER : '<#',
        RIGHT_DELIMITER : '#>'
    })
    .attr('isJsLike', true)
    .dest(false);

fis.on("**.less")
    .less({
        ext: "css"
    });

fis.when("**")
    .dest("${statics}/${namespace}$&");

//以下是FIS自带的基本配置
fis.on("**.js")
    .standard()
    .uglifyjs();

fis.on("**.css")
    .standard()
    .cleancss();

fis.on("**.png")
    .standard()
    .pngcompress();

增加一个规范

覆盖增加(类似目前的形式)

fis.when(/^\/widget\/(.*\.css)$/i)
    .standard()
    .cleancss()
    .dest("${statics}/${namespace}/css/$&");

针对特定文件增加规范

无法完备的增加流程规范,但是对于编译属性的添加比较自然

fis.on("/widget/widgetA/a.sass")
    .attr("useHash", false)
    .sass()

增加一个流程

上述这种写法对于增加流程的确弱于以前的扩展点的形式,但是通过一些trick,我们依然可以保留原有的扩展方式

比如依然使用optimize而不是uglifyjs, cleanss,然后根据后缀名进行配置

fis.optimize = fis.extRouter({
    "js" : "uglifyjs",
    "css": "cleancss",
    "tpl": "smartyxss,htmlcompress"
});

fis.when("**.js")
    .standard()
    .optimize()
    .dest();

这样就可以基于后缀名进行统一扩展

打包配置

无论是pack还是csssprite,我觉得目前配置的效果还不错,上述配置都只是单文件流程的配置,单文件与打包的配合可以后面再考虑,因为这种配置模式只是做一个尝试。

回头来看,也许我们在目前的配置基础上做一些改进

  1. 增加一个流程顺序调整
  2. 调整roadmap.path的merge能力,使merge = unshift让用户认知统一
  3. 添加一个新的接口专门用于文件编译属性的设置(合并而不是靠优先级设置)

就可以实现上面这些折腾一样的效果了呢?

hefangshi commented 10 years ago

目前想动配置的主要起因还是

  1. 解决流程固化导致部分特殊需求不好实现的问题。
  2. unshift的使用方法比较生僻,当然这是解决方案与自定义配置之间的冲突问题,我觉得直接将merge实现为unshift就可以解决。
  3. 大部分使用者都会被规则的优先级问题坑,仅仅希望对某一个文件作一个细微调整就要找到原有的规则将其余配置手动继承,很不自然,也不利于维护。
fouber commented 10 years ago
  1. 被固化的流程是一种经验值。fis1时代是可配的,后来发现所有的处理都是一个相同的流程,到fis2就固化了
  2. 可调序的流程容易引起一些不必要的错误,比如没有调用standard,这是不合理的
  3. 内核其实只是在语义上约定了流程,极个别情况下可以在一个阶段里干另外一个阶段的事情,甚至完全不要整个compile,直接在打包阶段重新实现构建流程,只是退化到了gulp而已,上面展示的改进设计有这样的趋势。
  4. 规范可以轻易修改,这不是应该被期许的功能,还是那句话,应该加强对规范的设计要求,而不是增加后门允许规范被最终用户打乱。一旦这样的缺口被打开了,类似百度这样有30多个产品线使用fis-plus的情况,未来如果要做一些统一的架构调整将成为自己给自己挖的深坑。
oxUnd commented 10 years ago

每次FIS后来来的同学都会问

其实,这些都是FIS在成型过程中踩过的一个又一个坑。 就对于第一条,前面由于没有写明具体的版本号引发的问题。如果真的安装到了项目目录,那问题也会出现更多,而且出问题了无从查起。

@fouber 说的第四点也是很重要的,如果不是固定的工具输出,其后续做解决方案就很蛋疼。