微博登录后即可参与讨论。
berg

FIS VS coolie vs webpack 论战 14个回复 专栏 @ FIS

berg 发布于 1 年前

QQ群里已经聊得如火如荼,把聊天记录贴出来,缺了若干图片,大家根据上下文理解吧~

提示,里面的「真·berg」是 @前端农民工 哦。

我觉得很多事情还是要讨论的,尤其是针锋相对的讨论。只是看文章写文章隔空对阵,没有直接的对话,很多问题讨论不明白。更重要的是,大家都有意无意的会在文章中忽略对手的优点,突出自己的特点,读者就更迷糊了。

聊天记录

云淡然() 14:37:15

coolie 能做
JS 文件的分析、合并、压缩、版本管理
CSS 文件的分析、合并、压缩、版本管理
HTML 文件分析、压缩、版本管理
入口模块的分析、分块、合并、压缩、版本管理
静态资源的分析、压缩、版本管理

我是 Berg 的学弟() 14:38:33
这些静态优化也就那么回事儿吧,说白了makefile也能做。

云淡然() 14:38:42

……

云淡然() 14:38:44

你试试

云淡然() 14:39:43

Nimo() 14:39:52
又要开始构建工具约架了~

云淡然() 14:39:55

Frank() 14:40:09
能构建less跟sass么?

云淡然() 14:40:21

less -> css 那不就构建

云淡然() 14:40:25

不叫
IntPtr() 14:40:38
webpack 党路过

云淡然() 14:40:38

webstorm 一个配置即可
Frank() 14:40:40
能编译么?

云淡然() 14:40:50

编译有专门的工具

云淡然() 14:41:06

less => lessc
sass => node-sass
Frank() 14:41:40
也是
真·berg() 14:42:46
所有资源都走js管理是有一定的局限的

云淡然() 14:43:02

但,目前来说,这是最好的管理方式
真·berg() 14:43:06
不是的

云淡然() 14:43:19

一个组件:js、css、html、image 都可以以模块的方式进行合并
真·berg() 14:43:28
有更优雅的方案
Nimo() 14:43:29
咖啡已备好,开课了。
IntPtr() 14:43:35
webpack 的 css 可以独立输出的啊

云淡然() 14:43:56

独立输出到哪?
IntPtr() 14:44:04
独立文件
IntPtr() 14:44:05
css 文件

云淡然() 14:44:08

……

云淡然() 14:44:17

coolie 分块构建,也支持

云淡然() 14:44:23

你把 css 分出来即可
IntPtr() 14:44:33
不是 js 文件, 是纯 css 的
真·berg() 14:44:41
所有资源通过js加载只能适用一部分前端开发场景,并不完全通用

云淡然() 14:44:46

纯 css 文件,然后 link 加载?
真·berg() 14:45:01
更加通用的方案是基于表的静态资源管理框架
我是 Berg 的学弟() 14:45:05
等我攒够能量,用 makefile 撸一个大家玩玩。
IntPtr() 14:45:06

真·berg() 14:45:21
可以让你设计更加复杂资源加载和性能优化方案
真·berg() 14:45:28
而且开发中是完全的组件化开发
IntPtr() 14:45:28

最近在写的个人的一个小网站

云淡然() 14:45:30

嗯,是个方案
IntPtr() 14:45:51
makefile + webpack, react + redux
Nimo() 14:45:51
运行在前后端中的通用的资源管理框架?
真·berg() 14:45:56
全兼容SPA和MPA,甚至可以扩展为支持bigpipe、quickling等高级模式

云淡然() 14:46:14

没必要这么多新词
IntPtr() 14:46:30
webpack 也可以兼容 mpa 和 spa 的
IntPtr() 14:46:33
多 entry
星期五() 14:46:50
budongya

云淡然() 14:46:50

coolie 也可以啊,一个网站一个入口即可
星期五() 14:47:00
麻烦汉化一下
真·berg() 14:47:05
webpack是静态构建,没有一个资源加载框架的结合,很多动态的事情做不了
我是 Berg 的学弟() 14:47:04
已经实践了四年了,从来没有掉坑里,感觉这个方案就是绝杀技,没有之一。
IntPtr() 14:47:38
我是比较偏向前后端彻底分离的

云淡然() 14:47:46

什么叫基于表的静态资源管理框架
IntPtr() 14:47:48
所以静态构建就够了
真·berg() 14:48:49

