webpack 基本原理

96 阅读6分钟

代码原理

// minus.js
export const minus = (a,b)=>{
    return a-b
}

// add.js
export default (a,b)=>{
    return a+b;
}

// index.js
import add from "./add.js"
import {minus} from "./minus.js";

const sum = add(1,2);
const division = minus(2,1);

console.log(sum);
console.log(division);

const fs = require('fs');
const path = require('path');
const parser = require('@babel/parser'); // 用于将代码解析成AST
const traverse = require('@babel/traverse').default; // 用于遍历AST
const babel = require('@babel/core'); // 用于代码转换

// 获取模块信息
const getModuleInfo = (file) => {
    const body = fs.readFileSync(file, 'utf-8'); // 读取文件内容
    // 下文打印body
   
    const ast = parser.parse(body, {
        sourceType: 'module' // 告诉解析器解析的是ES模块
    });
    // 下文打印ast
  
    const deps = {}; // 存储模块的依赖关系
    traverse(ast, {
        ImportDeclaration({node}) {
            const dirname = path.dirname(file); // 获取当前文件所在的目录名
            const abspath = "./" + path.join(dirname, node.source.value); // 计算依赖的绝对路径
            deps[node.source.value] = abspath; // 存储依赖关系
        }
    });
    // 下文打印deps 
    
    const {code} = babel.transformFromAst(ast, null, {
        presets: ["@babel/preset-env"] // 将ES6+代码转换为ES5
    });
    // 下文打印code
    
    
    const moduleInfo = {file, deps, code}; // 模块信息对象
    return moduleInfo;
};

// 解析模块
const parseModules = (file) => {
    const entry = getModuleInfo(file); // 获取入口模块信息
    const temp = [entry]; // 用于存储待解析的模块信息
    const depsGraph = {}; // 存储所有模块的依赖关系图
    for (let i = 0; i < temp.length; i++) {
        const deps = temp[i].deps; // 获取模块的依赖关系
        if (deps) {
            for (const key in deps) {
                if (deps.hasOwnProperty(key)) {
                    temp.push(getModuleInfo(deps[key])); // 递归获取依赖模块的信息
                }
            }
        }
    }
    // 将模块信息存储到依赖关系图中
    temp.forEach(moduleInfo => {
        depsGraph[moduleInfo.file] = {
            deps: moduleInfo.deps,
            code: moduleInfo.code
        };
    });
    return depsGraph;
};

// 打包
const bundle = (file) => {
    const depsGraph = JSON.stringify(parseModules(file)); // 获取依赖关系图并序列化为JSON字符串
    // 构建打包后的代码
    return `(function (graph) {
        function require(file) {
            function absRequire(relPath) {
                return require(graph[file].deps[relPath]);
            }
            var exports = {};
            (function (require, exports, code) {
                eval(code);
            })(absRequire, exports, graph[file].code);
            return exports;
        }
        require('${file}');
    })(${depsGraph})`;
};

// 生成打包后的内容
const content = bundle('./src/index.js');

console.log(content);

// 将打包后的内容写入到dist目录下
fs.mkdirSync('./dist'); // 创建dist目录
fs.writeFileSync('./dist/bundle.js', content); // 写入打包后的内容

打印body(String类型)

`import add from "./add.js"
import {minus} from "./minus.js";
const sum = add(1,2);
const division = minus(2,1);
console.log(sum);
console.log(division);`

打印ast

