【敲黑板】手把手带你写一个简易版webpack!内附超详细分解
作者:炸鸡排我们走
来源:SegmentFault 思否社区
明确webpack实现的功能

开始开发
entry.js
import message from './message.js'
console.log(message)
message.js
import name from "./name.js"
export default `${name} is a girl`
name.js
export const name = 'Yolanda'
读取文件需要用到node的一个基础api-fs(文件系统),fs.readFileSync可以同步拿到js文件中的代码内容。
mywebpack.js
const fs = require('fs')
function creatAsset (filename){
const content = fs.readFileSync(filename,'utf-8')
console.log(content)
}
creatAsset('./source/entry.js')
node mywebpack.js
import message from './message.js';
console.log(message);
看一下entry.js文件的ast是什么?
3.2 在program的body属性里, 就是我们各种语法的描述
3.3 可以看到第一个就是 ImportDeclaration, 也就是引入的声明.
3.4 ImportDeclaration里有一个source属性, 它的value就是引入的文件地址 './message.js'
首先安装一个Babylon(基于Babel的js解析工具)
npm i babylon
mywebpack.js
const fs = require('fs');
const babylon = require('babylon');
function createAsset(filename) {
const content = fs.readFileSync(filename, 'utf-8');
const ast = babylon.parse(content, {
sourceType: 'module'
});
console.log(ast);
}
createAsset('./source/entry.js');
首先,需要遍历出ImportDeclaration节点,那就需要一个工具:babel-traverse(可以像遍历对象一样遍历ast中的节点)
npm i babel-traverse
然后利用它遍历并获取到对应节点,提供一个函数来操作此节点。
mywebpack.js
const fs = require('fs');
const babylon = require('babylon');
const traverse = require('babel-traverse').default;
function createAsset(filename) {
const content = fs.readFileSync(filename, 'utf-8');
const ast = babylon.parse(content, {
sourceType: 'module'
});
traverse(ast, {
ImportDeclaration: ({
node
}) => {
console.log(node)
}
})
}
createAsset('./source/entry.js');
可能会出现多个依赖,这里需要建一个数组存储。
mywebpack.js
const fs = require('fs');
const babylon = require('babylon');
const traverse = require('babel-traverse').default;
function createAsset(filename) {
const content = fs.readFileSync(filename, 'utf-8');
const ast = babylon.parse(content, {
sourceType: 'module'
});
const dependencies = [];
traverse(ast, {
ImportDeclaration: ({
node
}) => {
dependencies.push(node.source.value);
}
})
console.log(dependencies);
}
createAsset('./source/entry.js');
mywebpack.js
const fs = require('fs');
const babylon = require('babylon');
const traverse = require('babel-traverse').default;
let ID = 0;
function createAsset(filename) {
const content = fs.readFileSync(filename, 'utf-8');
const ast = babylon.parse(content, {
sourceType: 'module'
});
const dependencies = [];
traverse(ast, {
ImportDeclaration: ({
node
}) => {
dependencies.push(node.source.value);
}
})
const id = ID++;
return {
id,
filename,
dependencies
}
}
const mainAsset = createAsset('./source/entry.js');
console.log(mainAsset);
新建一个createGraph函数,在这个函数里引用createAsset。
同时entry这个参数是动态的,所以createGraph接收entry这个参数。
mywebpack.js - createGraph
function createGraph(entry) {
const mainAsset = createAsset(entry);
}
const graph = createGraph('./source/entry.js');
console.log(graph);
mywebpack.js - createGraph
function createGraph(entry) {
const mainAsset = createAsset(entry);
}
const graph = createGraph('./source/entry.js');
console.log(graph);
我们在dependencies中存储的都是相对路径,但是我们需要绝对路径才能拿到模块的Asset,这个时候要想办法拿到每个模块的绝对路径。
1.path.dirname(获取当前文件的路径名)
2.path.join(拼接路径)
mywebpack.js - createGraph
function createGraph(entry) {
const mainAsset = createAsset(entry);
const allAsset = [mainAsset];
for (let asset of allAsset) {
const dirname = path.dirname(asset.filename);
asset.dependencies.forEach(relativePath => {
const absoultePath = path.join(dirname, relativePath);
const childAsset = createAsset(absoultePath);
});
}
}
map可以存储模块间的依赖关系,方便后续的查找。
mywebpack.js - createGraph
function createGraph(entry) {
const mainAsset = createAsset(entry);
const allAsset = [mainAsset];
for (let asset of allAsset) {
const dirname = path.dirname(asset.filename);
asset.mapping = {};
asset.dependencies.forEach(relativePath => {
const absoultePath = path.join(dirname, relativePath);
const childAsset = createAsset(absoultePath);
asset.mapping[relativePath] = childAsset.id;
});
}
}
关注公众号:拾黑(shiheibook)了解更多
赞助链接:
关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

随时掌握互联网精彩
- ScreenToGif功能强大的屏幕录制和动画编辑工具
- 打造数字化核心引擎,中国移动磐维数据库2.0重磅发布
- 卢布汇率人民币2023年6月16日
- GPT-4 震撼发布,能读图,考高分,训练更高效
- 【制造业成功案例】无人工厂的下一步,排产也能“无人化”?
- 社区精选|世界杯火热进行中, 用一个div画个足球场助助兴
- 华为汪涛:持续创新,全面迈向5.5G时代
- 俄乌冲突中的无人机运用
- PPT 模板插件 iSlide 5 周年回馈,买两年送一年,每月不到 5 块钱
- 消息称iPhone 13零部件已到货;FTC起诉Facebook垄断被驳回;软银机器人业务裁员|Do早报
- 【周末荐书】掌控工作:从有序中获得效率
- 大国竞争中,3个关键新兴信息技术
赞助链接