博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【smart-transform】取自 Atom 的 babeljs/coffeescript/typescript 智能转 es5 库
阅读量:6691 次
发布时间:2019-06-25

本文共 3599 字,大约阅读时间需要 11 分钟。

  hot3.png

简介

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

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

特色定制

毋容置疑,最核心的地方是取自于 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文件,并输出到另一个目录。
  • 忽略某些文件,不对其进行转换操作。
  • 转换时,可选支持同时进行压缩和混淆操作。压缩和混淆,目前使用的是

代码不长,但是本身有一些 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.projectvar 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.minifyvar 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代码中的 类,主要区别是,禁用代码地图并禁用输出代码内的注释。考虑到项目本身的内部兼容性,并没有直接使用最新版的 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 源码中的 。有极小的修改,典型的 拿来主义 。有兴趣的,直接去看下源码,此处不做赘述。

注意

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

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

参考文章

转载于:https://my.oschina.net/ios122/blog/1580670

你可能感兴趣的文章
Android学习笔记--universal_image_loader图片加载框架
查看>>
C++中的也能使用正则表达式----转载
查看>>
.net c# 开发ActiveX组件
查看>>
AngularJS 包含
查看>>
CSS3 @media 查询
查看>>
2019.3.29 区块链论文翻译
查看>>
使用HTML辅助方法载入分部视图
查看>>
检测硬件RDMA卡是否存在
查看>>
递归算法
查看>>
使用Linux的tcpdump命令结合Windows的wireshark抓包和分析
查看>>
数论的题
查看>>
Android onclicklistener中使用外部类变量时为什么需要final修饰【转】
查看>>
《Spring2之站立会议9》
查看>>
0059-乘积问题
查看>>
2019年的第一篇随笔
查看>>
关于公网ip的一些信息(摘抄)
查看>>
5分钟弄懂Docker!
查看>>
BZOJ1076:[SCOI2008]奖励关(状压DP,期望)
查看>>
BZOJ2223/3524:[POI2014] Couriers(主席树)
查看>>
MyEclipse — Maven+Spring+Struts+Hibernate 整合 [学习笔记-5]
查看>>