webpack——使用、分析打包代码
世上本无nodejs
js最初是在前端浏览器上运行的语言,js代码一旦脱离了浏览器环境,就无法被运行。直到nodejs的出现,我们在电脑上配置了node环境,就可以让js代码脱离浏览器,在node环境中运行。
浏览器不支持模块化
nodejs
nodejs可其他后端语言一样,支持模块化,享受了模块化的优点。
浏览器环境
可是浏览器并不支持nodejs的模块化语法
代码
//index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="./module1.js"></script> </head> <body> <div id="btn">我是一个标题</div> </body> </html>
//module1.js const module2=require('./module2') console.log('module2',module2)
//module2.js const a=1 console.log('module2',a) module.exports.a=a
目录结构
效果
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" } }
运行结果
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,控制台打印出
分析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"); })() ;
代码分析
和上面的打包结果差不多。