使用Babel和ES7创建JavaScript模块
创始人
2025-01-29 02:50:46
0次

去年,新版的JavaScript发布了,它有很多新的优点。其中之一就是导入导出模块的语法被整理为JavaScript模块处理的“唯一方法”。好吧,终于等到了。另一桩好事儿是,它的编排方式使你可以静态分析整棵模块依赖树。真是相当厉害。

让我们来扫一眼这些语法:

  1. import v from "mod";  
  2. import * as obj from "mod";  
  3. import {x} from "mod";  
  4. import {x as v} from "mod";  
  5. import "mod";  
  6.  
  7. export var v;  
  8. export default function f(){};  
  9. export default function(){};  
  10. export default 42;  
  11. export {x};  
  12. export {x as v};  
  13. export {x} from "mod";  
  14. export {x as v} from "mod";  
  15. export * from "mod"; 

所以,基本上你可以导入一个模块(“default”)的主要值,或者导入从显式导出(explicit exports)而来的一个特定属性,或者这二者的组合,或者是任何东西。相对应的,你也可以为默认模块导出一个值,或者带有多个属性的对象。你也可以逐个导出这些属性。***风格还是请参考风格指南吧;)

ES7中还加入了一些对这类语法的小补充。

  1. export * as ns from "mod";  
  2. export v from "mod"; 

没啥特别的,但我们什么时候能使用它们呢?择日不如撞日吧。就像对待很多ES6的语法特性,如果你目前不打算支持它们,可以用一种叫Babel的工具把它们转译回ES5。一旦你准备支持它们了,就可以让Babel停止转译。

让我们来看一眼具体如何操作。我们将在Node.js与NPM中实现它。试试看执行这个文件;

src/letter_keys.js

  1. // you would have a constant for each key  
  2. // (I would normally uppercase all constants)  
  3. const a = 119;  
  4. const d = 100;  
  5. const s = 115;  
  6. const w = 119;  
  7.  
  8. // you would export all keys here  
  9. // note: you can't say `w: 119` here. It just isn't valid.  
  10. // This destructures to `w: w, a: a, ...`  
  11. export {  
  12.   w,  
  13.   a,  
  14.   d,  
  15.   s,  
  16. } 

src/arrow_keys.js

  1. const UP = 38;  
  2. const RIGHT = 39;  
  3. const DOWN = 40;  
  4. const LEFT = 37;  
  5.  
  6. export {  
  7.   UP,  
  8.   RIGHT,  
  9.   DOWN,  
  10.   LEFT,  
  11. } 

 src/move.js

  1. export {a, w, s, d} from './letter_keys';  
  2. export * as ARROWS from './arrow_keys'; 

我们的设想是,index.js 主文件用于内部模块内容的导出,它假设这些键是从其它文件中导出的。这个例子有点费解,但是这并无大碍。

src/index.js

  1. import * as keys from './move';  
  2. console.log(keys); 

 这可以作为依赖这个模块的某个项目的一部分。它应当打印awsd键以及箭头对象。让我们先从npm开始吧。创建repo dir并初始化:

  1. ~$ mkdir foo  
  2. ~$ cd foo  
  3. ~/foo$ mkdir src  
  4. # put src files above in ~/foo/src  
  5. ~/foo$ npm init -yes  
  6. ~/foo$ npm install babel-cli babel-preset-es2015 babel-preset-stage-1 -D 

  这得花点时间。你可能已经猜到了, babel-cli 支持从命令行运行Babel (6),并且, babel-preset-stage-1 包提供了相关的ES7模块转译工具(在撰写本文之时)。 -yes 标记会让npm创建一个默认的 package.json ,而不会询问用户。 -D 标记是 --save-dev 的缩写,它会在 package.json 中把包添加到 devDependency 条目下。现在,把预设参数添加入到默认的babel配置文件中:

 .babelrc

  1. {  
  2.   "presets": ["es2015", "stage-1"]  
  3. } 

 如果这能顺利运行,那就太好了,拥抱未来吧!但是,在笔者写本文时,这些示例在ES6中都无法运行,更不用说Node.js了。经过这些转译步骤,不管怎样,它们可以被执行了。

现在还应该有一个几乎为空的package.json文件,它包含了我们添加的那三个dev 依赖。让我们给这个package.json 文件加一段脚本,来实现转译:

  1. ...  
  2.   "scripts": {  
  3.     "test": "echo "Error: no test specified" && exit 1",  
  4.     "translate": "node_modules/babel-cli/bin/babel-node.js src/index.js" 
  5.   },  
  6.   ... 

 (仅在“test”那行之后添加“translate”行及逗号)。

