黎清龙

1 年前
  • 1830

    浏览
  • 3

    评论
  • 0

    收藏

fis3 新特性应用

本文作者:IMWeb 黎清龙 原文出处:IMWeb社区 未经同意,禁止转载

fis3 新特性应用

1 前言

fis3相比fis2,核心思路并没有改变

还是围绕3个核心做处理:

而整体构建流程也没有做过多的改动。

fis3相对于fis2来说,用户更容易使用,给插件开发者提供更多的能力

这主要体现于以下两点:

  1. 类似css的覆盖式配置方式,不需要用命令行参数来进行配置
  2. 提供许多事件锚点

这篇文章主要介绍的就是第2点,讲解fis3提供的特殊事件,及其作用。

2 lookup:file

fis3 在查找文件资源的时候,通过统一的接口【fis.project.lookup】查找

在该接口里面,会抛出lookup:file事件,看如下注释:

 /**
   * 当查找文件时派送, 可以扩展 fis 默认的查找文件功能。如:支持无后缀文件查找,支持 components 文件查找。
   * @event lookup:file
   * @property {Object} info 包含查找路径信息。
   * @property {File} file 文件对象。
   * @memberOf fis
   */
  fis.emit('lookup:file', info, file);

info参数是一个对象,因此,我们通过监听lookup:file事件来对文件资源的id进行额外处理

fis3-hook-lego是一个fis3 版本的 lego组件系统 包管理的模块查找插件

它的作用是让用户使用lego组件如同使用node组件一样,让系统能够智能的识别lego组件,感兴趣的读者可以深入了解该插件

实际上,fis3-hook-lego的核心原理就是利用了lookup:file事件,看如下源代码:

module.exports = function(fis, opts) {
    fis.on('lookup:file', function(info, file) {
        // 不处理相对路径的文件和已经处理了的文件
        if (file.isJsLike && info.rest && info.rest[0] !== '.' && !info.id) {
            var ret = lookup(info.rest, opts); // 尝试lego模块查找
            if (ret && ret.file) { // 如果找到,则修改id,定位到相应文件
                info.id = ret.file.getId();
                info.file = ret.file;
            }
        }
    });
};

3 proccess:start, proccess:end, release:start, release:end

这4个事件的用意非常明显,fis3的构建流程主要分为2步:每个文件的compile和所有文件的package

以上4个事件就是这两个过程的开始以及结束锚点

这4个关键节点的用处不言而喻,下面笔者举两个例子

3.1 检测构建时间

var timeMap = {};
fis.on('proccess:start', function(file) {
    timeMap[file.id] = +new Date();
});
fis.on('proccess:end', function(file) {
    console.log(file.id, 'compile use:', +new Date() - timeMap[file.id], 'ms');
});
fis.on('release:start', function(file) {
    timeMap['release:'] = +new Date();
});
fis.on('release:end', function(file) {
    console.log('release use:',  +new Date() - timeMap['release:'], 'ms');
});

结果如下:

3.2 缓存清理

在打包过程中,通常我们需要许多复杂的处理,为了提升构建效率,可能我们需要做一些缓存机制

但是,我们需要在构建结束的时候,把这些缓存清掉,否则就会影响下一次构建(在watch的情况下)

这个时候,release:end事件就可以很好的为我们工作:

fis.on('release:end', function() {
    // 每次处理完都需要重置cache
    readCache = {};
});

4 compile:parser, compile:preprocessor, compile:standard, compile:postprocessor, compile:optimizer

以上5个事件是文件compile阶段中5个关键节点的锚点

在每个阶段中,对file进行相应阶段的处理之前,fis3都会先抛出一个事件

这些节点的意义也非常深远,甚至可以改变fis3的compile流程,同样笔者也举两个例子

4.1 不需要两个插件!

因为fis3的构建流程固化了,有时候我们在进行某些处理的时候发现,我们需要在某个操作的前后分别进行处理,比如我要在资源inline替换的前后做某些操作,我们知道inline替换是standard步骤进行的,那么我们可能需要写两个插件,分别是:

fis3-preprocessor-xxx 和 fis3-postprocessor-xxx

我们真的需要吗?

No,通过事件,我们可以只需要一个插件!看如下代码:

// file: fis3-preprocessor-xxx
var conf;

fis.on('compile:postprocessor', function(file) {
    // some process after inline
});

module.exports = function(content, file, settings) {
    // some process before inline
    conf = settings; // save the settings which can be used on postprocessor
};

需要注意以下两点:

  1. 一般我们把插件定义为最开始需要处理的那个阶段插件,否则就无意义了
  2. 因为两个插件组合为一个插件了,所以我们只有一个地方配置参数了,两个插件的参数会组合在一起,这个时候就要好好的组织一下参数格式,并保存起来,以便其他插件使用

有5个事件,所以我们可以把5个插件何在一起!!!

4.2 你可以不孤单!

compile是单文件处理,在这个过程中是拿不到其他文件的,它不像package阶段插件那样,有一个ret参数可以使用

但是,有时候,我们在compile阶段真的需要其他一些文件资源的时候怎么办?

在fis2或者不知道有额外能力的情况下,往往我们会把我们的处理放到package阶段,在这里我们才能找到其他文件,然后做相应处理,然后,可能,你需要蛋疼的重新compile一次该文件(笔者是做过这种事情的)

解决方案是,你可以在compile阶段自己存储所有的文件资源!

请看如下代码:

// file: fis3-parser-xxx
// parse是最早的事件点,所以要定义这个点的插件,详见4.1

var fileMap = {};

fis.on('compile:postprocessor', function(file) {
    var deps = findDepsOfFile(file);

    if (deps.length) { // 需要依赖依赖其他文件
        if (hasAllDepsFile(deps)) {
            // 所有依赖的资源已经compile,现在可以进行处理了!
            process(file);

            // 然后需要看下其他文件是否依赖这个文件
            processIfOtherFileNeedThisFile(file);
        } else {
            // 资源还没到齐,先缓存起来
            fileMap[file.id].deps = deps;
        }
    } else {
        processIfOtherFileNeedThisFile(file);
    }
});

module.exports = function(content, file, settings) {
    // 收集file对象
    fileMap[file.id] = {
        file: file
    };
};

看起来很绕,也确实很绕,在这里只是想让读者知道,可以这样子处理

这样处理已经违背了fis3的核心理念,慎用!

后续

可以看到,fis3最重大的改进就是提供了更多的想象空间给插件开发者

合理利用这些特性,我们可以在fis3的环境下做许多事情

但就只有这些吗?

No!还有另外一些更加有趣更加开放的特性还没介绍。

敬请期待下一期!

3条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。