mocha
是我比较喜欢的一款的单元测试框架。使用mocha直接测试TypeScript文件,须要结合babel,preset-env,preset-typescript以及babel-register。javascript
// linked-list.ts export default class LinkedList(){ } // ./test/linked-list.js require('@babel/register')({ presets: [ ['@babel/preset-env', { modules: 'commonjs'}], ['@babel/preset-typescript'] ], extensions: ['.ts'] }) const LinkedList = require('./src/linked-list.ts') describe('#test', function(){ it('#1', function(){ let linkedList = new LinkedList() ... }) })
须要注意的是java
而后在命令行中执行git
mocha ./test/linked-list.js
发现报以下错误LinkedList is not a constructor
es6
排查以后发现,在测试文件./test/linked-list.js 中github
const LinkedList = require('./src/linked-list.ts')
导入的LinkedList真实为typescript
{ default: function LinkedList(){}, __esModule: true }
因此我应该在测试文件中加上npm
const LinkedList = require('./src/linked-list.ts').default
才能正确执行。json
可是上面的写法很麻烦,并且很蠢。很显然babel将个人ts文件从ES module 转换为 commonjs的时候,是将export default 的内容挂载module.exports.default上面,而不是我一开始指望的export default === module.exports = bash
在babel v6以后,export default 导出的内容再也不使用module.exports = 导出。babel
// es6.js export default function sum(){} // commonjs exports.__module = true exports['default'] = function sum(){}
exports.__module
用来告诉打包工具(基本上这是全部打包工具的事实标准)当前模块是从ES module 转换过来的,彻底兼容ES module。因此当使用import 导入这样一个commonjs模块的时候,应该使用__importDefault helper来加载
var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; } exports.__esModule = true; var bar_1 = __importDefault(require("bar"));
这也是咱们前面必须加上.default的缘由。
可是这样子很麻烦,并且很蠢。若是咱们还想保持es5 以前的模块交互逻辑,也就是export default导出的内容使用commonjs module.exports = 默认导出。咱们可使用babel-plugin-add-module-exports。
require('@babel/register')({ presets: [ ['@babel/preset-env', { modules: 'commonjs'}], ['@babel/preset-typescript'] ], plugins: ['add-module-exports'], extensions: ['.ts'] })
该插件会在当你的模块只有export default 默认导出的时候,转换为commonjs的默认导出。
// es6.js export default function sum(){} // commonjs exports.__module = true exports['default'] = function sum(){} modules.exports = exports['default']
这样子咱们就不须要加上麻烦的.default了。
对因而否使用默认导出(export default / module.exports =
),好像愈来愈多的人开始持否认态度。就连javascript 的创造者Nicholas C. Zakas也表示不会再使用默认导出了。要知道npm上大多数的包或者模块都是使用module.exports默认导出的。
那么默认导出到底有什么弊端呢?根据尼古拉斯的说法,默认导出最重要的一个弊端是会悄无声息地转移到其余变量,没法经过搜索代码的方式来跟踪。这给代码阅读,排查错误形成了很大的干扰。导出的最佳实践应该是**只使用具名导出
举个例子
// linked-list.js export default class LinkedList{} // a.js import list from './linked-list'
在一开始,咱们知道list就是LinkedList类。可是随着项目的迭代,咱们可能在多处使用了这个LinkedList类,可是咱们都想a.js同样改变了这个类名,当咱们想经过LinkedList全局搜索何处引用的时候,咱们就已经没法获得正确的结果了。每次阅读代码的时候,咱们都须要拉到头部看下这个list是从何处导入的,导入的是什么,这会严重中断咱们的开发进程。
PS: export default 也是一种具名导出(named export),只不过这个名字是default.
// a.js export default function LinkedList(){} // b.js import { default } from './a.js' import LinkedList from './a.js' // default === LinkedList