自定义打包工具
使用babel
工具对js文件做语法解析,从而将多个js文件模块打包成一个文件
- 使用
npm install @babel/parser
安装js语法解析工具 - 使用
npm install @babel/traverse
安装对解析后的js语法进行过滤工具 - 使用
npm install @babel/core @babel/preset-env
安装将es6翻译成es5工具
const fs = require("fs");
const path = require("path");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default; //兼容es6模块化导出
const babel = require("@babel/core");
/**
* 根据入口文件生成依赖映射
* @param {*} entry 入口文件
*/
function dependenceMap(entry) {
/**
* 将单个文件依赖以对象形式返回(路径形式)
* @param {*} entry 入口文件
* 当前返回的对象中的依赖是{相对路径:绝对路径}
*/
function moduleAnalysis(entry) {
const dependence = {}; //依赖对象
const content = fs.readFileSync(entry, "utf-8"); //读取文件内容
const ast = parser.parse(content, { //将文件内容解析成抽象语法树
sourceType: "module" //以es6模块化解析
});
const { code } = babel.transformFromAst(ast, null, { //将抽象语法树翻译成es5代码
presets: ["@babel/preset-env"]
})
const dirname = path.dirname(entry); //获取入口文件目录的相对路径
traverse(ast, {
ImportDeclaration({ node }) { //过滤出es6模块导入语句
const relativePath = node.source.value
dependence[relativePath] = path.join(dirname, relativePath); //将依赖文件存储到依赖对象中
}
});
return {
code, //编译成es5的代码
dependence, //依赖对象
entry //入口文件
}
}
const rootModule = moduleAnalysis(entry)
/**
* 将以moduleRoot为根的返回的依赖对象进行路径和内容之间的转化
* @param {*} rootModule 以该对象为根的依赖对象
* 处理后的对象中的依赖是{相对路径:具体内容}
*/
function replacePath(rootModule) {
key = Object.keys(rootModule.dependence); //获取模块对象的依赖对象的key
key.forEach(item => { //根据key遍历模块对象的依赖对象
const drelativePath = rootModule.dependence[item]; //获取依赖文件的绝对路径
const moduleObj = moduleAnalysis(drelativePath); //根据依赖的绝对路径转化成模块对象
rootModule.dependence[item] = moduleObj; //将模块对象替换掉原来的路径
replacePath(moduleObj); //以替换掉的模块对象为根递归调用,直到整棵树中的路径都替换为对象
});
}
replacePath(rootModule);
const map = {
[entry]: rootModule.code
};
/**
* 将树状依赖对象拉平放入到map中,调用一次拉平一层
* @param {*} obj 要拉平的对象
*/
function flot(obj) {
if (!obj.dependence) return;
const keys = Object.keys(obj.dependence);
keys.forEach(item => {
map[item] = obj.dependence[item].code; //map存放{入口:代码}对象
flot(obj.dependence[item]); //依赖对象递归调用
})
}
flot(rootModule);
return map;
}
/**
* 根据入口文件生成浏览器可执行代码
* @param {*} entry 入口文件
*/
function generateCode(entry) {
const map = dependenceMap(entry);
const code = `
(function (map) {
function require(module) {
var exports = {}; //导出对象,否则无法导出
(function (exports, code) { eval(code); })(exports, map[module]);
return exports;
};
require("${entry}");
})(${JSON.stringify(map)})
`
return code
}
const code = generateCode("index.js");
fs.writeFileSync("./dist/main.js", code);
Comments NOTHING