构建

由 fis3-command-release 插件提供构建能力

FIS3 的构建不会修改源码,而是会通过用户设置,将构建结果输出到指定的目录。

例子

在正式介绍 FIS3 功能之前,我们给定一个简单的例子,例子下载地址 demo-simple

命令

进入项目根目录,执行命令,进行构建。

项目根目录:FIS3 配置文件(默认fis-conf.js)所在的目录为项目根目录。

  1. fis3 release -d <path>
  • <path> 任意目录
  • fis3 release -h 获取更多参数

构建发布到项目目录的 output 目录下

  1. fis3 release -d ./output

构建发布到项目父级目录的 dist 子目录下

  1. fis3 release -d ../dist

发布到其他盘 (Windows)

  1. fis3 release -d D:\output

资源定位

我们在项目根目录执行命令 fis3 release -d ../output 发布到目录 ../output 下。然后通过 diff 工具查看源码和构建结果的内容变化。

文件变化

构建 - 图1

  • index.htmlstyle.css 发生了变化

index.html

构建 - 图2

style.css

构建 - 图3

如上,构建过程中对资源 URI 进行了替换,替换成了绝对 URL。通俗点讲就是相对路径换成了绝对路径。

这是一个 FIS 的很重要的特性,资源定位

资源定位能力,可以有效地分离开发路径与部署路径之间的关系,工程师不再关心资源部署到线上之后去了哪里,变成了什么名字,这些都可以通过配置来指定。而工程师只需要使用相对路径来定位自己的开发资源即可。这样的好处是 资源可以发布到任何静态资源服务器的任何路径上,而不用担心线上运行时找不到它们,而且代码 具有很强的可移植性,甚至可以从一个产品线移植到另一个产品线而不用担心线上部署不一致的问题。

在默认不配置的情况下只是对资源相对路径修改成了绝对路径。通过配置文件可以轻松分离开发路径(源码路径)与部署路径。比如我们想让所有的静态资源构建后到 static 目录下。

  1. // 配置配置文件,注意,清空所有的配置,只留下以下代码即可。
  2. fis.match('*.{png,js,css}', {
  3. release: '/static/$0'
  4. });

同样构建到 ../output 目录下看变化。

  1. fis3 release -d ../output

构建 - 图4

以上示例只是更改部署路径,还可以给 url 添加 CDN domain 或者添加文件指纹(时间戳或者md5戳)。

再次强调FIS3 的构建是不会对源码做修改的,而是构建产出到了另外一个目录,并且构建的结果才是用来上线使用的

可能有人会疑惑,修改成了绝对路径,本地如何调试开发?下一节介绍调试的方法。

配置文件

默认配置文件为 fis-conf.js,FIS3 编译的整个流程都是通过配置来控制的。FIS3 定义了一种类似 CSS 的配置方式。固化了构建流程,让工程构建变得简单。

fis.match()

首先介绍设置规则的配置接口

  1. fis.match(selector, props);
  • selector :FIS3 把匹配文件路径的路径作为selector,匹配到的文件会分配给它设置的 props。关于 selector 语法,请参看 Glob 说明
  • props :编译规则属性,包括文件属性和插件属性,更多属性

我们修改例子的配置文件 fis-conf.js,添加以下内容

  1. fis.match('*.js', {
  2. useHash: false
  3. });
  4. fis.match('*.css', {
  5. useHash: false
  6. });
  7. fis.match('*.png', {
  8. useHash: false
  9. });

重要特性

  • 规则覆盖

    假设有两条规则 A 和 B,它俩同时命中了文件 test.js,如果 A 在 B 前面,B 的属性会覆盖 A 的同名属性。不同名属性追加到 test.js 的 File 对象上。

    1. // A
    2. fis.match('*', {
    3. release: '/dist/$0'
    4. });
    5. // B
    6. fis.match('test.js', {
    7. useHash: true,
    8. release: '/dist/js/$0'
    9. })

    那么 test.js 分配到的属性

    1. {
    2. useHash: true, // B
    3. release: '/dist/js/$0' // B
    4. }

fis.media()

fis.media() 接口提供多种状态功能,比如有些配置是仅供开发环境下使用,有些则是仅供生产环境使用的。

  1. fis.match('*', {
  2. useHash: false
  3. });
  4. fis.media('prod').match('*.js', {
  5. optimizer: fis.plugin('uglify-js')
  6. });
  1. fis3 release <media>
  • <media> 配置的 media 值
  1. fis3 release prod

编译时使用 prod 指定的编译配置,即对 js 进行压缩。

如上,fis.media() 可以使配置文件变为多份(多个状态,一个状态一份配置)。

  1. fis.media('rd').match('*', {
  2. deploy: fis.plugin('http-push', {
  3. receiver: 'http://remote-rd-host/receiver.php'
  4. })
  5. });
  6. fis.media('qa').match('*', {
  7. deploy: fis.plugin('http-push', {
  8. receiver: 'http://remote-qa-host/receiver.php'
  9. })
  10. });
  • fis3 release rd push 到 RD 的远端机器上
  • fis3 release qa push 到 QA 的远端机器上

media dev 已经被占用,默认情况下不加 <media> 参数时默认为 dev

更多配置接口

