创建依赖关系 
本节全部代码 
js
// webpack\cheny-pack\lib\Complier.js
let path = require('path')
let fs = require('fs')
class Complier {
    constructor(config) {
        // 将配置文件挂载到实例上,所有实例都能拿到了
        // webpack.config.js
        this.config = config
        // 1. 保存入口文件的路径
        this.entryId; // './src/index.js'
        // 2. 需要保存所有模块的依赖
        // 解析文件的依赖,变成webpack打包传递的参数,key value的形式
        // key 是路径名,value就是模块代码
        this.modules = {}
        this.entry = config.entry // 入口路径
        this.root = process.cwd() // 工作路径 运行 npx cheny-pack 时候的路径
    }
    run() {
        // 执行,并且创建模块的依赖关系
        // 从入口开始执行
        this.buildModule(path.resolve(this.root, this.entry), true) // true 表示解析的是主模块
        // 发射一个文件 打包后的文件
        this.emitFile()
    }
    // 创建模块的依赖关系
    buildModule(modulePath, isEntry) {
        // 模块的key是相对路径 value是模块中的代码,不过需要做一些替换
        // require都变成了webpack_require等
        let source = this.getSource(modulePath) // 模块内容
        // 模块id是一个相对路径 总路径 减去 rootPath
        // 总路径modulePath F:\code\note_code\webpack\webpack-dev-3\src\index.js
        // 工作路径this.root F:\code\note_code\webpack\webpack-dev-3
        let moduleName = './' + path.relative(this.root, modulePath) // ./src/index.js  模块id
        if (isEntry) { // 如果是主入口的话,记录一下主入口的id
            this.entryId = moduleName // 保存入口的名字
        }
        // path.dirname(moduleName)获取父路径 ./src/index.js -> ./src
        // 解析模块代码,替换相应的内容
        let { sourceCode, dependencies } = this.parse(source, path.dirname(moduleName))
        // 把相对路径和模块中的内容对应起来
        this.modules[moduleName] = sourceCode
    }
    // 解析文件
    // 需要把source源码进行改造 返回一个依赖列表
    // 因为每一个模块里面还可能会引另外的模块,所以需要一个依赖列表
    parse(source, parentPath) { // AST 解析语法树
        console.log(source, parentPath);
        return {}
    }
    // 发射文件
    emitFile() { }
    // 获取模块代码
    getSource(modulePath) {
        return fs.readFileSync(modulePath, 'utf8')
    }
}
module.exports = Complier总结 
这一节开始构建模块,主要做了几件事
- 读取模块代码 js- // 1. 配置文件中,拿到主入口的路径 this.buildModule(path.resolve(this.root, this.entry), true) // true 表示解析的是主模块 // 2. 从主入口开始解析,fs.readFileSync 读取源代码 getSource(modulePath) { return fs.readFileSync(modulePath, 'utf8') } // 3. 读取 let source = this.getSource(modulePath) // 模块内容
- 获取模块的id js- // 1. 工作路径 工作路径 运行 npx cheny-pack 时候的路径 this.root = process.cwd() // 2. 模块id是一个相对路径 通过总路径 减去 工作路径来获取 // 总路径modulePath F:\code\note_code\webpack\webpack-dev-3\src\index.js // 工作路径this.root F:\code\note_code\webpack\webpack-dev-3 // path.relative(this.root, modulePath) 计算出的结果为 src\index.js,所以再拼接一个 ./ let moduleName = './' + path.relative(this.root, modulePath) // ./src/index.js 模块id
- 保存主入口的id js- if (isEntry) { // 如果是主入口的话,记录一下主入口的id this.entryId = moduleName // 保存入口的名字 }
- 搭架子,分析接下来需要做的事 js- // path.dirname(moduleName)获取父路径 ./src/index.js -> ./src // 解析模块代码,替换相应的内容 let { sourceCode, dependencies } = this.parse(source, path.dirname(moduleName)) // 把相对路径和模块中的内容对应起来 this.modules[moduleName] = sourceCode // 解析文件 // 需要把source源码进行改造 返回一个依赖列表 // 因为每一个模块里面还可能会引另外的模块,所以需要一个依赖列表 parse(source, parentPath) { // AST 解析语法树 console.log(source, parentPath); return {} }- 因为原本webpack打包是自己封装的一个require方法,我们只需要往里塞内容即可。  - 我们写的require全部需要替换成 - __webpack_require__,并且路径全部变为了- ./src开头的,所以需要使用- path.dirname(moduleName)获取父路径 ./src/index.js -> ./src,接下来的事就是开始解析源码了
- 解析源码需要用到AST语法树,下一节学习 
参考 
https://www.bilibili.com/video/BV1a4411e7Bz?p=35&spm_id_from=pageDriver