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