构建工具 - FIS 的使用

13年下半年的时候,第一次接触前端的构建工具,那时候好像刚好在某个会议上百度宣布了 FIS 这个工具,然后就选择了 FIS (其实小部分的原因是因为有中文文档,这个习惯非常不好,我现在已经强制改掉了)。由于那时候前置知识比较欠缺,使用起来还是有点吃力的,但是基本的功能也在项目开发中起到了很大的帮助。嗯,那时候还比较菜,啥都不知道。

后来来到了现在这个团队,根据公司内部已有的项目,改用了 Grunt 来作为项目的构建工具。那时候需求还比较简单,Grunt 并没有太多欠缺的地方。再后来,由我操刀对项目进行全面的重构,我再次选择了 FIS。

由于前置知识的积累以及对 Grunt 的使用,再次使用 FIS 并没有遇到太多的阻碍。我想,如果你已经掌握了 Grunt,可以尝试下使用 FIS 作为某个项目的构建工具,应该会很快的清楚两者之间的差距。

以下开始介绍 FIS 在我所跟的项目里的使用,并没有太基础的入门教程哦,官方的文档虽然写的烂七八糟的,但是还是可以看滴。实在不懂就可以搜索下 issue 或者加入官方基友群,900多号全国顶级互联网公司前端为你解答疑问!

第三方组件的管理

为了避免重复的制造轮子,一般项目中均会有一定数量的第三方组件,这些第三方的组件理应该不属于源码一样进行管理,而需要在一个地方用一个工具统一的管理它们,方便后期的维护。你可能比较熟悉的包管理工具是 Bower , FIS 内置的一个组件生态跟 Bower 其实是一样的理念。通过 fis install 等命令可以替代 Bower。之所以在选择中选择了 fis-components ,主要是因为:

  • 项目中使用了 mod.js ,需要遵循 commonJS ,fis-components 内置的转换工具可以转换任意的第三方组件
  • 我们需要可以管理我们内部的私有组件
配置项目组件依赖

在我们的根目录下面建立 component.json 依赖声明文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"protocol": "github",
"gihub": {
"author": "fis-components"
},
"gitlab": {
"domain": "http://gitlab.rd.mt/",
"author": "fee-components"
},
"dependencies": [
"jquery@~1.9.1",
"vue@~0.11.10",
"gitlab:fee-components/jquery-drag@~0.0.1"
]
}

在项目目录下,通过 fis install 安装或者更新第三方组件

转换一个第三方组件

将转换工具 fis-components/components clone 回本地,在 modules 文件夹内新建一个组件的转换规则

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
'use strict';

module.exports = (function() {
return [
{
repos: 'https://github.com/jquery/jquery.git',
version: '1.9.1',
name: 'jquery',
main: 'jquery.js',
build: 'npm install && npm install grunt-cli && ./node_modules/.bin/grunt',
mapping: [
{
reg: /\.min\.(js|css)$/,
release: false
},
{
reg: /^\/dist\/(.*\.js)/,
release: '$1'
},
{
reg: /^\/README\.md$/,
release: '$&'
},
{
reg: '*',
release: false
}
]
},

{
version: '2.1.0',
build: 'npm run build',
extend: '1.9.1'
}

]
})();

本地拉取远程源仓库代码,并执行转换 node test.js modules/jquery.js 。转换出来的是符合 CommonJs 规范的组件,并去掉了多余的文件。

如果这是个公开的组件,将配置文件通过 Pull requests 提交回 FIS 组件生态;如果这是个私有组件,提交回内部的 gitlab。

使用一个第三方组件

像写 node.js 一样写前端代码

1
2
3
4
5
6
7
require('bootstrap/button');
var $ = require('jquery');


$('.btn').click(function() {
alert('Magic');
});

模块化

借助 FIS,我们可以使项目组件化更加的容易。通过 isMod 标记文件为组件化文件,被标记成组件化的 JS 文件会进行组件化包装。

1
2
3
4
5
6
7
8
9
10
{
reg: /\/modules\/([^\/]+)\/\1\.js$/,
id: '$1',
isMod: true
},
{
reg: /^\/modules\/(.*)\.(js)$/i,
isMod: true,
id: '$1'
}

这里通过设置更短的 ID 进行依赖声明,这样我们就可以更方便的对一个组件进行引用 require('modules/login')

同时,FIS 支持同名依赖自动引用

1
2
3
4
5
6
7
/**
* 这里 require 了 login 模块
* 除了 module/login/login.js 的文件会被加载外
* 同级目录下的 module/login/login.css 也会被自动加载
*/
require('modules/login');

常规的性能优化

压缩资源 通过 -o 指令可以对项目的资源进行压缩,包括 JS、CSS、HTML 等。压缩 HTML 需要额外插件支持 BelinChung/fis-optimizer-html-minifier

合并资源 通过 -p 指令可以对项目的资源进行打包合并。这个在下面会独立说一下,现在没啥说的,可能后面需求不同,觉得有可以详细说的余地。

添加MD5戳 通过 -m 指令可以对项目的文件添加MD5戳。很多人停留在文件后面添加时间戳 xxx.js?t=xxxx 的时代,并仍希望继续做。通过对文件添加MD5戳进行“非覆盖式发布”的好处是:

  • 部署安全。每次上线,先上线静态资源,它不会覆盖线上文件,然后再上线html页面,就能切换资源了
  • 缓存策略非常简单。对静态资源进行强缓存,性能好,缓存策略也简单
  • 防止HTTP缓存投毒。这个我没接触到,只能说了解了下,具体可以看 这里

添加资源域名 通过 -D 命令可以对项目的文件添加域名。配置项 fis.config.set('roadmap.domain','http://cdn.domain.com');,可以配置单机、多机,进行全部署或随机部署。

智能打包

项目打包也是性能优化的一部分,独立开来讲,是因为每个项目的打包需求不一样,而且 FIS 提供了不同的打包方式来满足不同的需求。

目前我在项目中通过额外的打包插件 fex-team/fis-packager-depscombine 进行打包。在 pack 中命中的文件,其依赖也会自动命中,意思就是指定某个入口的 HTML 文件,这个 HTML 依赖的所有 JS、CSS 都会被命中,打成一个合并包。

1
2
3
4
fis.config.set('pack', {
'pkg/web_app.css': 'index.html',
'pkg/web_app.js': 'index.html'
});

最后会在 pkg/ 文件夹内产出一个 all-in-one 的 web_app.cssweb_app.js