代码原理
// 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;"
}
})