FIS源码-fis release概览

开篇

前面已经已fis server open为例,讲解了FIS的整体架构设计,以及命令解析&执行的过程。下面就进入FIS最核心的部分,看看执行fis release这个命令时,FIS内部的代码逻辑。

这一看不打紧,基本把fis-kernel的核心模块翻了个遍,虽然大部分细节已经在脑海里里,但是要完整清晰的写出来不容易。于是决定放弃大而全的篇幅,先来个概要的分析,后续文章再针对涉及的各个环节的细节进行展开。

看看fis-command-release

老规矩,献上精简版的 release.js,从函数名就大致知道干嘛的。release(options)是我们重点关注的对象。

'use strict';

exports.register = function(commander){

    //  fis relase --watch 时,就会执行这个方法
    function watch(opt){
        // ...
    }

    // 打点计时用,控制台里看到的一堆小点点就是这个方法输出的
    function time(fn){
        // ...
    }

    // fis release --live 时,会进入这个方法,对浏览器进行实时刷新
    function reload(){
        //...
    }

    // 高能预警!非常重要的方法,fis release 就靠这个方法走江湖了
    function release(opt){
        // ...
    }

    // 可以看到有很多配置参数,每个参数的作用可参考对应的描述,或者看官方文档
    commander
        .option('-d, --dest <names>', 'release output destination', String, 'preview')
        .option('-m, --md5 [level]', 'md5 release option', Number)
        .option('-D, --domains', 'add domain name', Boolean, false)
        .option('-l, --lint', 'with lint', Boolean, false)
        .option('-t, --test', 'with unit testing', Boolean, false)
        .option('-o, --optimize', 'with optimizing', Boolean, false)
        .option('-p, --pack', 'with package', Boolean, true)
        .option('-w, --watch', 'monitor the changes of project')
        .option('-L, --live', 'automatically reload your browser')
        .option('-c, --clean', 'clean compile cache', Boolean, false)
        .option('-r, --root <path>', 'set project root')
        .option('-f, --file <filename>', 'set fis-conf file')
        .option('-u, --unique', 'use unique compile caching', Boolean, false)
        .option('--verbose', 'enable verbose output', Boolean, false)
        .action(function(){

            // 省略一大堆代码

            // fis release 的两个核心分支,根据是否有加入 --watch 进行区分
            if(options.watch){
                watch(options);    // 有 --watch 参数
            } else {
                release(options);   // 这里这里!重点关注!没有 --watch 参数
            }
        });
};

release(options); 做了些什么

用伪代码将逻辑抽象下,主要分为四个步骤。虽然最后一步才是本片文章想要重点讲述的,不过前三步是第四步的基础,所以这里还是花点篇幅介绍下。

findFisConf();    // 找到当前项目的fis-conf.js

setProjectRoot();    // 设置项目根路径,需要编译的源文件就在这个根路径下

mergeFisConf();    // 导入项目自定义配置

readSourcesAndReleaseToDest(options);    // 将项目编译到默认的目录下

下面简单对上面几个步骤进行一一讲解。

findFisConf() + setProjectRoot()

由于这两步之间存在比较紧密的联系,所以这里就放一起讲。在没有任何运行参数的情况下,比较简单

  1. 从命令运行时所在的工作目录开始,向上逐级查找fis-conf.js,直到找到位置
  2. 如果找到fis-conf.js,则以它为项目配置文件。同时,将项目的根路径设置为fis-conf.js所在的目录。
  3. 如果没有找到fis-conf.js,则采用默认项目配置。同时,将项目的根路径,设置为当前命令运行时所在的工作目录。

fis release的支持的配置参数可以知道,可以分别通过:

  1. --file:指定fis-conf.js的路径(比如多个项目公用编译配置)
  2. --root:指定项目根路径(在A工作目录,编译B工作目录)

由本小节前面的介绍得知,--file--root两个配置参数之间是存在联系的,有可能同时存在。下面用伪代码来说明下

