当前位置:网站首页>How to write vite plug-ins
How to write vite plug-ins
2022-06-23 13:23:00 【Yisu cloud】
How to write vite plug-in unit
This article mainly explains “ How to write vite plug-in unit ”, The explanation in the text is simple and clear , Easy to learn and understand , Next, please follow Xiaobian's ideas and go deeper slowly , Study and learn together “ How to write vite plug-in unit ” Well !
1. What is? vite plug-in unit
vite In fact, it is an original ES Module The new drive Web Develop front-end build tools .
vite plug-in unit It can be well extended vite Things you can't do by yourself , such as File image compression 、 Yes commonjs Support for 、 Pack progress bar wait .
2. Why write vite plug-in unit
I believe that every student here , Up to now, yes webpack You know the relevant configurations and common plug-ins of ;
vite As a new front-end building tool , It's still very young , It also has a lot of scalability , So why don't we join hands with it now ? Do something more meaningful to you, me and everyone ?
To write a plug-in , That must start with creating a project , Below vite Plug in common template You can write plug-ins directly in the future clone Use ;
Plug in common template github: Experience entrance
plug-in unit github: Experience entrance
It is recommended that the package manager use priority :pnpm > yarn > npm > cnpm
Cut a long story short , Let's go straight to work ~
establish vite Plug in common template
1. initialization
1.1 Create a folder and initialize : Initialize and follow the prompts
mkdir vite-plugin-progress && cd vite-plugin-progress && pnpm init
1.2 install typescript
pnpm i typescript @types/node -D
1.3 To configure 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/*", "*.d.ts" ], "exclude": [ "node_modules", "examples", "dist" ]}1.4 install vite
// Get into package.json{ ... "devDependencies": { "vite": "*" } ...}2. To configure eslint and prettier( Optional )
install eslint
pnpm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
To configure .eslintrc: configure connections
install prettier ( Optional )
pnpm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev
To configure .prettierrc : configure connections
3. newly added src/index.ts entrance
import type { PluginOption } from 'vite';export default function vitePluginTemplate(): PluginOption { return { // The plug-in name name: 'vite-plugin-template', // pre Compared with post Execute first enforce: 'pre', // post // Indicates that they are available only in 'build' or 'serve' Called when in mode apply: 'build', // apply It can also be a function config(config, { command }) { console.log(' Here is config hook '); }, configResolved(resolvedConfig) { console.log(' Here is configResolved hook '); }, configureServer(server) { console.log(' Here is configureServer hook '); }, transformIndexHtml(html) { console.log(' Here is transformIndexHtml hook '); }, }}Among them vite The plug-in function hook will be explained in detail below ~
Come here , Then our basic template will be built , But let's think about it now , How should we run this plug-in ?
So we need to create some examples Example to run this code ;
4. establish examples Catalog
I have created three sets of projects here demo, Everybody directly copy That's it , I won't go into details here
vite-react
vite-vue2
vite-vue3
If your plug-in needs to run more demo, Create your own project ;
Then we need to configure examples The project under and the plug-in of the current root directory have been debugged ( Let's say examples/vite-vue3 For example ).
5. To configure examples/vite-vue3 project
modify examples/vite-vue3/package.json
{ ... "devDependencies": { ... "vite": "link:../../node_modules/vite", "vite-plugin-template": "link:../../" }}What the above means is :
To put examples/vite-vue3 In the project vite Version and root directory vite-plugin-template Consistent versions of ;
At the same time examples/vite-vue3 In the project vite-plugin-template Point to the plug-ins developed in your current root directory ;
Introducing plug-ins : examples/vite-vue3/vite.config.ts
import template from 'vite-plugin-template';export default defineConfig({ ... plugins: [vue(), template()], ...});install : cd examples/vite-vue3 && pnpm install
cd examples/vite-vue3 && pnpm install
Be careful :
examples/vite-vue2 and examples/vite-react The configuration of is consistent with this
reflection :
Come here , Let's think about it again , We put examples/vite-vue3 The items in are configured , But how should we run it ?
Go directly to examples/vite-vue3 Run in directory pnpm run build perhaps pnpm run dev ?
Obviously, this will not run successfully , Because our root directory src/index.ts It can't run directly , So we need to take .ts The file is escaped to .js file ;
So what do we do ?
So we have to try to use a light and small tool without configuration tsup 了 .
6. install tsup Configure run command
tsup Is a light, small and non configurable , from esbuild Supported build tools ;
At the same time, it can directly put .ts、.tsx Convert to a different format esm、cjs、iife Tools for ;
install tsup
pnpm i tsup -D
In the root directory package.json Middle configuration
{ ... "scripts": { "dev": "pnpm run build -- --watch --ignore-watch examples", "build": "tsup src/index.ts --dts --format cjs,esm", "example:react": "cd examples/vite-react && pnpm run build", "example:vue2": "cd examples/vite-vue2 && pnpm run build", "example:vue3": "cd examples/vite-vue3 && pnpm run build" }, ...}7. Development environment running
Development environment running : The real-time monitoring file is repackaged after modification ( Hot update )
pnpm run dev
function examples Any item in ( With vite-vue3 For example )
pnpm run example:vue3
Be careful :
If your plug-in will only be in build run , Then set up.
"example:vue3": "cd examples/vite-vue3 && pnpm run build" ;
On the contrary, it runs
pnpm run dev
Output :

Here you can Run while developing 了 , Youyuxi looked at it and said it was refreshing ~
8. Release
install bumpp Add version control and tag
pnpm i bumpp -D
To configure package.json
{ ... "scripts": { ... "prepublishOnly": "pnpm run build", "release": "npx bumpp --push --tag --commit && pnpm publish", }, ...}Run the release after developing the plug-in
# First step pnpm run prepublishOnly# The second step pnpm run release
So over here , our vite Plug in templates It's already written , You can clone directly vite-plugin-template Templates Use ;
If you are right about vite Plug-in hook and Achieve a real vite plug-in unit Interested can continue to look down ;
vite Plug-in hook hooks People
1. vite Unique hook
enforce : Values can be pre or post , pre Compared with post Execute first ;
apply : Values can be build or serve It can also be a function , Indicates that they are available only in build or serve Called when in mode ;
config(config, env) : Can be in vite Modify before being parsed vite Related configuration of . The hook receives the original user configuration config And a variable that describes the configuration environment env;
configResolved(resolvedConfig) : In parsing vite Call after configuration . Use this hook to read and store the final parsed configuration . When a plug-in needs to do something different according to the command it runs , It's very useful .
configureServer(server) : Mainly used to configure development The server , by dev-server (connect Applications ) Add custom middleware ;
transformIndexHtml(html) : transformation index.html Special hook for . The hook receives the current HTML String and conversion context ;
handleHotUpdate(ctx): Perform customization HMR to update , Can pass ws Send custom events to the client ;
2. vite And rollup The construction phase of the universal hook
options(options) : Called when the server starts : obtain 、 manipulation Rollup Options , Strictly speaking , It executes before it belongs to the construction phase ;
buildStart(options): Call each time you start a build ;
resolveId(source, importer, options): Called on each incoming module request , Create a custom confirmation function , Can be used to locate third-party dependencies ;
load(id): Called on each incoming module request , You can customize the loader , Can be used to return customized content ;
transform(code, id): Called on each incoming module request , It is mainly used to convert a single module ;
buildEnd(): Called at the end of the build phase , The end of construction here just means that all modules have been escaped ;
3. vite And rollup The output phase of the universal hook
outputOptions(options): Accept output parameters ;
renderStart(outputOptions, inputOptions): Every time bundle.generate and bundle.write It will be triggered when calling ;
augmentChunkHash(chunkInfo): To give chunk increase hash;
renderChunk(code, chunk, options): Translate single chunk Trigger when .rollup Output every chunk File will be called ;
generateBundle(options, bundle, isWrite): Calling bundle.write Trigger this immediately before hook;
writeBundle(options, bundle): Calling bundle.write after , be-all chunk After writing to the file , It will be called once finally writeBundle;
closeBundle(): Called when the server shuts down
4. Plug in hook function hooks Execution order of ( Here's the picture )

5. The order in which the plug-ins are executed
The alias processing Alias
User plug-in settings enforce: 'pre'
vite Core plug-ins
User plug-in is not set enforce
vite Build plug-ins
User plug-in settings enforce: 'post'
vite Build post plug-ins (minify, manifest, reporting)
Roll a hand vite plug-in unit
Let's say vite Pack progress bar Plug in as an example
inde.ts
import type { PluginOption } from 'vite';import colors from 'picocolors';import progress from 'progress';import rd from 'rd';import { isExists, getCacheData, setCacheData } from './cache';type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;type PluginOptions = Merge< ProgressBar.ProgressBarOptions, { /** * total number of ticks to complete * @default 100 */ total?: number; /** * The format of the progress bar */ 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'); } }; /** * run cache data of progress */ 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 { /** * Transform all count */ cacheTransformCount: number; /** * chunk all count */ cacheChunkCount: number}/** * It has been cached * @return boolean */export const isExists = fs.existsSync(filePath) || false;/** * Get cached data * @returns ICacheData */export const getCacheData = (): ICacheData => { if (!isExists) return { cacheTransformCount: 0, cacheChunkCount: 0 }; return JSON.parse(fs.readFileSync(filePath, 'utf8'));};/** * Set the data to be cached * @returns */export const setCacheData = (data: ICacheData) => { !isExists && fs.mkdirSync(dirPath); fs.writeFileSync(filePath, JSON.stringify(data));};Thank you for reading , That's all “ How to write vite plug-in unit ” Content. , After learning this article , I believe everyone knows how to write vite I have a deeper understanding of the problem of plug-ins , The specific use needs to be verified by practice . This is billion speed cloud , Xiaobian will push you articles with more relevant knowledge points , Welcome to your attention !
边栏推荐
- 90%的人都不懂的泛型,泛型的缺陷和应用场景
- Tt-slam: dense monocular slam for flat environment (IEEE 2021)
- Getting started with reverse debugging - learn about PE structure files
- CDH mail alarm configuration
- &lt; Sicily&gt; 1000. number reversal
- js: 获取页面最大的zIndex(z-index)值
- Esp32-c3 introductory tutorial problem ⑦ - fatal error: ESP_ Bt.h: no such file or directory ESP not found_ bt.h
- What are the risks of opening a mobile account? Is it safe to open an account?
- Configure SSH Remote Login for H3C switch
- 理财产品长期是几年?新手最好买长期还是短期?
猜你喜欢

