今天在实现组件库换皮肤时,希望能够动态引入css文件,具体实现
const isDark = false;
isDark ? require('./dark.scss') : require('./white.scss');
发现动态引入需要使用require,而其他的文件引入都是import,因此总结一下import与require的区别
遵循的规则不同
- require/exports 遵循的是CommonJS规范
- import/export 是ES6中的模块使用规范
出现时间不同
- CommonJS作为Node.js的规范,一致沿用至今。由于npm上CommonJS的类库众多,以及CommonJS和ES6之间的差异,Node.js无法直接兼容ES6;所以require/exports仍然是必要且必须的;
- ES6的import/export出现相对晚了许多,目前编写的import/export最终都是通过babel编译为require/exports来执行的;
使用方式不同
- require/exports的用法
const fs = require('fs');
exports.fs = fs;
module.exports = fs;
- import/export的用法
import fs from 'fs'
import { default as fs } from 'fs'
import * as fs from 'fs'
import { readFile } from 'fs'
import { readFile as read } from 'fs'
import fs, { readFile } from 'fs'
export default fs
export const fs
export function readFile
export { readFile, read }
export * from 'fs'
引入本质不同
require/exports引入本质
- require是动态加载的
- require导入是运行时,理论上可以在任意地方调用
- require()的路径可以是表达式
- require导出的是module.exports对象
- exports是对module.exports的一个引用,当module.exports指向变化,exports导出就会出问题了
- require返回对应module.exports对象的浅拷贝
- 如果module.exports里是基本类型的值,会得到此值得副本
- 如果module.exports里是对象类型的值,会得到该值得引用
import/export引入本质
- import 在编译时确定导入
- 路径只能是字符串
- import会被提升到文件最顶部
- 导入的变量是只读的
- import 导入的是值得引入,而不是值拷贝
- 模块内部值发生变化,会对应影响到引用的地方
- import导入与导出需要有一一映射关系,类似结构赋值
举个🌰
// counter.js
exports.count = 0
setTimeout(function () {
console.log('increase count to', ++exports.count, 'in counter.js after 500ms')
}, 500)
// commonjs.js
const {count} = require('./counter')
setTimeout(function () {
console.log('read count after 1000ms in commonjs is', count)
}, 1000)
//es6.js
import {count} from './counter'
setTimeout(function () {
console.log('read count after 1000ms in es6 is', count)
}, 1000)
分别运行的结果
➜ test node commonjs.js
increase count to 1 in counter.js after 500ms
read count after 1000ms in commonjs is 0
➜ test babel-node es6.js
increase count to 1 in counter.js after 500ms
read count after 1000ms in es6 is 1