{
    "type": "File",
    "start": 0,
    "end": 155,
    "loc": {
        "start": {
            "line": 1,
            "column": 0,
            "index": 0
        },
        "end": {
            "line": 9,
            "column": 0,
            "index": 155
        }
    },
    "errors": [],
    "program": {
        "type": "Program",
        "start": 0,
        "end": 155,
        "loc": {
            "start": {
                "line": 1,
                "column": 0,
                "index": 0
            },
            "end": {
                "line": 9,
                "column": 0,
                "index": 155
            }
        },
        "sourceType": "module",
        "interpreter": null,
        "body": [
            {
                "type": "ImportDeclaration",
                "start": 0,
                "end": 26,
                "loc": {
                    "start": {
                        "line": 1,
                        "column": 0,
                        "index": 0
                    },
                    "end": {
                        "line": 1,
                        "column": 26,
                        "index": 26
                    }
                },
                "specifiers": [
                    {
                        "type": "ImportDefaultSpecifier",
                        "start": 7,
                        "end": 10,
                        "loc": {
                            "start": {
                                "line": 1,
                                "column": 7,
                                "index": 7
                            },
                            "end": {
                                "line": 1,
                                "column": 10,
                                "index": 10
                            }
                        },
                        "local": {
                            "type": "Identifier",
                            "start": 7,
                            "end": 10,
                            "loc": {
                                "start": {
                                    "line": 1,
                                    "column": 7,
                                    "index": 7
                                },
                                "end": {
                                    "line": 1,
                                    "column": 10,
                                    "index": 10
                                },
                                "identifierName": "add"
                            },
                            "name": "add"
                        }
}
],
                "source": {
                    "type": "StringLiteral",
                    "start": 16,
                    "end": 26,
                    "loc": {
                        "start": {
                            "line": 1,
                            "column": 16,
                            "index": 16
                        },
                        "end": {
                            "line": 1,
                            "column": 26,
                            "index": 26
                        }
                    },
                    "extra": {
                        "rawValue": "./add.js",
                        "raw": "\"./add.js\""
                    },
                    "value": "./add.js"
                }
},
            {
                "type": "ImportDeclaration",
                "start": 27,
                "end": 60,
                "loc": {
                    "start": {
                        "line": 2,
                        "column": 0,
                        "index": 27
                    },
                    "end": {
                        "line": 2,
                        "column": 33,
                        "index": 60
                    }
                },
                "specifiers": [
                    {
                        "type": "ImportSpecifier",
                        "start": 35,
                        "end": 40,
                        "loc": {
                            "start": {
                                "line": 2,
                                "column": 8,
                                "index": 35
                            },
                            "end": {
                                "line": 2,
                                "column": 13,
                                "index": 40
                            }
                        },
                        "imported": {
                            "type": "Identifier",
                            "start": 35,
                            "end": 40,
                            "loc": {
                                "start": {
                                    "line": 2,
                                    "column": 8,
                                    "index": 35
                                },
                                "end": {
                                    "line": 2,
                                    "column": 13,
                                    "index": 40
                                },
                                "identifierName": "minus"
                            },
                            "name": "minus"
                        },
                        "local": {
                            "type": "Identifier",
                            "start": 35,
                            "end": 40,
                            "loc": {
                                "start": {
                                    "line": 2,
                                    "column": 8,
                                    "index": 35
                                },
                                "end": {
                                    "line": 2,
                                    "column": 13,
                                    "index": 40
                                },
                                "identifierName": "minus"
                            },
                            "name": "minus"
                        }
}
],
                "source": {
                    "type": "StringLiteral",
                    "start": 47,
                    "end": 59,
                    "loc": {
                        "start": {
                            "line": 2,
                            "column": 20,
                            "index": 47
                        },
                        "end": {
                            "line": 2,
                            "column": 32,
                            "index": 59
                        }
                    },
                    "extra": {
                        "rawValue": "./minus.js",
                        "raw": "\"./minus.js\""
                    },
                    "value": "./minus.js"
                }
},
            {
                "type": "VariableDeclaration",
                "start": 62,
                "end": 83,
                "loc": {
                    "start": {
                        "line": 4,
                        "column": 0,
                        "index": 62
                    },
                    "end": {
                        "line": 4,
                        "column": 21,
                        "index": 83
                    }
                },
                "declarations": [
                    {
                        "type": "VariableDeclarator",
                        "start": 68,
                        "end": 82,
                        "loc": {
                            "start": {
                                "line": 4,
                                "column": 6,
                                "index": 68
                            },
                            "end": {
                                "line": 4,
                                "column": 20,
                                "index": 82
                            }
                        },
                        "id": {
                            "type": "Identifier",
                            "start": 68,
                            "end": 71,
                            "loc": {
                                "start": {
                                    "line": 4,
                                    "column": 6,
                                    "index": 68
                                },
                                "end": {
                                    "line": 4,
                                    "column": 9,
                                    "index": 71
                                },
                                "identifierName": "sum"
                            },
                            "name": "sum"
                        },
                        "init": {
                            "type": "CallExpression",
                            "start": 74,
                            "end": 82,
                            "loc": {
                                "start": {
                                    "line": 4,
                                    "column": 12,
                                    "index": 74
                                },
                                "end": {
                                    "line": 4,
                                    "column": 20,
                                    "index": 82
                                }
                            },
                            "callee": {
                                "type": "Identifier",
                                "start": 74,
                                "end": 77,
                                "loc": {
                                    "start": {
                                        "line": 4,
                                        "column": 12,
                                        "index": 74
                                    },
                                    "end": {
                                        "line": 4,
                                        "column": 15,
                                        "index": 77
                                    },
                                    "identifierName": "add"
                                },
                                "name": "add"
                            },
                            "arguments": [
                                {
                                    "type": "NumericLiteral",
                                    "start": 78,
                                    "end": 79,
                                    "loc": {
                                        "start": {
                                            "line": 4,
                                            "column": 16,
                                            "index": 78
                                        },
                                        "end": {
                                            "line": 4,
                                            "column": 17,
                                            "index": 79
                                        }
                                    },
                                    "extra": {
                                        "rawValue": 1,
                                        "raw": "1"
                                    },
                                    "value": 1
},
                                {
                                    "type": "NumericLiteral",
                                    "start": 80,
                                    "end": 81,
                                    "loc": {
                                        "start": {
                                            "line": 4,
                                            "column": 18,
                                            "index": 80
                                        },
                                        "end": {
                                            "line": 4,
                                            "column": 19,
                                            "index": 81
                                        }
                                    },
                                    "extra": {
                                        "rawValue": 2,
                                        "raw": "2"
                                    },
                                    "value": 2
}
]
                        }
}
],
                "kind": "const"
},
            {
                "type": "VariableDeclaration",
                "start": 84,
                "end": 112,
                "loc": {
                    "start": {
                        "line": 5,
                        "column": 0,
                        "index": 84
                    },
                    "end": {
                        "line": 5,
                        "column": 28,
                        "index": 112
                    }
                },
                "declarations": [
                    {
                        "type": "VariableDeclarator",
                        "start": 90,
                        "end": 111,
                        "loc": {
                            "start": {
                                "line": 5,
                                "column": 6,
                                "index": 90
                            },
                            "end": {
                                "line": 5,
                                "column": 27,
                                "index": 111
                            }
                        },
                        "id": {
                            "type": "Identifier",
                            "start": 90,
                            "end": 98,
                            "loc": {
                                "start": {
                                    "line": 5,
                                    "column": 6,
                                    "index": 90
                                },
                                "end": {
                                    "line": 5,
                                    "column": 14,
                                    "index": 98
                                },
                                "identifierName": "division"
                            },
                            "name": "division"
                        },
                        "init": {
                            "type": "CallExpression",
                            "start": 101,
                            "end": 111,
                            "loc": {
                                "start": {
                                    "line": 5,
                                    "column": 17,
                                    "index": 101
                                },
                                "end": {
                                    "line": 5,
                                    "column": 27,
                                    "index": 111
                                }
                            },
                            "callee": {
                                "type": "Identifier",
                                "start": 101,
                                "end": 106,
                                "loc": {
                                    "start": {
                                        "line": 5,
                                        "column": 17,
                                        "index": 101
                                    },
                                    "end": {
                                        "line": 5,
                                        "column": 22,
                                        "index": 106
                                    },
                                    "identifierName": "minus"
                                },
                                "name": "minus"
                            },
                            "arguments": [
                                {
                                    "type": "NumericLiteral",
                                    "start": 107,
                                    "end": 108,
                                    "loc": {
                                        "start": {
                                            "line": 5,
                                            "column": 23,
                                            "index": 107
                                        },
                                        "end": {
                                            "line": 5,
                                            "column": 24,
                                            "index": 108
                                        }
                                    },
                                    "extra": {
                                        "rawValue": 2,
                                        "raw": "2"
                                    },
                                    "value": 2
},
                                {
                                    "type": "NumericLiteral",
                                    "start": 109,
                                    "end": 110,
                                    "loc": {
                                        "start": {
                                            "line": 5,
                                            "column": 25,
                                            "index": 109
                                        },
                                        "end": {
                                            "line": 5,
                                            "column": 26,
                                            "index": 110
                                        }
                                    },
                                    "extra": {
                                        "rawValue": 1,
                                        "raw": "1"
                                    },
                                    "value": 1
}
]
                        }
}
],
                "kind": "const"
},
            {
                "type": "ExpressionStatement",
                "start": 114,
                "end": 131,
                "loc": {
                    "start": {
                        "line": 7,
                        "column": 0,
                        "index": 114
                    },
                    "end": {
                        "line": 7,
                        "column": 17,
                        "index": 131
                    }
                },
                "expression": {
                    "type": "CallExpression",
                    "start": 114,
                    "end": 130,
                    "loc": {
                        "start": {
                            "line": 7,
                            "column": 0,
                            "index": 114
                        },
                        "end": {
                            "line": 7,
                            "column": 16,
                            "index": 130
                        }
                    },
                    "callee": {
                        "type": "MemberExpression",
                        "start": 114,
                        "end": 125,
                        "loc": {
                            "start": {
                                "line": 7,
                                "column": 0,
                                "index": 114
                            },
                            "end": {
                                "line": 7,
                                "column": 11,
                                "index": 125
                            }
                        },
                        "object": {
                            "type": "Identifier",
                            "start": 114,
                            "end": 121,
                            "loc": {
                                "start": {
                                    "line": 7,
                                    "column": 0,
                                    "index": 114
                                },
                                "end": {
                                    "line": 7,
                                    "column": 7,
                                    "index": 121
                                },
                                "identifierName": "console"
                            },
                            "name": "console"
                        },
                        "computed": false,
                        "property": {
                            "type": "Identifier",
                            "start": 122,
                            "end": 125,
                            "loc": {
                                "start": {
                                    "line": 7,
                                    "column": 8,
                                    "index": 122
                                },
                                "end": {
                                    "line": 7,
                                    "column": 11,
                                    "index": 125
                                },
                                "identifierName": "log"
                            },
                            "name": "log"
                        }
                    },
                    "arguments": [
                        {
                            "type": "Identifier",
                            "start": 126,
                            "end": 129,
                            "loc": {
                                "start": {
                                    "line": 7,
                                    "column": 12,
                                    "index": 126
                                },
                                "end": {
                                    "line": 7,
                                    "column": 15,
                                    "index": 129
                                },
                                "identifierName": "sum"
                            },
                            "name": "sum"
}
]
                }
},
            {
                "type": "ExpressionStatement",
                "start": 132,
                "end": 154,
                "loc": {
                    "start": {
                        "line": 8,
                        "column": 0,
                        "index": 132
                    },
                    "end": {
                        "line": 8,
                        "column": 22,
                        "index": 154
                    }
                },
                "expression": {
                    "type": "CallExpression",
                    "start": 132,
                    "end": 153,
                    "loc": {
                        "start": {
                            "line": 8,
                            "column": 0,
                            "index": 132
                        },
                        "end": {
                            "line": 8,
                            "column": 21,
                            "index": 153
                        }
                    },
                    "callee": {
                        "type": "MemberExpression",
                        "start": 132,
                        "end": 143,
                        "loc": {
                            "start": {
                                "line": 8,
                                "column": 0,
                                "index": 132
                            },
                            "end": {
                                "line": 8,
                                "column": 11,
                                "index": 143
                            }
                        },
                        "object": {
                            "type": "Identifier",
                            "start": 132,
                            "end": 139,
                            "loc": {
                                "start": {
                                    "line": 8,
                                    "column": 0,
                                    "index": 132
                                },
                                "end": {
                                    "line": 8,
                                    "column": 7,
                                    "index": 139
                                },
                                "identifierName": "console"
                            },
                            "name": "console"
                        },
                        "computed": false,
                        "property": {
                            "type": "Identifier",
                            "start": 140,
                            "end": 143,
                            "loc": {
                                "start": {
                                    "line": 8,
                                    "column": 8,
                                    "index": 140
                                },
                                "end": {
                                    "line": 8,
                                    "column": 11,
                                    "index": 143
                                },
                                "identifierName": "log"
                            },
                            "name": "log"
                        }
                    },
                    "arguments": [
                        {
                            "type": "Identifier",
                            "start": 144,
                            "end": 152,
                            "loc": {
                                "start": {
                                    "line": 8,
                                    "column": 12,
                                    "index": 144
                                },
                                "end": {
                                    "line": 8,
                                    "column": 20,
                                    "index": 152
                                },
                                "identifierName": "division"
                            },
                            "name": "division"
}
]
                }
}
],
        "directives": []
    },
    "comments": []
}

