最近在写一个组件时候遇到一个问题,用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
方式,兼容性好。
参考链接: