简介

有时间研究下开源库的源码,总是会有些收获的。注意到 Atom 插件编写时,可以直接使用 babel, coffeescript 或者 typescript。有些诧异,毕竟 Electron 中内置的 node 引擎,也一定不是完全兼容 es6,更不用说 coffeescript 和 typescript了。所以,必然在加载插件时,Atom 有某种自动转换的操作。刚好最近有一些类似的需求,需要批量以单个文件的方式转换一些其他语法的文件到 es5 兼容的js文件,于是就把 Atom 的转换机制拆分了出来,写成一个 cli。

他山之玉,不敢私藏。如果只是使用,请直接在npmjs上查找:smart-transform

特色定制

毋容置疑,最核心的地方是取自于 Atom 本身。之所以把这个逻辑单独剥离出来,主要是我很羡慕 Atom 插件编写时,各种语法随心使用的舒爽!要是自己项目,也能这么随意,岂不是爽歪歪!!!

为了独立于 Atom 使用,同时又具备一定的通用新,主要定制性体现在:

  • 将逻辑剥离成一个 cli 命令行工具,以后不管自己还是别人,拿来即用。不是每个前端,都很擅长 nodejs,所以我觉得,这还是能方便一些人的。
  • 通过配置文件,允许个性化定制。即,每个项目的输入和输出目录可以通过配置文件来自由配置。现在还不够灵活,只支持指定唯一一个输入文件夹和唯一一个输出文件夹,不过暂时够用了。
  • 引入 uglify-js 进行压缩和混淆。这一点,确实是项目本身的需要,我相信大部分人,都有这个需求吧?另外,之所以直接使用 uglify-js ,当然是因为我不想再额外配置 webpack 呀!!

扔一个 smart-transform.json 配置文件示例上来吧:

{
"in":"./src",
"out":"./lib",
"exclude":["./src/hi-ignore.js"],
"minify":true,
"minifyExclude":["./src/hi-ts.ts"]
}

源码解读

package.json

  "bin": {
"smart-transform": "index.js"
}

比较特殊的是 bin 字段。第一次写 cli 的童鞋,常常因为没有写这个字段,导致没有以全局命令的形式使用自己的工具库。

index.js

这是定制最多的一个文件。它实现的主要功能是,读取具体项目根目录的配置文件 smart-transform.json ,然后根据内部字段,来进行一些个性化的转换操作。

目前支持的操作有:

  • 将指定目录的 babeljs/coffeescript/typescript 转为 es5 兼容的js文件,并输出到另一个目录。
  • 忽略某些文件,不对其进行转换操作。
  • 转换时,可选支持同时进行压缩和混淆操作。压缩和混淆,目前使用的是 uglify-js

代码不长,但是本身有一些 node 相关的代码,所以我就还是贴出来,感兴趣的顺便瞅一眼:

#!/usr/bin/env node
'use strict'
var path = require("path")
var fs = require ('fs-plus')
var fse = require('fs-extra')
var os = require("os")
var {execSync} = require("child_process")
var UglifyJS = require("uglify-js") var argv = require('minimist')(process.argv.slice(2)) var project = argv.project
var configInfo = require(path.resolve(project,"./smart-transform.json")) var inDir = path.resolve(project,configInfo.in)
var outDir = path.resolve(project,configInfo.out)
var minify = configInfo.minify var excludeFiles = configInfo.exclude.map(function (filePath) {
return path.resolve(project,filePath)
}) var minifyExcludeFiles = configInfo.minifyExclude.map(
function (filePath) {
return path.resolve(project,filePath)
}
) fse.ensureDirSync(outDir) var inFiles = fs.listSync(inDir,[".js",".ts","coffee"]) for (var inFile of inFiles) {
if (excludeFiles.includes(inFile)) { // 不需要处理的,直接复制到输出目录
var outFile = path.resolve(project,outDir,path.basename(inFile))
fse.copySync(inFile,outFile)
continue
} var sourceCode = require("./compile-file")(inFile) if (minify && !minifyExcludeFiles.includes(inFile)) {
sourceCode = UglifyJS.minify(sourceCode).code
} var outFile = path.resolve(project,outDir,path.basename(inFile,path.extname(inFile)) + ".js")
fse.ensureFileSync(outFile)
fs.writeFileSync(outFile,sourceCode)
}

compile-file.js

相关预编译逻辑取自原Atom代码中的 src/compile-cache.js 类,主要区别是,禁用代码地图并禁用输出代码内的注释。考虑到项目本身的内部兼容性,并没有直接使用最新版的 Atom 源码演绎。如果自己有其他定制需求,可以直接看 Atom 源码。

这个文件比较出彩的地方是,它把各种类似的语法都使用 COMPILERS 的机制管理。一种语法对应一个 COMPILER。在某些特定情况下,如果你想解析或转换其他类型的文件,只需要修改这个类,新增一个 COMPILER 即可。

'use strict'
var path = require('path')
var fs = require('fs-plus') var COMPILERS = {
'.js': require('./babel'),
'.ts': require('./typescript'),
'.coffee': require('./coffee-script')
} function compileFileAtPath (filePath) {
const extension = path.extname(filePath)
const compiler = COMPILERS[extension] var sourceCode = fs.readFileSync(filePath, 'utf8') if (compiler.shouldCompile(sourceCode, filePath)) {
const compiledCode = compiler.compile(sourceCode, filePath)
return compiledCode
} return sourceCode
} module.exports = compileFileAtPath

