webpack最終生成bundle原理(主要是js模組化的原理)
這是生成的依賴樹
{
'./src/index.js': {
code: '"use strict";\n' +
'\n' +
'var _add = _interopRequireDefault(require("./add.js"));\n' +
'\n' +
'var _count = _interopRequireDefault(require("./count.js"));\n' +
'\n' +
'function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n' +
'\n' +
'console.log((0, _add["default"])(1, 2));\n' +
'console.log((0, _count["default"])(3, 1));',
deps: {
'./add.js': 'D:\\webpack5進階\\05.myWebpack\\src\\add.js',
'./count.js': 'D:\\webpack5進階\\05.myWebpack\\src\\count.js'
}
},
'D:\\webpack5進階\\05.myWebpack\\src\\add.js': {
code: '"use strict";\n' +
'\n' +
'Object.defineProperty(exports, "__esModule", {\n' +
' value: true\n' +
'});\n' +
'exports["default"] = void 0;\n' +
'\n' +
'var _new = _interopRequireDefault(require("./new.js"));\n' +
'\n' +
'function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }\n' +
'\n' +
'function add(x, y) {\n' +
' return x + y;\n' +
'}\n' +
'\n' +
'console.log(_new["default"]);\n' +
'var _default = add;\n' +
'exports["default"] = _default;',
deps: { './new.js': 'D:\\webpack5進階\\05.myWebpack\\src\\new.js' }
},
'D:\\webpack5進階\\05.myWebpack\\src\\count.js': {
code: '"use strict";\n' +
'\n' +
'Object.defineProperty(exports, "__esModule", {\n' +
' value: true\n' +
'});\n' +
'exports["default"] = void 0;\n' +
'\n' +
'function count(x, y) {\n' +
' return x - y;\n' +
'}\n' +
'\n' +
'var _default = count;\n' +
'exports["default"] = _default;',
deps: {}
},
'D:\\webpack5進階\\05.myWebpack\\src\\new.js': {
code: '"use strict";\n' +
'\n' +
'Object.defineProperty(exports, "__esModule", {\n' +
' value: true\n' +
'});\n' +
'exports["default"] = void 0;\n' +
'var _default = 123;\n' +
'exports["default"] = _default;',
deps: {}
}
}
這是簡單版的bundle生成方法
generate(depsGraph) {
const bundle = `
(function(depsGraph){
// require目的:為了載入入口檔案
function require(module){
// 定義模組內部的require函式
function localRequire(relativePath){
// 為了找到要引入模組的絕對路徑,通過require載入
return require(depsGraph[module].deps[relativePath]);
}
// 定義暴露物件(將來我們要暴露的內容)
var exports = {};
(function(require,exports,code){
eval(code)
})(localRequire, exports, depsGraph[module].code);
// 作為require函式的返回值返回出去
// 後面的require函式能得到暴露的內容
return exports;
}
// 載入入口檔案
require('${this.options.entry}');
})(${JSON.stringify(depsGraph)})
`;
// 生成輸出檔案的絕對路徑
const filePath = path.resolve(this.options.output.path, this.options.output.filename);
// 寫入檔案
fs.writeFileSync(filePath, bundle, 'utf-8');
}
首先可以從依賴樹裡面看到,es6的模組語法都已經被轉為了require和exports之類的。
關於require:
執行generate方法時,首先會從入口檔案開始執行require('${this.options.entry}')
,然後require函式裡面,有一個立即執行方法,這個方法可以執行入口檔案裡面的程式碼:
(function(require,exports,code){
eval(code)
})(localRequire, exports, depsGraph[module].code);
如果這些程式碼裡面有模組引入(require),那麼又會繼續遞迴呼叫require函式,並且根據依賴樹把模組引入的相對路徑轉為絕對路徑,這樣就可以在依賴樹裡面找到該模組內部的程式碼了,那麼require函式的立即執行方法又可以繼續執行引入模組內部的程式碼了。
關於exports:
但是僅僅遞迴呼叫require是不夠的,因為require返回的是一個模組,外層模組必須基於require的返回值來進行下一步操作,所以要對exports進行處理,其實處理很簡單,對於有exports語法的模組,在require方法內部先定義一個空的exports物件var exports = {};
,也就是我們的暴露物件,然後再在這個物件上新增要暴露出去的屬性或方法,最後返回這個物件即可。那麼當我外層模組require時,就可以拿到內層模組的想要暴露出來的值了。
總結:
所謂的模組化其實最後都生成了一段程式碼,最重要的有三點,第一點是依賴樹,第二點是require的遞迴呼叫,第三點是exports的返回值。
相關文章
- Webpack 模組打包原理Web
- webpack最簡單的入門教程裡bundle.js之執行單步除錯的原理解析WebJS除錯
- js module bundle 模組捆綁JS
- webpack模組非同步載入原理解析Web非同步
- node.js中的模組實現原理Node.js
- JavaScript模組化原理淺析JavaScript
- NodeJS的模組原理NodeJS
- 剖析 | 詳談 SOFABoot 模組化原理boot
- Webpack之模組化優化Web優化
- webpack runoob1.js bundle.js 錯誤WebJS
- webpack原理Web
- JS模組化JS
- webpack系列--淺析webpack的原理Web
- 前端模組化之AMD與CMD原理(附原始碼)前端原始碼
- Node.js 的 模組化Node.js
- 探索 JS 中的模組化JS
- 前端ES6模組化,Webpack,前端Web
- webpack模組化學習記錄Web
- webpack是如何實現前端模組化的Web前端
- 概述nodejs模組系統核心原理NodeJS
- webpack 熱更新原理Web
- Webpack 原理淺析Web
- webpack原理解析Web
- Js模組化開發的理解JS
- JS模組化系統JS
- JS模組化規範JS
- webpack-bundle-analyzer的使用Web
- SAP UI5 Library Resource Bundle 的設計原理UI
- 【CSS模組化之路2】webpack中的Local ScopeCSSWeb
- 結合原始碼分析 Node.js 模組載入與執行原理原始碼Node.js
- Clojure 執行原理之位元組碼生成篇
- webpack 支援的模組方法Web
- Nestjs模組機制的概念和實現原理JS
- 進擊的模組化+webpack的簡單實現Web
- iOS-生成Bundle包-引入bundle-使用bundleiOS
- 單步除錯理解webpack裡通過require載入nodejs原生模組實現原理除錯WebUINodeJS
- Webpack原理與實踐Web
- Webpack Tapable原理詳解Web