就是你的这个图,根本不用构建工具做这么多黑盒的事情
构建工具只要把你图上的关系输出为一个json数据结构
然后交给前端模块化加载器,整个方案就解决了
人工智能() 14:49:22
瓶神又得普及Fis了
IntPtr() 14:49:23
感觉现在的构建工具主要是两个问题, 或者是模块化过度了, 导致模块之间的配合相当麻烦, 而且各种 bug. 或者是模块化程度不足

云淡然() 14:49:23

IntPtr() 14:49:38
@真·berg 我感觉, 在 http 2 普及之前大概还是得后端做合并的
IntPtr() 14:49:49
等 http 2 普及了大概就能 polymer 上了

云淡然() 14:49:49

给你个 json 配置,那还不是要一个一个的加载啊?和没构建有区别吗
真·berg() 14:49:57
不是的

云淡然() 14:50:06

怎么说?后端合并?
真·berg() 14:50:10
可以合并请求,可以配置更加合理的打包方案
IntPtr() 14:50:11
我个人比较看好 polymer 的那种加载方式

云淡然() 14:50:22

……这种方式最丑了
我是 Berg 的学弟() 14:50:25
开始 FIS 模式。

云淡然() 14:50:52

前端静态构建一劳永逸,根本用不到后端
真·berg() 14:50:53
我一个个回复哈,@IntPtr 在HTTP2时代为了充分利用一次HTTP请求,我们更加需要在服务端管理静态资源,可以提前推送资源。虽然不用合并,但是需要利用推送
Nimo() 14:50:58
瓶粉强势围观

云淡然() 14:51:07

一个 nginx + coolie 构建,就一个网站出来了
真·berg() 14:51:30
呵呵,基于表的静态资源加载仍然可以是纯前端的
不能忘记() 14:51:52
体验下fis不就好了

云淡然() 14:52:20

恕我大话之言,fis 真看不上
人工智能() 14:52:38
看完Fis的文档就会明白一切
我是 Berg 的学弟() 14:52:43
那只能各自的道场各自修炼了。

云淡然() 14:52:45

闪光点没让我看到
Nimo() 14:52:46
。。。
不能忘记() 14:53:00
那话题可以终结了。。
真·berg() 14:53:40
假设我有一段json:

{
res: { 'a.js': { url: 'a-md5.js', deps: [ 'b.js' ] }, 'b.js': { url: 'b-md5.js', deps: [ 'b.css' ] }, 'b.css': { url: 'b-md5.css' } } }

根据以上数据结构,你能不能写一个模块化加载器,当你需要使用'a.js'的时候,就能自动加载b.js和b.css?

云淡然() 14:54:00

……

云淡然() 14:54:21

这个模块加载是不是要去加载 a.md5.js 和 b.js
真·berg() 14:54:26
构建工具只是生成资源依赖关系和表,而框架才是最终性能优化的关键
而不是把性能优化强制做到工具里,这是fis的闪光点
真·berg() 14:54:39
好,我接下来解释一下基于表怎么玩打包

云淡然() 14:55:05

这个 json 表,能解决什么?和静态打包有什么优势?
真·berg() 14:56:15
{
res: { 'a.js': { url: 'a-md5.js', deps: [ 'b.js' ], pack: 'aio.js' }, 'b.js': { url: 'b-md5.js', deps: [ 'b.css' ], pack: 'aio.js' }, 'b.css': { url: 'b-md5.css' } }, pack: { 'aio.js': { url: 'aio-md5.js', has: [ 'a.js', 'b.js' ]} } }

当你的前端框架,发现资源有pack属性的时候,去加载这个资源就行了

云淡然() 14:56:48

那不是没合并吗,多个资源请求了,如果依赖长的话
真·berg() 14:57:08
构建工具负责生成资源依赖关系和表,而框架才是最终性能优化的关键
而不是把性能优化强制做到工具里,这是fis的闪光点

这样,我一个工具,可以实现各种性能优化方案,SPA也好,MPA也好,基于相同的表结构,只是框架逻辑不同,可能在前端做资源管理,可能在后端做资源管理
IntPtr() 14:57:18
我还没仔细看过 fis, 不过我对 fis 的第一印象并不好, 因为我感觉 fis 并不是 do one thing and do it well
berg() 14:57:52
哈哈,很多人都没好好看fis怎么弄的,就来喷了。。。
IntPtr() 14:57:57
同时我对 webpack 的印象也不好, 因为 webpack 必须注入自己的 runtime, 而且无法选择注入到哪里

