可以使用 npx my-pick 命令后,我们就可以在 my-pick 中编写自己的 webpack:
webpack.config.js 中导出的是一个对象,这个对象是 webpack 的配置参数。说白了,导出对象的入口 出口 module plugins… 什么的 全是 webpack 参数中的其中一个。那 webpack 就可以理解为一个很大的函数,把参数传递进去 返回结果。
1 在 bin 同级目录 创建 lib 目录,用来存放打包的核心的配置文件 -> mkdir lib -> cd /lib -> touch Compiler.js
2 在 my-pick.js 中引入 webpack.config.js 的配置
#! /usr/bin/env node
let path = require(‘path’);
let config = require(path.resolve(‘webpack.config.js’));
let Compiler = require(‘../lib/Compiler’);
let compiler = new Compiler(config);
compiler.run();
在 my-pick.js 中,首先通过 path 模块引入了 webpack.config.js,其次 又引入了 lib/Compiler.js, 不难发现,Compiler 是一个类,并且通过 new,new 出了 Compiler 的实例对象 compiler。最后执行 compiler 的 run()方法。3 接下来就要在 lib/Compiler.js 中新建 Compiler 类
let path = require(‘path’);
let fs = require(‘fs’);
class Compiler{
constructor(config){
this.config = config;
this.entry = config.entry;
this.entryId = ”;
this.modules = {};
this.rootPath = process.cwd();
}
run(){
this.buildModule(path.reaolve(this.rootPath,this.entry),true);
this.emit();
}
buildModule(modulePath, isEntry){
}
emit(){
}
}
module.exports = Compiler;
constructor 中传入了刚才获取到的 webpack.config.js 的配置对象 config,拿到配置中的入口 entry,entryId 用来存放主入口,modules 对象用来存放依赖 key 和源码 value,rootPath 是当前工作路径,类似于 dirname。原型上添加了 run 方法,run 方法内部又执行了 buildModule()和 emit()方法。buildModule 方法的作用是通过传入的路径,获取到文件源码,解析模块之间的依赖 (不是它的主要作用)。emit 方法作用是把最后解析好的源码和依赖关系发射出去。下面开始写 buildModule() 方法:
let path = require(‘path’);
let fs = require(‘fs’);
class Compiler{
constructor(config){
this.config = config;
this.entry = config.entry;
this.entryId = ”;
this.modules = {};
this.rootPath = process.cwd();
}
run(){
this.buildModule(path.resolve(this.rootPath,this.entry),true);
this.emit();
}
buildModule(modulePath, isEntry){
let source = this.getSource(modulePath);
let moduleName = ‘./’+path.relative(this.rootPath,modulePath);
if(isEntry){this.entryId = moduleName};
let {sourceCode, dependencies} = this.parse(source, path.dirname(moduleName));
}
getSource(sourcePath){
return fs.readFileSync(sourcePath,’utf8′);
}
emit(){
}
}
module.exports = Compiler;
buildModule()传入了两个参数。第一个参数是文件的路径,在本次代码中是主入口路径,但是之后不一定是主入口的路径。第二个参数是判断该路径是否为主入口的表示,true 表示是主入口,false 表示不是主入口。很显然,本次调用的 buildModule()函数是主入口,所以第二个参数传递的是 true。buildModule 函数第一行表示根据路径获取到源码,根据单独写的 this.getSource()方法。第二行是把传入的绝对路径转换为相对路径。第三行是判断是否是主入口,是的话就把该路径保存到主入口 entryId 中。第四行中又多了一个 parse()方法,parse()方法返回了源码 sourceCode 和依赖 dependencies。它是核心方法,这个函数传入了源码和路径,注意这个路径是父级路径,path.dirname()。比如 原路径是‘./src/index.js’, 父路径就是 ’./src’。为什么这样写,待会在 parse()中会体现出来。
未完待续 …