在实际 JS 开发工作中, 我们通常会以模块化的方式进行开发, 所以我们用到了 babel-loader , ts-loader , 以及 webpack , 在代码中, 经常会用到 ES , CommonJS , AMD 等多种模块系统混用, 所以有必要知晓打包器为我们做了什么让最终代码能够在浏览器等不支持原有模块系统的环境下正常工作这里因为 AMD 有自己特有的模块库不做讨论, 主要讨论 ES 和 CommonJS 模块系统
CommonJS 多模块 Webpack 打包
首先写两个模块, 以及一个入口文件引入模块
然后使用 webpack 进行打包, 得到单一文件, 对这个文件内的代码进行分析, 整体代码是多个 IIFE, 主要为了模块作用域隔离, 其中首先定义了一个自己的模块加载函数:
这里 webpack 实现的模块系统是 CommonJS , 为了适用浏览器环境, 对不支持的 module 全局变量提供了自有实现, 同时对模块加载做了缓存处理, 避免重复加载
webpack 实现 module 这个可能在有些环境不存在的对象之后, CommonJS 模块在打包后其实变化不大
ES 模块 Webpack 打包
这里全部改用了 ES 的模块导出和导入方式, 其中模块 A 除了定义默认导出, 还有其他额外导出
打包后的代码, 其中模块 A 部分示例如下:
webpack 为每个模块定义了导出函数, 因为导入模块 A 的方式是
import A from "./moduleA"
即默认导入, 所以同样的这里的模块定义并没有对其他非默认导出进行暴露, 而只对默认导出以属性
__webpack_exports__.a
的方式进行了暴露如果将导入模块 A 的方式改成
import * as A from "./moduleA"
, 模块 A 的导出函数定义将变成如下结果:
为了暴露所有导出, webpack 将默认导出以
__webpack_exports__.default
方式暴露, 其他则以
__webpack_exports__. [exportName]
方式暴露
执行打包后的代码, 其结果输出为
- { say: [Function: say], default: 'module A' }
- module B
即调用模块 A 的默认导出要使用 A.default 了
Webpack 打包 UMD
当设置 webpack 配置的
output.libraryTarget
为 umd 时, 打包文件又有所区别但是 UMD 不能作为 CommonJS 和 ES 模块等的同级, 它只是多种模块系统的环境兼容解决方案, 会根据具体环境, 选择执行某一种模块系统其中最重要的一部分, 即为这个环境监测适配模块系统的函数, webpack 中的如下:
其中 factory 参数即是原来的非 UMD 打包的整个 IIFE 函数, 最终挂载到合适的模块系统变量之上
来源: http://www.tuicool.com/articles/zIryEvY