关于JS模块系统,Webpack做了什么

2018-02-27 11:01:54来源:http://blog.fedepot.com/guan-yu-jsmo-kuai-xi-tong-da-bao-qi-作者:Fedepot人点击

分享

在实际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函数,最终挂载到合适的模块系统变量之上。


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台