资讯专栏INFORMATION COLUMN

webpack进阶教程(一)

neuSnail / 616人阅读

摘要:本文讨论模块化方案时,的打包工作。省略省略这部分是这部分是这部分是在上面代码中,我们的和被放进了一个数组中。入口文件的依赖和,会根据依赖的情况往后排。第一个函数也就是执行数组中的第二个函数。还有一个重要的变量。

注:本文重点不是怎样配置webpack.config.js并实现相应的功能,而是通过对比webpack编译前和编译后文件,探究webpack打包后的文件是怎样加载执行的。
本文讨论commonJS模块化方案时,webpack的打包工作。
为了便于讨论,我们准备了一个非常简单的例子,涉及三个文件,分别是

文件a.js

</>复制代码

  1. module.exports ={
  2. say:function(){
  3. console.log("A is saying.");
  4. }
  5. }

文件b.js

</>复制代码

  1. module.exports ={
  2. say:function(){
  3. console.log("B is saying.");
  4. }
  5. }

文件index.js

</>复制代码

  1. var a = require("./a");
  2. var b = require("./b");
  3. a.say();
  4. b.say();

依赖关系非常简单,即index.js文件依赖a.jsb.js两个文件。而且是采用commonJS方式来引用的。
我的config文件也贴一下。

</>复制代码

  1. var htmlPlugin = require("html-webpack-plugin");
  2. module.exports = {
  3. entry:{
  4. index:"./src/index.js"
  5. },
  6. output:{
  7. path:"builds",
  8. filename:"[name].js",
  9. chunkFilename:"chunk.[name].js"
  10. },
  11. plugins:[
  12. new htmlPlugin({
  13. filename:__dirname+"/builds/index.html",
  14. template:"./index.html"
  15. })
  16. ],
  17. devServer:{
  18. contentBase:"./builds",
  19. inline:true
  20. }
  21. }

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

</>复制代码

  1. commonJS测试

另外,本问的示例代码已经放到Github上,请 点击这里查看。
我们在目录下运行一下webpack命令,builds文件夹里的文件,就是被webpack处理过的文件,也是我们要讨论的重点。
我们来看看文件目录:

builds 里,是编译后的文件,src里,是我们的原始文件。
那么a.jsb.js呢?打包进builds/index.js文件里面了。打包其实就是干这个的,把多个文件合并到一个或少数几个文件里。
我们点开builds/index.js,发现我们的代码被改的面目全非。大家点击这里看完整的代码,下面是部分片段。

</>复制代码

  1. (function(modules){
  2. var installedModules = {};
  3. function __webpack_require__(moduleId) {/*省略*/}
  4. /*省略*/
  5. return __webpack_require__(0);
  6. })([
  7. //这部分是index.js
  8. function(module, exports, __webpack_require__){
  9. var a = __webpack_require__(1);
  10. var b = __webpack_require__(2);
  11. a.say();
  12. b.say();
  13. },
  14. //这部分是a.js
  15. function(module, exports){
  16. module.exports ={
  17. say:function(){
  18. console.log("A is saying.");
  19. }
  20. }
  21. },
  22. //这部分是b.js
  23. function(module, exports){
  24. module.exports ={
  25. say:function(){
  26. console.log("B is saying.");
  27. }
  28. }
  29. }
  30. ])

在上面代码中,我们的index.jsa.jsb.js被放进了一个数组中。入口文件(index.js)都是在数组的0的位置。入口文件的依赖(a.jsb.js),会根据依赖的情况往后排。
这个数组作为IIFE中函数的参数modules传入function中。注意匿名函数中的return __webpack_require__(0);,这句调用将执行数组中的第一个函数。

第一个函数:

</>复制代码

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

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

第二个函数:

</>复制代码

  1. function(module, exports) {
  2. module.exports ={
  3. say:function(){
  4. console.log("A is saying.");
  5. }
  6. }
  7. }

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

