webpack组织模块的原理 - external模块
2018-03-10 14:24
405 查看
这篇文章讨论Webpack打包library时经常需要用到的一个选项
我们仍然使用前一篇文章的例子,定义一个库
AMD:在
Var:从全局域中取出
然后不管是哪种情况,它们都将载入后的
文章来源:学什么网
external,它用于避免将一些很通用的模块打包进你发布的library里,而是选择把它们声明成external的模块,在你的library被上层使用后,在最后阶段由Webpack统一把这个external的依赖模块打包进来。
external选项一般都是用在打包library上面,如果不是library而是一个最终的app的发布JS文件,那external也没有什么意义。关于Webpack打包library的分析和一些选项的作用。
external
选项
我们仍然使用前一篇文章的例子,定义一个库util.js:
import $ from 'jquery' function hideImages() { $('img').hide(); } export default { "hideImages": hideImages }我们使用Webpack打包发布这个库:
// 入口文件 entry: { util: './util.js', } // 输出文件 output: { path: './dist', filename: '[name].dist.js' library: 'util', libraryTarget: commonjs2, targetExport: 'default' }这样打包出来的
util.dist.js文件会把
jquery的代码完整地注入进去,因为你的源代码使用到了它。但是这往往并不是我们希望的,因为
jquery是很通用的模块,在一个app中,很可能其它的库也会用到它,最顶层的入口文件app也可能用到它,如果每一个库模块的发布版本都将jquery原封不动地打包进了自己的bundle,最后拼到一起,在最终的app发布代码里就会有很多份jquery的复制,当然这可能并不会影响它的正常功能,但是会占据很大的代码体积。所以通常情况下当你的库需要依赖到例如
jquery,
bootstrap这样的通用JS模块时,我们可以不将它打包进bundle,而是在Webpack的配置中声明
external:
externals: { jquery: { root: 'jquery', commonjs: 'jquery', commonjs2: 'jquery', amd: 'jquery', }, },这就是在告诉Webpack:请不要将这个模块注入编译后的JS文件里,对于我源代码里出现的任何
import/require这个模块的语句,请将它保留。我们可以看一下编译后的bundle文件的结构:
module.exports = (function(modules) { var installedModules = {}; function webpack_require(moduleId) { // ... } return webpack_require('./util.js'); }) ({ './util.js': generated_util, // '/path/to/jquery.js': generated_jquery 原本有这一行,现在被删去。 });可以看到
jquery模块没有被打包进bundle文件,而对于
util,它的生成代码即
generated_util函数中关于
import jquery相关的语句也被保留了原意:
function generated_util(module, exports, webpack_require) { var $ = require('jquery'); // util的其它源代码 // ... }当然也并非完全没有修改,例如将
import的改回了传统的
require关键词,因为我们这里用的是CommonJS风格的打包方式。不过这些都是次要的,关键是它保留了
require这个关键词,而没有使用
webpack_require将jquery真的引入进来。这就是说,当前的这个JS文件的模块管理系统中是没有jquery的,它是一个external的模块,需要在这个JS文件被其它人引用并且在上层编译时,jquery才可能被真的引入进来,到那个时候这里的
require关键词才会被替换为
webpack_require。对于external的依赖模块,通常你可以这样做,例如你使用npm发布你的库,你可以将jquery在
package.json文件中添加到
dependencies,这样别人
npm install你发布的库时,jquery也会被自动下载到node_modules供别人打包使用。umd格式下的打包如果我们使用
umd格式打包,我们可以看到在不同环境中,external模块是如何发挥作用的:
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') // commonjs2 module.exports = factory(require('jquery')); else if(typeof define === 'function' && define.amd) define("util", ['jquery'], factory); // amd else if(typeof exports === 'object') exports["util"] = factory(require('jquery')); // commonjs else root["util"] = factory(root['jquery']); // var }) (window, function(__webpack_external_module_jquery__) { return (function(modules) { var installedModules = {}; function webpack_require(moduleId) { // ... } return webpack_require('./util.js'); }) ({ './util.js': generated_util, }); }而
generated_util也相应地增加一个参数
__webpack_external_module_jquery__:
function generated_util(module, exports, webpack_require, __webpack_external_module_jquery__) { var $ = __webpack_external_module_jquery__; // util的其它源代码 // ... }这样的写法似乎结构和上面的CommonJS的编译版本不太一样,但实际上本质是一样的。因为现在umd要照顾到不同的运行环境,所以它把
require('jquery')提前了,作为factory的参数传入。对于每种运行环境,各有各的做法:CommonJS:保留
require('jquery')语句。
AMD:在
define中将
jquery定义为依赖模块。
Var:从全局域中取出
jquery变量,这需要jquery在该模块之前就已经被加载。
然后不管是哪种情况,它们都将载入后的
jquery模块作为参数传入
factory函数,这样就能正确加载
util模块了。以上涉及到Webpack生成代码的部分可能有点绕,需要你比较了解Webpack打包模块的机制和原理,关于这部分我在这篇文章里做了详细讨论。
总结
以上就是关于Webpack的external选项的使用,并且从编译后的JS代码分析了它到底是如何起作用的。我想阅读Webpack相关的生成代码还是很重要的,这样才算是真正地理解了external的机制,在碰到一些坑时才能知道怎么去debug。
文章来源:学什么网
相关文章推荐
- 浅谈webpack组织模块的原理
- webpack组织模块打包Library的原理及实现
- 单步调试理解webpack里通过require加载nodejs原生模块实现原理
- webpack构建React应用五:使用webpack Loaders 模块加载器(三)
- 用webpack把我们的业务模块分开打包
- webpack 样式加载的实现原理
- Webpack 4.0.0 正式发布,模块加载打包工具
- 一份关于webpack2和模块打包的新手指南
- webpack-dev-server原理分析与HMR实现
- 详解webpack异步加载业务模块
- .NET快速信息化系统开发框架 V3.2 -> Web 用户管理模块编辑界面-组织机构选择支持级联选择
- 模块打包工具webpack的使用
- 【webpack】-- 模块热替换
- 用webpack打包模块
- webpack热模块替换(HMR)/热更新的方法
- Webpack模块的导出以及之间的依赖引用
- 【webpack】 模块加载器兼打包工具
- [webpack]--webpack 如何解析代码模块路径
- .NET快速信息化系统开发框架 V3.2 -> Web 用户管理模块编辑界面-组织机构选择支持级联选择
- 详解用webpack把我们的业务模块分开打包的方法