1.bundle和 bundless [vite-my]
bundle打包: webpack 基于模块化规范,依赖分析完毕后构建依赖图,再转换打包成一个或多个文件。
2. vite如何做到bundless?
前置条件:模块化规范有 CommonJS , AMD, UMD,CMD ,ESM
正是有了基于现代浏览器的ESM 模块化支持,才有了bundless方案; 不用构建依赖图,实现按需加载依赖。
浏览器三大件 浏览器只认识html,js,css, 而jsx,ts,tsx,vue等文件浏览器不认识,如何处理 交由开发服务器处理:
产物构建过程:不依赖打包工具,而是依赖于编译工具 在webpack中编译最常使用工具为babel。 在vite中
1.开发环境:使用 esbuild[基于go语音] 处理 jsx,ts,tsx,vue
2.生成环境: 使用rollup [基于rust] 作为编译打包工具
Vite 目前的插件 API 与使用 esbuild
作为打包器并不兼容。尽管 esbuild
速度更快,但生产环境下 Vite 采用了 Rollup 灵活的插件 API 和基础建设.未来会接入Rolldown
3.实践部分:compiler server 实现
3.1.可以支持在home页以 type='module',让浏览器接管 模块化的加载【以http请求的方式】
依赖引用关系
index.html ->index.js->utils.js->math.ts;
可以看到 浏览器是根据import的情况依次发送请求的,也就不用像以前必须先构建依赖图打包完成后再启动务。浏览已经接管了模块依赖加载的部分工作。
3.2.语法转换,esm 是发送请求动态加载模块,因此可以提供本地sever拦截请求,根据不同文件类型使用不同的转换过程【这个过程类似于vite插件】这个是一个非常简单的vite实现,但最本质的原理已然显露
const express = require('express');
const app = express();
const port = 5000;
const esbuild=require('esbuild');
const fs=require('fs');
//可以定义存放插件容器
const plginContainner =[]
//绑定端口
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
// 定义一个中间件函数,用于拦截所有请求
const interceptAllRequests = (req, res, next) => {
console.log(` intercepted request for ${req.url}`);
// 可以在这里对请求进行一些预处理,比如验证、日志记录等
const path=req.path;
if(path=="/"){
res.type="text/html";
res.sendFile(__dirname+"/src/index.html");
}
//依次调用插件方法todo
// plginContainner.forEach(plugin=>{
// plugin?.transformer()
//})
if(path.endsWith(".js")){
res.type="text/javascript";
res.sendFile(__dirname+"/src"+req.path);
}
if(path.endsWith(".ts")){
const fileCode=fs.readFileSync(__dirname+"/src"+req.path,'utf-8')
// 使用esbuild进行编译转换
const result=esbuild.transformSync(fileCode,{loader:'ts',target:'es6',format:'esm'})
res.setHeader('Content-Type', 'application/javascript');
res.end(result.code, 'utf-8');
}
//....其他如jsx /vue 使用不通的转换过程每个转换过程类似一个插件,如vite-plugin-vue
//...构建过程还需加入 tree shaking,和代码分割等优化代码体积和数量
// next();发送响应即调用了一次,不要重复调用
};
app.use(interceptAllRequests);