PantoJS

文件转换引擎
授权协议 Apache
开发语言 JavaScript
所属分类 Web应用开发、 常用JavaScript包
软件类型 开源软件
地区 国产
投 递 者 越风史
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

PantoJS 是一个极其灵活的文件转换引擎,通常用于项目的构建和编译,特别是 Web 前端项目。

它比较类似于 Grunt 或 Gulp,但更高效、强大和灵活。

核心特性

  • 支持任意定义的拓扑构建流程

只要是你能定义出来的构建流程,无论如何复杂,只要是合理的,Panto 都可以支持

  • 支持遗留文件的收集

在选择特定的文件类型后,可以一次性访问到未被选择的其它文件

  • 保证对每个源文件最多读取一次

对于同一个文件存在一个以上不同的处理流程,读取也最只有一次

  • 保证对于每个文件的同样处理流程只有一次

尽最大努力避免重复工作

  • 支持文件级别的精确缓存,最大程度上避免不必要的计算

不必重新构建的文件,尽最大努力利用缓存

  • 支持文件级别的精确增量构建

高效重复构建

与Grunt/Gulp相比

  Grunt Gulp Panto
流式任务
拓扑流程
一次读取
精确缓存
精确增量

快速入门

与 Grunt 和 Gulp 一样,Panto 也需要在项目根目录下定义流程配置文件 pantofile.js,但不支持 coffeescript 语法。一个最简单的 pantofile.js 内容如下:

module.exports = panto => {};

注意 Panto 对 Node.js 的最低版本要求是 6.0.0,因此可以放心使用 ES2015 的语法。

接着,就像加载 Grunt/Gulp 的插件一样,需要先加载转换器(Transformer)。转换器定义了如何变换文件内容的逻辑。

module.exports = panto => { panto.loadTransformer('read'); 
    panto.loadTransformer('less');
    panto.loadTransformer('copy');
    panto.loadTransformer('write');
};

以上需要使用npm加载相应的package:

npm install panto panto-transformer-read panto-transformer-less panto-transformer-copy panto-transformer-write --save-dev

下面先要定义几个参数:cwd、src、output。其中 src、output 相对于 cwd:

panto.setOptions({
    cwd: __dirname,
    src: 'src',
    output: 'output' });

现在开始定义构建流程,这里以转换less文件为例:

panto.pick('*.less').read().less().write();

这个流程的意义是在 src 目录内搜索以 .less 为扩展名的文件,并读取其内容,转换为CSS格式,并写入 output 的对应目录内。比如 src/style/foo.less,转换后写入 output/style/foo.less

现在,我们把除了less文件以外的其它文件拷贝到 output 中:

panto.rest().copy();

那么 src/config/c.yml 拷贝至 output/config/c.yml

现在,完整的构建配置文件的内容是:

module.exports = panto => { panto.loadTransformer('read');
panto.loadTransformer('less');
panto.loadTransformer('copy');
panto.loadTransformer('write');
panto.setOptions({
        cwd: __dirname,
        src: 'src',
        output: 'output' }); panto.pick('*.less').read().less().write(); panto.rest().copy();
};

你可以使用 load-panto-transformers 来避免书写大量 panto.loadTransformer('xxx') 语句,同时你也可以使用 time-panto来监控构建信息,这样,简化并完整的 pantofile.js 是:

module.exports = panto => { require('load-panto-transformers')(panto);
require('time-panto')(panto);
panto.setOptions({
        cwd: __dirname,
        src: 'src',
        output: 'output' }); panto.pick('*.less').read().less().write(); panto.rest().copy();
};

最后,为了在命令行环境下调用构建任务,你需要先安装 panto-cli

npm install panto-cli -g

在命令行中执行:

panto -f pantofile.js

以上示例请参考 https://github.com/pantojs/simple-panto-usage

转换器

转换器(Transformer) 定义了如何转换文件的逻辑。实现一个 Transformer 可以继承自 panto-transformer

const Transformer = require('panto-transformer'); 
class FooTransformer extends Transformer {
     _transform(file) { 
         file.content += 'A'; return Promise.resolve(file);
     } isTorrential() { 
           return false;
        } isCacheable() { 
            return true;
        }
} 
module.exports = FooTransformer;

