Understanding ES6 Modules(译)

原文地址

这篇文章探索ES6 modules,在编译器的帮助下展示他们如何被使用到今天

几乎每种语言都有模块的概念- 一种在另一个文件中包含功能性的声明的文件。一般的,开发者创建一个封装好的表示处理相关任务的代码库。这个库可以被其他应用或者其他模块引用。

模块的益处:

  1. 代码可以被分割成更小的独立功能文件
  2. 同一个模块可以被多个应用共享
  3. 理想情况,模块不需要其他开发者检查其可用性,因为他们已经被证实可以运行。
  4. 代码里引用一个模块可以理解这是一个依赖。如果这个模块文件修改了或者移动了,问题会立马显现。
  5. 模块代码通常帮助我们彻底根除命名冲突。module1中的x()函数不会与modules2中的x()函数发生冲突。使用了类似命名空间的选项,因此调用变成了module1.x()和module2.x().

javascript的模块在哪里

几年前开始web开发的人会惊奇的发现在JavaScript中没有模块的概念。在另一个js文件中是不可能直接引用或者包含一个JavaScript文件的。因此,开发人员寻找其他选择。

多个html

在2018年,平均每个网页使用了25个分割的scripts,但这不是一个切实的解决方案:

  • 每个脚本会发起一个新的HTTP请求,这会影响页面的性能。HTTP/2在某种程度上缓解了这个问题,但这对其他域(例如CDN)上引用的脚本无济于事
  • 每个脚本在运行时都会阻塞进一步的处理
  • 依赖管理是一个人工处理的过程.在代码中,如果lib1.js引用lib2.js的代码,这部分代码可能出错,因为它没有加载。这有可能损害深层次的JavaScript程序。
  • 函数可能覆盖其他函数,除非使用合适的模块模式。早期的JavaScript库因使用全局函数名称或覆盖原生方法而臭名昭著。

脚本级联

解决多个

或内联:


无论模块在页面或其他模块中被引用多少次,模块都会被解析一次。

服务器注意事项

模块必须使用MIME类型application/javascript提供服务。大多数服务器将自动执行此操作,但对动态生成的脚本或.mjs文件保持警惕(请参阅下面的Node.js部分)。

常规

模块背后

没有模块支持的浏览器将不会运行type="module"脚本。可以为备用脚本提供nomodule属性,而模块兼容的浏览器会忽略该属性。例如:



您应该在浏览器中使用模块吗?

浏览器支持正在增长,但切换到ES6模块可能还为时过早。目前,最好使用模块捆绑器来创建一个可在任何地方使用的脚本。

在Node.js中使用ES6模块

当Node.js在2009年发布时,对于任何运行时不提供模块来说都是不可思议的。 采用CommonJS,这意味着可以开发Node软件包管理器npm。 从那时起,使用量呈指数增长。

CommonJS模块的编码方式类似于ES2015模块。 使用module.exports而不是export:

// lib.js
const PI = 3.1415926;

function sum(...args) {
  log('sum', args);
  return args.reduce((num, tot) => tot + num);
}

function mult(...args) {
  log('mult', args);
  return args.reduce((num, tot) => tot * num);
}

// private function
function log(...msg) {
  console.log(...msg);
}

module.exports = { PI, sum, mult };

require(而不是import)用于将此模块拉入另一个脚本或模块:

const { sum, mult } = require('./lib.js');

console.log( sum(1,2,3,4) );  // 10
console.log( mult(1,2,3,4) ); // 24

require还可以导入所有项目:

const lib = require('./lib.js');

console.log( lib.PI );            // 3.1415926
console.log( lib.add(1,2,3,4) );  // 10
console.log( lib.mult(1,2,3,4) ); // 24

所以ES6模块很容易在Node.js中实现,对吗? 呃没有。

ES6模块位于Node.js 9.8.0+中的标志后面,直到至少版本10才能完全实现。 语法,它们以根本不同的方式工作:

  • 在执行代码之前,已预先解析了ES6模块,以解决进一步的导入问题。
  • CommonJS模块在执行代码时按需加载依赖项。
    在上面的示例中没有什么区别,但是请考虑以下ES2015模块代码:
// ES2015 modules

// ---------------------------------
// one.js
console.log('running one.js');
import { hello } from './two.js';
console.log(hello);

// ---------------------------------
// two.js
console.log('running two.js');
export const hello = 'Hello from two.js';

ES2015输出

running two.js
running one.js
hello from two.js

使用CommonJS编写的类似代码:

// CommonJS modules

// ---------------------------------
// one.js
console.log('running one.js');
const hello = require('./two.js');
console.log(hello);

// ---------------------------------
// two.js
console.log('running two.js');
module.exports = 'Hello from two.js';

CommonJS输出

running one.js
running two.js
hello from two.js

在某些应用程序中,执行顺序可能很关键,如果将ES2015和CommonJS模块混合在同一文件中,会发生什么情况? 要解决此问题,Node.js将仅允许文件扩展名为.mjs的ES6模块。 扩展名为.js的文件将默认为CommonJS。 这是一个简单的选项,可消除大部分复杂性,并有助于代码编辑器和lint。

是否应该在Node.js中使用ES6模块?

ES6模块仅适用于Node.js v10及更高版本(于2018年4月发布)。 转换现有项目不太可能带来任何好处,并且会使应用程序与Node.js的早期版本不兼容。

对于新项目,ES6模块提供了CommonJS的替代方法。 语法与客户端编码相同,并且可以提供更容易的同构JavaScript路由,该JavaScript可在浏览器或服务器上运行。

模块竞争

标准化的JavaScript模块系统花了很多年才能实现,甚至花了更长的时间才能实现,但问题已得到纠正。从2018年中期开始,所有主流浏览器和Node.js都支持ES6模块,尽管在每个人升级时都可能会有切换滞后的情况。

立即学习ES6模块,以使您明天的JavaScript开发受益。

你可能感兴趣的:(Understanding ES6 Modules(译))