let fs = require'fs'); let path = require'path'); let babylon = require'babylon'); // Babylon 把源码转换为AST let t = require'@babel/types'); // @babel-types 替换节点 let traverse = require'@babel/traverse').default; // @babel-traverse 遍历节点 let generator = require'@babel/generator').default; // @babel/generator 生成 let ejs = require'ejs'); // js模版 class Compiler { // 构造函数 constructorconfig) { // entry out this.config = config; // 1、保存入口文件的路径 this.entryId; // 2、博阿村所有的模块依赖 this.modules = {}; // 入口路径 this.entry = config.entry; // 工作路径 this.root = process.cwd); } // 获取文件源码 getSourcemodulePath){ let content = fs.readFileSyncmodulePath,'utf8'); return content; } // 解析源码 parsesource,parentPath){ // AST解析语法树 let ast = babylon.parsesource); let dependencies = []; traverseast,{ CallExpressionp){ let node = p.node; // 对应的节点 ifnode.callee.name === 'require'){ node.callee.name = '__webpack_require__'; let moduleName = node.arguments[0].value; // 取到的就是模块的引用名字 moduleName = moduleName + path.extnamemoduleName)?'':'.js'); moduleName = './'+path.joinparentPath,moduleName); dependencies.pushmoduleName); node.arguments = [t.stringLiteralmoduleName)]; } } }); let sourceCode = generatorast).code; return { sourceCode, dependencies } } // 建立模块 buildModulemodulePath,isEntry){ // 拿到模块的内容 let source = this.getSourcemodulePath); // 模块id modulePath modulePath-this.root = src/index.js let moduleName = './'+path.relativethis.root,modulePath); ifisEntry){ // 保存入口的名字 this.entryId = moduleName; } // 解析需要把source源码进行改造,返回一个依赖列表 let {sourceCode,dependencies} = this.parsesource,path.dirnamemoduleName)); this.modules[moduleName] = sourceCode; dependencies.forEach // 父模块的加载,递归加载 dep)=>{ this.buildModulepath.jointhis.root,dep),false) } ); } emitFile){ // 发射文件 // 用数据渲染 // 输出路径 let main = path.jointhis.config.output.path,this.config.output.filename); // 模板的路径 let tempateStr = this.getSourcepath.join__dirname,'main.ejs')); let code = ejs.rendertempateStr,{ entryId:this.entryId, modules: this.modules }); // this.assets = {}; // // 路径对应的代码 // this.assets[main] = code; // fs.writeFileSyncmain,this.assets[main]); fs.writeFileSyncmain,code); } run) { // 执行并创建模块依赖关系 this.buildModulepath.resolvethis.root, this.entry),true); // 发射一个打包后的文件 this.emitFile); } } module.exports = Compiler;