if(options.root){

    if(options.file){
        // 项目根路径,为 options.root 指定的路径
        // fis-conf.js路径,为 options.file 指定的路径
    }else{
        // 项目根路径,为 options.root 指定的路径
        // fis-conf.js路径,为 options.root/fis-conf.js
    }
}else{

    if(options.file){
        // fis-conf.js路径,为 options.file 指定的路径
        // 项目根路径,为 fis-conf.js 所在的目录
    }else{
        // fis-conf.js路径,为 逐层向上遍历后,找到的 fis-conf.js 路径
        // 项目根路径,为 fis-conf.js 所在的目录
    }
}

mergeFisConf()

合并项目配置文件。从源码可以清楚的看到,包含两个步骤:

  1. fis-conf.js创建缓存。除了配置文件,FIS还会为项目的所有源文件建立缓存,实现增量编译,加快编译速度。缓存的细节后面再讲,这里知道有这么回事就行。
  2. 合并项目自定义配置
// 如果找到了 fis-conf.js
if(conf){
    var cache = fis.cache(conf, 'conf');
    if(!cache.revert()){
        options.clean = true;
        cache.save();
    }
    require(conf);  // 加载 fis-conf.js,其实就是合并配置
} else {
    // 还是没有找到 fis-conf.js
    fis.log.warning('missing config file [' + filename + ']');
}

readSourcesAndReleaseToDest()

通过这个死长的伪函数名,就知道这个步骤的作用了,非常关键。根据当前项目配置,读取项目的源文件,编译后输出到目标目录。

编译过程的细节,下一节会讲到。

项目编译大致流程

项目编译发布的细节,主要是在release这个方法里完成。细节非常的多,主要在fis.release()这个调用里完成,基本上用到了fis-kernel里所有的模块,如releasecompilecache等。

  1. 读取项目源文件,并将每个源文件抽象为一个File实例。
  2. 读取项目配置,并根据项目配置,初始化File实例。
  3. 为File实例建立编译缓存,提高编译速度。
  4. 根据文件类型、配置等编译源文件。(File实例各种属性的修改)
  5. 项目部署:将编译结果实际写到本地磁盘。

伪代码流程如下:fis-command-release/release.js

var collection = {};    // 跟total一样,key=>value 为 “编译的源文件路径”=》"对应的file对象"
    var total = {};
    var deploy = require('./lib/deploy.js');    // 文件部署模块,完成从 src -> dest 的最后一棒

function release(opt){

    opt.beforeEach = function(file){
        // 用compile模块编译源文件前调用,往 total 上挂 key=>value
        total[file.subpath] = file;
    };
    opt.afterEach = function(file){
        // 用compile模块编译源文件后调用,往 collection 上挂 key=>value
        collection[file.subpath] = file;
    };

    opt.beforeCompile = function(file){
        // 在compile内部,对源文件进行编译前调用(好绕。。。)
        collection[file.subpath] = file;
    };

    try {
        //release
        // 在fis-kernel里,fis.release = require('./lib/release.js');
        // 在fis.release里完成除了最终部署之外的文件编译操作,比如文件标准化等
        fis.release(opt, function(ret){

            deploy(opt, collection, total);    // 项目部署(本例子里特指将编译后的文件写到某个特定的路径下)
        });
    } catch(e) {
        // 异常处理,暂时忽略
    }
}

至于fis.release()

前面说了,细节非常多,后续文章继续展开。。。

时间: 2024-10-28 16:00:08

FIS源码-fis release概览的相关文章

FIS源码-fis release增量编译与依赖扫描细节

开篇 前面已经提到了fis release命令大致的运行流程.本文会进一步讲解增量编译以及依赖扫描的一些细节. 首先,在fis release后加上--watch参数,看下会有什么样的变化.打开命令行 fis release --watch 不难猜想,内部同样是调用release()方法把源文件编译一遍.区别在于,进程会监听项目路径下源文件的变化,一旦出现文件(夹)的增.删.改,则重新调用release()进行增量编译. 并且,如果资源之间存在依赖关系(比如资源内嵌),那么一些情况下,被依赖资源

FIS源码解析-整体架构