云淡然() 14:58:14

用 coolie 吧
IntPtr() 14:58:19
很明显, webpack 并做不到灵活的合并, 以及前端的定制
真·berg() 14:58:27
SPA有一种需求:

router('/:page', function(ctx){
require(ctx.page + '.js', function(page){ page.init(); }); });

来,说说怎么打包?
acme() 14:58:31
构建工具 怎么还做一件事,当然要可以做多件事,而且还做的好
acme() 14:58:54
= =
真·berg() 14:59:03
SPA有一种需求:

router('/:page', function(ctx){
require(ctx.page + '.js', function(page){ page.init(); }); });

来,说说怎么打包?

云淡然() 14:59:02

IntPtr() 14:59:04
webpack 有异步功能, async 的 chunk 独立出去, 然后 require.ensure()
berg() 14:59:12
re,构建工具就是用最简单的思想,把无数种可能性给组织好
Nimo() 14:59:19
FIS根本就不是构建工具,他提供了一整套的解决方案~~
IntPtr() 14:59:23
IntPtri@intptr.im 14:59:04
webpack 有异步功能, async 的 chunk 独立出去, 然后 require.ensure()
真·berg() 14:59:39
错了,这个问题不能这样解决
IntPtr() 14:59:40
@#云淡然 webpack 支持 css 的合并压缩
真·berg() 14:59:49
单页面应用,只有一个物理页面
acme() 14:59:51
好好好,集成了一整套的解决方案,他就是不是构建工具了

云淡然() 14:59:59

@IntPtr 不支持 真·berg() 15:00:02
用户访问之后,不知道是哪个页面打开
真·berg() 15:00:09
都是动态计算页面资源组合的
肥鱼() 15:00:12
求个大牛罩着我啊
肥鱼() 15:00:14

真·berg() 15:00:15
静态是不行的
肥鱼() 15:00:20

云淡然() 15:00:51

IntPtr() 15:00:53

肥鱼() 15:01:26 @IntPtr 这是什么?
真·berg() 15:01:28
表记录了依赖关系,和资源发布路径,打包合并情况

前端框架可以根据表信息自由的组合资源加载,动态计算最优组合
IntPtr() 15:01:48
@#云淡然 webpack 的做法并不是在 html 中写 css: 很明显, webpack 的 html-loader 并不能用.
IntPtr() 15:02:01
webpack 的做法是在 js 中, 或者直接在配置文件中写 css 的依赖

云淡然() 15:02:18

@IntPtr 是的,所以回复你,webpack 不支持 IntPtr() 15:02:22
然后由 css-loader (带 clean-css) + extract-text 输出
IntPtr() 15:02:49
这个只是 webpack 不支持 html 作为 entry 而已, 但并不是不支持 css 压缩合并

云淡然() 15:03:05

不用什么表了,构建工具分析的时候就已经生成一个虚拟表了,动态分析之后做
真·berg() 15:03:21
表是给加载时候做动态计算用的
IntPtr() 15:03:34
@真·berg 你那个可以用一个技巧去做
真·berg() 15:03:36
如果你用工具写死了,早晚会遇到问题
IntPtr() 15:03:43
ctx.page + ".page.js"

云淡然() 15:03:45

@IntPtr 嗯,所以说,webpack 只支持模块依赖的 css,而不是 link 真·berg() 15:03:51
how?
IntPtr() 15:03:54
然后 webpack 会自动依赖所有 *.page.js
IntPtr() 15:03:59
然后可以异步加载

云淡然() 15:04:12

@真·berg 工具还真写不死,依赖关系都是动态计算出来的
真·berg() 15:04:28
我说运行时你的合并都已经固化了
IntPtr() 15:04:42
webpack 支持异步的模块独立 chunk 啊
IntPtr() 15:04:49
然后 require.ensure 在前端是异步加载的

云淡然() 15:05:01

@真·berg 对,运行之后,这个固化是合理的,因为已经到生产了

云淡然() 15:05:44

@真·berg 而如果要调整的话,可以重新构建,这个成本也不大,并且有版本管理,对历史无影响
真·berg() 15:05:45
不过没事,我已经传达出
工具→表→框架加载
以后你发现你的工具有不支持的情况,可以考虑这种方案,你会发现你的工具更容易适用其他前端项目,因为不同的只有框架
IntPtr() 15:05:59 http://webpack.github.io/docs/code-splitting.html#defining-a-split-point
人工智能() 15:06:09
现在讨论的都是资源加载,但是我觉得这只是FIS的一部分,FIS还有很多其它功能很亮。

