中级使用

初级使用中,为了解析 less 和 进行简单的资源合并,我们安装了两个已经提供好的插件,使用插件完成了我们的工作。假设某些情况下,还没有相关插件,该怎么办?

那么这节讨论一下 FIS 中插件如何编写。在工作原理 中,已经介绍了整个构建的过程,以及说明了 FIS 与其他构建工具的不同点。

预处理插件编写

假设给定项目中要是用 es6,线上运行时解析成标准 js 性能堪忧,想用自动化工具进行预处理转换。如原理介绍 parser 阶段就是进行归一化的过程,通过预处理阶段,整个文件都会翻译为标准的文件,即浏览器可解析的文件。

这时候我们搜罗开源社区,看转换 es6es5 哪个转换工具更好一些,发现 babel 具有无限的潜能。

任务

  • 预处理 es6es5

前期准备

  • .es6 后缀最终变为 .js
  • 使用 babel 进行 es6 的转换
  • FIS3 实现一个 parser 类型的插件,取名叫 translate-es6,插件全名 fis3-parser-translate-es6

开发插件

开发插件文档详细介绍了开发插件的步骤,但为了更友好的进行接下来的工作,我们在这里简述一下整个过程。

FIS3 支持 local mode 加载一个插件。当你调用一个插件的时候,配置如下:

  1. {
  2. parser: fis.plugin('translate-es6')
  3. }

如果项目的根目录 node_modules 下有这个插件,就能挂载起来。

  1. my-proj/node_modules/fis3-parser-translate-es6

这样我们就知道,插件逻辑放到什么地方能用 fis.plugin 接口挂载。

  1. my-proj/node_modules/fis3-parser-translate-es6/index.js
  1. // vi index.js
  2. // babel node.js api 只有 babel-core 不能完成翻译
  3. // babel-core 需要安装依赖 babel-preset-es2015
  4. // 参考: 阮一峰的es6入门 http://es6.ruanyifeng.com/#docs/intro
  5. var babel = require('babel-core');
  6. module.exports = function (content, file, options) {
  7. var result = babel.transform(content, opts);
  8. return result.code; // 处理后的文件内容
  9. }

如上我们调用 babel-core 封装了一个 fis3-parser 插件。

现在我们要在项目使用它

  1. my-proj/fis-conf.js # 项目 fis3 配置文件
  2. my-proj/node_modules/fis3-parser-translate-es6/index.js # 插件逻辑
  3. my-proj/style.es6
  4. my-proj/index.html

配置使用

  1. fis.match('*.es6', {
  2. parser: fis.plugin('translate-es6', {
  3. presets: ['es2015']
  4. }),
  5. rExt: '.js' // .es6 最终修改其后缀为 .js
  6. })

构建

  1. fis3 release -d ./output

打包插件编写

在开始之前,我们需要阐述下打包这个名词,打包在前端工程中有两个方面。

  • 收集页面用到的 js、css,分别合并这些引用,将资源合并成一个。
  • 打包,对某些资源进行打包,而记录它们打包的信息,譬如某个文件打包到了哪个包文件。

其实一般意义上来说,对于第一种情况收集打包只适合于纯前端页面,并且要求资源都是静态引入的。假设出现这种情况:

  1. <script type="text/javascript">
  2. // load common.js and index.js
  3. F.load([
  4. 'common',
  5. 'index'
  6. ]);
  7. </script>

需要通过动态脚本去加载的资源,就无法通过工具静态分析来去做合并了。

还有一种情况,如果模板是后端模板,也依然无法做到这一点,因为加载资源只有在运行时、解析时才能确定。

那么对于这类打包合并资源,需要特殊的处理思路。

  1. 直接将所有资源合并成一个文件,进行整站(整个项目)合并;
  2. 通过配置文件配置打包,并且合并时记录合并信息,在运行时根据这些打包信息吐给浏览器合适的资源。

第一种,粗暴问题多,并且项目足够大时效率明显不合适。我们主要探讨第二种。

FIS3 默认内置了一个打包插件 fis3-packager-map,它根据用户的配置信息对资源进行打包。

  1. //fis-conf.js
  2. fis.match('/widget/*.js', {
  3. packTo: '/static/widget_pkg.js'
  4. })

标明 /widget 目录下的 js 被合并成一个文件 widget_pkg.js

假设

  1. /widget/a.js
  2. /widget/b.js
  3. /widget/c.js
  4. /map.json

编译发布后:

  1. /widget/a.js
  2. /widget/b.js
  3. /widget/c.js
  4. /static/widget_pkg.js
  5. /map.json

我们前面说过

  1. 当某文件包含字符 __RESOURCE_MAP__ 时,最终静态资源表(资源之间的依赖、合并信息)会替换这个字符。

构建后,出现一个合并资源以外,还会产出一张某资源合并到什么文件中的关系信息。

  1. {
  2. "res": {
  3. "widget/a.js": {
  4. "uri": "/widget/a.js",
  5. "type": "js",
  6. "pkg": "p0"
  7. },
  8. "widget/b.js": {
  9. "uri": "/widget/b.js",
  10. "type": "js",
  11. "pkg": "p0"
  12. },
  13. "widget/c.js": {
  14. "uri": "/widget/c.js",
  15. "type": "js",
  16. "pkg": "p0"
  17. }
  18. },
  19. "pkg": {
  20. "p0": {
  21. "uri": "/static/widget_pkg.js",
  22. "has": [
  23. "widget/a.js",
  24. "widget/b.js",
  25. "widget/c.js"
  26. ],
  27. "type": "js"
  28. }
  29. }
  30. }

发布插件

FIS3 的插件都放在 NPM 平台上,把插件发布到其上即可。

参考链接 npm publish

发布的插件如何使用

  • npm install -g <plugin> 安装插件
  • FIS3 配置文件中按照配置规则进行配置,fis.plugin(<plugin-name>)