当前位置:网站首页>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 !
边栏推荐
- Hanyuan high tech new generation green energy-saving Ethernet access industrial switch high efficiency energy-saving Gigabit Industrial Ethernet switch
- Go write permissions to file writefile (FileName, data, 0644)?
- Configure SSH Remote Login for H3C switch
- 逆向调试入门-了解PE结构文件
- Getting started with reverse debugging - learn about PE structure files
- Windows install MySQL
- R language uses matchit package for propensity matching analysis (set the matching method as nearest, match the control group and case group with the closest propensity score, 1:1 ratio), and use matc
- Unity small demand - simple realization of imitation King Diamond (single draw)
- 互联网技术发展内卷后的出路——iVX的诞生
- #云原生征文#深入了解Ingress
猜你喜欢

Getting started with reverse debugging - learn about PE structure files

腾讯的技术牛人们,是如何完成全面上云这件事儿的?

Stimulsoft Ultimate Reports 2022.3.1
![[deeply understand tcapulusdb technology] transaction execution of document acceptance](/img/d9/f6735906a130834c4b3e28de2b2617.png)
[deeply understand tcapulusdb technology] transaction execution of document acceptance

Androd Gradle模块依赖替换如何使用

Stimulsoft Ultimate Reports 2022.3.1

MySQL使用ReplicationConnection导致的连接失效分析与解决

HomeKit支持matter协议,这背后将寓意着什么?

What if the test time is not enough?

PHP handwriting a perfect daemon
随机推荐
Configure SSH Remote Login for H3C switch
What is the reason why maxcompute is sometimes particularly slow to execute SQL queries
RestCloud ETL解决shell脚本参数化
Lm05 former VIX (second generation product)
Interview question: for example, how do you do interface testing at work?
Getting started with reverse debugging - learn about PE structure files
The two 985 universities share the same president! School: true
在线文本过滤小于指定长度工具
C # learning (advanced course) day15 - exception handling and namespace
When did the redo log under InnoDB in mysql start to perform check point disk dropping?
Deep thinking: in-depth analysis of some scenes in Gaia Altman and the philosophy and perception reflected
First exposure! The only Alibaba cloud native security panorama behind the highest level in the whole domain
How can testers get started quickly when they change jobs to a new company?
【网站架构】10年数据库设计浓缩的绝技,实打实的设计步骤与规范
Js: get the maximum zindex (Z-index) value of the page
[deeply understand tcapulusdb technology] transaction execution of document acceptance
618的省钱技术攻略 来啦 -体验场景 领取10元猫超卡!
Follow the promotional music MV of domestic tour in Thailand and travel to Bangkok like local people
How long is the financial product? Is it better for novices to buy long-term or short-term?
Windows install MySQL