如何在NodeJS項目中優雅的使用ES6
如何在NodeJS項目中優雅的使用ES6
NodeJs最近的版本都開始支持ES6(ES2015)的新特性了,設置已經支持了async/await這樣的更高級的特性。只是在使用的時候需要在node后面加上參數: --harmony 。但是,即使如此node也還是沒有支持全部的ES6特性。所以這個時候就需要用到 Babel 了。
現在開始Babel
在開始使用Babel之前,假設
-
你已經安裝了nodejs,并且已經熟悉了Js。
-
你也可以使用 npm 安裝各種依賴包。
-
而且你也對ES6(后來改為ES2015)有一定程度的熟悉。
同時假設你已經安裝了 yarn ,并且也熟悉了yarn。Yarn最大的優點就是它比 npm 要快很多,因為yarn只把需要的庫下載一次,之后用到的時候直接使用本地緩存的版本。npm每次都會下載這些庫。這簡直就是浪費生命。如果你還沒有安裝yarn,也沒有關系,下面也會有npm的使用方法。
接下來開始安裝配置Babel。安裝babel-cli
yarn add babel-cli --dev // npm install --save-dev babel-cli
安裝babel的presets。
yarn add babel-preset-es2015 --dev // npm install --save-dev babel-preset-es2015
這個時候你就可以使用ES2015的特性了。但是,這還不夠,比如我不想用 Promise 我想用更加方便的 async/await 語法。只有es2015這個preset是不夠的。
Babel的plugin和preset
Babel本身不處理語言特性的轉碼。這些功能都是由 plugin 和 preset 實現的(preset也是一個plugin的集合)。如上文所述,要使用es2015的內容就需要安裝 babel-preset-es2015 這個preset。要使用async/await那么就需要安裝對應的preset或者插件。為了簡單我們安裝preset: babel-preset-stage-0 。preset stage-0 包含了async/await相關的插件: babel-plugin-syntax-async-functions 、 babel-plugin-transform-regenerator 。
yarn add babel-preset-stage-0 --dev // npm install --save-dev babel-preset-stage-0
這樣還是不能在項目中使用es7的async/await了。還需要更多的配置,有兩種方法可以達到目的:
-
使用 babel-polyfill 。有一個不好地地方, babel-polyfill 會污染global對象,所以不適合于library之類的使用。僅適合于web app使用。
-
使用babel運行時轉碼工具, transform-runtime 插件。使用這個方法正好彌補了上面的方法的不足之處。它是尤其適合于library一類的項目使用。
分別介紹這兩種方法。
安裝 babel-polyfill :
yarn add babel-polyfill --dev // npm install --save-dev babel-polyfill
之后,在你的項目的入口文件的最上方引入 babel-polyfill 。比如我現在有一個Express的Web App,那么的入口文件就是開啟這個app的 index.js 文件。在這個文件的最上方引入polyfill, require('babel-polyfill') 。或者你的入口文件已經是ES2015 的寫法了,那么就直接import, import 'babel-polyfill' 。
使用 transform-runtime 也非常簡單。安裝:
yarn add babel-plugin-transform-runtime --dev // npm install --save-dev babel-plugin-transform-runtime
另外還需要安裝 babel-runtime :
yarn add babel-runtime // npm install --save babel-runtime
之后在 .babelrc 文件中添加如下的配置,兩個二選其一即可:
// without options
{
"plugins": ["transform-runtime"]
}
// with options
{
"plugins": [
["transform-runtime", {
"helpers": false, // defaults to true
"polyfill": false, // defaults to true
"regenerator": true, // defaults to true
"moduleName": "babel-runtime" // defaults to "babel-runtime"
}]
]
}</code></pre>
剩下的就是歡暢的使用 async/await 了。
另外如果要使用 Object.assing 這樣的方法的話,也可以使用插件: babel-plugin-transform-object-assign ,如果要使用解構賦值可以使用插件: babel-plugin-transform-object-rest-spread 。當然這些都包含在了 stage-0 這個preset中。
現在就開始寫ES2015的代碼吧。在項目中安裝ExpressJs,創建一個 index.js 文件。我們來試著創建一個小小的web app作為練習:
import Express from 'express'
let app = Express()
app.get('/', (req, res) => {
res.send('hello world')
})
app.listen(8080, () => console.log('server is running at http://localhost:8080'))</code></pre>
運行命令:
./node_modules/.bin/babel-node index.js --preset es2015, stage-0
使用命令 babel-node *就可以讓代碼運行起來,后面的參數指定了在轉義js代碼的時候使用的preset和plugin。
Babel官方推薦的方法是時候用 .babelrc 文件,這一方式可以更加靈活。在項目的更目錄上創建 .babelrc 文件,在里面添加你安裝的preset和plugin的描述:
{
"presets": ["es2015", "stage-0"]
}
這樣可以直接使用 babel-node 來執行代碼,或者使用命令 babel 來轉義代碼。如:
babel -w code/ -d build/
babel命令會從配置文件中讀取配置,來變異 code/ 目錄下的文件,并把轉義之后的JavaScript文件導出到 build/ 目錄下。還有命令行里的參數 -w ,這個命令參數指定的是 watch ,每次code目錄的文件修改后都會觸發babel命令的再次執行。
在文件中使用Source Maps
上面看起來很不錯了。但是還有一個問題,在你調試代碼的時候,你調試的實際是 babel 命令轉碼之后的js,不是原來你編寫的源代碼所在的文件。調試的不是源文件,多少會有些不便。比如下面的文件會拋出一個異常:
async function errorAsyncFunc() {
try{
throw new Error('Async function error')
} catch(e) {
throw e
}
}
errorAsyncFunc()</code></pre>
在轉碼命令中加一個 --source-maps 可以解決這個問題:
babel code/ -d build/ --source-maps
最后在 package.json 里添加scripts節點:
"scripts": {
"build": "babel src -d build --source-maps",
"start": "node build/index.js"
},
接下來:
npm run build
// to be continued...
來自:https://segmentfault.com/a/1190000008162239