webpack——分析打包代码

世上本无nodejs

js最初是在前端浏览器上运行的语言,js代码一旦脱离了浏览器环境,就无法被运行。直到nodejs的出现,我们在电脑上配置了node环境,就可以让js代码脱离浏览器,在node环境中运行。

浏览器不支持模块化

nodejs

nodejs可其他后端语言一样,支持模块化,享受了模块化的优点。

浏览器环境

可是浏览器并不支持nodejs的模块化语法

代码

//index.html



    
    
    
    Document
    


    
我是一个标题
//module1.js
const module2=require('./module2')
console.log('module2',module2)
//module2.js
const a=1
console.log('module2',a)
module.exports.a=a

 目录结构

webpack——分析打包代码_第1张图片

效果

Uncaught ReferenceError: require is not defined  
[Five Server] connecting...
[Five Server] connected.

webpack使用

webpack.config.js配置

//webpack.config.js
const path=require("path")
module.exports={
    mode:'development',
    entry:"./module1.js",
    output:{
        path:path.join(__dirname,"dist"),
        filename:"bundle.js"
    }
}

重要配置项

入口(entry)、出口(output)、插件(plugins)、装载器(loader)、模式(mode)

运行结果

webpack——分析打包代码_第2张图片

webpack打包代码

例一commonJs

模块代码

//module1.js
const module2=require('./module2')
console.log('module2',module2)

 

打包代码bundle.js

//打包代码稍作修正一(功能不改变)
(() => {

  var __webpack_modules__ = ({
    "./module1.js":
    (__unused_webpack_module, __unused_webpack_exports, __webpack_require__) =>{
      eval(`
          const module2=__webpack_require__("./module2.js");
          console.log('module2',module2.a)
      `);
    },
    "./module2.js":
    (module) =>{
      eval(`
          const a=1;console.log('module2',a);
          module.exports.a=a
      `);
    }
  });

  var __webpack_module_cache__ = {};

  function __webpack_require__(moduleId) {
    var cachedModule = __webpack_module_cache__[moduleId];
    if (cachedModule !== undefined) {
      return cachedModule.exports;
    }
    var module = __webpack_module_cache__[moduleId] = {
      exports: {}
    };
    __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
    return module.exports;
  }

  var __webpack_exports__ = __webpack_require__("./module1.js");

 })();
//打包代码稍作修正二(功能不改变)
(function(){
  var cache = {};

  function require(modulePath) {
    // var cachedModule = cache[moduleId];
    // if (cachedModule !== undefined) {
    //   return cachedModule.exports;
    // }
    // var module = cache[moduleId] = {
    //   exports: {}
    // };
    module={
      exports:{}
    }
    modules[modulePath](module, module.exports, require);
    return module.exports;
  }

  var modules={
    ["./module1.js"](module, exports, require){
      eval(`
          const module2=require("./module2.js");
          console.log('module2',module2.a)
      `);
    },

    ["./module2.js"](module){
      eval(`
          const a=1;console.log('module2',a);
          module.exports.a=a
      `);
    }
  }

  var exports = require("./module1.js");
 })();

打包代码分析

①webpack实现了自己的require()函数

②webpack采用了立即执行函数

③webpac把各个模块的代码放到modules中

④各模块代码字符串形式存储,使用eval()函数执行

例二commonJs+ES6

模块代码

//module1.js
const module2=require('./module2')
console.log('module1',module2.a)
//module2.js
const module3=require('./utils/modules3')
console.log('module2',module3.a)
module.exports.a=module3.a
//module3.js
export const a=1
console.log('module3',a)

打包代码 

//打包代码稍作修正(功能不改变)
(() => { 
	var modules = ({
    "./module1.js":
    ((module, exports, require) => {
        eval(`
          const module2=require("./module2.js");
          console.log('module1',module2.a)
        `);
    }),

    "./module2.js":
    ((module, exports, require) => {
        eval(`
            const module3=require('./utils/modules3.js');
            console.log('module2',module3.a);
            module.exports.a=module3.a
        `);
    }),

    "./utils/modules3.js":
    ((module, exports, require) => {
        "use strict";
        eval(`
              require.r(exports);
              require.d(exports, {"a":() => (a)});
              const a=1;
              console.log('module3',a)
        `);
    })
  });

	var _cache = {};
	
	function require(moduleId) {		
		var cachedModule = _cache[moduleId];
		if (cachedModule !== undefined) {
			return cachedModule.exports;
		}
		var module = _cache[moduleId] = {	
			exports: {}
		};
		modules[moduleId](module, module.exports, require);
		return module.exports;
	}

	(() => {
		require.d = (exports, definition) => {
			for(var key in definition) {
				if(require.o(definition, key) && !require.o(exports, key)) {
					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
				}
			}
		};
	})();
	
	(() => {
		require.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
	})();
	
	(() => {	
		require.r = (exports) => {
			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
			}
			Object.defineProperty(exports, '__esModule', { value: true });
      console.log(exports)
      // debugger
		};
	})();

	var exports = require("./module1.js");
})()
;

打包代码分析

较例一,require函数对象上添加了d、r、o三个函数,它们的功能分析。

解开debugger的注释,控制台打印出

Module {__esModule: true, Symbol(Symbol.toStringTag): 'Module'}
    __esModule: true
    Symbol(Symbol.toStringTag): "Module"
   [[Prototype]]: Object

分析r函数功能

r函数向exports对象添加__esModule、Symbol(Symbol.toStringTag)两个属性,来标注采用了ES6模块化

注释debugger,控制台打印出

webpack——分析打包代码_第3张图片

分析d。r函数功能

d。r函数向exports对象添加a属性

例三ES6

模块代码

//module1.js
import {a} from './module2'
console.log('module1',a)
export const a=1
console.log('module2',a)

打包代码

(() => {
  "use strict";
  var modules = ({

    "./module1.js":
      ((module, exports, require) => {

        eval(`require.r(exports);
              var _module2__WEBPACK_IMPORTED_MODULE_0__ = require("./module2.js");
              console.log('module1',_module2__WEBPACK_IMPORTED_MODULE_0__.a)
        `);
      }),

    "./module2.js":

      ((module, exports, require) => {

        eval(`require.r(exports);
              require.d(exports, {"a": () => (a)});
              const a=1;
              console.log('module2',a)`);

      })

  });
  
  var cache = {};

  function require(moduleId) {
    var cachedModule = cache[moduleId];
    if (cachedModule !== undefined) {
      return cachedModule.exports;
    }

    var module = cache[moduleId] = {

      exports: {}
    };


    modules[moduleId](module, module.exports, require);


    return module.exports;
  }


  (() => {

    require.d = (exports, definition) => {
      for (var key in definition) {
        if (require.o(definition, key) && !require.o(exports, key)) {
          Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
        }
      }
    };
  })();


  (() => {
    require.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
  })();


  (() => {
    require.r = (exports) => {
      if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
        Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
      }
      Object.defineProperty(exports, '__esModule', { value: true });
    };
  })();
  var exports = require("./module1.js");

})()
  ;

代码分析

和上面的打包结果差不多。

你可能感兴趣的:(webpack,webpack,javascript,前端)