babel.js coffee-script.js typescript.js

分别取自 Atom 源码中的 babel.js coffee-script.js typescript.js。有极小的修改,典型的 拿来主义 。有兴趣的,直接去看下源码,此处不做赘述。

注意

使用 bable 的js文件,开头应是以下几种的其中一种,否则无法被识别:

/** @babel */
"use babel"
'use babel'
/* @flow */

参考文章

【smart-transform】取自 Atom 的 babeljs/coffeescript/typescript 智能转 es5 库的更多相关文章

  1. 大众点评评论数据抓取 反爬虫措施有css文字映射和字体库反爬虫

    大众点评评论数据抓取  反爬虫措施有css文字映射和字体库反爬虫 大众点评的反爬虫手段有那些: 封ip,封账号,字体库反爬虫,css文字映射,图形滑动验证码 这个图片是滑动验证码,访问频率高的话,会出 ...

  2. APICloud支持Atom编辑器,并建立开发工具核心库

    APICloud支持Atom编辑器开发工具 APICloud始终坚持多开发工具支持策略,开发者无论使用Sublime Text3.Eclipse还是Webstorm,都可以在APICloud平台中找到 ...

  3. 爬取百度贴吧前1000页内容(requests库面向对象思想实现)

    此程序以李毅吧为例子,以面向对象的设计思想实现爬取保存网页数据,暂时并未用到并发处理,以后有机会的话会加以改善 首先去百度贴吧分析贴吧地址栏中url后的参数,找到分页对应的参数pn,贴吧名字对应的参数 ...

  4. APICloud重磅支持Atom编辑器,并建立开发工具核心库

    APICloud技术再次升级,不仅支持Atom编辑器开发工具,并推出核心开发工具库,使开发者进行App开发更便捷高效. APICloud支持Atom编辑器开发工具 APICloud始终坚持多开发工具支 ...

  5. 用浏览器(支持WebSocket)和node-inspector 调试后端(CoffeeScript,Typescript)代码

    调试效果 配置 npm安装node-inspector: $ npm install -g node-inspector 配置gulp,gulp可以用 gulp-node-inspector 或 用g ...

  6. [TypeScript] Transform Existing Types Using Mapped Types in TypeScript

    Mapped types are a powerful and unique feature of TypeScript's type system. They allow you to create ...

  7. Webduino Smart 从入门到起飞

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 试用了一下,感觉这板子+WebduinoBlockly在线开发环境,下限低.上限也低,以后肯定要刷其他固件的.举个简单的例子,WB ...

  8. Tools - Atom编辑器

    Atom官网 Atom编辑器的常用插件 预览 document-outline:Show a heirarchical outline of a text document minimap:A pre ...

  9. Atom实用配置插件for C++

    autocomplete-clang  自动补全 autocomplete for C/C++/ObjC using clang autocomplete-python 自动补全 Python pac ...

随机推荐

  1. Go 单例模式[个人翻译]

    原文地址:http://marcio.io/2015/07/singleton-pattern-in-go/ 最近几年go语言的增长速度非常惊人,吸引着各界人士切换到Go语言.最近有很多关于使用Rub ...

  2. WPF 如何画出1像素的线

    如何有人告诉你,请你画出1像素的线,是不是觉得很简单,实际上在 WPF 上还是比较难的. 本文告诉大家,如何让画出的线不模糊 画出线的第一个方法,创建一个 Canvas ,添加一个线 界面代码 < ...

  3. MTV模型

    django的MTV分别代表: model(模型):负责业务对象与数据库的对象(orm) template(模板):负责把页面展示给用户 view(视图):负责业务逻辑,并在适当的时候调用model和 ...

  4. 【转】浅谈UML的概念和模型之UML九种图

    原文地址:浅谈UML的概念和模型之UML九种图 目录: UML的视图 UML的九种图 UML中类间的关系 上文我们介绍了,UML的视图,在每一种视图中都包含一个或多种图.本文我们重点讲解UML每种图的 ...

  5. bug:未考虑实际使用场景

    最近bug比较多,汗颜. 1.需求背景 (1)app活动页面,用户参与并完成能够以1分钱价格购买指定商品(2)这个页面可分享至app以外的渠道,如微信.QQ等 2.这个bug的表现形式:用户在第三方渠 ...

  6. C++ 多态与虚函数

    1.多态的概念 由虚函数实现的动态多态性就是:同一类族中不同类的对象,对同一函数调用作出不同的响应. 先看下面这个简单的例子: #include<iostream> using std:: ...

  7. 深度学习系列 Part (2)

    1. 神经网络原理 神经网络模型,是上一章节提到的典型的监督学习问题,即我们有一组输入以及对应的目标输出,求最优模型.通过最优模型,当我们有新的输入时,可以得到一个近似真实的预测输出. 我们先看一下如 ...

  8. HDU6127Hard challenge

    Hard challenge Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others) ...

  9. Connections between cities

    Connections between cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java ...

  10. JS模块化-requireJS

    1. 为什么要使用require.js 刚开始的时候,网页需要用到很多不同的插件,都是依次加载,需要注意其中的加载顺序即依赖关系. <script src="1.js"> ...