找回 Node.js 里面那些遺失的 ES6 特性
由于 Babel,WebPack, React 技術的流行, 小明同學已經開始在前端代碼里面用上了 ECMAScript 2015 (以下稱 ES6 ) 的眾多特性。 import , export , class , arrow function , let const 等等關鍵詞甚至都已經開始變成小明的肌肉記憶。
但是等等,對于小明這樣既寫 React 又寫 Node.js 的的人來說,又有點分裂了。經常性的在 Node.js 里面寫 import xxx from 'xxx'; 然后被 Node.js 的解析器無情的拒絕;
另外對于一致性有點追求的人肯定受不了同一個倉庫, 同一類腳本, 同一個人維護卻有兩種風格。
恩, 不能忍!
Node.js 對 ES6 的支持
其實 Node.js 對 ES6 的很多特性都已經開始支持了。 在 Node.js 使用的 JS 引擎 V8 里面將不同狀態 ES6 特性分成了 3 個等級:
- shipping (已經分發并默認開啟的特性)
- staged (已經分發, 但需要使用 –harmony 參數開啟的特性)
- in progress (開發中, 還不穩定或者未實現的特性, 不推薦使用)
『shipping』 已經開啟的 ES6 特性
本文使用的 Node.js 版本號:
穩定版本:4.2.4
對應 V8 引擎的版本:4.5.103.35
最新版本:5.3.0
對應 V8 引擎版本:4.6.85.31
目前默認開啟的 ES6 特性如下:
- Block scoping
- let (strict mode only)
- const
- function-in-blocks (strict mode only [1])
- Classes (strict mode only)
- Collections
- Map
- WeakMap
- Set
- WeakSet
- Typed arrays
- Generators
- Binary and Octal literals
- Object literal extensions (shorthand properties and methods)
- Promises
- New String methods
- Symbols
- Template strings
- Arrow Functions
- new.target [2]
- Object.assign
- Spread operator [2]
對于這些官方引擎的特性,由于在底層實現,在性能與穩定性都有更高保障,在任何時候我們都應該優先使用。
『staged』 需要使用 --harmony 參數開啟的 ES6 特性
- Symbol.toStringTag
- Array.prototype.includes (可以直接使用 polyfill 支持, 5.x 版本)
- Rest Parameters (可以直接用 transform-es2015-parameters 轉換,支持更全面, 5.x 版本)
『in progress』 開發中的 ES 特性
--harmony_modules (enable "harmony modules") --harmony_array_includes (enable "harmony Array.prototype.includes") --harmony_regexps (enable "harmony regular expression extensions") --harmony_proxies (enable "harmony proxies") --harmony_sloppy (enable "harmony features in sloppy mode") --harmony_unicode_regexps (enable "harmony unicode regexps") --harmony_reflect (enable "harmony Reflect API") --harmony_destructuring (enable "harmony destructuring") --harmony_sharedarraybuffer (enable "harmony sharedarraybuffer") --harmony_atomics (enable "harmony atomics") --harmony_new_target (enable "harmony new.target")
『in progress』特性是那些將要支持(但具體時間未知)的特性。
開啟模塊的 ES6 模式
Babel 是一個插件式的 JavaScript 編譯器, 能將一些當前 JS 引擎中不支持的特性和語法, 通過一個個特定插件,轉換成當前引擎可以理解的 JS 腳本。 我們可以使用 Babel 來轉換我們的 Node.js 腳本。
接下來, 我們就可以去 Babel 插件列表去選擇對應的轉換插件來為我們的 Node.js 插上隱形的翅膀了。
首先, 我們需要確認我們需要 Babel 添加哪些特性支持。
選擇 ES 轉換的原則
- 優先使用原生特性
- 優先選擇那些穩定實現的特性。 由于一些 ES 特性需要引擎的底層支持才能完美支持, 通過代碼轉換可能很難完美支持, 對于這種特性只能不用或少用
基于這個原則, 小明篩選出如下插件。
- transform-strict-mode (由于很多 ES 特性需要 嚴格模式才能打開, 添加這個插件就會自動在所有文件上添加 'use strict'; )
- transform-es2015-modules-commonjs (將 ES6 模塊標準 轉換成 Node.js 用的 CMD 模塊標準)
- transform-es2015-spread (支持 ES6 的 spread 操作符 )
- transform-es2015-destructuring (支持 賦值解構 )
- transform-es2015-parameters (支持默認參數, 參數解構, 以及其他參數)
轉換示例: import
from
import Mod from './mod'; new Mod();
to
'use strict'; var _mod = require('./mod'); var _mod2 = _interopRequireDefault(_mod); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } new _mod2.default();
轉換示例: export
from:
export default class Mod { }
to:
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class Mod {} exports.default = Mod;
上面這些選擇的插件可以根據個人口味以及 Node.js 版本 進行添加或刪除。選好模塊, 我們就可以安裝插件以及創建對應得babel配置文件去處理
安裝插件
在 npm 模塊或應用目錄下執行
# 安裝 core 和命令行工具 $ npm install --save-dev babel-core babel-cli # 安裝所有插件 $ npm install --save-dev babel-plugin-transform-strict-mode babel-plugin-transform-es2015-modules-commonjs babel-plugin-transform-es2015-spread babel-plugin-transform-es2015-destructuring babel-plugin-transform-es2015-parameters
添加配置文件
在應用根目錄下面創建對應的配置文件 .babelrc ,
{ "plugins": [ "transform-strict-mode", "transform-es2015-modules-commonjs", "transform-es2015-spread", "transform-es2015-destructuring", "transform-es2015-parameters" ] }
文件組織
由于 Node.js本身有加載器, 所以不需要將所有文件打包成一個文件, 推薦的做法是, 添加一個 src 目錄, 用于存放 ES6 腳本, 然后將整個目錄打包到 lib 目錄下, 對應的腳本為
babel src --out-dir lib
開發調試的時候, 可以直接用 babel-cli 模塊提供 babel-node 代替 node 直接啟動 src 目錄下面的入口腳本。
babel-node src/index.js
最后, 將命令封裝到 package.json 里面
{ "name": "my-awasome-es6-package", "version": "1.0.0", "description": "use es6 in node", "main": "lib/index.js", "scripts": { "start": "babel-node src/index.js", "build": "babel src --out-dir lib" }, "devDependencies": { "babel-cli": "~6.3.17", "babel-core": "~6.3.26", "babel-plugin-syntax-object-rest-spread": "^6.3.13", "babel-plugin-transform-es2015-modules-commonjs": "^6.3.16", "babel-plugin-transform-es2015-spread": "^6.3.14", "babel-plugin-transform-object-rest-spread": "^6.3.13", "babel-polyfill": "^6.3.14" } }
我們就可以使用下面的命令啟動和編譯我們的代碼了
# npm run build 構建腳本 # npm start 使用 babel-node 啟動進程
這里的注意點:
- 模塊入口 main 應該指向構建后的腳本, 這樣用你模塊的用戶不需要去進行編譯, 以及線上運行得時候不用去編譯。
- babel-node 不適合用于生產環境,生產環境應使用編譯后的代碼。 不過在開發環境里面使用還是挺方便的。
接下來要做的事情
接下來你可能會問
- 測試怎么辦
- 怎么 Debugging
大家可以在這里 ( Using Babel ) 查到更多感興趣的信息
來自: http://taobaofed.org/blog/2016/01/07/find-back-the-lost-es6-features-in-nodejs/