【敲黑板】手把手带你写一个简易版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.jsimport 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 babylonmywebpack.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/
关注网络尖刀微信公众号随时掌握互联网精彩
- 闲鱼iOS版禁止搜索腾讯视频和游戏充值等虚拟商品 但仍可以通过淘宝跳转
- 卢布汇率人民币2024年7月24日
- 2024中国移动算力网络大会即将盛大开幕!
- 韩币对人民币汇率2023年5月7日
- 美国将与日本、荷兰讨论对华芯片限制措施
- 校园招聘丨统信软件2023届研发专场空中宣讲会10月20日来袭
- 2022年死掉的互联网产品,有眼熟的吗?
- Q2全球蜂窝物联网模组出货量同比增长20% 中国厂商包揽前六
- 美财长耶伦称美希望停止过度依赖中国稀土元素
- 世界上第一个街机游戏;武汉大学建校;真空管的发明者诞生| 历史上的今天
- 一年一度,亚马逊 12~18 TB 西部数据硬盘降价啦
- 没有参考答案的5G,在发牌两年后道路愈发清晰
赞助链接



微信扫码关注公众号