前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Webpack的简单实现(手写)

Webpack的简单实现(手写)

作者头像
玖柒的小窝
修改于 2021-11-08 01:36:36
修改于 2021-11-08 01:36:36
51900
代码可运行
举报
文章被收录于专栏:各类技术文章~各类技术文章~
运行总次数:0
代码可运行

首先介绍一下## Webpack 打包原理

Webpack 的构建过程一般会分为以下几步:

  • 读取 Webpack 基础配置
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    const path = require("path")\
    module.exports = {\
        entry:"./src/index.js"\
        mode:"development"\
        output:{\
          path:path.resolve(__dirname,"./dist"),\
          filename:"bundle.js"\
        }\
    }
    
复制代码
  • 入口文件分析
    • 分析依赖模块
    • 分析内容
    • 编译内容
  • 依赖模块分析
    • 分析依赖模块是否有其他模块
    • 分析内容
    • 编译内容
  • 生成打包文件
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    // 接收一个对象参数,key 为入口文件的目录,value为一个执行入口文件里面代码的函数\
    (function (modules) {\
      // installedModules 用来存放缓存\
      const installedModules = {};\
      // __webpack_require__用来转化入口文件里面的代码\
      function __webpack_require__(moduleIid) { ... }\
      // IIFE将 modules 中的 key 传递给 __webpack_require__ 函数并返回。\
      return __webpack_require__(__webpack_require__.s = './src/index.js');\
    }({\
      './src/index.js': (function (module, exports) {\
        eval('console.log(\'test webpack entry\')');\
      }),\
    }));
复制代码

具体实现

  1. 安装相关依赖
  • @babel/parser:用于将输入代码解析成抽象语法树(AST)
  • @babel/traverse:用于对输入的抽象语法树(AST)进行遍历
  • @babel/core:babel 的核心模块,进行代码的转换
  • @babel/preset-env:可根据配置的目标浏览器或者运行环境来自动将 ES2015 + 的代码转换为 es5

使用 npm 命令安装一下: npm install @babel/parser @babel/traverse @babel/core @babel/preset-env -D

2. 读取基本配置

要读取 Webpack 的基本配置,首先我们得有一个全局的配置文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const path = require('path');\
\
module.exports ={\
    entry: "./src/index.js",\
    mode: "development",\
    output: {\
      path: path.resolve(__dirname,"./dist"),\
      filename: "bundle.js"\
    }\
}
复制代码

然后我们新建一个类,用于实现分析编译等函数,并在构造函数中初始化配置信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
\
class MiniWebpack{\
    constructor(options){\
        this.options = options;\
    }\
    // ...\
}
复制代码

3. 代码转换,获取模块信息