云淡然() 15:06:39

@真·berg coolie 通用化,按照 cmd 约定来,任何框架、库都没问题
我是 Berg 的学弟() 15:06:39

IntPtr() 15:06:57
@真·berg https://github.com/petehunt/webpack-howto#9-async-loading
真·berg() 15:07:00
工具→表:你会发现工具是通用的
表→框架加载:你会发现框架可以针对不同的项目设计不同的优化策略
IntPtr() 15:07:16
IntPtri@intptr.im 15:06:57
@真·berg https://github.com/petehunt/webpack-howto#9-async-loading
真·berg() 15:07:18
稍等,@IntPtr 我不能同时vs两个人
真·berg() 15:07:25
你的问题我等下跟你慢慢展开

云淡然() 15:07:31

@真·berg 针对不同的项目进行优化,改下构建配置即可
真·berg() 15:09:02
恩,可以改,没问题的,你说的道理都对,只是fis的亮点在于让工具变得简单,只是生成表,而接下来做的就是资源加载框架,框架的设计成为工程的关键,
spa也好,mpa也好,都是相同的原理
真·berg() 15:09:36
后续项目的性能优化也都集中在资源框架的升级,开发者感受不到
真·berg() 15:09:55
比如移动端的首屏优化
真·berg() 15:10:10
构建工具完全无力,但是资源框架做的非常好,非常灵活
真·berg() 15:10:27
首屏位置是不固定的
真·berg() 15:14:45
SPA应用,只有一个物理页面,很多时候根据hash在前端来判定用户访问了什么页面,需要什么资源
真·berg() 15:15:03
所以,同一个物理页面的不同hash会出现不同的资源加载组合
真·berg() 15:15:22
这个是在前端做的,而你说的chunk方法可以,只是请求变成了至少2个
IntPtr() 15:16:48
但是你说的那个就涉及到后端动态合并了吧
真·berg() 15:16:51
所以SPA的一种合理做法是前端combo拼接url,当然,这种做法也有弊端,但算是理论上最理想的了。这也是资源加载策略的不同,有的是线下合并,有的是动态combo,如果改成表+框架,问题迎刃而解,不同的加载策略只是不同的读表方式而已,这是运行时的,可以自由组合,而工具在两种状态中完全没有改变
IntPtr() 15:17:07
后端动态合并不利于缓存啊
真·berg() 15:17:20
框架中再实现localstorage换乘
真·berg() 15:17:22
缓存

云淡然() 15:17:24

前端combo拼接url
=>

IntPtr() 15:17:43
webpack 是一个基准 entry 必须加载, 然后之后按需加载页面对应的 js
真·berg() 15:17:51
来,给我拼接一下:

router('/:page', function(ctx){
require(ctx.page + '.js', function(page){ page.init(); }); });

云淡然() 15:17:58

你们先讨论,后续 copy 你们的整理
IntPtr() 15:18:03
localStorage 做缓存的轮子似乎死的都很惨...
真·berg() 15:18:08
不会的
IntPtr() 15:18:11
而且不存在发展前景...
真·berg() 15:18:26
这只是一种“有就用,总比没有强”的方案
IntPtr() 15:18:30
以及 localStorage 的存储是永久的
IntPtr() 15:18:36
对用户的体验也不好
berg() 15:18:37
@#云淡然 别走啊,难道你这算是认输了?
真·berg() 15:18:45
我们虽然总是嘴上挂着“面向未来”但也要“着眼眼前”
IntPtr() 15:18:49
所以我更倾向 webpack 那种做法
IntPtr() 15:18:53
后端不做动态合并
berg() 15:18:57
我理解最后瓶子抛了一个问题,结果你没解决啊

云淡然() 15:18:59

