ECMAScript 最迷人的地方除了 First Class Function 外,可以前後端共用相同語言與 Package 也是一大特色,本文將使用 ECMAScript 2015+ 建立 ES Module,並透過 Babel 轉譯成 CommonJS Module,讓前後端都能使用相同 。
Version
Node 14.18.1
Add Package
$ mkdir my-package
$ cd my-package
建立 my-package
目錄。
$ yarn init --yes
使用 Yarn 建立 package.json
。
$ yarn add @babel/core @babel/cli @babel/preset-env --dev
安裝 Babel 相關 package,負責將 ES module 轉譯成 CommonJS module。
僅管 ES module 才是標準,但目前後端 Node 支援 ES module 程度仍然有限,但前端 Webpack 已經支援 CommonJS module,因此只能在開發階段使用 ES module,再透過 Babel 轉譯成現在前後端都能接受的 CommonJS module
日後等 Node 支援 ES Module 成熟,就可不必再使用 Babel,完全使用 ES Module 即可
$ yarn add ramda
安裝 package 本身所相依的 package。
本例會使用到 Ramda
.babelrc
{
"presets": [
"@babel/preset-env"
]
}
在 project 根目錄下建立 .babelrc
,使用剛剛安裝的 @babel/preset-env
的設定將 ES6+ 轉譯。
My First Package
src/index.js
export { isOdd } from './isOdd'
建立 src
目錄,package 所有的 source code 都在此目錄下。
index.js
主要用於統整所有 module。
從 isOdd.js
引入的 isOdd
馬上 export 出去。
src/isOdd.js
import { compose, equals, flip, modulo } from "ramda"
export let isOdd = compose (equals (1), flip (modulo) (2))
引用了 Ramda 的 function 組合出 isOdd()
。
package.json
{
"name": "wink-test",
"version": "1.0.0",
"main": "dist/index.js",
"files": [
"dist"
],
"license": "MIT",
"scripts": {
"build": "babel src --out-dir dist"
},
"dependencies": {
"ramda": "^0.26.1"
},
"devDependencies": {
"@babel/cli": "^7.7.0",
"@babel/core": "^7.7.2",
"@babel/preset-env": "^7.7.1"
}
}
第 9 行
"scripts": {
"build": "babel src --out-dir dist"
},
yarn build
將使用 Babel 編譯 src
目錄下所有 .js
到 dist
目錄。
第 4 行
"main": "dist/index.js",
Package 的起始檔案改成解譯後 dist
目錄下的 index.js
。
第 5 行
"files": [
"dist"
],
dist
目錄下所有檔案將安裝到 user 的 node_modules
目錄下。
$ yarn build
將 ES Module 轉譯成 CommonJS Module。
dist/index.js
dist/index.js
為轉譯後的 CommonJS module。
$ yarn publish
使用 yarn publish
發布 package 到 NPM。
Quokka
Quokka 可正常使用剛發佈 wink-test
的 isOdd()
。
Node
Node 也可正常使用剛發佈 wink-test
的 isOdd()
。
Vue
App.vue
<template>
<div>
<ul>
<li v-for="(item, index) in result" :key="index">
{{ item }}
</li>
</ul>
</div>
</template>
<script>
import { filter } from 'ramda';
import { isOdd } from 'wink-test';
let mounted = function() {
let data = [1, 2, 3];
this.result = filter(isOdd)(data);
}
export default {
name: 'app',
data: () => ({
result: []
}),
mounted
}
</script>
12 行
import { filter } from 'ramda';
import { isOdd } from 'wink-test';
let mounted = function() {
let data = [1, 2, 3];
this.result = filter(isOdd)(data);
}
Vue 也可正常使用剛發佈 wink-test
的 isOdd()
。
Conclusion
- 若要使用 ECMAScript 開發同時 Vue 與 Node 都能使用的 package,且使用 ES Module 語法,現階段只能透過 Babel 轉譯成 CommonJS module,等日後 Node 支援 ES module 更完整,則可不使用 Babel