打印deps

{ './add.js': './src/add.js', './minus.js': './src/minus.js' }

打印code(String类型,放在eval执行)

"use strict";
var _add = _interopRequireDefault(require("./add.js"));
var _minus = require("./minus.js");

function _interopRequireDefault(obj) {
    return obj && obj.__esModule ? obj : {
        "default": obj
    };
}
var sum = (0, _add[\"default\"])(1, 2);
var division = (0, _minus.minus)(2, 1);
console.log(sum);
console.log(division);

最终形成的代码

(function (graph) {
    function require(file) {
        function absRequire(relPath) {
            return require(graph[file].deps[relPath]);
        }
        var exports = {};
        (function (require, exports, code) {
            eval(code);
        })(absRequire, exports, graph[file].code);
        return exports;
    }
    require('./src/index.js');
})({
    "./src/index.js": {
        "deps": {
            "./add.js": "./src/add.js",
            "./minus.js": "./src/minus.js"
        },
        "code": "\"use strict\";\n\nvar _add = _interopRequireDefault(require(\"./add.js\"));\nvar _minus = require(\"./minus.js\");\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { \"default\": obj }; }\nvar sum = (0, _add[\"default\"])(1, 2);\nvar division = (0, _minus.minus)(2, 1);\nconsole.log(sum);\nconsole.log(division);"
    },
    "./src/add.js": {
        "deps": {},
        "code": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports[\"default\"] = void 0;\nvar _default = function _default(a, b) {\n return a + b;\n};\nexports[\"default\"] = _default;"
    },
    "./src/minus.js": {
        "deps": {},
        "code": "\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.minus = void 0;\nvar minus = function minus(a, b) {\n return a - b;\n};\nexports.minus = minus;"
    }
})

参考

github.com/Sunny-lucki…