webpack原理-實現webpack打包js
阿新 • • 發佈:2020-11-21
// 這裡匯入webpack配置,我用物件的形式表示,當然entry屬性上定義的檔案要有 // const config = require("./webpack.config"); const config = { entry: './src/index.js' }; const { join, dirname } = require("path"); const { readFileSync, writeFileSync } = require("fs"); const reg = /(?<=from\s+['"])[\.\/\w]+(?=['"])/g; class Complier { constructor({ entry }) { this.entry = entry; } run() { writeFileSync('generateFile.js', generateCode(this.entry)); } } const parser = (entry, prePath = '.') => { let temp = null; const filePath = `./${join(prePath, entry)}`; const code = Buffer.from(readFileSync(filePath)).toString(); const dependencies = {}; // 通過正則將當前檔案es匯入的模組識別並存到dependencies裡,註釋也會存起來,請不要寫註釋 while ((temp = reg.exec(code)) !== null) { temp.forEach(filePath => { dependencies[filePath] = `./${join(prePath, dirname(entry), filePath)}`; }) } return { filePath, dependencies, code, }; } const makeDependenciesGraph = (entry) => { const entryModule = parser(entry); const graphArray = [entryModule]; // 利用廣度遍歷的思想遍歷一遍 for (let i = 0; i < graphArray.length; i++) { const { dependencies } = graphArray[i]; if (dependencies) { for (let path in dependencies) { graphArray.push(parser(path, dirname(entry))); } } } const graph = {}; graphArray.forEach(({ filePath, dependencies, code }) => { graph[filePath] = { dependencies, code }; }); return graph; }; const generateCode = (entry) => { const graph = JSON.stringify(makeDependenciesGraph(entry)); return ` (function (graph) { function require(module) { function localRequire(relativePath) { return require(graph[module].dependencies[relativePath]); } var exports = {}; (function (require, exports, code) { eval(code); })(localRequire, exports, graph[module].code); return exports; } require("${`./${join('.', entry).replace(/\\/g, '\\\\')}`}"); })(${graph}); `; }; new Complier(config).run();