有時間研究下開源庫的源碼,老是會有些收穫的。注意到 Atom 插件編寫時,能夠直接使用 babel, coffeescript 或者 typescript。有些詫異,畢竟 Electron 中內置的 node 引擎,也必定不是徹底兼容 es6,更不用說 coffeescript 和 typescript了。因此,必然在加載插件時,Atom 有某種自動轉換的操做。恰好最近有一些相似的需求,須要批量以單個文件的方式轉換一些其餘語法的文件到 es5 兼容的js文件,因而就把 Atom 的轉換機制拆分了出來,寫成一個 cli。前端
他山之玉,不敢私藏。若是隻是使用,請直接在npmjs上查找:smart-transformnode
毋容置疑,最核心的地方是取自於 Atom 自己。之因此把這個邏輯單獨剝離出來,主要是我很羨慕 Atom 插件編寫時,各類語法隨心使用的舒爽!要是本身項目,也能這麼隨意,豈不是爽歪歪!!!webpack
爲了獨立於 Atom 使用,同時又具有必定的通用新,主要定製性體如今:ios
扔一個 smart-transform.json 配置文件示例上來吧:git
{ "in":"./src", "out":"./lib", "exclude":["./src/hi-ignore.js"], "minify":true, "minifyExclude":["./src/hi-ts.ts"] }
"bin": { "smart-transform": "index.js" }
比較特殊的是 bin 字段。第一次寫 cli 的童鞋,經常由於沒有寫這個字段,致使沒有以全局命令的形式使用本身的工具庫。es6
這是定製最多的一個文件。它實現的主要功能是,讀取具體項目根目錄的配置文件 smart-transform.json ,而後根據內部字段,來進行一些個性化的轉換操做。github
目前支持的操做有:web
代碼不長,可是自己有一些 node 相關的代碼,因此我就仍是貼出來,感興趣的順便瞅一眼:typescript
#!/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) }
相關預編譯邏輯取自原Atom代碼中的 src/compile-cache.js 類,主要區別是,禁用代碼地圖並禁用輸出代碼內的註釋。考慮到項目自己的內部兼容性,並無直接使用最新版的 Atom 源碼演繹。若是本身有其餘定製需求,能夠直接看 Atom 源碼。npm
這個文件比較出彩的地方是,它把各類相似的語法都使用 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
分別取自 Atom 源碼中的 babel.js coffee-script.js typescript.js。有極小的修改,典型的 拿來主義 。有興趣的,直接去看下源碼,此處不作贅述。
使用 bable 的js文件,開頭應是如下幾種的其中一種,不然沒法被識別:
/** @babel */ "use babel" 'use babel' /* @flow */