API پلاگین
پلاگینهای Vite بر پایهی رابط پلاگینهای Rollup ساخته شدهاند و چند گزینهی اضافی مخصوص Vite را ارائه میکنند. به همین دلیل، میتوانید یک پلاگین Vite بنویسید که هم در محیط توسعه و هم در زمان Build قابل استفاده باشد.
پیشنهاد میشود قبل از مطالعه این بخش به مستندات RollUp's plugin مراجعه کنید.
ساخت یک پلاگین
Vite الگوهای از پیش تعریف شدهای را ارائه میدهد، پس قبل از ساخت یک پلاگین جدید، حتماً راهنمای ویژگیها را بررسی کنید تا ببینید آیا نیاز شما قبلاً پوشش داده شده است یا خیر. همچنین، پلاگینهایی موجود در جامعهی توسعهدهندگان را بررسی کنید؛ پلاگینهای سازگار با Rollup و پلاگینهای مخصوص Vite.
هنگام ایجاد یک پلاگین، میتوانید آن را مستقیماً در فایل vite.config.js
خود تعریف کنید. نیازی به ایجاد یک پکیج جداگانه نیست. اما اگر میخواهید که از پلاگین خود در پروژههای مختلف استفاده شود، میتوانید آن را به اشتراک بگذارید تا به دیگر توسعهدهندگان کمک کنید.
نکته
هنگام یادگیری، دیباگ کردن یا ساخت پلاگینها، توصیه میکنیم از vite-plugin-inspect در پروژهی خود استفاده کنید. این پلاگین به شما امکان مشاهده وضعیت پلاگینهای Vite را میدهد. پس از نصب، میتوانید با مراجعه به localhost:5173/__inspect/
ماژولها و فرآیند تغییرات پروژهی خود را بررسی کنید. برای اطلاعات بیشتر، به مستندات vite-plugin-inspect مراجعه کنید.
قراردادها
اگر پلاگین شما از هوکهای اختصاصی Vite استفاده نمیکند میتواند بهعنوان یک پلاگین سازگار با Rollup پیاده سازی شود، توصیه میشود از قراردادهای نامگذاری پلاگینهای Rollup پیروی کنید.
- نام پلاگین باید واضح باشد و با پیشوند
-rollup-plugin
شروع شود. - در فایل
package.json
، کلمات کلیدیrollup-plugin
وvite-plugin
را اضافه کنید.
این کار باعث میشود پلاگین شما نهتنها در Vite، بلکه در Rollup خالص یا پروژههای مبتنی بر WMR نیز قابل استفاده باشد.
برای پلاگینهای اختصاصی Vite:
- نام پلاگین باید واضح باشد و با پیشوند
-vite-plugin
شروع شود. - در فایل package.json، کلیدواژهی
vite-plugin
را اضافه کنید. - در مستندات پلاگین توضیح دهید که چرا این پلاگین فقط مخصوص Vite است (مثلاً اگر از هوکهای مخصوص Vite استفاده میکند).
اگر پلاگین شما فقط برای یک فریمورک خاص طراحی شده است، نام آن باید شامل نام فریمورک باشد:
-vite-plugin-vue
برای پلاگینهای Vue-vite-plugin-react
برای پلاگینهای React-vite-plugin-svelte
برای پلاگینهای Svelte
برای اطلاعات بیشتر، به بخش قراردادهای ماژولهای مجازی مراجعه کنید.
تنظیمات پلاگینها
پلاگینها به devDependencies
پروژه اضافه میشود و از طریق آرایهی plugins
پیکربندی میشود.
import vitePlugin from 'vite-plugin-feature'
import rollupPlugin from 'rollup-plugin-feature'
export default defineConfig({
plugins: [vitePlugin(), rollupPlugin()],
})
پلاگینهای Falsy نادیده گرفته میشوند، بنابراین میتوان از این ویژگی برای فعال یا غیرفعال کردن پلاگینها استفاده کرد.
آرایهی plugins
از پیشتنظیمها پشتیبانی میکند که شامل چندین پلاگین در یک عنصر واحد هستند. این ویژگی برای قابلیتهای پیچیده (مانند یکپارچهسازی با فریمورکها) که از چند پلاگین تشکیل شدهاند، مفید است. این آرایه بهصورت داخلی تبدیل به یک لیست مسطح (Flattened) خواهد شد.
// framework-plugin
import frameworkRefresh from 'vite-plugin-framework-refresh'
import frameworkDevtools from 'vite-plugin-framework-devtools'
export default function framework(config) {
return [frameworkRefresh(config), frameworkDevTools(config)]
}
import { defineConfig } from 'vite'
import framework from 'vite-plugin-framework'
export default defineConfig({
plugins: [framework()],
})
مثال های ساده
نکته
طبق یک قرارداد رایج، پلاگینهای Vite/Rollup بهصورت تابع کارخانهای (Factory Function) نوشته میشوند که پلاگین را به صورت یک آبجکت بازمیگرداند. این تابع میتواند گزینههایی (Options) را بپذیرد که به کاربران اجازه میدهد پلاگین را سفارشیسازی کنند.
تبدیل انواع فایلهای سفارشی
const fileRegex = /\.(my-file-ext)$/
export default function myPlugin() {
return {
name: 'transform-file',
transform(src, id) {
if (fileRegex.test(id)) {
return {
code: compileFileToJS(src),
map: null, // provide source map if available
}
}
},
}
}
استفاده از یک فایل مجازی
مثالها را در بخش بعدی ببینید.
قرارداد ماژولهای مجازی
ماژولهای مجازی یک روش کاربردی هستند که به شما امکان میدهند اطلاعات مربوط به زمان ساخت (build time) را با استفاده از سینتکس معمولی ایمپورت ESM به فایلهای سورس منتقل کنید.
export default function myPlugin() {
const virtualModuleId = 'virtual:my-module'
const resolvedVirtualModuleId = '\0' + virtualModuleId
return {
name: 'my-plugin', // required, will show up in warnings and errors
resolveId(id) {
if (id === virtualModuleId) {
return resolvedVirtualModuleId
}
},
load(id) {
if (id === resolvedVirtualModuleId) {
return `export const msg = "from virtual module"`
}
},
}
}
که این امکان را فراهم میکند تا ماژول را در جاوااسکریپت ایمپورت کنید:
import { msg } from 'virtual:my-module'
console.log(msg)
ماژولهای مجازی در Vite (و Rollup) بهطور قراردادی با پیشوند virtual
شروع میشوند: برای مسیرهای قابل مشاهده توسط کاربر آغاز میشوند. اگر ممکن باشد، باید از نام پلاگین بهعنوان یک فضای نام برای جلوگیری از تداخل با پلاگینهای دیگر در اکوسیستم استفاده کرد. بهعنوان مثال، یک vite-plugin-posts
ممکن است از کاربران بخواهد که virtual:posts
یا virtual:posts/helpers
را بهعنوان ماژولهای مجازی وارد کنند تا اطلاعات زمان ساخت را دریافت کنند. از نظر داخلی، پلاگینهایی که از ماژولهای مجازی استفاده میکنند باید شناسه ماژول را هنگام حل کردن، با پیشوند \0
علامتگذاری کنند. این یک قرارداد از اکوسیستم Rollup است که از پردازش شناسه توسط سایر پلاگینها (مانند Node resolution) جلوگیری میکند. همچنین ویژگیهای اصلی مانند sourcemaps میتوانند از این اطلاعات برای تمایز میان ماژولهای مجازی و فایلهای معمولی استفاده کنند. \0
بهعنوان یک کاراکتر مجاز در آدرسهای ایمپورت شناخته نمیشود، بنابراین هنگام تجزیه و تحلیل ایمپورت باید آن را جایگزین کنیم. شناسه ماژول مجازی با \0{id}
در نهایت در توسعه در مرورگر به صورت /@id/__x00__{id}
کدگذاری میشود. این شناسه قبل از وارد شدن به پایپلاین پلاگینها مجدداً رمزگشایی میشود، بنابراین این مورد توسط کدهای هوک پلاگینها دیده نمیشود.
توجه داشته باشید که ماژولهایی که بهطور مستقیم از یک فایل واقعی مشتق شدهاند، مانند ماژول اسکریپت در یک کامپوننت تک فایلی (مانند فایلهای .vue یا .svelte)، نیازی به پیروی از این قرارداد ندارند. کامپوننتهای تکفایلی معمولاً مجموعهای از زیرماژولها را هنگام پردازش تولید میکنند، اما کد در این ماژولها میتواند به سیستم فایل بازگردانده شود. استفاده از \0
برای این زیرماژولها باعث میشود که sourcemaps بهدرستی کار نکند.
هوکهای عمومی
در زمان توسعه، سرور توسعه Vite یک کانتینر پلاگین ایجاد میکند که هوکهای ساخت Rollup را به همان شیوهای که Rollup انجام میدهد، فراخوانی میکند.
هوکهای زیر یکبار در زمان شروع سرور فراخوانی میشوند:
هوکهای زیر برای هر درخواست ماژول فراخوانی میشوند:
این هوکها همچنین دارای پارامتر options
گسترشیافتهای هستند که شامل ویژگیهای خاص Vite میشود. برای اطلاعات بیشتر میتوانید به مستندات SSR مراجعه کنید.
برخی از فراخوانیهای resolveId
ممکن است مقدار importer
را بهصورت یک مسیر مطلق برای یک فایل کلی index.html
در ریشه دریافت کنند. این به این دلیل است که به دلیل الگوی سرور توسعه بدون باندل Vite، همیشه امکان تعیین دقیق ایمپورتکننده (importer) وجود ندارد. با این حال، برای ایمپورتهایی که در مسیر حل وابستگیهای Vite پردازش میشوند، ایمپورتکننده را میتوان در مرحلهی تحلیل ایمپورتها ردیابی کرد و مقدار صحیح importer
را ارائه داد.
هوکهای زیر هنگامی که سرور بسته میشود، فراخوانی میشوند:
توجه داشته باشید که هوک moduleParsed
در زمان توسعه فراخوانی نمیشود، زیرا Vite برای بهبود عملکرد از تجزیه کامل AST اجتناب میکند.
هوکهای تولید خروجی Output Generation Hooks (بهجز closeBundle
) در زمان توسعه فراخوانی نمیشوند. شما میتوانید سرور توسعه Vite را بهعنوان فراخوانی فقط rollup.rollup()
بدون فراخوانی bundle.generate()
در نظر بگیرید.
هوک های مخصوص Vite
پلاگینهای Vite میتوانند هوکهایی ارائه دهند که مخصوص Vite هستند. این هوکها توسط Rollup نادیده گرفته میشوند.
config
تایپ:
(config: UserConfig, env: { mode: string, command: string }) => UserConfig | null | void
نوع اجرا:
async
,sequential
این هوک به شما امکان میدهد قبل از اینکه پیکربندی Vite نهایی شود، آن را تغییر دهید. این هوک پیکربندی اولیه کاربر (ترکیب گزینههای خط فرمان و فایل پیکربندی) و همچنین محیط جاری پیکربندی را دریافت میکند که شامل
mode
وcommand
است. میتواند یک آبجکت پیکربندی جزئی را بازگرداند که در پیکربندی موجود ادغام میشود، یا میتواند مستقیماً پیکربندی را تغییر دهد (اگر ادغام پیشفرض نتیجه مطلوب را ارائه ندهد).مثال:
js// return partial config (recommended) const partialConfigPlugin = () => ({ name: 'return-partial', config: () => ({ resolve: { alias: { foo: 'bar', }, }, }), }) // mutate the config directly (use only when merging doesn't work) const mutateConfigPlugin = () => ({ name: 'mutate-config', config(config, { command }) { if (command === 'build') { config.root = 'foo' } }, })
نکته
پلاگینهای کاربر قبل از اجرای این هوک پردازش میشوند، بنابراین اضافه کردن پلاگینهای دیگر داخل هوک
config
تأثیری نخواهد داشت.
configResolved
تایپ:
(config: ResolvedConfig) => void | Promise<void>
نوع اجرا:
async
,parallel
این هوک بعد از نهایی شدن تنظیمات Vite اجرا میشود. از این هوک برای خواندن و ذخیره تنظیمات نهایی استفاده کنید. همچنین زمانی مفید است که پلاگین نیاز دارد بر اساس دستوری که اجرا شده رفتار متفاوتی داشته باشد.
مثال:
jsconst examplePlugin = () => { let config return { name: 'read-config', configResolved(resolvedConfig) { // store the resolved config config = resolvedConfig }, // use stored config in other hooks transform(code, id) { if (config.command === 'serve') { // dev: plugin invoked by dev server } else { // build: plugin invoked by Rollup } }, } }
در نظر داشته باشید که مقدار
command
در حالت توسعه (dev) معادلserve
است (در cli، دستوراتvite
،vite dev
وvite serve
معادل هم هستند).
configureServer
تایپ:
(server: ViteDevServer) => (() => void) | void | Promise<(() => void) | void>
نوع اجرا:
async
,sequential
همچنین ببینید: ViteDevServer
این هوک برای پیکربندی سرور توسعه استفاده میشود. رایجترین کاربرد آن افزودن میانافزارهای (middlewares) سفارشی به برنامه داخلی connect است:
jsconst myPlugin = () => ({ name: 'configure-server', configureServer(server) { server.middlewares.use((req, res, next) => { // custom handle request... }) }, })
افزودن میانافزار
هوک
configureServer
قبل از نصب میانافزارهای داخلی اجرا میشود، بنابراین میانافزارهای سفارشی بهصورت پیشفرض قبل از میانافزارهای داخلی اجرا خواهند شد. اگر بخواهید یک میانافزار را بعد از میانافزارهای داخلی اضافه کنید، میتوانید یک تابع ازconfigureServer
بازگردانید. این تابع پس از نصب میانافزارهای داخلی فراخوانی خواهد شد:jsconst myPlugin = () => ({ name: 'configure-server', configureServer(server) { // return a post hook that is called after internal middlewares are // installed return () => { server.middlewares.use((req, res, next) => { // custom handle request... }) } }, })
ذخیره دسترسی به سرور
در برخی موارد، سایر هوکهای پلاگین ممکن است به نمونه سرور توسعه دسترسی داشته باشند (مثلاً برای دسترسی به سرور web socket، پایشگر سیستم فایل، یا گراف ماژولها). این هوک میتواند برای ذخیره نمونه سرور و استفاده از آن در سایر هوکها نیز استفاده شود:
jsconst myPlugin = () => { let server return { name: 'configure-server', configureServer(_server) { server = _server }, transform(code, id) { if (server) { // use server... } }, } }
توجه داشته باشید که
configureServer
هنگام اجرای نسخه نهایی فراخوانی نمیشود، بنابراین سایر هوکهای شما باید مراقب نبود آن باشند.
configurePreviewServer
تایپ:
(server: PreviewServer) => (() => void) | void | Promise<(() => void) | void>
نوع اجرا:
async
,sequential
همچنین ببینید: PreviewServer
این هوک مشابه
configureServer
است اما برای سرور پیشنمایش (preview server) استفاده میشود. درست مانندconfigureServer
، این هوک قبل از نصب سایر میانافزارها اجرا میشود. اگر میخواهید یک میانافزار را بعد از سایر میانافزارها اضافه کنید، میتوانید یک تابع ازconfigurePreviewServer
برگردانید که بعد از نصب میانافزارهای داخلی فراخوانی خواهد شد:jsconst myPlugin = () => ({ name: 'configure-preview-server', configurePreviewServer(server) { // return a post hook that is called after other middlewares are // installed return () => { server.middlewares.use((req, res, next) => { // custom handle request... }) } }, })
transformIndexHtml
تایپ:
IndexHtmlTransformHook | { order?: 'pre' | 'post', handler: IndexHtmlTransformHook }
نوع اجرا:
async
,sequential
این هوک برای تغییر و پردازش فایلهای HTML مانند
index.html
در نظر گرفته شده است. این هوک مقدار HTML فعلی و یک context transform را دریافت میکند. Context transform در حالت dev شامل نمونهای ازViteDevServer
است و در حالت build شامل بسته خروجی Rollup میشود.این هوک میتواند async باشد و یکی از موارد زیر را برگرداند:
- رشته HTML تغییر یافته
- یک آرایه از اشیای توصیفکننده (
{tag, attr, children}
) که به HTML موجود اضافه شوند. (هر تگ میتواند مشخص کند که در کجای صفحه قرار بگیرد، پیشفرض: ابتدای<head>
قرار میگیرد.) - یک آبجکت شامل هر دو مورد فوق به صورت
{ html, tags }
بهطور پیشفرض مقدار order
روی undefined
تنظیم شده است، به این معنا که این هوک بعد از پردازش HTML اجرا میشود.اگر بخواهید یک اسکریپت را به HTML اضافه کنید و این اسکریپت از پردازش پلاگینهای Vite عبور کند، باید order: 'pre'
را تنظیم کنید. و اگر بخواهید هوک شما بعد از همهی هوکهایی که مقدار order
آنها undefined است اجرا شود، order: 'post'
را تنظیم کنید.
مثال:
const htmlPlugin = () => {
return {
name: 'html-transform',
transformIndexHtml(html) {
return html.replace(
/<title>(.*?)<\/title>/,
`<title>Title replaced!</title>`,
)
},
}
}
امضاء کامل هوک:
type IndexHtmlTransformHook = (
html: string,
ctx: {
path: string
filename: string
server?: ViteDevServer
bundle?: import('rollup').OutputBundle
chunk?: import('rollup').OutputChunk
},
) =>
| IndexHtmlTransformResult
| void
| Promise<IndexHtmlTransformResult | void>
type IndexHtmlTransformResult =
| string
| HtmlTagDescriptor[]
| {
html: string
tags: HtmlTagDescriptor[]
}
interface HtmlTagDescriptor {
tag: string
attrs?: Record<string, string | boolean>
children?: string | HtmlTagDescriptor[]
/**
* default: 'head-prepend'
*/
injectTo?: 'head' | 'body' | 'head-prepend' | 'body-prepend'
}
نکته
این هوک در صورتی فراخوانی نخواهد شد که از فریمورکی استفاده کنید که مدیریت سفارشی فایلهای ورودی را انجام میدهد (برای مثال SvelteKit).
handleHotUpdate
تایپ:
(ctx: HmrContext) => Array<ModuleNode> | void | Promise<Array<ModuleNode> | void>
همچنین ببینید: HMR API
این هوک برای انجام مدیریت سفارشی بروزرسانی HMR (Hot Module Replacement) استفاده میشود. این هوک یک آبجکت کانتکست دریافت میکند که دارای امضای زیر است:
tsinterface HmrContext { file: string timestamp: number modules: Array<ModuleNode> read: () => string | Promise<string> server: ViteDevServer }
modules
: آرایهای از ماژولها است که تحت تأثیر فایل تغییر یافته قرار گرفتهاند. آرایه است زیرا یک فایل ممکن است به چندین ماژول سرو شده مربوط باشد (مثل SFCهای Vue).read
: یک تابع خواندن غیرهمزمان است که محتوای فایل را باز میگرداند. این تابع فراهم شده است زیرا در برخی سیستمها، callback تغییر فایل ممکن است خیلی سریع اجرا شود پیش از اینکه ویرایشگر فایل را بهطور کامل بهروزرسانی کند و فراخوانی مستقیمfs.readFile
ممکن است محتوای خالی برگرداند. تابع read این رفتار را نرمال میکند.
هوک میتواند تصمیم بگیرد که:
لیست ماژولهای تحت تأثیر را فیلتر کرده و دقیقتر کند تا HMR (Hot Module Replacement) دقیقتر باشد.
یک آرایه خالی برگرداند و یک بار بارگذاری کامل انجام دهد:
jshandleHotUpdate({ server, modules, timestamp }) { // Invalidate modules manually const invalidatedModules = new Set() for (const mod of modules) { server.moduleGraph.invalidateModule( mod, invalidatedModules, timestamp, true ) } server.ws.send({ type: 'full-reload' }) return [] }
یک آرایه خالی برگرداند و انجام مدیریت کامل HMR سفارشی را با ارسال رویدادهای سفارشی به کلاینت انجام دهد:
jshandleHotUpdate({ server }) { server.ws.send({ type: 'custom', event: 'special-update', data: {} }) return [] }
کد کلاینت باید هندلر مربوطه را با استفاده از API HMR ثبت کند (این میتواند از طریق هوک transform همان پلاگین اضافه شود):
jsif (import.meta.hot) { import.meta.hot.on('special-update', (data) => { // perform custom update }) }
ترتیب اجرای پلاگینها در Vite
یک پلاگین در Vite میتواند ویژگی enforce
را مشخص کند (مشابه لودرهای Webpack) تا ترتیب اجرای آن را تنظیم کند. مقدار enforce
میتواند "pre"
یا "post"
باشد. ترتیب اجرای پلاگینها پس از پردازش به شکل زیر خواهد بود:
- Alias
- پلاگینهای کاربر با
enforce: 'pre'
- پلاگینهای هستهای Vite
- پلاگینهای کاربر بدون مقدار
enforce
- پلاگینهای مربوط به ساخت (build) در Vite
- پلاگینهای کاربر با
enforce: 'post'
- پلاگینهای پس از ساخت Vite (مانند minify، manifest، گزارشگیری)
توجه داشته باشید که این ترتیب جدا از ترتیب اجرای هوکها است، زیرا هوکها همچنان مطابق با مقدار order
خود در Rollup پردازش میشوند.
برنامه های شرطی
بهطور پیشفرض، پلاگینها هم در حالت توسعه (serve) و هم در حالت بیلد (build) اجرا میشوند. اما اگر پلاگینای فقط در یکی از این دو حالت موردنیاز باشد، میتوان از ویژگی apply
برای مشخص کردن اینکه پلاگین فقط در 'build'
یا 'serve'
اجرا شود:
function myPlugin() {
return {
name: 'build-only',
apply: 'build', // or 'serve'
}
}
همچنین میتوان از یک تابع برای کنترل دقیقتر استفاده کرد:
apply(config, { command }) {
// apply only on build but not for SSR
return command === 'build' && !config.build.ssr
}
سازگاری با پلاگینهای Rollup
تعداد قابل توجهی از پلاگینهای Rollup مستقیماً به عنوان پلاگین Vite کار میکنند (مثلاً @rollup/plugin-alias
یا @rollup/plugin-json
) اما نه همه آنها، زیرا برخی از هوکهای پلاگین در یک سرور توسعه بدون باندل معنایی ندارند.
به طور کلی، اگر یک پلاگین Rollup دارای شرایط زیر باشد، باید بدون مشکل به عنوان پلاگین Vite کار کند:
- از هوک
moduleParsed
استفاده نمیکند. - وابستگی زیاد بین هوکهای مربوط به فاز باندل و فاز خروجی ندارد.
اگر یک پلاگین Rollup فقط برای مرحله ساخت (build) مناسب باشد، میتوان آن را در build.rollupOptions.plugins
مشخص کرد. این کار همان عملکردی را خواهد داشت که یک پلاگین Vite با enforce: 'post'
و apply: 'build'
دارد.
همچنین میتوان یک پلاگین Rollup موجود را با ویژگیهای مخصوص Vite تقویت کرد:
import example from 'rollup-plugin-example'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
{
...example(),
enforce: 'post',
apply: 'build',
},
],
})
نرمالسازی مسیرها
Vite در هنگام حل شناسهها مسیرها را نرمالسازی میکند تا از جداکنندههای POSIX ( / ) استفاده کند، در حالی که در ویندوز، حجم درایو را حفظ میکند. از طرف دیگر، Rollup بهطور پیشفرض مسیرهای حلشده را دستنخورده نگه میدارد، بنابراین شناسههای حلشده در ویندوز از جداکنندههای ( \ ) win32 استفاده میکنند. با این حال، پلاگینهای Rollup بهصورت داخلی از تابع کمکی normalizePath
از @rollup/pluginutils
استفاده میکنند، که جداکنندهها را قبل از انجام مقایسهها به فرمت POSIX تبدیل میکند. این بدان معناست که هنگام استفاده از این پلاگینها در Vite، مقادیر include
و exclude
در الگوهای پیکربندی و سایر مسیرهای مشابه در مقایسه با شناسههای حلشده بهدرستی کار میکنند.
بنابراین، برای پلاگینهای Vite، هنگام مقایسه مسیرها با شناسههای حلشده، مهم است که ابتدا مسیرها را نرمالسازی کرده و از جداکنندههای POSIX (/
) استفاده کنید. یک تابع کمکی معادل normalizePath نیز از ماژول vite صادر شده است.
import { normalizePath } from 'vite'
normalizePath('foo\\bar') // 'foo/bar'
normalizePath('foo/bar') // 'foo/bar'
فیلتر کردن، الگوی include/exclude
Vite تابع createFilter
از بسته @rollup/pluginutils
را در دسترس قرار میدهد تا پلاگینها و یکپارچهسازیهای مخصوص Vite از الگوی استاندارد فیلتر کردن include/exclude استفاده کنند. این الگو در خود هسته Vite نیز به کار میرود.
ارتباط کلاینت-سرور
از نسخه 2.9، Vite ابزارهایی را برای پلاگینها فراهم میکند تا به ارتباط با کلاینتها کمک کنند.
سرور به کلاینت
در سمت پلاگین، میتوان از server.ws.send
برای ارسال رویدادها به کلاینت استفاده کرد:
export default defineConfig({
plugins: [
{
// ...
configureServer(server) {
server.ws.on('connection', () => {
server.ws.send('my:greetings', { msg: 'hello' })
})
},
},
],
})
نکته
توصیه میکنیم همیشه یک پیشوند به نام رویدادهای خود اضافه کنید تا از تداخل با سایر پلاگینها جلوگیری شود.
در سمت کلاینت، از hot.on
برای گوش دادن به رویدادها استفاده کنید:
// client side
if (import.meta.hot) {
import.meta.hot.on('my:greetings', (data) => {
console.log(data.msg) // hello
})
}
کلاینت به سرور
برای ارسال رویدادها از کلاینت به سرور، میتوان از hot.send
استفاده کرد:
// client side
if (import.meta.hot) {
import.meta.hot.send('my:from-client', { msg: 'Hey!' })
}
سپس از server.ws.on
استفاده کنید و به رویدادها در سمت سرور گوش دهید.
export default defineConfig({
plugins: [
{
// ...
configureServer(server) {
server.ws.on('my:from-client', (data, client) => {
console.log('Message from client:', data.msg) // Hey!
// reply only to the client (if needed)
client.send('my:ack', { msg: 'Hi! I got your message!' })
})
},
},
],
})
TypeScript برای رویدادهای سفارشی
بهصورت داخلی، Vite تایپ payload را از رابط CustomEventMap
استنتاج میکند. میتوان رویدادهای سفارشی را با گسترش این ساختار گسترش داد:
نکته
باید هنگام مشخص کردن فایلهای تعریف ساختار تایپاسکریپت، حتماً پسوند d.ts.
را اضافه کنید. در غیر این صورت، تایپاسکریپت ممکن است نتواند تشخیص دهد که ساختار فایل چیست.
import 'vite/types/customEvent.d.ts'
declare module 'vite/types/customEvent.d.ts' {
interface CustomEventMap {
'custom:foo': { msg: string }
// 'event-key': payload
}
}
این تعریف ساختار توسط <InferCustomEventPayload<T
برای استنتاج تایپ داده payload برای رویداد T
استفاده میشود. برای کسب اطلاعات بیشتر در مورد نحوه استفاده از این ساختار، به مستندات API HMR مراجعه کنید.
type CustomFooPayload = InferCustomEventPayload<'custom:foo'>
import.meta.hot?.on('custom:foo', (payload) => {
// The type of payload will be { msg: string }
})
import.meta.hot?.on('unknown:event', (payload) => {
// The type of payload will be any
})