</>复制代码

  1. function __webpack_require__(moduleId) {
  2. // Check if module is in cache
  3. if(installedModules[moduleId])
  4. return installedModules[moduleId].exports;
  5. // Create a new module (and put it into the cache)
  6. var module = installedModules[moduleId] = {
  7. exports: {},
  8. id: moduleId,
  9. loaded: false
  10. };
  11. // Execute the module function
  12. modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  13. // Flag the module as loaded
  14. module.loaded = true;
  15. // Return the exports of the module
  16. return module.exports;
  17. }

这里注意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中:

</>复制代码

  1. module.exports ={
  2. say:function(){
  3. console.log("A is saying.");
  4. console.log(module.id);
  5. }
  6. }

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

index.js

</>复制代码

  1. if (module.loaded) {
  2. var a = require("./a");
  3. a.say();
  4. } else {
  5. var b = require("./b");
  6. b.say();
  7. }

在我们的例子中,这个是每次执行的结果都是B is saying.因为每次执行index.js模块中的代码都是第一次执行。
在实际的开发中,有可能有要判断当前代码是不是第一次执行的需求。
还有一个重要的变量installedModules。我们加载过的模块中的module.exports对象,会保存在installedModules[moduleId]中。这样下次调用,就可以直接返回module.exports
OK,这次就讲到这里,希望对同学们学习理解webpack能有帮助。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87985.html

相关文章

  • webpack-demos:全网最贴心webpack系列教程和配套代码

    摘要:全网最贴心系列教程和配套代码欢迎关注个人技术博客。所以我花费了个多月整理了这份教程,一共分成节,每节都有讲解,并且准备了配套代码。奈何深感水平不够,只有一腔热情,所以直接开放了教程和源码。 webpack-demos:全网最贴心 webpack 系列教程和配套代码 欢迎关注个人技术博客:godbmw.com。每周 1 篇原创技术分享!开源教程(webpack、设计模式)、面试刷题(偏前...

    LMou 评论0 收藏0
  • webpack 教程资源收集

    学习的过程中收藏了这些优秀教程和的项目,希望对你有帮助。 github地址, 有不错的就更新 官方文档 中文指南 初级教程 webpack-howto 作者:Pete Hunt Webpack 入门指迷 作者:题叶   webpack-demos 作者:ruanyf 一小时包教会 —— webpack 入门指南 作者:VaJoy Larn   webpack 入门及实践 作者:...

    Backache 评论0 收藏0
  • webpack进阶教程

    摘要:本文讨论模块化方案时,的打包工作。省略省略这部分是这部分是这部分是在上面代码中,我们的和被放进了一个数组中。入口文件的依赖和,会根据依赖的情况往后排。第一个函数也就是执行数组中的第二个函数。还有一个重要的变量。 注:本文重点不是怎样配置webpack.config.js并实现相应的功能,而是通过对比webpack编译前和编译后文件,探究webpack打包后的文件是怎样加载执行的。本文讨...

    Guakin_Huang 评论0 收藏0
  • webpack4详细教程,从无到有搭建react脚手架(

    摘要:是一个现代应用程序的静态模块打包器,前端模块化的基础。作为一个前端工程师切图仔,非常有必要学习。官网的文档非常的棒,中文文档也非常给力,可以媲美的文档。建议先看概念篇章,再看指南,然后看和配置总览。 webpack 是一个现代 JavaScript 应用程序的静态模块打包器,前端模块化的基础。作为一个前端工程师(切图仔),非常有必要学习。 showImg(https://segment...

    zhkai 评论0 收藏0
  • webpack4系列教程(十):总结

    摘要:传送门系列教程一初识系列教程二创建项目,打包第一个文件系列教程三自动生成项目中的文件系列教程四处理项目中的资源文件一系列教程五处理项目中的资源文件二系列教程六使用分割代码系列教程七使用系列教程八使用审查代码系列教程九开发环境和生产环境 在前端开发日益复杂的今天,我们需要一个工具来帮助我们管理项目资源,打包、编译、预处理、后处理等等。webpack的出现无疑是前端开发者的福音,我的博文只...

    hqman 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<