ES6的模块化: import
export default
node
common.js的模块化: require
module.exports
node.js使用该规范webpack
理想状况下,开发者只须要实现核心的业务逻辑,其余均可以加载别人已经写好的模块。es6
可是,Javascript不是一种模块化编程语言,在es6之前,它是不支持”类”(class),因此也就没有”模块”(module)了。同时之前也没有webpack这样的工具,可使用node去操做文件,读取文件内容, 而后达到引入文件内容的目的.(也就是模块化)--在不一样的文件中放着不一样的功能模块web
首先须要明白的在node中每一个文件都是一个自执行函数(只不过咱们肉眼凡胎看不出来,哈啊哈)编程
(function (exports, require, module, __filename, __dirname) {
module.exports = exports = this
return module.exports
})()
复制代码
为了说明module.exports = exports = this
请看下面例子element-ui
a.jsbabel
this.a = 123 // 第一种
exports.a = 123 //第二种
module.exports.a = 123 // 第三种
复制代码
b.js框架
let a = require('./a')
console.log(a)
复制代码
效果: 编程语言
import/export模块化
export default
和 export
的区别export
能够有多个,但 export default
仅有一个1.export
//a.js
export const str = "小生方勤";
//b.js
import { str } from 'a'; // 导入的时候须要花括号
2.export default
//a.js
const str = "小生方勤";
export default str;
//b.js
import str from 'a'; // 导入的时候无需花括号
复制代码
export default const a = 1;
这样写是会报错的哟。
es6 的导出模块写法有
export default 123;
export const a = 123;
const b = 3;
const c = 4;
export { b, c };
复制代码
虽然咱们通常在像Vue一些框架中均可以使用Es6的语法进行导入导出,可是babel 会将这些通通转换成 commonjs 的 exports。
exports.default = 123;
exports.a = 123;
exports.b = 3;
exports.c = 4;
exports.__esModule = true;
复制代码
babel 转换 es6 的模块输出逻辑很是简单,即将全部输出都赋值给 exports,并带上一个标志 __esModule
代表这是个由 es6 转换来的 commonjs 输出。
babel将模块的导出转换为commonjs规范后,也会将引入 import 也转换为 commonjs 规范。即采用 require 去引用模块,再加以必定的处理,符合es6的使用意图。
也就是全部最后经过webpack打包后都将转化为common.js的规范
对于最多见的
import a from './a.js';
复制代码
在es6中 import a from './a.js' 的本意是想去引入一个 es6 模块中的 default 输出。
经过babel转换后获得 var a = require(./a.js) 获得的对象倒是整个对象,确定不是 es6 语句的本意,因此须要对 a 作些改变。
咱们在导出提到,default 输出会赋值给导出对象的default属性。
exports.default = 123;
复制代码
因此这里最后的 a 变量就是 require 的值的 default 属性。若是原先就是commonjs规范的模块,那么就是那个模块的导出对象。
咱们使用 import * as a from './a.js'
es6语法的本意是想将 es6 模块的全部命名输出以及defalut输出打包成一个对象赋值给a变量。
已知以 commonjs 规范导出:
exports.default = 123;
exports.a = 123;
exports.b = 3;
exports.__esModule = true;
复制代码
那么对于 es6 转换来的输出经过 var a = require('./a.js') 导入这个对象就已经符合意图。
import { a } from './a.js'
直接转换成 require('./a.js').a
便可。
通过上面的转换分析,咱们得知即便咱们使用了 es6 的模块系统,若是借助 babel 的转换,es6 的模块系统最终仍是会转换成 commonjs 的规范。因此咱们若是是使用 babel 转换 es6 模块,混合使用 es6 的模块和 commonjs 的规范是没有问题的,由于最终都会转换成 commonjs。
为什么有的地方使用 require 去引用一个模块时须要加上 default?
require('xx').default
咱们在上文 babel 对导出模块的转换提到,es6 的 export default 都会被转换成 exports.default,即便这个模块只有这一个输出。
咱们常常会使用 es6 的 export default 来输出模块,并且这个输出是这个模块的惟一输出,咱们会误觉得这种写法输出的是模块的默认输出。
// a.js
export default 123;
复制代码
// b.js 错误
var foo = require('./a.js')
复制代码
在使用 require 进行引用时,咱们也会误觉得引入的是a文件的默认输出。
结果这里须要改为 var foo = require('./a.js').default
这个场景在写 webpack 代码分割逻辑时常常会遇到。
require.ensure([], (require) => {
callback(null, [
require('./src/pages/profitList').default,
]);
});
复制代码
咱们在使用各大 UI 组件库时都会被介绍到为了不引入所有文件,请使用 babel-plugin-component
等babel 插件。
import { Button, Select } from 'element-ui'
复制代码
由前文可知 import 会先转换为 commonjs, 即
var a = require('element-ui');
var Button = a.Button;
var Select = a.Select;
复制代码
var a = require('element-ui');
这个过程就会将全部组件都引入进来了。
因此 babel-plugin-component
就作了一件事,将 import { Button, Select } from 'element-ui'
转换成了
import Button from 'element-ui/lib/button'
import Select from 'element-ui/lib/select'
复制代码
即便转换成了 commonjs 规范,也只是引入本身这个组件的js,将引入量减小到最低。
因此咱们会看到几乎全部的UI组件库的目录形式都是
|-lib
||--component1
||--component2
||--component3
|-index.common.js
复制代码
index.common.js
给 import element from 'element-ui'
这种形式调用所有组件
给个element的连接去看看吧 :element.eleme.cn/#/zh-CN/com…