FIS 插件機制

FIS 插件機制
author: @TiffanysBearphp

當咱們使用 FIS 插件的時候,有沒有想過本身也開發一個基於 FIS 的插件,參與 FIS 打包編譯的整個流程;那麼問題就來了:css

  • FIS 的編譯過程運行原理是怎樣的呢?
  • FIS 編譯打包的過程有哪些?
  • 怎麼參與FIS 的打包編譯過程?
  • 怎麼實現一個基於FIS的插件?
  • FIS 是怎麼引入自定義插件的?

基於如下的問題,從原理再進行慢慢分析,瞭解 FIS 編譯的基本流程和原理,以及如何本身自定義一個 FIS 插件。html

編譯過程運行原理

fis的編譯過程能夠分爲兩個階段: 單文件編譯 和 打包。處理流程以下圖,圖片來自 FIS 官網:前端

[圖片上傳失敗...(image-e08187-1566795911500)]node

單文件編譯過程

從圖上能夠看出,單文件編譯過程都是經過pipe管道進行的,而且在最初都創建有緩存,以提高編譯效率,在單文件的處理過程當中,又主要分爲了如下的幾個步驟:git

  • parser(編譯器):將其餘語言編譯爲標準js、css,好比將前端模板、coffee-> script編譯爲js,將less、sass編譯爲css。
  • preprocessor(標準預處理器):在fis進行標準化處理以前進行某些修改,好比 支持image-set語法的預處理插件
  • standard(標準化處理):前面兩項處理會將文件處理爲標準的js、css、html語法,fis內核的標準化處理過程對這些語言進行 三種語言能力 擴展處理。這也就意味着,使用less、coffee等語法在fis系統中同樣具有 資源定位、內容嵌入,依賴聲明 的能力。該過程 不可擴展。
  • postprocessor(標準後處理器):對文件進行標準化以後的處理,好比利用依賴聲明能力實現的 js包裝器插件,能夠獲取js文件的依賴關係,並添加define包裝。
  • lint(可選)(校驗器):代碼校驗階段,使用 fis release命令的 --lint 參數會調用該過程。
  • test(可選)(測試器):自動測試階段,使用 fis release命令的 --test 參數會調用該過程。
  • optimize(可選)(優化器):代碼優化階段,使用 fis release命令的 --optimize 參數會調用該過程。fis內置的fis-optimizer-uglify-js插件和fis-optimizer-clean-css插件都是這類擴展。

打包過程

若是是文件的簡單合併,可使用 __inline 進行簡單的內容嵌入,若是嵌入的內容中須要實時嵌入動態變量,能夠考慮使用 bdtmpl 進行前端模塊的編譯和轉換。github

打包的原理是經過 FIS 的pack 配置,對文件資源進行合併等操做,最後產出關於文件打包信息到 map.json 文件中,併產生相應的打包文件。因此 FIS 的打包結果並 不會再嵌入到某個文件內,而是利用map.json中的數據進行運行時打包信息查詢。npm

1、 在fis-conf.js中配置:json

fis.config.merge({
    pack : {
        'aio.js' : ['a.js', 'b.js', 'c.js']
    }
});

2、 執行命令 fis release --pack --dest ./output後端

3、 進入output目錄,查看map.json文件,獲得內容:

{
    "res" : {
        "a.js" : {
            "uri" : "/a.js",
            "type" : "js",
            "pkg" : "p0"
        },
        "b.js" : {
            "uri" : "/b.js",
            "type" : "js",
            "pkg" : "p0"
        },
        "c.js" : {
            "uri" : "/c.js",
            "type" : "js",
            "pkg" : "p0"
        }
    },
    "pkg" : {
        "p0" : {
            "uri" : "/aio.js",
            "type" : "js",
            "has" : ["a.js", "b.js", "c.js"]
        }
    }
}

4、 將map.json交給某個前端或後端框架,當運行時須要「a.js」資源的時候,該框架應該讀取map.json的信息,並根據必定的策略決定是否應該返回「a.js」資源所標記的「p0」包的uri。

所以也能夠看出,FIS 團隊強調的一點,打包只是資源的備份。

fis系統的打包過程提供了4個可擴展的處理過程,它們是:

  1. prepackager(打包預處理器):在打包前進行資源預處理。
  2. packager(打包處理器):對資源進行打包。默認的打包器就是收集資源表,創建map.json的過程
  3. spriter(csssprite處理器):對css進行sprites化處理
  4. postpackager(打包後處理器):打包以後對文件進行處理,一般用來將map.json轉換成其餘語言的文件,好比php

插件調用機制

fis的插件也是一個npm包,利用fis.require函數來加載。當咱們在fis系統中加載一個插件的時候,會利用 nodejs的require向上查找機制 從 fis-kernel 模塊出發,向上查找所需模塊。

fis插件系統巧妙的利用了nodejs的require機制來實現其擴展機制。這意味着,要想擴展fis能夠有 三種途徑 :

