实现一个简易版webpack
现实 webpack 的打包产物
大概长这样(只把核心代码留下来):

实现一个简版的webpack
依葫芦画瓢,实现思路分2步:
1. 分析入口文件,把所有的依赖找出来(包括所有后代的依赖)
2. 拼接出类似上面的立即执行函数
找依赖
const fs = require('fs');
const path = require('path');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const { transformFromAST } = require('@babel/core');
// 分析一个文件,转成CommonJS Module,并找出它的依赖
function readCode(filePath) {
// 读取文件字符串
const content = fs.readFileSync(filePath, 'utf-8');
// 语法解析成 AST
const ast = parser(content, {
sourceType: 'module'
})
// 获取本文件的依赖
const dependiences = [];
// 遍历 AST,每当触发依赖钩子,就往依赖数组添加
traverse(ast, {
ImportDeclaration({node}) {
// 把对应的以来路径存起来
dependiences.push(node.source.value)
}
})
// 把 es6 转成 es5 字符串
// 最重要的是把 esModule 的 import export,转成 es5 能认识的 commonJs写法
const { code } = transformFromAST(ast, null, {
presets: ['@babel/preset-env']
})
return {
filePath,
code,
dependiences
}
}
// 广度优先算法,深入找出所有的依赖
function getAllDependencies(filePath) {
const entryObj = readCode(filePath);
const dependencies = [entryObj];
for (const dependency of dependencies) {
const curDirname = path.dirname(dependency.filePath)
for (const relativePath dependency.dependencies) {
const absolutePath = path.join(curDirname, relativePath);
const child = readCode(absolutePath);
child.relativePath = relativePath;
dependencies.push(child);
}
}
return dependencies;
}
ps: 我们用的是babel的配套工具来做语法分析和转化,但是真正的webpack用的是webassemblyjs的配套工具

拼写立即执行函数
function bundle(fileName) { const dependencies = getAllDependencies(fileName); const modulesStr = ''; dependencies.forEach(dependency => { const key = dependency.relativePath || dependency.filePath; modulesStr += `'${key}': function(module, exports, require) { ${ dependency.code } }` }) return `(function(modules) { const installedModules = {}; function require(id) { // 解决循环依赖 if (installedModules[id]) { return installedModules[id].exports; } var module = installedModules[id] = {exports: {}}; modules[id].call(module.exports, module, module.exports, require); return module.exports; } return require('${fileName}') })({${modulesStr}})` }

浙公网安备 33010602011771号