windows 安装 MySQL

Based on your work experience, talk about the quality system construction in software testing

Has aaig really awakened its AI personality after reading the global June issue (Part 1)? Which segment of NLP has the most social value? Get new ideas and inspiration ~

4E1 PDH optical transceiver 19 inch rack type single fiber transmission 20km E1 interface optical network optical transceiver

First exposure! The only Alibaba cloud native security panorama behind the highest level in the whole domain

Hanyuan high tech USB2.0 optical transceiver USB2.0 optical fiber extender USB2.0 optical fiber transmitter USB2.0 interface to optical fiber
[email protected] Hdmi2.0 optical transceiver HDMI HD video optical transceiver"/>4k-hdmi optical transceiver 1 channel [email protected] Hdmi2.0 optical transceiver HDMI HD video optical transceiver

Homekit supports the matter protocol. What does this imply?

Stimulsoft Ultimate Reports 2022.3.1

你管这破玩意儿叫 MQ?
随机推荐
Hanyuan high tech USB2.0 optical transceiver USB2.0 optical fiber extender USB2.0 optical fiber transmitter USB2.0 interface to optical fiber
R语言dplyr包mutate_all函数将dataframe中的所有数值数值列(变量)乘以某一固定值并生成新的数据列,为新的数据列(变量)指定自定义后缀名称
Hanyuan hi tech 1-way uncompressed 4k-dvi optical transceiver 4K HD uncompressed DVI to optical fiber 4k-dvi HD video optical transceiver
The GLM function of R language uses frequency data to build a binary logistic regression model. The input data for analysis is frequency data, which is transformed into normal sample data (split and s
怎么手写vite插件
有向图D和E
R语言使用构建有序多分类逻辑回归模型、ordinal.or.display函数获取有序逻辑回归模型的汇总统计信息(变量对应的优势比及其置信区间、以及假设检验的p值)、汇总统计结果保存到csv
Principle analysis of three methods for exchanging two numbers
Filtre de texte en ligne inférieur à l'outil de longueur spécifiée
在线文本实体抽取能力,助力应用解析海量文本数据
支持HomeKit、NFC:智汀智能门锁SL1仅需要149元
Based on your work experience, talk about the quality system construction in software testing
Hanyuan hi tech 1-channel gigabit optical port to 4-channel Gigabit Ethernet electrical port Gigabit 1-optical 4-electric optical fiber transceiver
Wallys/DR6018-S/ 802.11AX MU-MIMO OFDMA / 2* GE PORTS/WIFI 6e / BAND DUAL CONCURRENT
Synergetic process
What are the risks of opening a mobile account? Is it safe to open an account?
[deeply understand tcapulusdb technology] transaction execution of document acceptance
【网站架构】10年数据库设计浓缩的绝技,实打实的设计步骤与规范
Hanyuan high tech USB3.0 optical transceiver USB industrial touch screen optical transceiver USB3.0 optical fiber extender USB3.0 optical fiber transmitter
TUIKit 音视频低代码解决方案导航页