这篇文章主要讲解了“怎么手写vite插件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么手写vite插件”吧!
1. 什么是 vite 插件
vite 其实就是一个由原生 ES Module 驱动的新型 Web 开发前端构建工具。
vite 插件 就可以很好的扩展 vite 自身不能做到的事情,比如 文件图片的压缩、 对 commonjs 的支持、 打包进度条 等等。
2. 为什么要写 vite 插件
相信在座的每位同学,到现在对 webpack 的相关配置以及常用插件都了如指掌了吧;
vite 作为一个新型的前端构建工具,它还很年轻,也有很多扩展性,那么为什么我们不趁现在与它一起携手前进呢?做一些于你于我于大家更有意义的事呢?
要想写一个插件,那必须从创建一个项目开始,下面的 vite 插件通用模板 大家以后写插件可以直接clone使用;
插件通用模板 github:体验入口
插件 github:体验入口
建议包管理器使用优先级:pnpm > yarn > npm > cnpm
长话短说,直接开干 ~
创建 vite 插件通用模板
1. 初始化
1.1 创建一个文件夹并且初始化:初始化按照提示操作即可
mkdir vite-plugin-progress && cd vite-plugin-progress && pnpm init
1.2 安装 typescript
pnpm i typescript @types/node -D
1.3 配置 tsconfig.json
{ "compilerOptions": { "module": "ESNext", "target": "esnext", "moduleResolution": "node", "strict": true, "declaration": true, "noUnusedLocals": true, "esModuleInterop": true, "outDir": "dist", "lib": ["ESNext"], "sourceMap": false, "noEmitOnError": true, "noImplicitAny": false }, "include": [ "src total?: number; format?: string; }>;export default function viteProgressBar(options?: PluginOptions): PluginOption { const { cacheTransformCount, cacheChunkCount } = getCacheData() let bar: progress; const stream = options?.stream || process.stderr; let outDir: string; let transformCount = 0 let chunkCount = 0 let transformed = 0 let fileCount = 0 let lastPercent = 0 let percent = 0 return { name: 'vite-plugin-progress', enforce: 'pre', apply: 'build', config(config, { command }) { if (command === 'build') { config.logLevel = 'silent'; outDir = config.build?.outDir || 'dist'; options = { width: 40, complete: '\u2588', incomplete: '\u2591', ...options }; options.total = options?.total || 100; const transforming = isExists ? `${colors.magenta('Transforms:')} :transformCur/:transformTotal | ` : '' const chunks = isExists ? `${colors.magenta('Chunks:')} :chunkCur/:chunkTotal | ` : '' const barText = `${colors.cyan(`[:bar]`)}` const barFormat = options.format || `${colors.green('Bouilding')} ${barText} :percent | ${transforming}${chunks}Time: :elapseds` delete options.format; bar = new progress(barFormat, options as ProgressBar.ProgressBarOptions); // not cache: Loop files in src directory if (!isExists) { const readDir = rd.readSync('src'); const reg = /\.(vue|ts|js|jsx|tsx|css|scss||sass|styl|less)$/gi; readDir.forEach((item) => reg.test(item) && fileCount++); } } }, transform(code, id) { transformCount++ // not cache if(!isExists) { const reg = /node_modules/gi; if (!reg.test(id) && percent < 0.25) { transformed++ percent = +(transformed / (fileCount * 2)).toFixed(2) percent < 0.8 && (lastPercent = percent) } if (percent >= 0.25 && lastPercent <= 0.65) { lastPercent = +(lastPercent + 0.001).toFixed(4) } } // go cache if (isExists) runCachedData() bar.update(lastPercent, { transformTotal: cacheTransformCount, transformCur: transformCount, chunkTotal: cacheChunkCount, chunkCur: 0, }) return { code, map: null }; }, renderChunk() { chunkCount++ if (lastPercent <= 0.95) isExists ? runCachedData() : (lastPercent = +(lastPercent + 0.005).toFixed(4)) bar.update(lastPercent, { transformTotal: cacheTransformCount, transformCur: transformCount, chunkTotal: cacheChunkCount, chunkCur: chunkCount, }) return null }, closeBundle() { // close progress bar.update(1) bar.terminate() // set cache data setCacheData({ cacheTransformCount: transformCount, cacheChunkCount: chunkCount, }) // out successful message stream.write( `${colors.cyan(colors.bold(`Build successful. Please see ${outDir} directory`))}` ); stream.write('\n'); stream.write('\n'); } }; function runCachedData() { if (transformCount === 1) { stream.write('\n'); bar.tick({ transformTotal: cacheTransformCount, transformCur: transformCount, chunkTotal: cacheChunkCount, chunkCur: 0, }) } transformed++ percent = lastPercent = +(transformed / (cacheTransformCount + cacheChunkCount)).toFixed(2) }}
cache.ts
import fs from 'fs';import path from 'path';const dirPath = path.join(process.cwd(), 'node_modules', '.progress');const filePath = path.join(dirPath, 'index.json');export interface ICacheData { cacheTransformCount: number; cacheChunkCount: number}export const isExists = fs.existsSync(filePath) || false;export const getCacheData = (): ICacheData => { if (!isExists) return { cacheTransformCount: 0, cacheChunkCount: 0 }; return JSON.parse(fs.readFileSync(filePath, 'utf8'));};export const setCacheData = (data: ICacheData) => { !isExists && fs.mkdirSync(dirPath); fs.writeFileSync(filePath, JSON.stringify(data));};
感谢各位的阅读,以上就是“怎么手写vite插件”的内容了,经过本文的学习后,相信大家对怎么手写vite插件这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!