张云龙
张云龙
一般webapp是有一个物理页面,然后根据hash或者url加载不同的“虚拟页面”来展现应用,大致的资源关系如下:  从下往上看,应用一般有一个入口模块,比如app,这个入口模块根据url来动态决定异步加载某个页面(P₁-P₄),而每个页面并不是孤岛资源,它们还会依赖其他组件,组件与组件之间可能还有共享的基础库依赖。 基于这样的资源依赖树结构,webpack是怎么解决资源合并和按需加载的?感觉静态分析打包不能很好的处理按需和请求合并问题,要么每个chunk冗余合并,要么多个chunk串行加载
@chemdemo 我应该是理解webpack的做法的,只是你可能没有注意到我的例子是一个怎样的陷阱: > webpack可以通过CommonsChunkPlugin插件来对公共依赖模块进行提取 单独看我例子中的a、b依赖c的情况,这个说法是正确的。 > 对于按需加载,比如你提到的这种场景,p1-p4就当做chunk来加载了 单独看我例子中的app加载p1-p4,这个说法也是正确的。 但是,把二者结合起来,就不是那么回事了。。。 因为p1-p4各自为一个chunk,其结果就是p1-p4不用处理,就是文件本身就行了;而ab抽取公共依赖c,也等价于三个文件不用处理,自然就是“c为ab的公共chunk”,在静态分析的模式下,这个例子的最优合并结果居然是不合并! 现实中这样的例子其实更多,而且会更复杂,静态分析面对大工程最终的结果往往是要么因为其局限性而根本配不出来合理的方案,要么因为配置太多维护成本过高而变成一个bundle的情况,没有真正的优化空间,那些“有公共依赖抽取插件从而进行优化”的假设基本形同虚设。
看过很多号称使用了webpack的项目,基本上无外乎这么几种最终运行效果: - 图省事,一个大bundle(呵呵) - 一个页面一个chunk,公共资源冗余重复合并在各个chunk中(呵呵) - 刚好页面彼此很独立,完全没有公共资源(算你走运) 正如 @kerryChen95 在我的blog底下[留言说到的](https://github.com/fouber/blog/issues/10#issuecomment-136410156): > 以Webpack目前对WebApp架构支持的完善程度,它只差一步就能实现WebApp和WebSite(暂且这么叫,就是传统的服务端模板生成页面的意思)的通吃,只要它实现了生成资源表的API(前提是Webpack认同 资源表+资源加载框架 这种理念),然后,如果业界出现了某种资源表的事实标准,那么就一切就完美了~ 我觉得这种认识是早晚的,因为优势太明显了吧。。。 此外,我还想吐槽webpack的一些设计: 1. require的返回结果只有三种情况: - 返回文件uri——资源定位 - 返回文件内容(文本或base64)——资源内嵌 - 什么都不返回,只是在表中记录资源依赖关系(如果认可)——依赖声明 除了以上三种情况,前端构建不再需要多余的规则了。而返回文件内容时到底该返回文本还是文件base64是可以被唯一确定的,只要给出被require的文件就知道该返回哪种了。所以我觉得webpack还可以在精进一步概念。 2. 这个require标识可以扩展到html和css。有些技术选型的情况下我们可能也需要在html或者css中标记依赖或者资源定位,比如模板中可能直接写一个img src定位资源(当然,你可以准换成js中定位然后模板传值给html)。 在三种语言中分别提供资源定位、资源内嵌、依赖声明的构建标识,采用表+资源加载框架优化加载,以上这两点构成了fis的核心设计理念,不可否认webpack是目前最接近fis的构建工具
可以的,回头我加一下这个功能
想了一些配置接口,记录在这里方便讨论。 ## fis.set(key, value) - 参数 - key `String` - value `*` - 返回值 - `FIS` 返回fis对象,方便链式调用 > 以k-v的方式设置一些配置数据,可以通过fis.get(key)读取。推荐采用express的kv设置风格(有空格),是否需要支持 `多级路径` 的设置,这个需要讨论一下。 ``` js fis .set('foo', 123); .set('foo bar', 456); //...
@hefangshi ## 关于key设置 key设置需要接口,字符串中需要 `${key}` 引用,插件中也会需要 `fis.get(key)` 方式获取 ## 关于media `fis.media(mode)` 是为了让一份配置具有多种状态,跟alias无关,就算是有 `fis.alias()` 接口,那么怎么让不同alias下有不同的配置呢?仍然需要media接口。另外,alias的语义很不好,从给出的例子来看,这个接口应该是fis.task,那就不可避免的引导用户把fis当做task-based的工具来使用了 ## 关于 `fis.when().xxx().oo()` 的问题 不能把属性配置变成接口调用,很多时候,规范设计需要开辟新的属性,如果都成了接口,谁来为这些接口提供扩展呢?文件的属性应该是自由增减的,如果变成接口,维护接口的升级和兼容性是非常麻烦的事。此外,你应该拿这种配置去配一下现有的解决方案,蛋疼的不是一点点,fis的最终用户是配置fis的人,如果fis的设计者自己很爽,让最终用户蛋疼,这是不合适的做法 ## 关于流程固化 流程必须固化。你提到了 `fis不固化,让解决方案固化`,解决方案的定制者属于fis的目标用户,你怎么跟他们解释流程固化的策略?这会让fis的使用成本提高很多。此外,怎么进一步实现 `fis不固化,解决方案固化,解决方案使用者不能修改解决方案的固化`,这也是一件麻烦的事。 ## 资源定位能力是否可关闭 用户可以选择整体关闭资源定位,相应的也需要关闭内嵌,因为内嵌结果已经不正确了,不存在 `通用的不严谨资源定位方式`。注意,我这里强调了通用性。这件事只要你稍微带入到真实的开发中就能想象到原因。关闭资源定位之后,无法保留内嵌能力,因为内嵌中的资源定位有这么几个问题: 1. 如果被内嵌的是css,其中的资源定位...
https://github.com/scrat-team/scrat 浏览器应用研发 UC (基于fis定制的移动端解决方案)
@hangyangws fis一直都是向下兼容的,先看看你的报错吧
@ioriandy4 fis打包之后,会生成一个map.json文件,把这个文件的内容插入到页面上,然后针对seajs做一些扩展,监听seajs的文件路径查找事件,拦截,然后写一个小逻辑查这个map.json,返回pkg/lib.js这个url,让seajs加载。这样seajs也能支持fis的合并、md5等性能优化了
@ioriandy4 seajs没有直接接受资源表的接口,所以要用seajs需要这样扩展实现。不过我们自己用,其实模块化框架相当轻量,直接针对fis的map表写代码,代码很少,而且性能优化效果非常理想。模块化本身就非常非常少内容