未加星标

webpack进阶教程

字体大小 | |
[前端(javascript) 所属分类 前端(javascript) | 发布者 店小二04 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏

注:本文重点不是怎样配置 webpack.config.js 并实现相应的功能,而是通过对比 webpack 编译前和编译后文件,探究webpack打包后的文件是怎样加载执行的。

本文讨论 commonJS 模块化方案时, webpack 的打包工作。

为了便于讨论,我们准备了一个非常简单的例子,涉及三个文件,分别是

文件 a.js

module.exports ={ say:function(){ console.log('A is saying.'); } }

文件 b.js

module.exports ={ say:function(){ console.log('B is saying.'); } }

文件 index.js

var a = require('./a'); var b = require('./b'); a.say(); b.say();

依赖关系非常简单,即 index.js 文件依赖 a.js 和 b.js 两个文件。而且是采用commonJS方式来引用的。

我的 config 文件也贴一下。

var htmlPlugin = require('html-webpack-plugin'); module.exports = { entry:{ index:'./src/index.js' }, output:{ path:'builds', filename:'[name].js', chunkFilename:'chunk.[name].js' }, plugins:[ new htmlPlugin({ filename:__dirname+'/builds/index.html', template:'./index.html' }) ], devServer:{ contentBase:'./builds', inline:true } }

还有一个非常简单的 index.html 文件。

<!DOCTYPE html> <html> <head> <title>commonJS测试</title> </head> <body> </body> </html>

另外,本问的示例代码已经放到 Github 上,请 点击这里查看 。

我们在目录下运行一下 webpack 命令,builds文件夹里的文件,就是被webpack处理过的文件,也是我们要讨论的重点。

我们来看看文件目录:


webpack进阶教程

builds 里,是编译后的文件,src里,是我们的原始文件。

那么 a.js 和 b.js 呢?打包进 builds/index.js 文件里面了。打包其实就是干这个的,把多个文件合并到一个或少数几个文件里。

我们点开 builds/index.js ,发现我们的代码被改的面目全非。大家 点击这里 看完整的代码,下面是部分片段。

(function(modules){ var installedModules = {}; function __webpack_require__(moduleId) {/*省略*/} /*省略*/ return __webpack_require__(0); })([ //这部分是index.js function(module, exports, __webpack_require__){ var a = __webpack_require__(1); var b = __webpack_require__(2); a.say(); b.say(); }, //这部分是a.js function(module, exports){ module.exports ={ say:function(){ console.log('A is saying.'); } } }, //这部分是b.js function(module, exports){ module.exports ={ say:function(){ console.log('B is saying.'); } } } ])

在上面代码中,我们的 index.js 、 a.js 和 b.js 被放进了一个数组中。入口文件( index.js )都是在数组的 0 的位置。入口文件的依赖( a.js 和 b.js ),会根据依赖的情况往后排。

这个数组作为 IIFE 中函数的参数 modules 传入 function 中。注意匿名函数中的 return __webpack_require__(0); ,这句调用将执行数组中的第一个函数。

第一个函数:

function(module, exports, __webpack_require__) { var a = __webpack_require__(1); var b = __webpack_require__(2); a.say(); b.say(); }

__webpack_require__(1)也就是执行数组中的第二个函数。

第二个函数:

function(module, exports) { module.exports ={ say:function(){ console.log('A is saying.'); } } }

第二个函数的执行后的结果,就是把 module.exports 中的内容赋给了变量 a 。到这里,大家对代码的结构有了了解,但是关键的 __webpack_require__ 方法是怎样工作的呢?我们来分析下代码:

function __webpack_require__(moduleId) { // Check if module is in cache if(installedModules[moduleId]) return installedModules[moduleId].exports; // Create a new module (and put it into the cache) var module = installedModules[moduleId] = { exports: {}, id: moduleId, loaded: false }; // Execute the module function modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); // Flag the module as loaded module.loaded = true; // Return the exports of the module return module.exports; } 这里注意 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__) 这行代码。其中的 modules 就是我们刚才讲的数组( modules 不是 module )。 module.exports 是模块的上下文,也就是 this 。所以,如果我们在 index.js 里加一句 this.name='jack' ,那么最终这个等价于 module.exports.name='jack' ;

此外,我们还可以访问到 module.id 这个属性。这并没有什么实际的作用,只是可以加深我们的理解。比如,我在 a.js 中:

module.exports ={ say:function(){ console.log('A is saying.'); console.log(module.id); } }

是可以输出该模块的 id 的。多说一句,如果你用 webpack-dev-server ,它会打包进去其他的文件,这个 id 会变的比较大(我测试的是75)。有一个可能会用到的 module.loaded 属性。我们的模块在第一次执行的时候, module.loaded 还是 false ,执行过后才被设置为 true 。

比如下面的代码:

index.js

if (module.loaded) { var a = require('./a'); a.say(); } else { var b = require('./b'); b.say(); }

在我们的例子中,这个是每次执行的结果都是 B is saying. 因为每次执行 index.js 模块中的代码都是第一次执行。

在实际的开发中,有可能有要判断当前代码是不是第一次执行的需求。

还有一个重要的变量 installedModules 。我们加载过的模块中的 module.exports 对象,会保存在installedModules[moduleId]中。这样下次调用,就可以直接返回 module.exports 。

OK,这次就讲到这里,希望对同学们学习理解 webpack 能有帮助。

本文前端(javascript)相关术语:javascript是什么意思 javascript下载 javascript权威指南 javascript基础教程 javascript 正则表达式 javascript设计模式 javascript高级程序设计 精通javascript javascript教程

主题: Git其实变量需求模块化
分页:12
转载请注明
本文标题:webpack进阶教程
本站链接:http://www.codesec.net/view/484643.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 前端(javascript) | 评论(0) | 阅读(31)