webpack 实现
这是一个如何实现一个简单的webpack生成bundle.js的demo, 主要的实现流程:
入口entry -> 递归解析AST获取依赖 -> 生成依赖图
-> 为每个模块包裹factory function -> 以入口脚本为起点,递归执行模块 -> 拼接IIFE(factory, require实现) -> 产出bundle
另外需要用到以下插件:
- @babel/parser 用于分析源代码,产出 AST;
- @babel/traverse 用于遍历 AST,找到 import 声明;
- @babel/core 用于编译,将源代码编译为 ES5;
- @babel/preset-env 搭配@babel/core使用;
- resolve 用于获取依赖的绝对路径。
全局配置
1 | const fs = require("fs"); |
生成依赖图
1 | /** |
对依赖图谱进行处理生成IIFE
1 | /** |
webpack loader 和 plugin
下面再写一下简单的实现一个loader 和 plugin
代码地址如下
webpack hmr
基本实现原理大致这样的,构建 bundle 的时候,加入一段 HMR runtime 的 js 和一段和服务沟通的 js 。文件修改会触发 webpack 重新构建,服务器通过向浏览器发送更新消息,浏览器通过 jsonp 拉取更新的模块文件,jsonp 回调触发模块热替换逻辑。
服务端主要使用了: webpack, express, websocket
使用express启动本地服务,当浏览器访问资源时对此做响应
服务端和客户端使用websocket实现长连接webpack监听源文件的变化,即当开发者保存文件时触发webpack的重新编译
每次编译都会生成hash值、已改动模块的json文件、已改动模块代码的js文件
编译完成后通过socket向客户端推送当前编译的hash戳客户端的websocket监听到有文件改动推送过来的hash戳,会和上一次对比
一致则走缓存,不一致则通过ajax和jsonp向服务端获取最新资源使用内存文件系统去替换有修改的内容实现局部刷新
具体步骤如下:
启动webpack-dev-server服务器
创建webpack实例
创建Server服务器
添加webpack的done事件回调
编译完成向客户端发送消息
创建express应用app
设置文件系统为内存文件系统
添加webpack-dev-middleware中间件
中间件负责返回生成的文件(生成hash值、已改动模块的json文件、已改动模块代码的js文件)
启动webpack编译
创建http服务器并启动服务
使用sockjs在浏览器端和服务端之间建立一个 websocket 长连接
创建socket服务器
客户端具体步骤(客户端bundles.js内被webpack处理后加入了一段websocket客户端代码)
webpack-dev-server/client端会监听到此hash消息
客户端收到ok的消息后会执行reloadApp方法进行更新在reloadApp中会进行判断,是否支持热更新,如果支持的话发射webpackHotUpdate事件,如果不支持则直接刷新浏览器
在webpack/hot/dev-server.js会监听webpackHotUpdate事件
在check方法里会调用module.hot.check方法
HotModuleReplacement.runtime请求Manifest
它通过调用 JsonpMainTemplate.runtime的hotDownloadManifest方法
调用JsonpMainTemplate.runtime的hotDownloadUpdateChunk方法通过JSONP请求获取到最新的模块代码补丁JS取回来后会调用JsonpMainTemplate.runtime.js的webpackHotUpdate方法
然后会调用HotModuleReplacement.runtime.js的hotAddUpdateChunk方法动态更新模块代码
然后调用hotApply方法进行热更新