• 技术文章 >web前端 >js教程

    在webpack中如何使用external模块

    亚连亚连2018-05-31 13:51:15原创1210
    本篇文章主要介绍了webpack external模块的具体使用,现在分享给大家,也给大家做个参考。

    这篇文章讨论Webpack打包library时经常需要用到的一个选项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的参数传入。对于每种运行环境,各有各的做法:

    1. CommonJS:保留require('jquery')语句。

    2. AMD:在define中将jquery定义为依赖模块。

    3. Var:从全局域中取出jquery变量,这需要jquery在该模块之前就已经被加载。

    然后不管是哪种情况,它们都将载入后的jquery模块作为参数传入factory函数,这样就能正确加载util模块了。

    以上涉及到Webpack生成代码的部分可能有点绕,需要你比较了解Webpack打包模块的机制和原理,关于这部分我在这篇文章里做了详细讨论。

    总结

    以上就是关于Webpack的external选项的使用,并且从编译后的JS代码分析了它到底是如何起作用的。我想阅读Webpack相关的生成代码还是很重要的,这样才算是真正地理解了external的机制,在碰到一些坑时才能知道怎么去debug。

    上面是我整理给大家的,希望今后会对大家有帮助。

    相关文章:

    基于datepicker定义自己的angular时间组件的示例

    解决Vue.js 2.0 有时双向绑定img src属性失败的问题

    Vue.js 动态为img的src赋值方法

    以上就是在webpack中如何使用external模块的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:external webpack web
    上一篇:利用node.js对webpack打包 下一篇:使用webpack模块给Library打包原理及实现
    20期PHP线上班

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• 深入了解React中的任务调度算法• 什么是闭包?聊聊javascript中闭包,看看闭包有哪些作用?• JavaScript常见的Number对象汇总• JavaScript原型与原型链知识点详解• angular如何进行性能优化?变更检测方式浅析
    1/1

    PHP中文网