```我们使用 fs 读取文件内容,使用 parser 将模块代码转换成抽象语法树,再使用 traverse 遍历抽象语法树,针对其中的 ImportDeclaration 节点保存模块的依赖信息,最终使用 babel.transformFromAst 方法将抽象语法树还原成 ES5 风格的代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
parse = filename => {
    // 读取文件
    const fileBuffer = fs.readFileSync(filename, 'utf-8');
    // 转换成抽象语法树
    const ast = parser.parse(fileBuffer, { sourceType: 'module' });

    const dependencies = {};
    // 遍历抽象语法树
    traverse(ast, {
        // 处理ImportDeclaration节点
        ImportDeclaration({node}){
            const dirname = path.dirname(filename);
            const newDirname = './' + path.join(dirname, node.source.value).replace('\', '/');
            dependencies[node.source.value] = newDirname;
        }
    })
    // 将抽象语法树转换成代码
    const { code } = babel.transformFromAst(ast, null, {
        presets:['@babel/preset-env']
    });
    
    return {
        filename,
        dependencies,
        code
    }
}
复制代码

生成打包代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    return `\
    (function(graph){\
        function require(filename){\
            function localRequire(relativePath){\
                return require(graph[filename].dependencies[relativePath]);\
            }\
            const exports = {};\
            (function(require, exports, code){\
                eval(code);\
            })(localRequire, exports, graph[filename].code)\
\
            return exports;\
        }\
        \
        require('${entry}');\
    })(${graph})\
    `\
}
复制代码

输出最终文件

通过获取 this.options 中的 output 信息,将打包代码输出到对应文件中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    const { path: dirPath, filename } = output;\
    const outputPath = path.join(dirPath, filename);\
\
    // 如果没有文件夹的话,生成文件夹\
    if(!fs.existsSync(dirPath)){\
        fs.mkdirSync(dirPath)\
    }\
    // 写入文件中\
    fs.writeFileSync(outputPath, code, 'utf-8');\
}

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
手把手教你写一个迷你 Webpack
一、前言 最近正好在学习 Webpack,觉得 Webpack 这种通过构建模块依赖图来打包项目文件的思想很有意思,于是参考了网上的一些文章实现了一个简陋版本的 mini-webpack,通过入口文件将依赖的模块打包在一起,生成一份最终运行的代码。想了解 Webpack 的构建原理还需要补充一些相关的背景知识,下面一起来看看。 二、背景知识 1. 抽象语法树(AST) 什么是抽象语法树? 平时我们编写程序的时候,会经常在代码中根据需要 import 一些模块,那 Webpack 在构建项目、分析依赖的时候是
用户1097444
2022/06/29
5490
手把手教你写一个迷你 Webpack
Webpack4打包机制原理解析
webpack是一个打包模块化 JavaScript 的工具,在 webpack里一切文件皆模块,通过 Loader 转换文件,通过 Plugin 注入钩子,最后输出由多个模块组合成的文件。webpack专注于构建模块化项目。
桃翁
2019/12/04
9730
webpack打包原理 ? 看完这篇你就懂了 !
入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
null仔
2020/03/02
1.3K0
带你探究webpack究竟是如何解析打包模块语法的
在webpack中,我们发现配置我们能天然的使用esmodule这种模块化语法,那大家有没有好奇过呢?他究竟是怎么实现的呢?下面一起来探究一下,webpack究竟是怎么解析打包esmodule语法的。
用户7413032
2020/06/11
7750
带你探究webpack究竟是如何解析打包模块语法的
如何自己实现一个简单的webpack构建工具 【精读】
webpack可以说是目前最火的打包工具,如果用不好他,真的不敢说自己是个合格的前端工程师
Peter谭金杰
2019/09/04
1K0
如何自己实现一个简单的webpack构建工具    【精读】
带你秒懂 Webpack 原理
它是一个将一切资源(如scripts / images / styles/ assets)都当成模块的模块化打包工具。
前端bubucuo
2022/09/16
5520
带你秒懂 Webpack 原理
手撸webpack基础原理
根目录下创建src目录,./src/目录下创建index.js、a.js、b.js、c.js
刘嘿哈
2022/10/25
2150
【Webpack】632- 了不起的 Webpack 构建流程学习
Webpack 是前端很火的打包工具,它本质上是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 Webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有模块打包成一个或多个 bundle。
pingan8787
2020/06/24
1K0
动手实现一个简易的webpack
npm install --dev-save @babel/core @babel/preset-env @babel/traverse babylon magic-string
疯狂的技术宅
2020/11/17
3850
动手实现一个简易的webpack
面试官:webpack原理都不会?
前一段时间我把webpack源码大概读了一遍,webpack 到4.x版本后,其源码已经比较庞大,对各种开发场景进行了高度抽象,阅读成本也愈发昂贵。
前端森林
2020/08/11
6270
面试官:webpack原理都不会?
webpack打包原理分析和实现(三)
代码生成了,但是里面有require函数,exports浏览器是不认识的,因此接下来需要实现require和exports 具体步骤:
kiki.
2022/09/29
2980
手写webpack核心原理,再也不怕面试官问我webpack原理
我们创建了add.js文件和minus.js文件,然后 在index.js中引入,再将index.js文件引入index.html。
coder_koala
2020/08/27
1.7K0
手写webpack核心原理,再也不怕面试官问我webpack原理
从零实现简易版Webpack 什么是bundlerBundler实现思路实现bundler
市面上现在有很多bundler,最著名的就是webpack,此外常见的还有 browserify,rollup,parcel等。虽然现在的bundler进化出了各种各样的功能,但它们都有一个共同的初衷,就是能给前端引入模块化的开发方式,更好的管理依赖、更好的工程化。
MudOnTire
2020/05/12
1K0
从零实现简易版Webpack
                            什么是bundlerBundler实现思路实现bundler
6-4~7 Bundler 源码编写
我们获取到了文本以后,如果直接就拿来分析依赖当然也可以,但是处理起来非常麻烦,效率也低下,尤其是文件内容复杂的时候。所以我们需要将文本转化为 js 可直接操作的对象 ast。 前面我们讲到了 babel,它可以将 js 源文件根据我们的需要做内容变更,比如将我们的 es6 编写的源文件转成 es5,其实就是将我们的源文件内容先转为 ast 再去实现后续变更的。它有一个专门负责转换的模块,叫做 baben/parser,前身是 babylon。
love丁酥酥
2020/06/08
5030
6-4~7 Bundler 源码编写
手把手教你撸一个简易的 webpack
随着前端复杂度的不断提升,诞生出很多打包工具,比如最先的grunt,gulp。到后来的webpack和Parcel。但是目前很多脚手架工具,比如vue-cli已经帮我们集成了一些构建工具的使用。有的时候我们可能并不知道其内部的实现原理。其实了解这些工具的工作方式可以帮助我们更好理解和使用这些工具,也方便我们在项目开发中应用。
muwoo
2018/06/11
1.2K1
手把手教你撸一个简易的 webpack
webpack 基础知识整理
webpack是一个 模块打包工具,支持所有的打包语法,比如 ES Module、CommonJS、CMD、AMD。初期的webpack是用来模块打包js的,发展到现在,已经可以打包很多种文件类型,比如 css、img 。
神葳
2021/01/22
1.4K0
[ Webpack ] 实现一个 mini 版的 webpack
Vite 的发布是不是意味着 webpack 的终结?当然不是, webpack 存在这么多年是解决了不少奇奇怪怪的问题而且也适合处理那些深度复杂的场景,这一点 Vite 肯定是还有些距离的,而且尤雨溪在前不久的直播中针对 Vite 做了解释,他说到 Vite 的设计初衷就是为了改善开发时的反馈速度,是改善体验而不是干掉 webpack 。
GavinUI
2021/05/30
9190
[ Webpack ] 实现一个 mini 版的 webpack
手摸手实现一个webpack
在平时的工作和学习过程中,webpack 是一个重要的知识点,本文通过分析 webpack 的打包原理,最终带大家实现一个简易版的 webpack。
astonishqft
2022/05/10
4050
webpack原理实战笔记
爱学习的前端歌谣
2023/10/19
1550
webpack原理实战笔记
Webpack 原理—如何实现代码打包
👆 这是第 122 篇不掺水的原创,想要了解更多,请戳上方蓝色字体:政采云前端团队 关注我们吧~ 本文首发于政采云前端团队博客:Webpack 原理—如何实现代码打包 https://zoo.team/article/webpack-reason 前言 作为一个前端“攻城狮”,Webpack 再熟悉不过了,Webpack 能做的事太多了,可以将所有资源(包括 JS,TS,JSX,图像,字体和 CSS 等)打包后置于依赖关系中,使你可以按照需求引用依赖来使用资源。Webpack 很出色的完成了转译前端多
政采云前端团队
2021/11/19
5910
相关推荐
手把手教你写一个迷你 Webpack
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文