手写mini-webpack

    之前我们已经基于webpack是实现了一个简易的cli工具,这一节更加深入一点,研究下打包工具本身又是个啥

目标

    写一个打包工具,能实现打包,支持热更新

理论基础

    浏览器对esm模块的原生支持

思路

    打包:将使用了不同的模块规范的代码处理成esm格式

    本地服务:启一个node服务,监听发出的路由请求并作转换处理

    热更新:建立一个soket连接,实时监听文件变更(chokidar),并发送到浏览器客户端,客户端接收到更新提示后reload页面

依赖

    esno  用于将代码转为esm格式

    minimist  用于解析命令行

    ws  用于建立websocket链接

    koa  用于启一个node服务

    chokidar  用于监听文件修改

打包

    提供配置文件su.config.json,默认的打包入口entry为''./index.js",默认打包出口output为"./dist",可以配置clean在打包前先清空dist文件

    读取启动命令参数,默认执行打包

    如果配置了clean为true,则将dist文件清空后再调用esbuild模块的build方法进行打包

本地开发环境

    理论基础:浏览器解析到script标签后会发起请求下载src对应的文件,link亦然

    目标:将cra初始化的项目首页跑起来

    将入口修改为target下的main.jsx,并新增dev属性,指定服务的端口

    新增if分支,执行dev文件,在该文件中处理本地服务器代码

    根据配置的端口启一个node服务,并监听服务下的根路径,将index.html文件返回客户端

(指定type=module后,引入的文件将被支持import语法)

    浏览器在解析html文件时,遇到script标签时,将会根据src地址拉取对应的文件,如下

    监听根目录下的请求并做处理

        处理jsx文件

            I-文件引入的有两种,一种是以'.'或'..'开头的从当前文件下引入,一种则是从node_modules中引入。对于前者是可控的,对于后者则不能保证一定是esm模块的文件,就比如react遵循的就是cjs

(我们先通过 esbuild 的 transformSync 方法将jsx转成js;接着替换引入路径,以 @ from_node_modules 作标识;最后将\替换成/,否则是不认识的)

            这一步完成后,打开浏览器,可以看的已经被替换

            II-监听@ from_node_modules路由,并对其对应的文件做打包处理后放置到.cache目录,并从中读取(来自node_modules的文件通常具有极高的稳定性)

(其实一开始我是使用的 transformSync ,并不生成.cache文件,但是这样转出来的结果对于代码中的require未被正确转换处理,找了一圈文档也没看出个所以然来)

                若我们的main.jsx如下

                则执行后target目录下会多出.cache目录,分别对应react和react-dom

            当浏览器解析到import时就会尝试去拉取代码这两个文件    

            此时页面将被正确渲染

        处理css文件

            I-不能像这样返回

        II-我们指定,当使用import '路径时',浏览器会对文件进行执行。因此可以手动拼上export default,并将css样式添加到style中

            此时的页面效果如下

(需要使用类组件,函数组件内使用hooks报错了,具体我也不清楚为啥)

    处理svg文件

        由于svg是浏览器本身支持的文件,故可以直接从target下读取

        I-当执行到App.jsx时,遇到svg,打一个tag

        II-当浏览器解析到时,发起请求下载资源,在node中监听并处理

        III-当浏览器解析到img标签时,会根据src发起资源请求,在node中监听并返回给img

            效果如下

热更新

    I-若想实现与浏览器客户端建立socket通信,需要在客户端发起socket连接,这总是不太合适让用户自己建立一个socket文件的。故,自己塞一个给浏览器

        II-在node服务中创建一个socket服务,并使用chokidar监听target下的文件变动,当存在文件变动 时通知客户端

        III-在client.js中连接socket,当接收到文件变动通知时,刷新页面

(端口必须一致)

    esbuild

    websocket

    chokidar

    compression

    connect-history-api-fallback

你可能感兴趣的:(手写mini-webpack)