
最近在写一个组件时候遇到一个问题,用webpack将组件打包成一个符合UMD规范的组件时出现一个比较奇怪的现象:使用export default导出的全局变量会多一个default属性:
如:
– index.js
| 1 | let webpackDemo = { | 
打包之后发现在全局下只能这么访问val值:
| 1 | webpackDemo.default.val; | 
修改index.js代码
| 1 | let webpackDemo = { | 
则访问val属性变成了
| 1 | webpackDemo.webpackDemo.val; | 
为了弄明白怎么回事,准备了一个简单的webpack-umd项目,项目结构如下:

– package.json
| 1 | { | 
– src/index.js
| 1 | let webpackDemo = { | 
运行npm run build后查看源码,注意webpack配置mode: 'development':
简化打包后的结构为:
| 1 | (function webpackUniversalModuleDefinition(root, factory){ | 
我们知道export exports是ES6中新增的,而exports是CMD规范定义的,不难发现webpack编译的结果是将es6的export default语法转成CMD了exports.default, 这个时候可以想到CMD规范改写代码,如下:
–index.js
| 1 | let webpackDemo = { | 

重新打包之后发现在全局作用域下可以正常访问属性了:webpackDemo.val,但是从优雅角度考虑,同一个module下混用es6和cmd规范实为不妥,如:
| 1 | import a from './a'; | 
换个角度考虑,既然打包出来的是exports.default = webpackDemo,那么理论上只要将default干掉即可。而怎么干掉呢?答案只能从webpack本身着手,毕竟是webpack编译后的结果未能达到预期。查看webpack文档 发现了一个libraryExport属性,尝试了一下,完美解决~,修改webpack.config.js文件:
| 1 | 
 | 

重新编译后,可看到多了一个default属性访问
| 1 | ()()['default'] | 
也就可以知道libraryExport属性作用是取export下的default对象。再换个角度,如果是将export default webpackDemo; 换成export {webpackDemo};,那么按照刚才的思路只需要将libraryExport的值设置为webpackDemo即可。
| 1 | // index.js | 
到这里,再熟悉了一下webpack output的几个属性: 
output.library
- string或- object(从- webpack 3.1.0开始;用于 libraryTarget:- umd)
- output.library的值的作用,取决于- output.libraryTarget选项的值
- 如果生成的输出文件,是在HTML页面中作为一个script标签引入,则变量MyLibrary将与入口文件的返回值绑定。
output.libraryExport
这个属性的用法再上面已经体现了。注意默认值为undefined
output.libraryTarget
配置如何暴露library,可选的值为:var、this、window、global、commonjs、commonjs2、amd、amd-require、umd等。通常使用umd即可,umd是一种混合规范,可以将library暴露为所有的模块定义下都可运行的方式,可以在CommonJS, AMD环境下运行,兼容性最好。
ok~ 使用webpack打包模块化组件总结:
- 1、导出变量可以使用module.exports = webpackDemo,简单省事,但不够优雅
- 2、若要使用ES6的export、export default导出,需配合wenpack的output.libraryExport属性
- 3、webpack的output.libraryTarget建议采用umd方式,兼容性好。
参考链接: