理解webpack原理,手写一个100行的webpack

什么是webpack

它是一个模块打包器,也能够引用官网的一幅图解释,咱们能够看到webpack,能够分析各个模块的依赖关系,最终打包成咱们常见的静态文件,.js 、 .css 、 .jpg 、.png。今天咱们先不弄那么复杂,咱们就介绍webpack是怎么分析ES6的模块依赖,怎么把ES6的代码转成ES5的。css

实现

因为ES6转ES5中须要用到babel,因此要用到一下插件webpack

npm install @babel/core @babel/parser @babel/traverse @babel/preset-env --save-devgit

须要的文件

使用webpack确定少不了原文件,咱们会涉及三个须要打包的js文件(entry.jsmessage.jsname.jsgithub

// entry.js

import message from './message.js';
console.log(message);
复制代码
// message.js

import {name} from './name.js';
export default `hello ${name}!`;
复制代码
// name.js

export const name = 'world';
复制代码
//bundler.js 
// 读取文件信息,并得到当前js文件的依赖关系
function createAsset(filename) {//代码略}
// 从入口开始分析全部依赖项,造成依赖图,采用广度遍历
function createGraph(entry) {//代码略}
// 根据生成的依赖关系图,生成浏览器可执行文件
function bundle(graph) {//代码略}
复制代码

entry.js 就是咱们的入口文件,文件的依赖关系是,entry.js依赖message.jsmessage.js依赖name.jsweb

bundler.js 是咱们简易版的webpacknpm

目录结构数组

- example
    - entry.js
    - message.js
    - name.js
- bundler.js
复制代码

如何分析依赖

webpack分析依赖是从一个入口文件开始分析的,当咱们把一个入口的文件路径传入,webpack就会经过这个文件的路径读取文件的信息(读取到的本质实际上是字符串),而后把读取到的信息转成AST(抽象语法树),简单点来讲呢,就是把一个js文件里面的内容存到某种数据结构里,里面包括了各类信息,其中就有当前模块依赖了哪些模块。咱们暂时把经过传文件路径能返回文件信息的这个函数叫 createAsset浏览器

createAsset返回什么

第一步咱们确定须要先从 entry.js 开始分析,因而就有了以下的代码,咱们先不关心createAsset具体代码是怎么实现的,具体代码我会放在最后。bash

createAsset("./example/entry.js");
复制代码

当执行这句代码,createAsset 会返回下面的数据结构,这里包括了模块的id文件路径依赖数组entry.js依赖了message.js,因此会返回依赖的文件名),code(这个就是entry.js ES6转ES5的代码) babel

经过 createAsset 咱们成功拿到了 entry.js的依赖,就是 dependencies 数组。

createGraph返回什么,如何找下一个依赖

咱们经过上面能够拿到entry.js依赖的模块,因而咱们就能够接着去遍历dependencies 数组,循环调用createAsset这样就能够获得所有模块相互依赖的信息。想获得所有依赖信息须要调用 createGraph 这个一个函数,它会进行广度遍历,最终返回下面的数据

咱们能够看到返回的数据,字段以前都和你们解释了,除了 mappingmapping这个字段是把当前模块依赖的文件名称 和 模块的id 作一个映射,目的是为了更方便查找模块。

bundle返回什么 && 最后步骤

咱们如今已经能拿到每一个模块以前的依赖关系,咱们再经过调用bundle函数,咱们就能构造出最后的bundle.js,输出以下图

源码

点击查看源码

最后

文章可能有不足的地方,请你们见谅,若是有什么疑问能够下方留言讨论。

若是你们对文字描述仍是不太清楚,建议看我下方提供的视频,我就是从视频中学的,这个是在youtube上的视频,你们懂的,有条件的仍是建议看一下。😝

官方40分钟教你写webpack