这段转译脚本是一个编译步骤。在文章的结尾处,你可以找到本文(正式版本)使用的最终版package.json文件。现在,只剩下调用npm指令来运行脚本,以实现转译,并运行我们的代码了。

  1. ~/foo$ npm run translate --silent  
  2.  
  3. { A: [Getter],  
  4.   W: [Getter],  
  5.   S: [Getter],  
  6.   D: [Getter],  
  7.   ARROWS: { UP: 38, RIGHT: 39, DOWN: 40, LEFT: 37 } } 

加油!现在,作为额外奖励,我们可以使用Jscrambler来“混淆”一下代码。我们可以传递Babel转译后的代码,所以干嘛不这么做呢?

我们(最终的)package.json文件是这样的:

package.json

  1. {  
  2.   "name": "foo",  
  3.   "version": "1.0.0",  
  4.   "description": "",  
  5.   "main": "index.js",  
  6.   "scripts": {  
  7.     "test": "echo "Error: no test specified" && exit 1",  
  8.     "translate": "node_modules/babel-cli/bin/babel-node.js src/index.js" 
  9.   },  
  10.   "keywords": [],  
  11.   "author": "Your Name  (http://localhost/)",  
  12.   "license": "ISC",  
  13.   "devDependencies": {  
  14.     "babel-cli": "6.6.5",  
  15.     "babel-preset-es2015": "6.6.0",  
  16.     "babel-preset-stage-1": "6.5.0",  
  17.     "jscrambler": "0.7.5" 
  18.   }  
  19. } 

 像往常一样完成配置(如果使用的是Node.js,则需要一个专业版账号)。以下是笔者所用的文件

.jscramblerrc

  1. {  
  2.   "keys": {  
  3.     "accessKey": "See https://jscrambler.com/en/account/api_access",  
  4.     "secretKey": "See https://jscrambler.com/en/account/api_access" 
  5.   },  
  6.   "params": {  
  7.     "constant_folding": "%DEFAULT%",  
  8.     "dead_code": "%DEFAULT%",  
  9.     "dead_code_elimination": "%DEFAULT%",  
  10.     "dictionary_compression": "%DEFAULT%",  
  11.     "dot_notation_elimination": "%DEFAULT%",  
  12.     "function_outlining": "%DEFAULT%",  
  13.     "function-reorder": "%DEFAULT%",  
  14.     "literal_duplicates": "%DEFAULT%",  
  15.     "literal_hooking": "2;8",  
  16.     "member_enumeration": "%DEFAULT%",  
  17.     "mode": "nodejs",  
  18.     "rename_local": "%DEFAULT%",  
  19.     "string_splitting":"0.3",  
  20.     "whitespace": "%DEFAULT%" 
  21.   }  
  22. } 

我们用一段脚本来汇总一下。这段脚本将会用Babel翻译源文件,输出到/build文件夹,接着用Jscrambler混淆代码,再将结果放入/dist文件夹。/dist里的内容可以被正常运行,而不必用到ES7的任何特性。

run.sh

  1. #!/bin/sh  
  2.  
  3. echo "Babelifying src/*.js" 
  4. node_modules/babel-cli/bin/babel.js -d build src/*.js  
  5. echo "Scrambling build/*.js" 
  6. node_modules/jscrambler/bin/jscrambler -o dist build/src/**  
  7. echo "Clean up artifacts" 
  8. mv dist/build/src/* dist/  
  9. rmdir dist/build/src  
  10. rmdir dist/build  
  11. echo "Done! See dist/scrambled.js" 
  12. echo "Running:" 
  13. node dist/index.js 

 使之准备就绪:

 

  1. chmod +x run.sh 

接着,运行:

 

  1. ~/foo$ ./run.sh   
  2. Babelifying src/*.js  
  3. src/arrow_keys.js -> build/src/arrow_keys.js  
  4. src/index.js -> build/src/index.js  
  5. src/letter_keys.js -> build/src/letter_keys.js  
  6. src/move.js -> build/src/move.js  
  7. Scrambling build/*.js  
  8. Clean up artifacts  
  9. Done! See dist/ for your scrambled files  
  10. Running:  
  11. { a: [Getter],  
  12.   w: [Getter],  
  13.   s: [Getter],  
  14.   d: [Getter],  
  15.   ARROWS: { UP: 38, RIGHT: 39, DOWN: 40, LEFT: 37 } } 

 你可以去/dist文件夹查看结果。你会看到,结果和原文件相去甚远,这是因为我们通过Jscrambler来保护它,但是结果还是可以运行的。

教程到此结束,祝ES7用得开心!

OneAPM 助您轻松锁定Node.js 应用性能瓶颈,通过强大的Trace 记录逐层分析,直至锁定行级问题代码。以用户角度展示系统响应速度,以地域和浏览器维度统计用户使用情况。

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
只需三步,让你掌握阿尔法路由器... 请参照以下阿尔法路由器设置方法,通过浏览器进入及设置宽带路由器。经过这三个步骤的设置,基本上能够熟悉...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...