import, export, exports, module.exports, require, 解构导入, 它们之间到底是什么关系?Cjs 和 ESM

1,137 阅读2分钟

开始

1.一切从一个报错说起

> node b.js

/Users/test/src/import_export/b.js:1
import a from './a.js'
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at Module._compile (internal/modules/cjs/loader.js:895:18)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:995:10)
    at Module.load (internal/modules/cjs/loader.js:815:32)
    at Function.Module._load (internal/modules/cjs/loader.js:727:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1047:10)
    at internal/main/run_main_module.js:17:11

2.先看发生了什么 - js代码

// a.js

const a = 1
export a
// b.js

import a from './a.js'
console.log(a, 'a');

然后当我执行 node b.js 时,就发生了上面导报错

3.发生了什么?为什么会这样?

  • 我们在平时的前端项目中,经常会混用 import, export, exports, module.exports, require 这些关键字 来导入导出 文件间的变量。这就导致了,我们对于它们的认识的混乱,好像这些在项目中都能正常运行,怎么单独拿出来,就报错了?
  • 原因是,前端项目中 为了降低开发者 开发项目的门槛,项目创立者会在 webpack 中做额外的配置,使得 import, export, exports, module.exports, require 这些关键字 可以混用,而不会报错。

4.问题报错原因

  • 上面的代码中,实际上我们犯了一个最基本的错误,就是在 NodeJS 中,使用了 ES6 Module 的导入导出的关键字。
  • NodeJS 的导入导出 模块规范,是 CommonJS 规范。NodeJS 目前不支持 ES6 Module 的导入导出的规范。

什么是CommonJS?什么是ES6 Module

简单理解

CommonJS就是

  • 使用import .. from .. export, export default 关键字的代码
  • CommonJS 是 NodeJS 默认支持的 导入导出 模块规范
// a.js

const a = 1
module.exports = { a }
// b.js

const { a } = require('./a.js')
console.log(a)  // 1

ES6 Module 就是

// a.js

export const a = 1
// b.js

import { a } from './a.js'
console.log(a) // 1

ES6 Module 代码如何执行?

  • 下面是 在浏览器中执行的 测试代码
  • 简单的ES6模块import改变文字颜色实例页面
HTML代码:
<p>我是p,我的颜色是?</p>


script代码:
<script type="module">
  // 导入firstBlood模块
  import { pColor } from './firstBlood.mjs';
  // 设置颜色为红色
  pColor('red')
</script>
  
  
firstBlood.mjs代码:
// export一个改变p元素颜色的方法
export function pColor (color) {
  const p = document.querySelector('p');
  p.style.color = color;
}
  • 执行结果:可以看到<p>文字变红了:

参考文章