现实 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}})`
}

实现一个简易版webpack的更多相关文章

  1. .NET Core的文件系统[5]:扩展文件系统构建一个简易版“云盘”

    FileProvider构建了一个抽象文件系统,作为它的两个具体实现,PhysicalFileProvider和EmbeddedFileProvider则分别为我们构建了一个物理文件系统和程序集内嵌文 ...

  2. 依赖注入[5]: 创建一个简易版的DI框架[下篇]

    为了让读者朋友们能够对.NET Core DI框架的实现原理具有一个深刻而认识,我们采用与之类似的设计构架了一个名为Cat的DI框架.在<依赖注入[4]: 创建一个简易版的DI框架[上篇]> ...

  3. 依赖注入[4]: 创建一个简易版的DI框架[上篇]

    本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章(<控制反转>.<基于IoC的设计模式>和< 依赖注入模式>)从纯理论的角度 ...

  4. .NET CORE学习笔记系列(2)——依赖注入[4]: 创建一个简易版的DI框架[上篇]

    原文https://www.cnblogs.com/artech/p/net-core-di-04.html 本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章从 ...

  5. 手动实现一个简易版SpringMvc

    版权声明:本篇博客大部分代码引用于公众号:java团长,我只是在作者基础上稍微修改一些内容,内容仅供学习与参考 前言:目前mvc框架经过大浪淘沙,由最初的struts1到struts2,到目前的主流框 ...

  6. 如何实现一个简易版的 Spring - 如何实现 Setter 注入

    前言 之前在 上篇 提到过会实现一个简易版的 IoC 和 AOP,今天它终于来了...相信对于使用 Java 开发语言的朋友们都使用过或者听说过 Spring 这个开发框架,绝大部分的企业级开发中都离 ...

  7. 如何实现一个简易版的 Spring - 如何实现 Constructor 注入

    前言 本文是「如何实现一个简易版的 Spring」系列的第二篇,在 第一篇 介绍了如何实现一个基于 XML 的简单 Setter 注入,这篇来看看要如何去实现一个简单的 Constructor 注入功 ...

  8. 如何实现一个简易版的 Spring - 如何实现 @Component 注解

    前言 前面两篇文章(如何实现一个简易版的 Spring - 如何实现 Setter 注入.如何实现一个简易版的 Spring - 如何实现 Constructor 注入)介绍的都是基于 XML 配置文 ...

  9. 使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包

    使用 js 和 Beacon API 实现一个简易版的前端埋点监控 npm 包 前端监控,埋点,数据收集,性能监控 Beacon API https://caniuse.com/beacon 优点,请 ...

随机推荐

  1. springDataRedis的小demo

    1. 导入相关的依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  2. jmeter用什么查看结果报告

    JMeter查看测试结果的方法很多,最常用的几种是:察看结果树.聚合报告.图形报表.邮件观察仪等.

  3. JavaScript的深浅复制

    JavaScript的深浅复制 为什么有深复制.浅复制? JavaScript中有两种数据类型,基本数据类型如undefined.null.boolean.number.string,另一类是Obje ...

  4. unity 3D物体使用EventSystem响应事件

    在ugui中创建一个canvas 之后会自动创建一个EventSystem,用来处理UI上的时间响应.(可以通过UI>EventSystem创建EventSystem) EventSystem ...

  5. Navicat中文破解版(windows10)

    1.下载安装包 链接:https://pan.baidu.com/s/1hP3cD9aTv8nvJfNwjXPdrQ 提取码:xmsu 2.解压安装包  选择.exe 文件然后 安装 选择自己要安装的 ...

  6. CentOS 7.x 配置静态 IP 并启用

    centos 7.x 配置静态 IP 并启用 0 问题由来 通过查询本机的IP,发现本机并没有有效IP: [pan@localhost ~]$ ip addr 所以,我们需要设置本机的静态IP,并启用 ...

  7. zabbix Server 4.0 监控JMX监控详解

    zabbix Server 4.0 监控JMX监控详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   大家都知道,zabbix server效率高是使用C语言编写的,有很多应用 ...

  8. commons-io之FileUtils、IOUtils

    原文:https://blog.csdn.net/justry_deng/article/details/93616705 commons-io简单说明:Common IO 是一个工具库,用来帮助开发 ...

  9. java加密算法-MD5

    import java.security.MessageDigest; public class MD5Util { /*** * MD5加密 生成32位md5码 * @param 待加密字符串 * ...

  10. sort对二维字符数组排序

    转载:sort对二维字符数组排序