《vite技术揭秘、还原与实战》第7节--在svite中引入defineConfig类型辅助函数

前言

上一小节,我们发现直接引入defineConfig会导致程序报错,于是分析了产生报错的原因并查看了vite中的解决思路

本节,在svite中解决这个问题

好文推荐

源码获取

传送门

更新进度

公众号:更新至第17

博客:更新至第7

代码实现

结合上一节分析,我们知道问题出在buildBoundle函数中,并且我们已经知道了通过esbuild pluginonResolve钩子可以解决这个问题

如下,第一步我们需要对一些条件进行守卫:入口点本身、绝对路径、node内置模块

ts 复制代码
// packages\vite\src\node\config.ts
async function buildBoundle(fileName: string) {
  const result = await build({
    ...
    plugins:[{
      name: 'externalize-deps',
      setup(build) {
        build.onResolve({filter:/^[^.].*/},async ({path:id,importer,kind})=>{
            // id:导入的依赖地址,如import xxx from 'svite'语句中指的是svite
            // importer:当前正在处理的文件地址,如svite所在的文件地址为playground\config\svite.config.ts
            // kind:导入的类型,如entry-point表示导入入口点;entry-point表示导入依赖
            if (kind === "entry-point" || isAbsolute(id) || isBuiltin(id)) {
                return;
            }
            return {
                path:analizePathValue(id,importer,kind),
                external:true
            }
        })
      }
    }]
  });
  const { text } = result.outputFiles[0];
  return text;
}

当程序通过if守卫条件后,则说明命中了裸依赖,在我们的svite.config.ts文件中即指命中了svite。此时通过将钩子返回的对象的external设置为true从而将依赖从boundle中排除则能有效避免上一小节中我们遇到的报错问题:Dynamic require of "fs" is not supported

由于我们跳过了svite的处理,则最终代码里将无法找到defineConfig而引发报错,为了解决这个问题,我们要将导入的路径替换为绝对路径,这样node就能正确加载啦

因此我们的关键点就是去生成path的值来对引入模块路径做替换,即analizePathValue是如何实现的

ts 复制代码
function analizePathValue(id: string, importer: string, kind: string) {
  ...
}

想要实现这一点,我们需要从包的元数据中找相关的定义,即packages\vite\package.json中与模块引入相关的字段

json 复制代码
{
  "main": "./dist/node/index.js",
  "types": "./dist/node/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/node/index.d.ts",
      "import": "./dist/node/index.js"
    }
  }
}

vite中是自己去读取该json文件并对导出字段做比对的,且针对svite/xxx的形式也需要做额外的兼容处理。这里我们借助local-pkg来达到同样的目的

js 复制代码
pnpm i local-pkg

该包提供的resolveModule函数会自动帮我们完成路径的识别和转换工作,当然,我们要先判断对应的依赖包是否存在,当获取到路径之后,还需要通过node内置的pathToFileURL将其转换为URL路径

ts 复制代码
if (isPackageExists(id)) {
  const fileUrl = resolveModule(id);
  if (fileUrl) {
    return pathToFileURL(fileUrl).href;
  }
}

如果你是跟着笔者一起实现的话,当你运行的时候,你会得到如下的错误

txt 复制代码
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in C:\Users\11574\Desktop\git\mini-vite\node_modules\svite\package.json

这是因为resolveModule本质上是cjs的导入方式,而我们一开始在创建项目时缺少了对require的支持,为因此,需要找到packages\vite\package.json文件的exports并增加如下代码

json 复制代码
{
  "exports": {
    ".": {
      ...
      "require":"./dist/node/index.js"
    }
  },
}

设置好后,再次启动,程序正常运行即可

总结

本小节,依据上一节的分析思路解决了svite中引入ts辅助函数的报错问题,其实就是在打包处理该配置文件时将引入排除就可以了

相关推荐
字节颤抖1 天前
vite+vue3开发uni-app时低版本浏览器不支持es6语法的问题排坑笔记
前端·uni-app·es6·vue3·vite·babel·兼容
engchina2 天前
使用 Vite + React 19 集成 Tailwind CSS 与 shadcn/ui 组件库完整指南
css·react.js·ui·vite·tailwind·react 19·shadcn
minko3 天前
这给我干哪儿来了,这还是react-router吗
react.js·vite
cs_dn_Jie8 天前
uniapp + vite + 使用多个 ui 库
vue.js·ui·uni-app·vite
PBitW13 天前
vue3+vite+eslint|prettier+elementplus+国际化+axios封装+pinia
vue.js·vite·eslint·prettier·vue3+vite·eslint+prettier
程序猿000001号17 天前
Vite:现代前端开发的利器
前端·vite
漂流瓶jz1 个月前
谈一谈前端构建工具的本地代理配置(Webpack与Vite)
前端·webpack·node.js·vite·proxy·代理
柠檬豆腐脑1 个月前
前端构建工具的发展和现状:Webpack、Vite和其他
前端·webpack·vite
起来改bug1 个月前
vite5.x配置https
https·vite
WEB前端圈1 个月前
【bug修复系列】package.json中“type”: “module”的作用,解决明明是ES module却报是CommonJS的问题
json·bug·vite