详解webpack的out.libraryTarget属性
0 条评论Webpack 作为目前前端最热门的打包工具,相信很多人都在项目中使用过,其繁杂的配置项也确实“配”得上他老大的身份 o(╯□╰)o。output.library
和output.libraryTarget
属性可能大家都会比较陌生,因为一般如果只在项目中使用 webpack 不需要关注这两个属性,但是如果是开发类库,那么这两个属性就是必须了解的。
简介
回想一下,当我们引入别人开发的类库时有几种方式?下面假设我们引入一个demo
方法:
- 传统方式:
script
标签
1 | <scriptsrc="demo.js"></script><script>demo();</script> |
- AMD
1 | define(['demo'], function(demo) { |
- commonjs 方式
1 | const demo = require('demo'); |
- ES6 module
1 | import demo from 'demo'; |
大家思考一下,为什么这个类库能支持不同方式的引入?如何实现的?这就是 webpack 配置output.library
和output.libraryTarget
提供的功能。
output.library
支持输入string
或者object
(从 webpack 3.1.0 版本开始支持; 限于 libraryTarget: “umd” 时使用)类型的值。
output.library
的值被如何使用会根据output.libraryTarget
的取值不同而不同。而默认output.libraryTarget
的取值是var
,如果如下配置:
1 | output: { |
如果在 HTML 页面中使用script
标签引入打包结果文件,那么变量myDemo
对应的值将会是*入口文件(entry file)*的返回值。
output.libraryTarget
支持输入string
类型的值。默认值:var
此配置的作用是控制 webpack 打包的内容是如何暴露的。请注意这个选项需要和output.library
所绑定的值一起产生作用。在以下的 demo 中,假设output.library
值是myDemo
。*_entry_return_
表示入口点返回的值。在bundle中,它是webpack从入口点生成的函数的输出。*
暴露一个变量
以下选项会把打包返回的值(无论暴露的是什么)绑定到一个由output.library
指定的变量上,无论包是被如何引用。
libraryTarget: "var"
- (default)
使用这个配置,当库被加载时,那么库的返回值会被分配到使用用var
申明的变量上。
1 | var myDemo = _entry_return_; |
如果没有设置
output.library
值,那么将不会发生赋值行为。
libraryTarget: "assign"
使用这个设置,会把库返回值分配给一个没使用var
申明的变量中,如果这个变量没有在引入作用域中提前申明过,那么将会挂载在全局作用域中。(注意,这个行为有可能会覆盖全局作用域中的已有变量)
1 | myDemo = _entry_return_; |
通过对象属性暴露
以下选项将库的返回值(无论返回值是什么)分配给特定对象的指定属性,属性由output.library
指定,对象由output.libraryTarget
指定。
当output.library
没有指定为非空字符串,那么默认行为是将库返回值的所有属性(properties)都分配到对象中,代码如下:
1 | (function(e, a) {for(var i in a) e[i] = a[i]; }(${output.libraryTarget}, _entry_return_) |
注意,发生这个行为的时候 webpack 并不会检查对象中是否已经存在这些属性值,也就是会发生覆盖行为。
libraryTarget: "this"
- 将库的返回值分配给this
对象的由output.library
指定的属性。其中this
的意义由用户决定。
1 | this["myDemo"] = _entry_return_; |
libraryTarget: "window"
- 将库的返回值分配给window
对象的由output.library
指定的属性。
1 | window["myDemo"] = _entry_return_; |
libraryTarget: "global"
- 将库的返回值分配给global
对象的由output.library
指定的属性。
1 | global["myDemo"] = _entry_return_; |
libraryTarget: "commonjs"
- 将库的返回值分配给exports
对象的由output.library
指定的属性。正如名字所指,这个选项可以使用在 CommonJS 环境。
1 | exports["myDemo"] = _entry_return_; |
模块定义系统
以下选项将产生一个包含更完整兼容代码的包,以确保与各种模块系统的兼容性。 此时output.library
选项在不同的output.libraryTarget
选项下具有不同的含义。
libraryTarget: "commonjs2"
- 将库的返回值分配给module.exports
。正如名字所指,这个选项可以使用在 CommonJS 环境。
1 | module.exports = _entry_return_; |
注意,在这个情况下output.library
不是必须的,因为此时output.library
选项将会被忽略。
有没有注意到 CommonJS 和 CommonJS2 长的非常像?他们确实很相似,但是其中有微妙的区别,想了解更多可以参考这个issue
libraryTarget: "amd"
- 这个选项会把库作为 AMD 模块导出。
AMD模块要求输入脚本(例如由<script>
标签加载的第一个脚本)被定义为具有特定属性,例如通常由 RequireJS 或任何兼容的加载器(诸如almond)提供的require
和define
属性。否则,直接加载生成的 AMD 捆绑包将导致类似define is not defined
的错误。
由此定义生成的代码会如下:
1 | define("myDemo", [], function() {return _entry_return_;}); |
以上的代码可以作为script
标签引入代码的一部分被包含,然后在通过以下代码调用:
1 | require(['myDemo'], function(myDemo) {// Do something with the library... |
如果output.library
没有定义有效值,那么生成的代码将如下:
1 | define([], function() {return _entry_return_;}); |
如果直接使用<script>
标签加载,该库将无法按预期生效,或者根本无法生效(在 almond 加载器的情况下)。它只能通过与 RequireJS 兼容的异步模块加载器通过该文件的实际路径进行引入,因此在这种情况下,如果这些由服务器直接提供,那么output.path
和output.filename
配置可能变得非常重要。
libraryTarget: "umd"
- 这个选项会尝试把库暴露给前使用的模块定义系统,这使其和CommonJS
、AMD
兼容或者暴露为全局变量。output.library
选项在这里是必须的。最终代码输出如下:
1 | (functionwebpackUniversalModuleDefinition(root, factory) {if(typeof exports === 'object' && typeof module === 'object') |
如果 output.library
没有输入有效值,那么对于全局变量的处理会和上面提到的 暴露一个变量
一致。代码输出如下:
1 | (functionwebpackUniversalModuleDefinition(root, factory) {if(typeof exports === 'object' && typeof module === 'object') |
从 webpack 3.10.0 版本开始,我们可以通过把 output.library
定义为对象来控制不同目标环境的输出值。详情可参考这个Demo
1 | output: { |
其他类型
libraryTarget: "jsonp"
- 这个方法会使用 jsonp 的方式把结果包裹起来。
1 | myDemo(_entry_return_); |
库的依赖由 externals 定义。
总结
以上所有栗子可以下载 webpack-libraryTarget-demo 项目,运行 npm i
安装依赖,接着 npm run build-all
命令执行打包,最后在 dist
目录下查看不同打包方式生成的代码。
- 主要看第一行
(function(modules) { // webpackBootstrap
这一行开始,指代上述的_entry_return_
部分
output.libraryTarget
一共支持的值:
- var - 默认值
- assign
- this
- window
- global
- commonjs
- commonjs2
- amd
- umd
- jsonp
原文地址:https://blog.csdn.net/frank_yll/article/details/78992778 本文首发于 https://www.xlaoyu.info
- 本文链接:https://xuehuayu.cn/article/30818.html
- 版权声明:① 标为原创的文章为博主原创,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接。② 标为转载的文章来自网络,已标明出处,侵删。