插件开发

FIS3 是以 File 对象为中心构建编译的,每一个 File 都要经历编译、打包、发布三个阶段。运行原理讲述了 FIS3 中的插件扩展点;那么本节就将说明一个插件如何开发;

自定义插件 - 图1

如上图,编译起初,扫描项目目录下的所有文件(不包含指定排除文件),后实例化 File 对象,并对 File 内容进行编译分析;

编译阶段插件

在编译阶段,文件是单文件进行编译的,这个阶段主要是对文件内容的编译分析;这个阶段分为 lintparserpreprocessorpostprocessoroptimizer 等插件扩展点。

对于这些插件扩展点,可详见文档 单文件编译流程

其扩展点插件接口比较简单;

  1. /**
  2. * Compile 阶段插件接口
  3. * @param {string} content 文件内容
  4. * @param {File} file fis 的 File 对象 [fis3/lib/file.js]
  5. * @param {object} settings 插件配置属性
  6. * @return {string} 处理后的文件内容
  7. */
  8. module.exports = function (content, file, settings) {
  9. return content;
  10. };

为了搞清楚哪些功能用那种类型的插件去实现比较好,建议详细阅读单文件编译流程 这篇文档。

fis 的插件是以 NPM 包的形式提供的,这将意味着 fis 的插件都是一个 NPM 包,并且最终也需要发布到 NPM 平台上。在开始之前你需要了解 node 是如何加载一个 NPM 包的 https://nodejs.org/api/modules.html

FIS3 不再强制用户必须把插件(一个 NPM 包)进行全局安装,可把插件安装到项目根目录 (fis-conf.js 所在目录或 —root 指定的目录),这个遵循 node 加载一个包的规范即可。

  1. my-proj/
  2. my-proj/fis-conf.js
  3. my-proj/node_modules/fis3-<type>-<name>/index.js
  • 插件开发

    1. // vi my-proj/node_modules/fis3-<type>-<name>/index.js
    2. module.exports = function (content, file, settings) {
    3. // 只对 js 类文件进行处理
    4. if (!file.isJsLike) return content;
    5. return content += '\n// build ' + Date.now()
    6. }
  • 插件调用

    1. // fis-conf.js
    2. fis.match('*.js', {
    3. <type>: fis.plugin('<name>', {
    4. //conf
    5. })
    6. })
  • 发布 NPM 包

    https://docs.npmjs.com/getting-started/publishing-npm-packages

FIS团队建议,开发插件时为了方便可放到项目目录下,但发布到 NPM 后还是建议进行全局安装,一个团队使用的插件应该是被固化的。


为了便捷解决一些简短功能,也可以插件功能直接写到 fis-conf.js 中:

  1. fis.match('*.js', {
  2. // 直接设置插件属性的值为插件处理逻辑
  3. postprocessor: function (content, file, settings) {
  4. return content += '\n// build ' + Date.now();
  5. }
  6. });

参考插件

打包阶段插件

原理请详细参考文档 构建流程。到打包阶段,所有的文件都经过了单文件处理,该压缩的已经被压缩,该预编译的也进行了预编译。这个阶段主要实现一些共性的功能,比如打包合并。所以插件接口也不太一样了。

  1. /**
  2. * 打包阶段插件接口
  3. * @param {Object} ret 一个包含处理后源码的结构
  4. * @param {Object} conf 一般不需要关心,自动打包配置文件
  5. * @param {Object} settings 插件配置属性
  6. * @param {Object} opt 命令行参数
  7. * @return {undefined}
  8. */
  9. module.exports = function (ret, conf, settings, opt) {
  10. // ret.src 所有的源码,结构是 {'<subpath>': <File 对象>}
  11. // ret.ids 所有源码列表,结构是 {'<id>': <File 对象>}
  12. // ret.map 如果是 spriter、postpackager 这时候已经能得到打包结果了,
  13. // 可以修改静态资源列表或者其他
  14. }

跟编译时打包一样,也可项目本地开发或者是直接写到 fis-conf.js 中。参考 打包阶段插件。其配置方式与单文件编译阶段插件配置方式不同。由于 packager 时所有文件都在处理之列,所以需要通过以下方式进行配置;

  1. fis.match('::package', {
  2. <type>: fis.plugin('<name>')
  3. })

参考插件

Deploy 插件

deploy 插件是一类比较特殊的插件,它的功能只是发布数据,比如发布到某个文件夹下或者是发布到远端服务器上,以及用什么方式发布(http,ftp,git等等),deploy 插件是异步模型的。

deploy 作用于某些文件或者全部文件;它依然以文件属性的方式分配给某些文件,比如:

  1. fis.match('*.js', {
  2. deploy: [
  3. fis.plugin('replace', {
  4. from: 'some-string',
  5. to: 'another-string'
  6. }),
  7. fis.plugin('local-deliver') // 发布到本地,由 -d 参数制定目录
  8. ]
  9. })

也就是说可以在 deploy 阶段做一些转码、replace 这样的事情,最后一个插件必然是发布文件到磁盘或者远端的插件。

插件接口如下:

  1. /**
  2. * deploy 插件接口
  3. * @param {Object} options 插件配置
  4. * @param {Object} modified 修改了的文件列表(对应watch功能)
  5. * @param {Object} total 所有文件列表
  6. * @param {Function} next 调用下一个插件
  7. * @return {undefined}
  8. */
  9. module.exports = function(options, modified, total, next) {
  10. next(); //由于是异步的如果后续还需要执行必须调用 next
  11. };

参考插件

命令行插件

fis3 默认提供了 releaseserverinspectinitinstall五个子命令,每个子命令都是通过独立 npm 包来完成,命名规范为 fis3-command-xxxx。如果希望扩展新的子命令如 foo, 则需要开发 npm 包 fis3-command-foo,全局安装或者安装在对应的 fis 项目目录,代码请参考如下所示:

  1. exports.name = 'foo';
  2. exports.desc = 'description of foo.';
  3. exports.options = {
  4. '-h, --help': 'print this help message',
  5. '--files' : 'some options.'
  6. };
  7. exports.run = function(argv, cli) {
  8. // 如果输入为 fis3 foo -h
  9. // 或者 fis3 foo --help
  10. // 则输出帮助信息。
  11. if (argv.h || argv.help) {
  12. return cli.help(exports.name, exports.options);
  13. }
  14. // 可以通过 argv 知道命令行中有哪些参数以及是什么值。
  15. console.log('I am working..');
  16. };

参考插件

插件类型

  • lint
  • parser
  • preprocessor
  • standard
  • postprocessor
  • optimizer
  • prepackager
  • packager
  • spriter
  • postpackager
  • deploy