[webpack]手写一个mvp版本的webpack

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;

  

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注