本节主要介绍webpack中的模块方法,包括ES6的import以及CommonJS的require等。
Webpack是一个模块打包工具,对一切文件都视为模块。它本身支持非常多的模块化方法,包括本节中出现的所有模块化方法。
下一节我们将要学习Webpack资源入口,有必要先了解一些模块知识。
一、JavaScript模块化历史
在JavaScript这门语言最初的阶段,是没有模块化方法的,因为这门语言设计出来的初衷是作为web小脚本使用的。后来随着其在web应用的增长,不能模块化开始限制了其应用。
这个时候社区出现了一些模块化规范,比较著名的有CommonJS、AMD和CMD等。
社区的模块化规范可以解决一些JS模块化的问题,但各种模块化规范还是不统一的,有学习和兼容成本。
于是,JavaScript在制订ES6语言标准的时候,提出了自己的模块化,也就是我们现在一般叫做的ES6 Module(ES6模块化)。
ES6 Module经过五年的发展后,已经广泛应用在JS开发领域。目前,JS模块化使用的主要是ES6 Module和CommonJS这两种。
二、ES6 Module
ES6的模块化语法主要用import进行模块导入,export进行模块导出。
1.export模块导出
// 导出的模块有两个变量name和age,一个函数add // a.js export var name = 'Jack'; export var age = 18; export function add(a, b) { return a + b; }
上面的导出也可以换一个写法
// 导出的模块有两个变量name和age,一个函数add // b.js var name = 'Jack'; var age = 18; function add(a, b) { return a + b; } export { name, age, add };
export还可以导出匿名模块,方便在导入的时候使用
// 使用匿名(default)导出模块,这里导出的是一个对象 // c.js export default { price: 285, id: 12, }
2.import模块导入
我们使用import … from '…'方式导入模块。对于匿名(default)导出的模块,我们自定义一个变量代表其导出值。
// 对于匿名(default)导出的模块c.js,我们自定义一个变量moduleC代表其导出值 // d.js import moduleC from './c.js' console.log(moduleC) // 控制台输出一个对象{price: 285, id: 12}
对于非default导出的模块,我们可以使用大括号方式导出模块
// 对于模块a.js或b.js,我们使用大括号方式导出模块 // e.js import { name, age, add } from './b.js' console.log(name, age); // 控制台输出'Jack'和18 console.log(add(1, 8)); // 控制台输出9
除了使用import … from '…'方式导入模块,也可以使用import '…'。使用这种方式,导入模块后会执行模块内容,但是并不使用其对外提供的接口。
3.import()函数
注意import()函数与上面的import模块导入语法的区别。
import()函数是ES2020提案里提出来的。它与普通的import模块导入语法的区别,外观上是它的import后面跟的是一个括号(),而普通的import最后是一个引号''。
import()函数虽然是ES2020提案里的,但Webpack早已经支持该模块导入语法了。
// import()函数导入模块 import('./f.js')
除了外观上的区别,import()与引号形式import的核心区别是,import()可以动态导入模块。
在Vue-Router的路由懒加载中,我们就是通过使用import()来实现的,下图是Vue官方文档的截图。
简单解释一下import()的原理。Webpack在打包的时候,碰到import()引入的模块的时候并不会立刻把该模块内容打包到当前文件里。Webpack会使用动态生成JS的方式,在运行代码的时候生成script标签,script标签引入的就是import()里导入的内容。import()导入模块后是一个Promise对象,我们可以通过import().then()的方式来处理后续异步的工作。
三、CommonJS
CommonJS是目前比较流行的JS模块化规范,它主要在Node.js中使用。Node.js对CommonJS的实现并不完全与其规范一致,教程不会涉及这些细微差别。
CommonJS主要使用module.exports导出模块,require('…')导入模块。
// g.js module.exports = { name: 'Gola', age: 25 }
// h.js var person = require('./g.js') console.log(person) // 输出{name: 'Gola',age: 25}
Webpack对CommonJS也支持动态模块。如果你用过旧版本的Webpack,可以发现require.ensure导入模块的语法。注意该语法是Webpack特有的,现在推荐使用import()函数做动态导入模块。
// dependencies是一个数组,数组项是需要导入的模块;callback是成功回调函数;errorCallback是失败回调函数;chunkName是自定义的chunk名; require.ensure(dependencies, callback, errorCallback, chunkName)
小结
- Webpack支持ES6 Module、CommonJS和AMD等模块化方法,目前常用的是ES6 Module和CommonJS。
- ES6 Module通过export导出模块,import … from '…'或import '…'导入模块。
- CommonJS通过module.exports导出模块,require('…')导入模块。
- ES6 Module通过import()函数动态导入模块,CommonJS通过require.ensure动态导入模块,现在推荐使用import()函数动态导入模块。
笔记与思考