序言 这里假设本文读者对{{FIS}}已经比较熟悉,如还不了解,可猛击官方文档. 虽然FIS整体的源码结构比较清晰,不过讲解起来也是个系统庞大的工程,笔者尽量的挑重点的讲.如果读者有感兴趣的部分笔者没有提到的,或者是存在疑惑的,可以在评论里跑出来,笔者会试着去覆盖这些点. 下笔匆忙,如有错漏请指出. Getting started 如在开始剖析FIS的源码前,有三点内容首先强调下,这也是解构FIS内部设计的基础. 1. FIS支持三个命令,分别是fis release.fis server.fi

源码剖析AQS在几个同步工具类中的使用

感谢网友[张超盟]的投稿 1. 前言 AQS(AbstractQueuedSynchronizer)是 java.util.concurrent的基础.J.U.C中宣传的封装良好的同步工具类Semaphore.CountDownLatch.ReentrantLock.ReentrantReadWriteLock.FutureTask等虽然各自都有不同特征,但是简单看一下源码,每个类内部都包含一个如下的内部类定义: abstract static class Sync extends Abstra

产品打包工具的制作,ant,编译源码,打jar包,打tag,打war包,备份release版本等

1.  在进行打包工具的制作前,需要准备的软件有: svnant-1.3.1 作用是让ant和svn相关联 apache-ant-1.9.7 需要设置ant_home,path,我的配置是: ANT_HOME = D:\kaipu\cms4all\app-tpl-pack\apache-ant-1.9.7 Path = %ANT_HOME%\bin 2.准备好上面的操作之后,找个英文的目录,比如:D:\kaipu\cms4all\app-tpl-pack,在目录下创建两个文件build.xml和

Android 自定义相机及分析源码

Android 自定义相机及分析源码 使用Android 系统相机的方法: 要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下 <intent-filter> <action android:name="android.intent.action.IMAGE_CAPTURE" /> <category android:name="android.intent.category.DEFAULT" />

Apache Spark源码走读(四)Hive on Spark运行环境搭建 &amp;hiveql on spark实现详解

<一>Hive on Spark运行环境搭建 楔子 Hive是基于Hadoop的开源数据仓库工具,提供了类似于SQL的HiveQL语言,使得上层的数据分析人员不用知道太多MapReduce的知识就能对存储于Hdfs中的海量数据进行分析.由于这一特性而收到广泛的欢迎. Hive的整体框架中有一个重要的模块是执行模块,这一部分是用Hadoop中MapReduce计算框架来实现,因而在处理速度上不是非常令人满意.由于Spark出色的处理速度,有人已经成功将HiveQL的执行利用Spark来运行,这就

Hadoop2源码分析-MapReduce篇

1.概述 前面我们已经对Hadoop有了一个初步认识,接下来我们开始学习Hadoop的一些核心的功能,其中包含mapreduce,fs,hdfs,ipc,io,yarn,今天为大家分享的是mapreduce部分,其内容目录如下所示: MapReduce V1 MapReduce V2 MR V1和MR V2的区别 MR V2的重构思路 本篇文章的源码是基于hadoop-2.6.0-src.tar.gz来完成的.代码下载地址,请参考<Hadoop2源码分析-准备篇>. 2.MapReduce V

TOMCAT源码分析——停止服务

前言 在<TOMCAT源码分析--启动服务>一文中我介绍了Tomcat服务的启动过程分析,本文讲解Tomcat服务是如何停止的. 停止过程分析 我们停止Tomcat的命令如下: sh shutdown.sh 所以,将从shell脚本shutdown.sh开始分析Tomcat的停止过程.shutdown.sh的脚本代码见代码清单10. 代码清单10 os400=false case "`uname`" in OS400*) os400=true;; esac # resolv

ubuntu 11.10(32位系统)下编译android源码 make错误解决办法

本文介绍在ubuntu 11.10系统下编译android 2.3.3源码,编译之前请确定上两篇文章(http://www.cnblogs.com/dwayne/archive/2011/11/16/2250732.html和http://www.cnblogs.com/dwayne/archive/2011/11/11/2245383.html)中所需的准备工作已经成功完成.编译完成生成系统镜像文件,并在模拟器中运行. 准备工作完成后,开始编译工作.下载下来的源码有5G多,如果按照我之前写的获