詳解如何在NodeJS項(xiàng)目中優(yōu)雅的使用ES6
NodeJs最近的版本都開(kāi)始支持ES6(ES2015)的新特性了,設(shè)置已經(jīng)支持了async/await這樣的更高級(jí)的特性。只是在使用的時(shí)候需要在node后面加上參數(shù):--harmony。但是,即使如此node也還是沒(méi)有支持全部的ES6特性。所以這個(gè)時(shí)候就需要用到Babel了。
項(xiàng)目地址:https://github.com/future-challenger/petshop
現(xiàn)在開(kāi)始Babel
在開(kāi)始使用Babel之前,假設(shè)
1.你已經(jīng)安裝了nodejs,并且已經(jīng)熟悉了Js。
2.你也可以使用npm安裝各種依賴(lài)包。
3.而且你也對(duì)ES6(后來(lái)改為ES2015)有一定程度的熟悉。
同時(shí)假設(shè)你已經(jīng)安裝了yarn,并且也熟悉了yarn。Yarn最大的優(yōu)點(diǎn)就是它比npm要快很多,因?yàn)閥arn只把需要的庫(kù)下載一次,之后用到的時(shí)候直接使用本地緩存的版本。npm每次都會(huì)下載這些庫(kù)。這簡(jiǎn)直就是浪費(fèi)生命。如果你還沒(méi)有安裝yarn,也沒(méi)有關(guān)系,下面也會(huì)有npm的使用方法。
接下來(lái)開(kāi)始安裝配置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
這個(gè)時(shí)候你就可以使用ES2015的特性了。但是,這還不夠,比如我不想用Promise
我想用更加方便的async/await
語(yǔ)法。只有es2015這個(gè)preset是不夠的。
Babel的plugin和preset
Babel本身不處理語(yǔ)言特性的轉(zhuǎn)碼。這些功能都是由plugin和preset實(shí)現(xiàn)的(preset也是一個(gè)plugin的集合)。如上文所述,要使用es2015的內(nèi)容就需要babel-preset-es2015這個(gè)preset。要使用async/await那么就需要安裝對(duì)應(yīng)的preset或者插件。為了簡(jiǎn)單我們安裝preset:babel-preset-stage-0。preset stage-0包含了async/await相關(guān)的插件: babel-plugin-syntax-async-functions、babel-plugin-transform-regenerator。
yarn add babel-preset-stage-0 --dev // npm install --save-dev babel-preset-stage-0
這樣還是不能在項(xiàng)目中使用es7的async/await了。還需要更多的配置,有兩種方法可以達(dá)到目的:
1.使用babel-polyfill
。有一個(gè)不好地地方,babel-polyfill
會(huì)污染global對(duì)象,所以不適合于library之類(lèi)的使用。僅適合于web app使用。
2.使用babel運(yùn)行時(shí)轉(zhuǎn)碼工具,transform-runtime
插件。使用這個(gè)方法彌補(bǔ)了上面的方法的不足之處。它是尤其適合于library一類(lèi)的項(xiàng)目使用。
分別介紹這兩種方法。
babel-polyfill
:
yarn add babel-polyfill --dev // npm install --save-dev babel-polyfill
之后,在你的項(xiàng)目的入口文件的最上方引入babel-polyfill
。比如我現(xiàn)在有一個(gè)Express的Web App,那么的入口文件就是開(kāi)啟這個(gè)app的index.js文件。在這個(gè)文件的最上方引入polyfill,require('babel-polyfill')
?;蛘吣愕娜肟谖募呀?jīng)是ES2015的寫(xiě)法了,那么就直接import,import 'babel-polyfill'
。
使用transform-runtime
也非常簡(jiǎn)單。安裝:
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文件中添加如下的配置,兩個(gè)二選其一即可:
// 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" }] ] }
剩下的就是歡暢的使用async/await了。
另外如果要使用Object.assing
這樣的方法的話,也可以使用插件:babel-plugin-transform-object-assign
,如果要使用解構(gòu)賦值可以使用插件:babel-plugin-transform-object-rest-spread
。當(dāng)然這些都包含在了stage-0這個(gè)preset中。
現(xiàn)在就開(kāi)始寫(xiě)ES2015的代碼吧。在項(xiàng)目中安裝ExpressJs,創(chuàng)建一個(gè)index.js文件。我們來(lái)試著創(chuàng)建一個(gè)小小的web app作為練習(xí):
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'))
運(yùn)行命令:
./node_modules/.bin/babel-node index.js --preset es2015, stage-0
使用命令*babel-node**就可以讓代碼運(yùn)行起來(lái),后面的參數(shù)指定了在轉(zhuǎn)義js代碼的時(shí)候使用的preset和plugin。
Babel官方推薦的方法是時(shí)候用.babelrc文件,這一方式可以更加靈活。在項(xiàng)目的更目錄上創(chuàng)建.babelrc文件,在里面添加你安裝的preset和plugin的描述:
{ "presets": ["es2015", "stage-0"] }
這樣可以直接使用babel-node來(lái)執(zhí)行代碼,或者使用命令babel來(lái)轉(zhuǎn)義代碼。如:
babel -w code/ -d build/
babel命令會(huì)從配置文件中讀取配置,來(lái)變異code/目錄下的文件,并把轉(zhuǎn)義之后的JavaScript文件導(dǎo)出到build/目錄下。還有命令行里的參數(shù)-w,這個(gè)命令參數(shù)指定的是watch,每次code目錄的文件修改后都會(huì)觸發(fā)babel命令的再次執(zhí)行。
在文件中使用Source Maps
上面看起來(lái)很不錯(cuò)了。但是還有一個(gè)問(wèn)題,在你調(diào)試代碼的時(shí)候,你調(diào)試的實(shí)際是babel命令轉(zhuǎn)碼之后的js,不是原來(lái)你編寫(xiě)的源代碼所在的文件。調(diào)試的不是源文件,多少會(huì)有些不便。比如下面的文件會(huì)拋出一個(gè)異常:
async function errorAsyncFunc() { try{ throw new Error('Async function error') } catch(e) { throw e } } errorAsyncFunc()
在轉(zhuǎn)碼命令中加一個(gè)--source-maps
可以解決這個(gè)問(wèn)題:
babel code/ -d build/ --source-maps
最后在package.json里添加scripts節(jié)點(diǎn):
"scripts": { "build": "babel src -d build --source-maps", "start": "node build/index.js" },
接下來(lái):
npm run build
Gulp出場(chǎng)
上文講述了如何使用Babel實(shí)現(xiàn)ES201x的開(kāi)發(fā)。但是在正式的開(kāi)發(fā)中,上面的這些配置還略顯不足,尤其是你的項(xiàng)目包括web端、server端,尤其web端不僅處理ES201x的代碼還需要處理。所以需要Gulp出場(chǎng)。
這玩意兒看起來(lái)很復(fù)雜,你定義了編譯的過(guò)程。其實(shí)掌握了以后很好用,尤其是可以自動(dòng)處理很多東西,節(jié)約大把時(shí)間。要使用Gulp,必須先安裝NodeJS。這個(gè)基本是標(biāo)配。然后你會(huì)用到它的命令行工具。
安裝Gulp
在最新發(fā)布的Gulp里有一點(diǎn)調(diào)整。gulp-cli從gulp分離出來(lái)作為單獨(dú)的一部分使用。所以,如果你已經(jīng)安裝過(guò)gulp之前的版本需要先刪除:
npm rm --global gulp
安裝gulp-cli
yarn global add gulp-cli // npm install --global gulp-cli
在--dev模式下安裝gulp
yarn add gulp --dev // npm install --save-dev gulp
創(chuàng)建gulp配置文件
就像Babel要用.babelrc作為配置文件一樣,gulp也需要一個(gè)配置文件。這個(gè)配置文件就是gulpfile.js, 但是和babel同用的情況下把gulpfile.js重命名為gulp.babel.js:
mv "gulpfile.js" "gulpfile.babel.js"
gulp
的使用還是很簡(jiǎn)單的,主要就是在gulpfile.babel.js文件中添加各種task。在這些task中一定要添加一個(gè)叫做default的task,gulp命令的執(zhí)行起點(diǎn)就是從這里開(kāi)始。
假設(shè)有這么一個(gè)場(chǎng)景:
1.使用eslint檢查代碼,發(fā)現(xiàn)代碼風(fēng)格和潛在的錯(cuò)誤。
2.自動(dòng)實(shí)現(xiàn)ES201x -> ES5的代碼轉(zhuǎn)碼,并把轉(zhuǎn)碼后的代碼放在指定目錄下。
3.在轉(zhuǎn)碼的時(shí)候添加sourcemaps。
以上這些“任務(wù)”都是用gulp自動(dòng)實(shí)現(xiàn)。該如何配置呢?
gulp和eslint
要在gulp中使用各種請(qǐng)他的類(lèi)似于eslint這樣的功能的時(shí)候需要使用在gulp上的對(duì)應(yīng)的插件。沒(méi)錯(cuò),gulp的設(shè)計(jì)思路和gulp基本一樣:插件機(jī)制。
那么我們就需要首先下載eslint的插件:
yarn add --dev gulp-eslint // npm install --save-dev gulp-eslint
在開(kāi)始編寫(xiě)我們的第一個(gè)task之前, 做最后的準(zhǔn)備工作。首先需要配置.eslintrc文件。eslint會(huì)根據(jù)這個(gè)文件定義的規(guī)則檢查代碼的風(fēng)格。我們不準(zhǔn)備大批的配置規(guī)則,這樣非常耗時(shí)間而且也照顧不到很多我們項(xiàng)目已經(jīng)保留下來(lái)的編碼風(fēng)格。所以,airbnb的一套規(guī)則拿來(lái)使用時(shí)最好的辦法。
安裝eslint
yarn add --dev eslint // npm install --save-dev eslint
然后你可以運(yùn)行命令來(lái)初始化配置:./node_modules/.bin/eslint --init
。你也可以忽略這個(gè)命令,直接創(chuàng)建一個(gè).eslintrc的文件。
安裝eslint的airbnb擴(kuò)展
要使用airbnb的一套規(guī)則就需要安裝他們的eslint擴(kuò)展:
yarn add eslint-config-airbnb --dev // npm install --save-dev eslint-config-airbnb
命令執(zhí)行之后會(huì)提示有些依賴(lài)項(xiàng)沒(méi)有安裝,分別是eslint-plugin-import@^2.2.0
、eslint-plugin-import@^2.2.0
、eslint-plugin-jsx-a11y@^3.0.2
。依次安裝這些依賴(lài)項(xiàng)就好。
.eslintrc
{ "env": { "es6": true }, "rules": { "semi": "off", "import/no-extraneous-dependencies": ["error", { "devDependencies": true, "optionalDependencies": false, "peerDependencies": false }] ,"quotes": ["error", "single", {"allowTemplateLiterals": true}] }, "extends": "airbnb" }
env
指定環(huán)境是支持es6的,rules指定的是一些補(bǔ)充內(nèi)容,比如字符串使用單引號(hào)還是雙引號(hào)等。這個(gè)是根據(jù)個(gè)人喜好配置的,你可以選擇添加你需要的規(guī)則。最后是extends,這里配置airbnb就用上了airbnb的一套eslint編碼檢查規(guī)則。
gulp-eslint插件用起來(lái)
import gulp from 'gulp' import eslint from 'gulp-eslint // 配置需要處理的文件目錄和轉(zhuǎn)碼之后文件的存放目錄 const paramConfig = { source: 'src/**/*.js', dest: 'build', }
引入相關(guān)模塊之后開(kāi)始寫(xiě)任務(wù):
gulp.task('lint', () => { // eslint配置,使用配置的文件目錄。排除node_modules下的全部文件。 return gulp.src([paramConfig.source, '!node_modules/**']) .pipe(eslint()) .pipe(eslint.result(result => { console.log(`ESLint result: ${result.filePath}`); console.log(`# Messages: ${result.messages.length}`); console.log(`# Warnings: ${result.warningCount}`); console.log(`# Errors: ${result.errorCount}`); })) .pipe(eslint.format()) .pipe(eslint.failOnError()) })
如前文所述,default任務(wù)是必須:
gulp.task('default', ['lint'], function () { // lint任務(wù)成功執(zhí)行之后執(zhí)行這個(gè)方法 });
跳轉(zhuǎn)到項(xiàng)目的目錄下,運(yùn)行g(shù)ulp命令。會(huì)得到如下的輸出:
$ gulp [21:43:01] Requiring external module babel-register [21:43:01] Using gulpfile ~/Documents/test-polyfill/gulpfile.babel.js [21:43:01] Starting 'lint'... [21:43:02] Starting 'babel-sourcemaps'... ESLint result: ~/Documents/test-polyfill/src/index.js # Messages: 0 # Warnings: 0 # Errors: 0 ESLint result: ~/Documents/test-polyfill/src/test.js # Messages: 0 # Warnings: 0 # Errors: 0 [21:43:02] Finished 'lint' after 605 ms [21:43:02] Finished 'babel-sourcemaps' after 653 ms [21:43:02] Starting 'default'... gulp default task! [21:43:02] Finished 'default' after 98 μs
gulp和babel
這次同時(shí)處理babel和sourcemaps的問(wèn)題。
首先安裝插件:
yarn add --dev gulp-babel // npm install --save-dev gulp-babel
import gulp-babel
插件:
import babel from 'gulp-babel' import sourcemaps from 'gulp-sourcemaps'
添加任務(wù):
gulp.task('babel-sourcemaps', () => { return gulp.src(paramConfig.source) .pipe(sourcemaps.init()) .pipe(babel()) .pipe(sourcemaps.write('.')) .pipe(gulp.dest(paramConfig.dest)) })
修改default任務(wù):
javascript gulp.task('default', ['lint', 'babel-sourcemaps'], () => { console.log('gulp default task!') })
如果你不想用sourcemaps的話,可以這么寫(xiě):
javascript gulp.task('babel', () => { return gulp.src(paramConfig.source) .pipe(babel()) .pipe(gulp.dest(paramConfig.dest)) })
把gulp放在npm命令體系下
babel
老早就配置好了,現(xiàn)在和配置好了gulp。gulp每次輸入命令基本上就是手動(dòng)執(zhí)行?,F(xiàn)在應(yīng)該讓這個(gè)命令半自動(dòng)執(zhí)行了。
修改package.json文件,在其中添加scripts
節(jié)點(diǎn):
"scripts": { "build": "gulp", "start": "node build/index.js" },
如此一來(lái),很多的命令都可以像gulp一樣放在npm的scripts里執(zhí)行。比如,現(xiàn)在可以在命令行李輸入如下命令來(lái)實(shí)現(xiàn)lint和babel轉(zhuǎn)碼:
npm run build
開(kāi)始執(zhí)行:
npm start
總結(jié)
使用bebel可以提前使用最新的JavaScript語(yǔ)言特性,這樣編寫(xiě)很多代碼的時(shí)候會(huì)變得簡(jiǎn)潔高效。并且babel轉(zhuǎn)碼之后生成的代碼也是非常規(guī)范的ES5寫(xiě)法,同時(shí)是在嚴(yán)格模式下的。所以,我們?cè)趯?xiě)ES201x代碼的時(shí)候不需要再添加'use strict'
;標(biāo)識(shí)。
使用gulp又可以使很多不大不小但是很費(fèi)時(shí)間的事自動(dòng)處理。
把這兩者結(jié)合在一起會(huì)讓你的項(xiàng)目開(kāi)發(fā)效率提升很多。所以,看到這里你不覺(jué)得你應(yīng)該趕快在項(xiàng)目里使用這些技術(shù),讓開(kāi)發(fā)進(jìn)入快車(chē)道嗎?。。????
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
使用koa2創(chuàng)建web項(xiàng)目的方法步驟
這篇文章主要介紹了使用koa2創(chuàng)建web項(xiàng)目的方法步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-03-03node.js中的buffer.Buffer.byteLength方法使用說(shuō)明
這篇文章主要介紹了node.js中的buffer.Buffer.byteLength方法使用說(shuō)明,本文介紹了buffer.Buffer.byteLength的方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12windows系統(tǒng)下安裝yarn的詳細(xì)教程
yarn是一個(gè)新的JS包管理工具,它的出現(xiàn)是為了彌補(bǔ)npm的一些缺陷,下面這篇文章主要給大家介紹了關(guān)于windows系統(tǒng)下安裝yarn的詳細(xì)教程,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02NodeJS 實(shí)現(xiàn)多語(yǔ)言的示例代碼
這篇文章主要介紹了NodeJS 實(shí)現(xiàn)多語(yǔ)言的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09k8s node節(jié)點(diǎn)重新加入master集群的實(shí)現(xiàn)
這篇文章主要介紹了k8s node節(jié)點(diǎn)重新加入master集群的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02前端之npm運(yùn)行時(shí)配置文件.npmrc的方法(可用于配置npm淘寶源)
這篇文章主要給大家介紹了關(guān)于前端之npm運(yùn)行時(shí)配置文件.npmrc(可用于配置npm淘寶源)的相關(guān)資料,.npmrc 文件是用于配置 npm(Node.js 包管理器)行為的配置文件,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07Node.js中的EventEmitter類(lèi)使用小結(jié)
EventEmitter 是 Node.js 中的一個(gè)核心模塊,它提供了一種實(shí)現(xiàn)事件驅(qū)動(dòng)編程的機(jī)制,它是一個(gè)基于觀察者模式的類(lèi),用于在應(yīng)用程序中處理事件和觸發(fā)事件,這篇文章主要介紹了Node.js中的EventEmitter類(lèi)介紹,需要的朋友可以參考下2023-12-12