我们执行 fis3 inspect 来查看文件命中属性的情况。fis3 inspect 是一个非常重要的命令,可以查看文件分配到的属性,这些属性决定了文件将如何被编译处理。

  1. ~ /app.js
  2. -- useHash false `*.js` (0th)
  3. ~ /img/list-1.png
  4. -- useHash false `*.png` (2th)
  5. ~ /img/list-2.png
  6. -- useHash false `*.png` (2th)
  7. ~ /img/logo.png
  8. -- useHash false `*.png` (2th)
  9. ~ /style.css
  10. -- useHash false `*.css` (1th)
  11. ~ ::package
  12. -- empty

fis3 inspect <media> 查看特定 media 的分配情况

更多信息

文件指纹

文件指纹,唯一标识一个文件。在开启强缓存的情况下,如果文件的 URL 不发生变化,无法刷新浏览器缓存。一般都需要通过一些手段来强刷缓存,一种方式是添加时间戳,每次上线更新文件,给这个资源文件的 URL 添加上时间戳。

  1. <img src="a.png?t=12012121">

而 FIS3 选择的是添加 MD5 戳,直接修改文件的 URL,而不是在其后添加 query

对 js、css、png 图片引用 URL 添加 md5 戳,配置如下;

  1. //清除其他配置,只剩下如下配置
  2. fis.match('*.{js,css,png}', {
  3. useHash: true
  4. });

构建到 ../output 目录下看变化。

  1. fis3 release -d ../output

文件变化

构建 - 图5

  • 构建出的文件携带了 md5 戳

文件变化

构建 - 图6

  • 对应 url 也带上了 md5 戳

片段编译

有些插件会对文件中的一部分先进行片段编译fis.compile.partial, 这时可以对相应的片段编译配置对应的规则。

  1. // vue组件中的less片段处理
  2. fis.match('src/vue/**.vue:less', {
  3. rExt: 'css',
  4. parser: fis.plugin('less'),
  5. release: 'xxx' // 这个无效
  6. });
  7. // 注意:因为组件中的样式片段编译只是编译内容,所以上面的release配置是无效的。要配置其release,需要针对生成的css文件:
  8. fis.match('src/vue/(**.css)', {
  9. release: '/vue-style/$1'
  10. });

压缩资源

为了减少资源网络传输的大小,通过压缩器对 js、css、图片进行压缩是一直以来前端工程优化的选择。在 FIS3 中这个过程非常简单,通过给文件配置压缩器即可。

  1. // 清除其他配置,只保留如下配置
  2. fis.match('*.js', {
  3. // fis-optimizer-uglify-js 插件进行压缩,已内置
  4. optimizer: fis.plugin('uglify-js')
  5. });
  6. fis.match('*.css', {
  7. // fis-optimizer-clean-css 插件进行压缩,已内置
  8. optimizer: fis.plugin('clean-css')
  9. });
  10. fis.match('*.png', {
  11. // fis-optimizer-png-compressor 插件进行压缩,已内置
  12. optimizer: fis.plugin('png-compressor')
  13. });

构建到 ../output 目录下看变化。

  1. fis3 release -d ../output

查看 ../output 目录下已经被压缩过的结果。

CssSprite图片合并

压缩了静态资源,我们还可以对图片进行合并,来减少请求数量。

FIS3 提供了比较简易、使用方便的图片合并工具。通过配置即可调用此工具并对资源进行合并。

FIS3 构建会对 CSS 中,路径带 ?__sprite 的图片进行合并。为了节省编译的时间,分配到 useSprite: true 的 CSS 文件才会被处理。

默认情况下,对打包 css 文件启动图片合并功能。

  1. li.list-1::before {
  2. background-image: url('./img/list-1.png?__sprite');
  3. }
  4. li.list-2::before {
  5. background-image: url('./img/list-2.png?__sprite');
  6. }
  1. // 启用 fis-spriter-csssprites 插件
  2. fis.match('::package', {
  3. spriter: fis.plugin('csssprites')
  4. })
  5. // 对 CSS 进行图片合并
  6. fis.match('*.css', {
  7. // 给匹配到的文件分配属性 `useSprite`
  8. useSprite: true
  9. });

功能组合

我们学习了如何用 FIS3 做压缩、文件指纹、图片合并、资源定位,现在把这些功能组合起来,配置文件如下;

  1. // 加 md5
  2. fis.match('*.{js,css,png}', {
  3. useHash: true
  4. });
  5. // 启用 fis-spriter-csssprites 插件
  6. fis.match('::package', {
  7. spriter: fis.plugin('csssprites')
  8. });
  9. // 对 CSS 进行图片合并
  10. fis.match('*.css', {
  11. // 给匹配到的文件分配属性 `useSprite`
  12. useSprite: true
  13. });
  14. fis.match('*.js', {
  15. // fis-optimizer-uglify-js 插件进行压缩,已内置
  16. optimizer: fis.plugin('uglify-js')
  17. });
  18. fis.match('*.css', {
  19. // fis-optimizer-clean-css 插件进行压缩,已内置
  20. optimizer: fis.plugin('clean-css')
  21. });
  22. fis.match('*.png', {
  23. // fis-optimizer-png-compressor 插件进行压缩,已内置
  24. optimizer: fis.plugin('png-compressor')
  25. });
  • fis3 release 时添加 md5、静态资源压缩、css 文件引用图片进行合并

可能有时候开发的时候不需要压缩、合并图片、也不需要 hash。那么给上面配置追加如下配置;

  1. fis.media('debug').match('*.{js,css,png}', {
  2. useHash: false,
  3. useSprite: false,
  4. optimizer: null
  5. })
  • fis3 release debug 启用 media debug 的配置,覆盖上面的配置,把诸多功能关掉。