一、理念原理

  1. 集成很多能力,有一些包装解决方案。
  2. 抽象三大编译能力
  3. release: 整体移动,匹配到某些资源,定义文件属性或者然后放到一个新的位置,可以忽略某些文件不移动;
  4. 适合多页应用:本身定制的多页,传统的后端模板tpl渲染;

FIS3是基于文件对象进行构建的,每个进入 FIS3 的文件都会实例化成一个 File对象,整个构建过程都对这个对象进行操作完成构建任务

release原理

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
// 扫描项目目录拿到文件并初始化出一个文件对象列表
// 对文件对象中每一个文件进行单文件编译
// 获取用户设置的 package 插件,进行打包处理(包括合并图片)
// 其中打包处理开了四个扩展点,通过用户配置启用某些插件。

// prepackager 打包前处理插件扩展点
// packager 打包插件扩展点,通过此插件收集文件依赖信息、合并信息产出静态资源映射表
// spriter 图片合并扩展点,如 csssprites
// postpackager 打包后处理插件扩展点
fis.release = function (opt) {
var src = fis.util.find(fis.project.root);
var files = {};
src.forEach(function (f) {
var file = new File(f);
// 对每个文件对象进行编译
files[file.subpath] = fis.compile(file);
});

var packager = fis.matchRules('::package');
var keys = Object.keys(packager);
var ret = {
files: files,
map: {}
};
// 打包处理pre+
if (packager.indexOf('prepackager') > -1) {
pipe('prepackager', ret);
}

if (packager.indexOf('packager') > -1) {
pipe('packager', ret);
}

files.forEach(function (f) {
// 打包阶段产出的 map 表替换到文件
if (f._isResourceMap) {
f._content = f._content.replace(/\b__RESOURCE_MAP__\b/g, JSON.stringify(ret.map));
}

});
// 处理spriter
if (packager.indexOf('spriter') > -1) {
pipe('spriter', ret);
}

if (packager.indexOf('postpackager') > -1) {
pipe('postpackager', ret);
}

};

compile

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
fis.compile = function (file) {
if (file.isFile()) {
if (exports.useLint && file.lint) {
pipe('lint', file);
}

if (!file.hasCache) {
process(file);
}
else {
file.revertCache();
}
}
else {
process(file);
}
};

// parser:预处理阶段,比如 less、sass、es6、react 前端模板等都在此处预编译处理
// preprocessor:标准化前处理插件
// standard:标准化插件,处理内置语法(三大能力)
// postprocessor:标准化后处理插件
function process(file) {
if (file.parser) {
pipe('parser', file);
}

if (file.preprocessor) {
pipe('preprocessor', file);
}

if (file.standard) {
standard(file); // 标准化处理
}

if (file.postprocessor) {
pipe('postprocessor', file);
}

if (file.optimizer) {
pipe('optimizer', file);
}
}

// 当一个文件被实例化为一个 File 对象后,包括一些文件基本属性,如 filename、realpath 等等,当这个文件被处理时,FIS3 还会把用户自定义的属性 merge 到文件对象上。

function File(filepath) {
var props = path.info(filepath);
merge(props, fis.matchRules(filepath)); // merge 分配到的属性
assign(this, props); // merge 属性到对象
}

二、三大编译能力

资源定位

获取任何开发中所使用资源的线上路径;html中默认可以,js中:__uri

内容嵌入

html/css/js当中均可嵌入资源?__inline

依赖声明

在一个文本文件内标记对其他资源的依赖关系;
默认有同名依赖功能

  • html中声明依赖
1
2
3
4
<!--
@require demo.js
@require "demo.css"
-->
  • js中
1
2
3
4
5
6
7
8
9
10
11
12
/**
* @require demo.css
* @require list.js
*/
```
- css

``` css
/**
* demo.css
* @require reset.css
*/

三、功能性

处理能力

  • es6+vue
  • css/less/rem/css前缀
  • 短路径功能
  • 文件指纹:useHash

优化能力

  • js+png压缩
  • useSprite:雪碧图合并需要自己申明,路径带 ?__sprite 的图片进行合并
  • jdists:对js当中的多余代码进行清楚
  • 增加cdn
  • 打包

四、其他特性

模块化处理

在FIS 中,依赖本身在构建过程中就已经分析完成,并记录在静态资源映射表中,那么对于线上运行时,模块化框架就可以省掉依赖分析这个步骤了。

自身不带,要引入mod.js文件,需要配置进行包装处理,不同的模块化框架需要配合不同的资源mod.js
对node_modules也要进行模块化处理;

mock功能;

有测试文件

内置server

media多环境

开发环境下deploy推送功能;

五、对比webpack

fis3

前端工作流框架

  • 前端工程化的角度设计
    不单单是一个打包工具,构建流程不单单根据js来,而是分析每一个文件的依赖关系,生成一个资源表sourceMap,资源表记录每一个文件的依赖关系,以及发布前的位置,和发布后的去向。
  • 插件职能清晰
    单文件编译和打包两个阶段。parser插件 => preprocessor 插件 => … => packager 插件 => … => postpackager 插件。而webpack各个插件还可能穿插混淆。
    文件流从一个阶段的插件流到下一个阶段的插件,插件不相互调用
  • 没有入口概念
    fis3 将所有的文件进行编译,生成资源map,然后根据资源map配置各种打包策略
    fis3没有所谓的入口文件,所有文件(html,css,js等等)同等对待,自定义输出策略
  • 多页按需加载
    每个页面只需要加载自己依赖的所有文件即可
  • 依赖查找
    fis不但能通过require,import等查找依赖,而且会搜寻src,href等各处与资源定位有关的地方,将他们计入依赖列表。
  • 文件产出
    fis3 任何文件可以灵活地发布到任何位置,相关引用的路径也自动更新

比较好的:__inline语法
fis3 的设计理念完爆 Webpack ,但社区太弱、国际化太差, Webpack 正好相反。

webpack理念

  • 模块打包器,单页应用和类库打包方面的确使用非常方便
  • 一切根据entry进行处理,最后将一个entry的所有依赖打包进去。可以通过插件将打包文件chunk为多个,也可以将多个entry文件的依赖的公共部分进行common chunk,对于多页,总不能真正达到按需加载的地步

参考文章

前端构建工具漫谈,fis3、webpack、rollup.js