如果文件的转换是相互独立的,那么实现 _transform 方法即可,否则需要实现 transformAll 方法,它们都返回 Promise 对象,两种转换器使用 isTorrential() 方法来区分。具体请参见 panto-transformer-browserify 与 panto-transformer-uglify的不同实现。

如果转换器是严格幂等的,则是可缓存的,这通过 isCacheable() 方法来区分。任何可能通过文件内容之外其它因素导致两次转换结果不一致的情景,都不能是可缓存的。例如,计算内容md5值的逻辑,只要内容相同,md5值即是一样的,不涉及任何其它因素,这就是可缓存的。再例如,为文件增加当前时间的时间戳内容,则一定是不可缓存的。

转换器的输入和输出都是文件对象或者是集合。文件对象是一个纯JavaScript对象(PlainObject),至少包含 filename 和 content 两个属性,你也可以增加其它属性。

Panto 使用流(Stream)来定义转换任务。作为节点,流可以构建为任意的有向无环图。

const Stream = require('panto').Stream; 
const s1 = new Stream(); 
const s2 = new Stream(); 
const s3 = new Stream(); 
const s4 = new Stream(); 
s1.connect(s2).connect(s4); 
s1.connect(s3);

以上代码构建的拓扑图如下:

流以一个转换器为构造参数,但也可以不传入任何参数。

new Stream(new Transformer())

通过定义拓扑流和转换器,可以简洁和清晰地描述如何构建一个项目。下面是一个复杂的构建流程示例:

panto topology

一个更典型的配置案例:

module.exports = panto => { panto.setOptions({
        cwd: __dirname,
        src: 'src',
        output: 'output' // 不可以与src相同 }); 
    require('load-panto-transformers')(panto); 
    const srcJs = panto.pick('**/*.{js,jsx}').tag('js(x)').read(); 
    srcJs.babel(clientBabelOptions).write(); 
    srcJs.babel(serverBabelOptions).write(); 
    panto.pick('**/*.less').tag('less').read().less().write(); // node_modules 的文件只需处理一次    
    panto.pick('node_modules/**/*', true).tag('node_modules').copy();
    panto.rest().tag('others').ignore().copy();
}
 相关资料
  • 把reg2all 用nsDialogs重写了界面,nsDialogs使自定义页面的互动性更强了。 Function nsDialogsPage nsDialogs::Create /NOUNLOAD 1018 Pop $Dialog ${If} $Dialog == error Abort ${E

  • 问题内容: 我有一个.mwb格式的数据库。我想在日食中使用它,所以我需要将其转换为.sql格式。如果有人知道如何使用任何工具来做到这一点。我认为我的sql工作台可以做到这一点,但不知道该怎么做。 问题答案: 在菜单中单击“数据库”,然后单击“正向工程”(快捷键CTRL + G)。 更新: 您的.mwb文件是专有格式,还包含Workbench中图形表示的信息。生成的.sql文件是一个脚本,您的MyS

  • 我用APKTool反向设计了一个Android应用程序,得到了一个。Smali文件作为源代码输出。我转换了。Smali文件和应用程序。Java文件。我成功地编辑了。Java文件,但现在我想把它们转换回。这样我就可以用新的重新编译应用程序了。Smali文件。当我离开的时候。Java文件,它没有重新编译,并给出了一些错误。我找不到任何关于编译的信息。Java到。所以我希望你们能帮我。 提前谢谢你。

  • 我想将xml文件格式转换为另一种格式;使用XSL1.0或2.0版。 http://www.w3.org/1999/xsl/transform“version=”1.0“> 这段代码是从“struct”节点的“members”属性中提取相关ID的起点,以后只用于发出“field”节点。 xslt处理器需要解析Struct节点的'members'属性。“members”属性是字段ID的列表。 在上面的

  • 问题内容: 我使用APKTool对Android应用程序进行了反向工程,并获得了.Smali文件作为源代码输出。我将带有应用程序的.Smali文件转换为.Java文件。我能够成功编辑.Java文件,但现在我想将它们转换回.Smali,以便可以使用新的.Smali文件重新编译应用程序。当我只留下.Java文件时,它不会重新编译并给出一些错误。我在互联网上找不到有关将.Java编译为.Smali的任何