一、使用fis的用戶,本身須要某種插件,能夠在fis安裝目錄的 同級,安裝本身擴展的插件。好比: npm install -g fis npm install -g fis-parser-coffee-script
二、使用 FIS 內置的插件,目前已經內置的插件包括:

  • fis-kernel:fis編譯機制內核
  • fis-command-release:fis release命令的提供者,處理編譯過程,並提供文件監聽、自動上傳等功能
  • fis-command-install:fis install命令的提供者,用於從fis倉庫下載組件、配置、框架、素材等資源
  • fis-command-server:fis server命令的提供者,用於開啓一個本地php-cgi服務器,對項目進行預覽、調試。
  • fis-optimizer-uglify-js:fis的優化插件,調用uglify-js對文件內容進行js壓縮。
  • fis-optimizer-clean-css:fis的優化插件,調用clean-css對文件內容進行css壓縮。
  • fis-postprocessor-jswrapper:fis的後處理器插件,用於對js文件進行包裝,支持amd的define包裝或者匿名自執行函數包裝。

三、開發一個依賴於fis模塊的npm包,並在這個包裏定製所須要的插件。這種方式與上一條相似,也是將插件安裝在fis的同級目錄下。

可擴展時機

在整個編譯流程能夠擴展的點有如下,也就說說咱們本身自定義的插件能夠在下列的時機進行本身需求的定製,經過回調獲取該階段編譯的結果,進行自定義配置。
編譯階段:

  • parser
  • preprocessor
  • postprocessor
  • lint
  • test

打包階段:

  • prepackager
  • packager
  • spriter
  • postpackager

自定義插件

自定義插件須要的,須要封裝一個npm包,結合上面的可擴展時機,命名規則通常爲:fis-[須要插入的時機名稱]-[自定義插件名],例如:fis-parse-my-css;

編譯階段插件

一、在自定義插件的index.js中:

/*
 * fis
 * http://fis.baidu.com/
 */

'use strict';

var sass = require('node-sass');

module.exports = function(content, file, settings) {
    // content: 內容
    // file: 文件
    // settings: 如今的配置
    var opts = fis.util.clone(settings);
    opts.data = content;
    return sass.renderSync(opts);
};

二、插件配置調用
在fis-config.js中調用格式以下:

// vi fis-conf.js
// 文件後綴 .scss 的調用插件 my-sass 進行解析
fis.config.set('modules.parser.scss', 'my-sass');
fis.config.set('settings.parser.my-sass', {
    // my-sass 的配置
});
fis.config.set('roadmap.ext.scss', 'css'); // 因爲 scss 文件最終會編譯成 css,設置最終產出文件後綴爲 css

三、發佈npm包,這個能夠參考我以前寫過的一個文檔,從0到1發佈一個npm包

打包階段插件

一、插件接口如此:

/**
 * 打包階段插件接口
 * @param  {Object} ret      一個包含處理後源碼的結構
 * @param  {Object} conf     通常不須要關心,自動打包配置文件
 * @param  {Object} settings 插件配置屬性
 * @param  {Object} opt      命令行參數
 * @return {undefined}          
 */
module.exports = function (ret, conf, settings, opt) {
    // ret.src 全部的源碼,結構是 {'<subpath>': <File 對象>}
    // ret.ids 全部源碼列表,結構是 {'<id>': <File 對象>}
    // ret.map 若是是 spriter、postpackager 這時候已經能獲得打包結果了,
    // 能夠修改靜態資源列表或者其餘
}

以prepackager插件爲例。prepackager即打包前須要對文件作某些處理,好比想在全部的html註釋裏面插入編譯時間。

二、插件開發

咱們爲這個插件取名叫 append-build-time

<npm/global/path>/fis-prepackager-append-build-time
<npm/global/path>/fis-prepackager-append-build-time/index.js

在其 index.js 中:

module.exports = function(ret, conf, settings, opt) {
    fis.util.map(ret.src, function(subpath, file) {
        if (file.isHtmlLike) {
            var content = file.getContent();
            content += '<!-- build '+ (new Date())+'-->';
            file.setContent(content);
        }
    });
};

三、配置使用

// vi fis-conf.js
fis.config.set('modules.prepackager', 'append-build-time'); // packager階段插件處理全部文件,因此不須要給某一類後綴的文件設置。
fis.config.set('settings.prepackager.append-build-time', {
    // settings
})

四、發佈npm包,這個能夠參考我以前寫過的一個文檔,從0到1發佈一個npm包

小提示:

固然爲了更快速的搞定一些小需求,能夠把插件功能直接寫到配置文件 fis-conf.js 中;

// vi fis-conf.js
fis.config.set('modules.postprocessor.js', function (content) {
    return content += '\n// build time: ' + Date.now();
});

注意:配置使用插件時,同一個擴展點能夠配置多個插件,好比;

// 調用 fis-prepackager-a, fis-prepackager-b ...插件
fis.config.set('modules.prepackager', 'a,b,c,d');
// or
fis.config.set('modules.prepackager', ['a', 'b', 'c', 'd']);
// or
fis.config.set('modules.prepackager', [function () {}, function () {}])

具體的原理和封裝步驟就講到這麼多,具體封裝解決方案能夠見 FIS 的官網 —— 封裝解決方案

本文參考文檔:
一、插件擴展點列表 http://fex-team.github.io/fis-site/docs/more/extension-point.html
二、插件調用機制 http://fex-team.github.io/fis-site/docs/more/how-plugin-works.html
三、編譯過程運行原理 http://fex-team.github.io/fis-site/docs/more/fis-base.html

相關文章
相關標籤/搜索