我自己学习webpack
已有很长时间了,但是经常会遇到这样的问题: 可以熟练配置webpack
的一些常用配置,但是对一些不常见的api
或者概念总是云里雾里。因此,对着网上资料手写了一个简易版的webpack
,现在对其中的依赖图谱收集部分进行梳理,搞清楚webpack
是如何进行打包的。
打包流程
获取入口文件
根据 webpack.config.js
配置文件 的 entry
属性获取入口文件的绝对路径
getEntry() {let entry = Object.create(null)const { entry: optionsEntry } = this.optionsif (typeof optionsEntry === 'string') {entry['main'] = optionsEntry} else {entry = optionsEntry}// 将entry变为绝对路径Object.keys(entry).forEach(key => {const value = entry[key]if (!path.isAbsolute(value)) {// 转化为绝对路径的同时统一路径分隔符为 /entry[key] = toUnixPath(path.join(this.rootPath, value))}})return entry
}
编译入口文件
编译入口文件主要是要分析入口文件依赖了哪些模块,然后继续递归编译依赖的模块。
buildEntryModule(entry) {Object.keys(entry).forEach(entryName => {const entryPath = entry[entryName]// 编译入口文件const entryObj = this.buildModule(entryName, entryPath)// 每个文件都是一个模块对象this.entries.add(entryObj)})
}
buildModule(moduleName, modulePath) {// 1. 读取文件原始代码const originSourceCode = (this.originSourceCode = fs.readFileSync(modulePath,'utf-8'))// moduleCode为修改后的代码,现在赋初始值this.moduleCode = originSourceCode// 2. 调用loader进行处理this.handleLoader(modulePath)// 3. 调用webpack进行模块编译,获得最终的module对象const module = this.handleWebpackCompiler(moduleName, modulePath)// 4. 返回modulereturn module
}
编译的工作主要