ویژگیها
در ابتداییترین سطح، توسعه با Vite تفاوت زیادی با استفاده از یک سرور فایل استاتیک ندارد. اما Vite امکانات بیشتری فراتر از ایمپورت ESM بومی ارائه میدهد تا از ویژگیهای مختلفی که معمولاً در راهاندازی مبتنی بر باندلر دیده میشوند، پشتیبانی کند.
حل وابستگیهای npm و پیشباندل کردن
ایمپورت ES بومی از ایمپورت ماژولهای بدون مسیر مشخص مانند نمونه زیر پشتیبانی نمیکند:
import { someMethod } from 'my-dep'
کد بالا در مرورگر خطا ایجاد میکند. Vite ایمپورت ماژولهای بدون مسیر مانند این را در تمامی فایلهای منبع شناسایی کرده و اقدامات زیر را انجام میدهد:
پیشباندل: این فرآیند سرعت بارگذاری صفحه را بهبود میبخشد و ماژولهای CommonJS/UMD را به ESM تبدیل میکند. مرحله پیشباندل (پیش بستهبندی) با استفاده از ابزار esbuild انجام میشود که زمان زمان راهاندازی اولیه (cold start) ابزار Vite را به طور قابل توجهی سریعتر از هر باندلر جاوااسکریپتی دیگر میکند.
بازنویسی ایمپورتها به آدرسهای معتبر مانند
/node_modules/.vite/deps/my-dep.js?v=f3sf2ebd
تا مرورگر بتواند آنها را به درستی ایمپورت کند.
وابستگیها بهشدت در کش ذخیره میشوند
Vite درخواستهای مربوط به وابستگیها را از طریق هدرهای HTTP کش میکند، بنابراین اگر بخواهید یک وابستگی را بهصورت محلی ویرایش یا دیباگ کنید، مراحل ذکر شده اینجا را دنبال کنید.
جایگزینی سریع ماژول (Hot Module Replacement)
Vite یک API جایگزینی سریع ماژول (HMR) بر پایه ESM بومی ارائه میدهد. فریمورکهایی که از قابلیت HMR پشتیبانی میکنند، میتوانند از این API استفاده کنند تا بهروزرسانیهای فوری و دقیق را بدون نیاز به بارگذاری مجدد صفحه یا از دست رفتن وضعیت برنامه ارائه دهند. Vite یکپارچهسازیهای HMR اختصاصی برای کامپوننتهای تکفایلی Vue و React Fast Refresh فراهم میکند. همچنین یکپارچهسازیهای رسمی برای Preact از طریق @prefresh/vite وجود دارد.
توجه داشته باشید که نیازی به تنظیم دستی این موارد ندارید. زمانی که یک برنامه را از طریق create-vite
ایجاد میکنید، قالبهای انتخابی این تنظیمات را از پیش برای شما پیکربندی کردهاند.
تایپاسکریپت
Vite بهطور پیشفرض از ایمپورت کردن فایلهای .ts
پشتیبانی میکند.
فقط تبدیل (Transpile Only)
توجه داشته باشید که Vite تنها عملیات تبدیل (transpilation) را روی فایلهای .ts
انجام میدهد و هیچگونه بررسی تایپ (type checking) انجام نمیدهد. این ابزار فرض میکند که بررسی تایپ توسط IDE یا فرآیند ساخت شما مدیریت میشود.
دلیل اینکه Vite بررسی تایپ را بهعنوان بخشی از فرآیند تبدیل انجام نمیدهد این است که این دو وظیفه بهصورت بنیادی متفاوت عمل میکنند. تبدیل (Transpilation) میتواند بهصورت مستقل برای هر فایل انجام شود و کاملاً با مدل کامپایل در لحظه Vite هماهنگ است. در مقایسه، بررسی تایپ به اطلاعات کامل از کل گراف ماژول نیاز دارد. گنجاندن بررسی تایپ در مراحل تبدیل Vite بهناچار مزایای سرعتی آن را کاهش میدهد.
وظیفه Vite این است که ماژولهای منبع شما را به شکلی درآورد که بتوانند در سریعترین زمان ممکن در مرورگر اجرا شوند. به همین منظور، پیشنهاد میشود که بررسیهای تحلیلی استاتیک (مثل ESLint و موارد مشابه) را از مراحل تبدیل Vite جدا کنید.
برای بیلدهای پروداکش، میتوانید دستور
tsc --noEmit
را علاوه بر دستور بیلد Vite اجرا کنید.در طول توسعه، اگر به اطلاعات بیشتری فراتر از پیشنهادات IDE نیاز دارید، پیشنهاد میشود که دستور
tsc --noEmit --watch
را در یک فرآیند جداگانه اجرا کنید، یا اگر ترجیح میدهید که خطاهای تایپ مستقیماً در مرورگر گزارش شوند، از vite-plugin-checker استفاده کنید.
Vite از esbuild برای تبدیل تایپاسکریپت به جاوااسکریپت استفاده میکند که حدود ۲۰ تا ۳۰ برابر سریعتر از tsc
معمولی است و بهروزرسانیهای HMR میتوانند در کمتر از ۵۰ میلیثانیه در مرورگر منعکس شوند.
برای جلوگیری از مشکلات احتمالی مانند باندل نادرست ایمپورت فقط تایپ (type-only imports)، از سینتکس Type-Only Imports and Export استفاده کنید. بهعنوان مثال:
import type { T } from 'only/types'
export type { T }
گزینههای کامپایلر TypeScript
برخی از فیلدهای پیکربندی در compilerOptions
در فایل tsconfig.json
نیاز به توجه ویژه دارند.
isolatedModules
باید به true
تنظیم شود.
به این دلیل که esbuild
ترنسپایل را بدون اطلاع از تایپها انجام میدهد و از ویژگیهایی مانند const enum و ایمپورت تایپ ضمنی پشتیبانی نمیکند.
باید "isolatedModules": true
را در tsconfig.json
زیر compilerOptions
تنظیم کنید تا TypeScript به شما در مورد ویژگیهایی که با ترنسپایل ایزوله کار نمیکنند، هشدار دهد.
اگر یک وابستگی با "isolatedModules": true
به خوبی کار نمیکند، میتوانید از "skipLibCheck": true
استفاده کنید تا به طور موقت خطاها را تا زمانی که در بالادست رفع شوند، نادیده بگیرید.
useDefineForClassFields
مقدار پیشفرض این گزینه زمانی برابر با true
خواهد بود که target در تایپاسکریپت روی ES2022
یا نسخههای جدیدتر از جمله ESNext
تنظیم شده باشد. این رفتار با عملکرد TypeScript نسخه 4.3.2 به بعد هماهنگ است. سایر target ها در تایپاسکریپت به طور پیشفرض false
خواهند بود.
true
مطابق با استاندارد رانتایم ECMAScript است.
اگر از کتابخانهای استفاده میکنید که به شدت به فیلدهای کلاس وابسته است، لطفاً مطمئن شوید که کتابخانه با تنظیمات شما سازگار است. در حالی که بیشتر کتابخانهها انتظار دارند که "useDefineForClassFields": true
باشد، اگر کتابخانه شما از این ویژگی پشتیبانی نمیکند، میتوانید به صراحت useDefineForClassFields
را به false
تنظیم کنید.
target
Vite مقدار target
در tsconfig.json
را نادیده میگیرد و از همان تنظیمات esbuild
پیروی میکند.
برای مشخص کردن target در حالت توسعه، میتوانید از گزینه esbuild.target
استفاده کنید که به طور پیشفرض esnext
برای کمترین ترنسپایل تنظیم شده است. در بیلد، گزینه build.target
اولویت بالاتری نسبت به esbuild.target
دارد و در صورت نیاز میتوانید آن را تنظیم کنید.
useDefineForClassFields
اگر target
در tsconfig.json
برابر با ESNext
یا ES2022
یا جدیدتر نباشد، یا اگر فایل tsconfig.json
وجود نداشته باشد، مقدار پیشفرض useDefineForClassFields
برابر با false
خواهد بود که ممکن است با مقدار پیشفرض esbuild.target
یعنی esnext
مشکلساز شود. این ممکن است به static initialization blocks ترنسپایل شود که ممکن است مرورگر شما از آنها پشتیبانی نکند.
بنابراین، توصیه میشود که target
را به ESNext
یا ES2022
یا جدیدتر تنظیم کنید، یا useDefineForClassFields
را به صراحت در tsconfig.json
به true
تنظیم کنید.
سایر گزینههای کامپایلر که بر نتیجه بیلد تأثیر میگذارند
extends
importsNotUsedAsValues
preserveValueImports
verbatimModuleSyntax
jsx
jsxFactory
jsxFragmentFactory
jsxImportSource
experimentalDecorators
alwaysStrict
skipLibCheck
قالبهای شروع Vite به طور پیشفرض "skipLibCheck": "true"
دارند تا از بررسی تایپ وابستگیها جلوگیری کنند، زیرا ممکن است فقط از نسخهها و تنظیمات خاصی از TypeScript پشتیبانی کنند. میتوانید اطلاعات بیشتری را در vuejs/vue-cli#5688 بیابید.
تایپهای کلاینت
تایپهای پیشفرض Vite برای API مورد استفاده در Node.js آن هستند. برای شبیهسازی محیط کد سمت کلاینت در یک برنامه Vite، یک فایل تعریف d.ts
اضافه کنید:
/// <reference types="vite/client" />
استفاده از compilerOptions.types
به طور جایگزین، میتوانید vite/client
را به compilerOptions.types
در tsconfig.json
اضافه کنید:
{
"compilerOptions": {
"types": ["vite/client", "some-other-global-lib"]
}
}
توجه داشته باشید که اگر compilerOptions.types
مشخص شده باشد، تنها این پکیجها در محدوده سراسری گنجانده خواهند شد (به جای همه پکیجهای قابل مشاهده @types
).
vite/client
کار تایپهای زیر را فراهم میکند:
- ایمپورت asset ها (مثلاً ایمپورت یک فایل
.svg
) - تایپها برای ثابتها تزریق شده توسط Vite در
import.meta.env
- تایپها برای HMR API در
import.meta.hot
نکته
برای بازنویسی تایپهای پیشفرض، یک فایل تعریف تایپ اضافه کنید که تایپهای شما را شامل شود. سپس، مرجع تایپ را قبل از vite/client
اضافه کنید.
برای مثال، برای تبدیل ایمپورت پیشفرض *.svg
به یک کامپوننت React:
vite-env-override.d.ts
(فایلی که تایپهای شما را شامل میشود):tsdeclare module '*.svg' { const content: React.FC<React.SVGProps<SVGElement>> export default content }
- فایلی که مرجع به
vite/client
را شامل میشود:ts/// <reference types="./vite-env-override.d.ts" /> /// <reference types="vite/client" />
HTML
فایلهای HTML در پروژه Vite به عنوان نقاط ورودی برای برنامه شما عمل میکنند و ساخت برنامههای تکصفحهای و چندصفحهای را ساده میکنند.
میتوان به هر فایل HTML که در ریشه پروژه شماست، مستقیماً از طریق مسیر دایرکتوری آن دسترسی پیدا کرد:
<root>/index.html
->http://localhost:5173/
<root>/about.html
->http://localhost:5173/about.html
<root>/blog/index.html
->http://localhost:5173/blog/index.html
asset هایی که توسط عناصر HTML مانند <script type="module" src>
و <link href>
ارجاع داده میشوند، به عنوان بخشی از برنامه پردازش و بستهبندی میشوند. لیست کامل عناصر پشتیبانی شده به شرح زیر است:
<audio src>
<embed src>
<img src>
و<img srcset>
<image src>
<input src>
<link href>
و<link imagesrcset>
<object data>
<script type="module" src>
<source src>
و<source srcset>
<track src>
<use href>
و<use xlink:href>
<video src>
و<video poster>
<meta content>
- فقط اگر ویژگی
name
باmsapplication-tileimage
،msapplication-square70x70logo
،msapplication-square150x150logo
،msapplication-wide310x150logo
،msapplication-square310x310logo
،msapplication-config
،twitter:image
مطابقت داشته باشد. - یا فقط اگر ویژگی
property
باog:image
،og:image:url
،og:image:secure_url
،og:audio
،og:audio:secure_url
،og:video
،og:video:secure_url
مطابقت داشته باشد.
- فقط اگر ویژگی
<!doctype html>
<html>
<head>
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" href="/src/styles.css" />
</head>
<body>
<img src="/src/images/logo.svg" alt="logo" />
<script type="module" src="/src/main.js"></script>
</body>
</html>
برای غیرفعال کردن پردازش HTML در برخی المنتها، میتوانید ویژگی vite-ignore
را به عنصر اضافه کنید که میتواند در هنگام ارجاع به asset های خارجی یا CDN مفید باشد.
فریمورکها
تمام فریمورکهای مدرن با Vite یکپارچهسازی شدهاند. بیشتر پلاگینهای فریمورک توسط تیمهای هر فریمورک نگهداری میشوند، به جز پلاگینهای رسمی Vue و React Vite که توسط سازمان Vite نگهداری میشوند:
- پشتیبانی از Vue از طریق @vitejs/plugin-vue
- پشتیبانی از Vue JSX از طریق @vitejs/plugin-vue-jsx
- پشتیبانی از React از طریق @vitejs/plugin-react
- پشتیبانی از React با استفاده از SWC از طریق @vitejs/plugin-react-swc
برای اطلاعات بیشتر، به راهنمای پلاگینها مراجعه کنید.
JSX
فایلهای .jsx
و .tsx
نیز به صورت پیشفرض پشتیبانی میشوند. ترنسپایل JSX نیز از طریق esbuild انجام میشود.
فریمورک انتخابی شما به طور پیشفرض JSX را پیکربندی خواهد کرد (برای مثال، کاربران Vue باید از پلاگین رسمی @vitejs/plugin-vue-jsx استفاده کنند که ویژگیهای خاص Vue 3 از جمله HMR، حل و فصل سراسری کامپوننتها، دایرکتیوها و اسلاتها را فراهم میکند).
اگر از JSX با فریمورک خودتان استفاده میکنید، میتوانید jsxFactory
و jsxFragment
سفارشی را با استفاده از گزینه esbuild
تنظیم کنید. به عنوان مثال، پلاگین Preact از این تنظیمات استفاده میکند:
import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
jsxFactory: 'h',
jsxFragment: 'Fragment',
},
})
جزئیات بیشتر در مستندات esbuild.
میتوانید از jsxInject
(که یک گزینه مخصوص Vite است) برای تزریق کمککنندههای JSX استفاده کنید تا از ایمپورت دستی جلوگیری کنید:
import { defineConfig } from 'vite'
export default defineConfig({
esbuild: {
jsxInject: `import React from 'react'`,
},
})
CSS
ایمپورت فایلهای .css
محتوای آنها را از طریق یک تگ <style>
به صفحه اضافه میکند و از HMR پشتیبانی میکند.
درونخطی کردن و بازنویسی @import
Vite به صورت پیشفرض برای پشتیبانی از درونخطی کردن @import
در CSS با postcss-import
پیکربندی شده است. همچنین، نامهای مستعار Vite برای @import
در CSS نیز رعایت میشوند. علاوه بر این، تمام ارجاعات url()
در CSS، حتی اگر فایلهای ایمپورت شده در دایرکتوریهای مختلف باشند، به طور خودکار بازنویسی میشوند تا از صحت آنها اطمینان حاصل شود.
نامهای مستعار @import
و بازنشانی URL برای فایلهای Sass و Less نیز پشتیبانی میشوند (به پیشپردازندههای CSS مراجعه کنید).
PostCSS
اگر پروژه شامل پیکربندی معتبر PostCSS باشد (هر فرمتی که توسط postcss-load-config پشتیبانی میشود، مانند postcss.config.js
)، به طور خودکار به تمام CSS ایمپورت شده اعمال میشود.
توجه داشته باشید که کوچکسازی CSS پس از PostCSS اجرا میشود و از گزینه build.cssTarget
استفاده خواهد کرد.
ماژولهای CSS
هر فایل CSS که با .module.css
ختم شود، به عنوان یک فایل ماژولهای CSS در نظر گرفته میشود. ایمپورت چنین فایلی آبجکت ماژول مربوطه را برمیگرداند:
.red {
color: red;
}
import classes from './example.module.css'
document.getElementById('foo').className = classes.red
تنظیمات ماژولهای CSS را میتوان از طریق گزینه css.modules
پیکربندی کرد.
اگر css.modules.localsConvention
تنظیم شده باشد تا نامهای محلی به صورت camelCase فعال شوند (مثلاً localsConvention: 'camelCaseOnly'
)، میتوانید از ایمپورتهای نامگذاری شده نیز استفاده کنید:
// .apply-color -> applyColor
import { applyColor } from './example.module.css'
document.getElementById('foo').className = applyColor
پیشپردازندههای CSS
از آنجا که Vite فقط مرورگرهای مدرن را هدف قرار میدهد، توصیه میشود از متغیرهای بومی CSS با پلاگینهای PostCSS که پیشنویسهای CSSWG را پیادهسازی میکنند (مثلاً postcss-nesting) استفاده کنید و CSS ساده و مطابق با استانداردهای آینده بنویسید.
با این حال، Vite پشتیبانی داخلی از فایلهای .scss
، .sass
، .less
، .styl
و .stylus
را فراهم میکند. نیازی به نصب پلاگینهای مخصوص Vite برای آنها نیست، اما باید پیشپردازنده مربوطه نصب شده باشد:
# .scss and .sass
npm add -D sass-embedded # or sass
# .less
npm add -D less
# .styl and .stylus
npm add -D stylus
اگر از کامپوننتهای تکفایلی Vue استفاده میکنید، این به طور خودکار <style lang="sass">
و موارد مشابه را فعال میکند.
Vite بهبودهایی در حل @import
برای Sass و Less ارائه میدهد تا نامهای مستعار Vite نیز رعایت شوند. علاوه بر این، ارجاعات نسبی url()
در فایلهای Sass/Less ایمپورت شده که در دایرکتوریهای مختلف از فایل ریشه قرار دارند، به طور خودکار بازنویسی میشوند تا از صحت آنها اطمینان حاصل شود.
نام مستعار @import
و بازنویسی URL برای Stylus به دلیل محدودیتهای API آن پشتیبانی نمیشوند.
همچنین میتوانید از ماژولهای CSS همراه با پیشپردازندهها استفاده کنید، با اضافه کردن .module
به پسوند فایل، به عنوان مثال style.module.scss
.
غیرفعال کردن تزریق CSS به صفحه
تزریق خودکار محتوای CSS را میتوان از طریق پارامتر ?inline
غیرفعال کرد. در این حالت، رشته CSS پردازش شده به عنوان خروجی پیشفرض ماژول برگردانده میشود، اما استایلها به صفحه تزریق نمیشوند.
import './foo.css' // به صفحه تزریق خواهد شد
import otherStyles from './bar.css?inline' // تزریق نخواهد شد
نکته
ایمپورتهای پیشفرض و نامگذاری شده از فایلهای CSS (مثلاً import style from './foo.css'
) از Vite 5 حذف شدهاند. به جای آن از کوئری ?inline
استفاده کنید.
Lightning CSS
از Vite 4.4، پشتیبانی آزمایشی برای Lightning CSS وجود دارد. میتوانید با اضافه کردن css.transformer: 'lightningcss'
به فایل پیکربندی خود و نصب وابستگی اختیاری lightningcss
از آن استفاده کنید:
npm add -D lightningcss
اگر فعال شود، فایلهای CSS توسط Lightning CSS به جای PostCSS پردازش خواهند شد. برای پیکربندی آن، میتوانید گزینههای Lightning CSS را به گزینه پیکربندی css.lightningcss
پاس دهید.
برای پیکربندی ماژولهای CSS، باید از css.lightningcss.cssModules
به جای css.modules
استفاده کنید (که نحوه پردازش ماژولهای CSS توسط PostCSS را پیکربندی میکند).
به طور پیشفرض، Vite از esbuild برای کوچکسازی CSS استفاده میکند. Lightning CSS نیز میتواند به عنوان کوچکساز CSS با گزینه build.cssMinify: 'lightningcss'
استفاده شود.
assets های استاتیک
ایمپورت یک assets استاتیک، URL عمومی ساخته شده آن را برمیگرداند:
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl
کوئریهای خاص میتوانند نحوه بارگذاری assets ها را تغییر دهند:
// URL به عنوان assets بارگذاری صریح
import assetAsURL from './asset.js?url'
// به عنوان رشته assets بارگذاری
import assetAsString from './shader.glsl?raw'
// Web Workers بارگذاری
import Worker from './worker.js?worker'
// در زمان بیلد درونخطی میشوند base64 به صورت رشتههای Web Workers
import InlineWorker from './worker.js?worker&inline'
جزئیات بیشتر در مدیریت assets های استاتیک.
JSON
فایلهای JSON میتوانند به طور مستقیم ایمپورت شوند - ایمپورتهای نامگذاری شده نیز پشتیبانی میشوند:
// import the entire object
import json from './example.json'
// import a root field as named exports - helps with tree-shaking!
import { field } from './example.json'
ایمپورت Glob
Vite از ایمپورت چندین ماژول از فایل-سیستم با استفاده از تابع خاص import.meta.glob
پشتیبانی میکند:
const modules = import.meta.glob('./dir/*.js')
کد بالا به شکل زیر تبدیل خواهد شد:
// Vite کد تولید شده توسط
const modules = {
'./dir/bar.js': () => import('./dir/bar.js'),
'./dir/foo.js': () => import('./dir/foo.js'),
}
سپس میتوانید بر روی کلیدهای آبجکت modules
حلقه بزنید تا به ماژولهای مربوطه دسترسی پیدا کنید:
for (const path in modules) {
modules[path]().then((mod) => {
console.log(path, mod)
})
}
فایلهای پیدا شده به طور پیشفرض از طریق ایمپورت داینامیک به صورت lazy-loaded بارگذاری میشوند و در زمان بیلد به چندین chunk (بخش) جداگانه تقسیم میشوند. اگر ترجیح میدهید همه ماژولها را مستقیماً ایمپورت کنید (مثلاً برای اعمال اثرات جانبی این ماژولها در ابتدا)، میتوانید { eager: true }
را به عنوان آرگومان دوم پاس دهید:
const modules = import.meta.glob('./dir/*.js', { eager: true })
کد بالا به شکل زیر تبدیل خواهد شد:
// Vite کد تولید شده توسط
import * as __vite_glob_0_0 from './dir/bar.js'
import * as __vite_glob_0_1 from './dir/foo.js'
const modules = {
'./dir/bar.js': __vite_glob_0_0,
'./dir/foo.js': __vite_glob_0_1,
}
الگوهای متعدد
آرگومان اول میتواند یک آرایه از glob ها باشد، برای مثال:
const modules = import.meta.glob(['./dir/*.js', './another/*.js'])
الگوهای منفی
الگوهای glob منفی نیز پشتیبانی میشوند (با پیشوند !
). برای نادیده گرفتن برخی فایلها از نتیجه، میتوانید الگوهای exclude را به آرگومان اول اضافه کنید:
const modules = import.meta.glob(['./dir/*.js', '!**/bar.js'])
// Vite کد تولید شده توسط
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
}
ایمپورتهای نامگذاری شده
امکان ایمپورت بخشهایی از ماژولها با استفاده از گزینه import
وجود دارد.
const modules = import.meta.glob('./dir/*.js', { import: 'setup' })
// Vite کد تولید شده توسط
const modules = {
'./dir/bar.js': () => import('./dir/bar.js').then((m) => m.setup),
'./dir/foo.js': () => import('./dir/foo.js').then((m) => m.setup),
}
هنگامی که با eager
ترکیب شود، حتی میتوان tree-shaking را برای این ماژولها فعال کرد.
const modules = import.meta.glob('./dir/*.js', {
import: 'setup',
eager: true,
})
// Vite کد تولید شده توسط
import { setup as __vite_glob_0_0 } from './dir/bar.js'
import { setup as __vite_glob_0_1 } from './dir/foo.js'
const modules = {
'./dir/bar.js': __vite_glob_0_0,
'./dir/foo.js': __vite_glob_0_1,
}
برای ایمپورت خروجی پیشفرض، import
را به default
تنظیم کنید.
const modules = import.meta.glob('./dir/*.js', {
import: 'default',
eager: true,
})
// Vite کد تولید شده توسط
import { default as __vite_glob_0_0 } from './dir/bar.js'
import { default as __vite_glob_0_1 } from './dir/foo.js'
const modules = {
'./dir/bar.js': __vite_glob_0_0,
'./dir/foo.js': __vite_glob_0_1,
}
کوئریهای سفارشی
همچنین میتوانید از گزینه query
برای ارائه کوئریها به ایمپورتها استفاده کنید، به عنوان مثال، برای ایمپورت asset ها به عنوان رشته یا به عنوان URL:
const moduleStrings = import.meta.glob('./dir/*.svg', {
query: '?raw',
import: 'default',
})
const moduleUrls = import.meta.glob('./dir/*.svg', {
query: '?url',
import: 'default',
})
// Vite کد تولید شده توسط
const moduleStrings = {
'./dir/bar.svg': () => import('./dir/bar.svg?raw').then((m) => m['default']),
'./dir/foo.svg': () => import('./dir/foo.svg?raw').then((m) => m['default']),
}
const moduleUrls = {
'./dir/bar.svg': () => import('./dir/bar.svg?url').then((m) => m['default']),
'./dir/foo.svg': () => import('./dir/foo.svg?url').then((m) => m['default']),
}
همچنین میتوانید کوئریهای سفارشی برای استفاده سایر پلاگینها ارائه دهید:
const modules = import.meta.glob('./dir/*.js', {
query: { foo: 'bar', bar: true },
})
نکات مهم درباره Glob Import
توجه داشته باشید که:
- این یک ویژگی مخصوص Vite است و یک استاندارد وب یا ES نیست.
- الگوهای glob مانند مشخصکنندههای ایمپورت در نظر گرفته میشوند: آنها باید یا نسبی باشند (با
./
شروع شوند) یا مطلق (با/
شروع شوند و نسبت به ریشه پروژه اضافه شوند) یا یک مسیر مستعار باشند (به گزینهresolve.alias
مراجعه کنید). - تطبیق glob از طریق
tinyglobby
انجام میشود. - همچنین باید توجه داشته باشید که تمام آرگومانها در
import.meta.glob
باید به صورت ثابت پاس داده شوند. نمیتوانید از متغیرها یا عبارات در آنها استفاده کنید.
ایمپورت داینامیک
مشابه glob import، ابزار Vite همچنین از ایمپورت داینامیک با متغیرها پشتیبانی میکند.
const module = await import(`./dir/${file}.js`)
توجه داشته باشید که متغیرها فقط نام فایلها را در یک عمق نشان میدهند. اگر file
برابر با 'foo/bar'
باشد، ایمپورت شکست خواهد خورد. برای استفاده پیشرفتهتر، میتوانید از ویژگی glob import استفاده کنید.
WebAssembly
فایلهای .wasm
پیشکامپایل شده را میتوان با ?init
ایمپورت کرد. خروجی پیشفرض یک تابع راهاندازی خواهد بود که یک Promise از WebAssembly.Instance
را برمیگرداند:
import init from './example.wasm?init'
init().then((instance) => {
instance.exports.test()
})
تابع init همچنین میتواند یک importObject بگیرد که به عنوان آرگومان دوم به WebAssembly.instantiate
پاس داده میشود:
init({
imports: {
someFunc: () => {
/* ... */
},
},
}).then(() => {
/* ... */
})
در بیلد پروداکش، فایلهای .wasm
که کوچکتر از assetInlineLimit
هستند به صورت رشتههای base64 درونخطی خواهند شد. در غیر این صورت، به عنوان یک asset استاتیک در نظر گرفته میشوند و در صورت درخواست بارگذاری خواهند شد.
نکته
پیشنهاد یکپارچهسازی ماژول ES برای WebAssembly در حال حاضر پشتیبانی نمیشود. از vite-plugin-wasm
یا سایر پلاگینهای جامعه برای مدیریت این موضوع استفاده کنید.
دسترسی به ماژول WebAssembly
اگر نیاز به دسترسی به آبجکت Module
دارید، مثلاً برای نمونهسازی چندباره آن، از یک ایمپورت URL صریح برای حل و فصل asset استفاده کنید و سپس نمونهسازی را انجام دهید:
import wasmUrl from 'foo.wasm?url'
const main = async () => {
const responsePromise = fetch(wasmUrl)
const { module, instance } =
await WebAssembly.instantiateStreaming(responsePromise)
/* ... */
}
main()
دریافت ماژول در Node.js
در SSR، در fetch()
که به عنوان بخشی از ایمپورت ?init
انجام میشود، ممکن است با خطای TypeError: Invalid URL
مواجه شود. به مشکل پشتیبانی از wasm در SSR مراجعه کنید.
در اینجا یک روش جایگزین آورده شده است، با فرض اینکه پایه پروژه دایرکتوری فعلی است:
import wasmUrl from 'foo.wasm?url'
import { readFile } from 'node:fs/promises'
const main = async () => {
const resolvedUrl = (await import('./test/boot.test.wasm?url')).default
const buffer = await readFile('.' + resolvedUrl)
const { instance } = await WebAssembly.instantiate(buffer, {
/* ... */
})
/* ... */
}
main()
Web Workers
ایمپورت با سازندهها (Constructors)
یک اسکریپت web worker میتواند با استفاده از new Worker()
و new SharedWorker()
ایمپورت شود. در مقایسه با پسوندهای worker، این سینتکس به استانداردها نزدیکتر است و روش توصیهشده برای ایجاد workers است.
const worker = new Worker(new URL('./worker.js', import.meta.url))
سازنده Worker همچنین گزینههایی را میپذیرد که میتوان از آنها برای ایجاد «ماژول Worker» استفاده کرد:
const worker = new Worker(new URL('./worker.js', import.meta.url), {
type: 'module',
})
شناسایی Worker تنها در صورتی کار میکند که سازنده new URL()
بهطور مستقیم در دستور new Worker()
استفاده شده باشد. علاوه بر این، تمامی پارامترها باید مقادیر ثابتی مانند رشتههای ثابت باشند.
ایمپورت با پسوندهای دارای کوئری
یک اسکریپت web worker میتواند با اضافه کردن ?worker
یا ?sharedworker
به درخواست ایمپورت، مستقیماً ایمپورت شود. خروجی پیشفرض یک سازنده worker سفارشی خواهد بود:
import MyWorker from './worker?worker'
const worker = new MyWorker()
اسکریپت worker میتواند از دستور ESM import
به جای importScripts()
استفاده کند. توجه: در زمان توسعه، این موضوع به پشتیبانی بومی مرورگر متکی است، اما در زمان بیلد پروداکشن، کد ماژولها کامپایل و از بین میرود.
به طور پیشفرض، اسکریپت worker در بیلد پروداکشن به صورت یک chunk جداگانه خروجی گرفته میشود. اگر میخواهید worker را به صورت رشتههای base64 درونخطی کنید، کوئری inline
را اضافه کنید:
import MyWorker from './worker?worker&inline'
اگر مایلید worker را به صورت یک URL دریافت کنید، کوئری url
را اضافه کنید:
import MyWorker from './worker?worker&url'
برای مشاهده جزییات درباره نحوه باندل شدن همهی worker ها، به گزینههای Worker مراجعه کنید.
سیاست امنیت محتوایی (CSP)
به دلیل ساختار داخلی Vite، برای استفاده از CSP باید بعضی دستورالعملها یا تنظیمات خاص اعمال شوند.
'nonce-{RANDOM}'
وقتی html.cspNonce
تنظیم شود، Vite یک اتریبیوت nonce با مقدار تعیینشده به تمام تگهای <script>
و <style>
اضافه میکند و همچنین تگهای <link>
برای استایلها و ماژولهای preload. علاوه بر این، وقتی این گزینه تنظیم شود، Vite یک تگ متا نیز تزریق میکند.
(<meta property="csp-nonce" nonce="PLACEHOLDER" />
).
مقدار nonce در یک تگ متا با property="csp-nonce"
هنگام توسعه و پس از بیلد، در صورت نیاز توسط Vite استفاده میشود.
هشدار
اطمینان حاصل کنید که این placeholder را برای هر درخواست با مقدار یکتایی جایگزین کنید. این کار برای جلوگیری از دور زدن سیاست امنیتی محتوا ضروری است.
data:
Vite به طور پیشفرض، در زمان بیلد، asset های کوچک را به صورت data URIs درونخطی میکند. برای استفاده از آن در بخشهای مرتبط (مثلاً img-src
و font-src
) باید data:
مجاز باشد، یا با تنظیم build.assetsInlineLimit: 0
میتوانید آن را غیرفعال کنید.
هشدار
هرگز data:
را برای script-src
مجاز نکنید. این کار امکان تزریق اسکریپتهای دلخواه را فراهم میکند.
بهینهسازی بیلد
امکانات زیر به صورت خودکار در فرآیند بیلد اعمال میشوند و نیازی به پیکربندی صریح ندارند، مگر در صورتی که بخواهید آنها را غیرفعال کنید.
تقسیم کد CSS
Vite به صورت خودکار CSS استفادهشده توسط ماژولهای موجود در یک chunk ناهمگام (chunk ناهمگام 'async chunk'، منظور بخشی از کد است که به صورت مجزا و در زمان نیاز بارگذاری میشود) را استخراج کرده و یک فایل جداگانه برای آن ایجاد میکند. این فایل CSS به صورت خودکار از طریق یک تگ <link>
هنگام بارگیری chunk ناهمگام لود میشود و اطمینان حاصل میشود که ارزیابی chunk بعد از بارگیری کامل CSS انجام شود تا از FOUC جلوگیری شود.
اگر ترجیح میدهید تمام CSS در یک فایل گردآوری شود، میتوانید با تنظیم build.cssCodeSplit
روی false
تقسیم کد CSS را غیرفعال کنید.
تولید دستورالعملهای پیشبارگیری
Vite به طور خودکار دستورالعملهای <link rel="modulepreload">
را برای بخشهای ورودی و ایمپورتهای مستقیم آنها در HTML نهایی تولید میکند.
بهینهسازی بارگیری بخشهای async
در برنامههای دنیای واقعی، Rollup اغلب "بخشهای مشترک" را تولید میکند - کدهایی که بین دو یا چند بخش دیگر به اشتراک گذاشته میشوند. همراه با ایمپورتهای پویا، چنین سناریویی بسیار رایج است:
در سناریوهای بهینهنشده، وقتی بخش A
که async هست ایمپورت میشود، مرورگر باید ابتدا A
را درخواست و پردازش کند تا متوجه شود که به بخش مشترک C
نیز نیاز دارد. این باعث یک رفت و برگشت اضافی در شبکه میشود:
Entry ---> A ---> C
Vite به طور خودکار فراخوانیهای ایمپورت پویای تقسیمشده کد را با یک مرحله پیشبارگیری بازنویسی میکند، به طوری که وقتی A
درخواست میشود، C
به صورت موازی دریافت میشود:
Entry ---> (A + C)
ممکن است C
نیز ایمپورتهای دیگری داشته باشد که در حالت بهینهنشده منجر به رفت و برگشتهای بیشتری میشود. بهینهسازی Vite تمام ایمپورتهای مستقیم را ردیابی میکند تا صرف نظر از عمق ایمپورت، رفت و برگشتها را به طور کامل حذف کند.