我没认输,这样太浪费时间了
IntPtr() 15:19:07
其实吧...
webpack 应该也能做动态合并的
你后端把 webpack 输出的文件合并输出就好了
真·berg() 15:19:26
动态合并就是意味着有一个前端框架
IntPtr() 15:19:35
就是前端 localStorage 缓存没那么容易去分离
真·berg() 15:19:57
唉,这个说来可能稍微话长一些,不展开了,我们线上都是这么搞的
我是 Berg 的学弟(954573307) 15:20:05
我们线上也是
真·berg() 15:20:14 http://qiqu.uc.cn/?uc_param_str=frpfvedncpssntnw#!/index/index
可以看看这个项目的ls
IntPtr() 15:20:17
webpack 的异步加载没记错的话
IntPtr() 15:20:22
是类似 jsonp 那种做法
IntPtr() 15:20:30
所以你同步合并在一起也不会影响代码执行
真·berg() 15:20:53
你得有表,才能提前知道依赖关系,才能拼出一个url的合并结果
IntPtr() 15:21:00
但是还是那个, localStorage 缓存做起来就麻烦了
真·berg() 15:21:54
或者换句话说吧,给我你们的项目,我应该用fis+一个自定义的小框架秒杀你的性能
真·berg() 15:22:31
表+框架的方法最容易调整优化策略了
IntPtr() 15:22:32
大概是需求不太一样吧
真·berg() 15:22:42
不管你什么需求,我有这个 自信
IntPtr() 15:22:43
没什么可争的...
真·berg() 15:23:32
那些做了很复杂构建策略的工具,在表+框架的面前应该没有性能上的优势,但却有调整策略的劣势
Hiufan() 15:24:01
UC那个奇趣百科相似的构建我见识过,的确很快,而且代码维护很方便。
IntPtr() 15:24:02
fis 现在内部是高度模块化的么
真·berg() 15:24:10
高度模块化
IntPtr() 15:24:26
内部建表的这块可以独立出来用么
真·berg() 15:24:33
只有一个非常轻量的内核,剩下的全是插件
应该可以,我自己就是用fis定制方案,只用到内核
berg() 15:25:18
这是fis的另外一个精髓,可以基于不同的业务,不同的语言,不同的优化场景做定制和封装
IntPtr() 15:25:41
webpack 内部的模块化程度如何你们研究过么.
真·berg() 15:25:41
恩,因为工具不用改,写个读表框架就行了
berg() 15:25:44
资源分析和建表是核心
十分之一() 15:26:38
berg的这句总结,很赞。
真·berg() 15:26:39
你是指loader么
十分之一() 15:26:46
资源分析和建表是核心
IntPtr() 15:27:14
唔...
IntPtr() 15:27:21
回头有时间研究一下 fis 去
真·berg() 15:27:54
那些为当下需求写的构建工具,将来技术调整之后维护起来负重难行,这些过程我们不是没走过,而是深谙其中的弊端
berg() 15:28:59
欢迎分析研究提需求提bug
也欢迎在了解fis内部机制的前提下,对设计提任何意见
否则我们也没有fis3,哈哈
berg() 15:29:59
fis1 - fis2 - fis3
是一步步去伪存真的过程,fis1大量的过度设计,fis2也有一些,fis3,或许能更少了吧

  • polandeme

    这是个什么群呀。。。。

    #1
  • qdsang

    berg粉丝群

    #2
  • nimo

    berg 家族

    #3
  • berg

    @polandeme 页面最下方有群号

    #4
  • sliwey

    然而fis3什么时候出?

    #5
  • berg

    @sliwey 已经出了啊

    #6
  • sliwey

    @berg 嗯,已经在尝试了

    #7
  • imweb.daniel

    这种东西发一篇文章……也是醉了

    #8
  • zack

    抽了时间看完了,作为瓶神团队的一员,就我所了解到的,目前还没有一个移动端的 SPA 项目复杂度会比我们的一个业务还要大,共 40 + hash 页,180+ 大小模块化组件,在移动端的首屏时间最快可以达 2s 以内,这样庞大的项目和苛刻的性能要求,真的只有 FIS 才能满足,其他的构建工具,基本上 hold 不住,因为项目越庞大越往后,这些构建工具的规则最后成了无法收拾的烂摊子

    #9
  • fansekey

    我也爆点料吧,某产品线 PC 端大概有 59 个 FIS 项目模块。其中某个模块大概有 168 个组件,而配置文件不到 100 来行。

    大家开发都按照统一的标准。

    #10
  • chenwery

    叼叼叼,求进群,必须是百度T8以上才有资格吗?

    #11
  • ktangel

    刚朋友推荐到fis,搜到这里来。有讨论群最好了,求拉进群。群号是115907020么?

    #12
  • ktangel

    对了,注册这个,谁有邀请码给个?

    #13
  • Faraday

    服!

    #14
微博登录后即可参与讨论。