webpack组织模块打包Library的原理及实现

网友投稿 398 2023-02-13


webpack组织模块打包Library的原理及实现

之前一篇文章分析了Webpack打包js模块的基本原理,所介绍的案例是最常见的一种情况,即多个JS模块和一个入口模块,打包成一个bundle文件,可以直接被浏览器或者其它javaSchttp://ript引擎执行,相当于直接编译生成一个完整的可执行的文件。不过还有一种很常见的情况,就是我们要构建发布一个javascript的库,比如你在npm社区发布自己的库,这时Webpack就需要相应的配置,编译生成的代码也会略有不同。

和之前一篇文章一样,本文主要分析的是Webpack的生成代码,并结合它来说明编译库时Webpack那些关于library的配置选项的具体作用,相应的官方文档在这里。

编写JS的库

我们还是从简单的案例开始,我们随便编写一个简单的库util.js:

import $ from 'jquery'

function sayHello() {

console.log("Hello");

}

function hideImages() {

$('img').hide();

}

export default {

sayHello: sayHello,

hideImages: hideImages

}

提供了两个函数,当然它们之间毫无关系,也实际上没有任何卵用,纯粹是仅供教学参考。。。

接下来写Webpack的配置:

// 入口文件

entry: {

util: './util.js',

}

// 输出文件

output: {

path: './dist',

filename: '[name].dist.js'

}

但仅仅这样是不够的,这样输出的文件就是一个立即执行的函数,最后会返回util.js的exports,参照上一篇文章中分析,最后生成的bundle代码结构大致是这样的:

(function(modules) {

var installedModules = {};

function webpack_require(moduleId) {

// ...

}

return webpack_require('./util.js');

}) ({

'./util.js': generated_util,

'/path/to/jquery.js': generated_jquery

});

它如果执行完,那就结束了,将util.js的export部分返回而已,而我们需要的是将这个返回值交给编译后的文件的module.export,这样编译后的文件就成了一个可以被别人import的库。所以我们希望得到的编译文件应该是这样的:

module.exports = (function(modules) {

var installedModules = {};

function webpack_require(moduleId) {

// ...

}

return webpack_require('./util.js');

}) ({

'./util.lLmufsojs': generated_util,

'/path/to/jquery.js': generated_jquery

});

要得到这样的结果,Webpack配置output部分需要加入library信息:

// 入口文件

output: {

path: './dist',

filename: '[name].dist.js',

library: 'util',

libraryTarget: commonjs2

}

这里最重要的就是libraryTarget,我们现在采用commonjs2的格式,就会得到上面的编译结果,也就是说Webpack会library把最后的输出以CommonJS的形式export出来,这样就实现了一个库的发布。

其它发布格式

除了commonjs2,libraryTarget还有其它选项:

var (默认值,发布为全局变量)

commonjs

commonjs2

amd

umd

使用不同的选项,编译出来的文件就能够在不同JavaScript执行环境中使用。在这里我们直接看万金油umd格式的输出是怎么样的:

(function webpackUniversalModuleDefinition(root, factory) {

if(typeof exports === 'object' && typeof module === 'object') // commonjs2

module.exports = factory();

else if(typeof define === 'function' && define.amd)

define("util", [], factory); // amd

else if(typeof exports === 'object')

exports["util"] = factory(); // commonjs

else

root["util"] = factory(); // var

}) (window, function() {

return (function(modules) {

var installedModules = {};

function webpack_require(moduleId) {

// ...

}

return webpack_require('./util.js');

}) ({

'./util.js': generated_util,

'/path/to/jquery.js': generated_jquery

});

}

比之前的commonjs2的情况要复杂得多,因为它需要处理各种不同的case,但其实后面的部分都是一样的,最重要的就是最前面的几行,这是umd模块的标准写法。它运行传入的factory函数,实际上就是加载模块的函数,然后把返回的结果根据不同的运行环境交给相应的对象。例如var,那就会把结果设置为一个全局变量,这用于浏览器通过


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:嵌入式接口测试(嵌入式接口测试用例)
下一篇:Vuex实现计数器以及列表展示效果
相关文章

 发表评论

暂时没有评论,来抢沙发吧~