استفاده از نمونههای Environment 
Experimental
رابط Environment API هنوز در مرحلهی آزمایشی (experimental) هست. با این حال، ما تلاش میکنیم بین نسخههای اصلی (major) پایداری این APIها را حفظ کنیم تا جامعهی توسعهدهندگان بتوانند با آنها کار کرده و تجربیات خود را بر اساس آنها توسعه دهند. ما قصد داریم این APIهای جدید را در یکی از نسخههای اصلی آینده به حالت پایدار (stable) برسانیم. البته ممکن است در این فرآیند تغییرات شکننده (breaking changes) نیز اعمال شود، اما این کار زمانی انجام خواهد شد که پروژهها و کتابخانههای وابسته فرصت کافی برای آزمایش و ارزیابی این قابلیتهای جدید را داشته باشند.
منابع:
- بحث و گفتگو جایی که ما در حال جمعآوری نظرات درباره APIهای جدید هستیم.
- PR مربوط به Environment API جایی که API جدید پیادهسازی و بررسی شده است.
لطفاً نظرات و بازخوردهای خود را با ما به اشتراک بگذارید.
دسترسی به محیطها 
در حالت توسعه (dev)، میتوان با استفاده از server.environments به محیطهای موجود در یک سرور توسعه دسترسی داشت:
// دریافت کنید configureServer سرور را ایجاد کنید یا آن را از هوک
const server = await createServer(/* options */)
const clientEnvironment = server.environments.client
clientEnvironment.transformRequest(url)
console.log(server.environments.ssr.moduleGraph)همچنین میتوانید از طریق پلاگینها به محیط فعلی دسترسی داشته باشید. برای جزئیات بیشتر، به API محیط برای پلاگینها مراجعه کنید.
کلاس DevEnvironment 
در حالت توسعه (dev)، هر محیط یک نمونه از کلاس DevEnvironment است:
class DevEnvironment {
  /**
   * Vite شناسهی منحصربهفرد برای محیط در یک سرور
   * را در دسترس قرار میدهد 'ssr' و 'client' محیطهای Vite ، بهطور پیشفرض
   */
  name: string
  /**
   * کانال ارتباطی برای ارسال و دریافت پیامها از
   * اجراکننده ماژول مرتبط در رانتام هدف
   */
  hot: NormalizedHotChannel
  /**
   * گراف نودهای ماژول، با روابط وارد شده بین
   * ماژولهای پردازش شده و نتیجه کش شده کد پردازش شده
   */
  moduleGraph: EnvironmentModuleGraph
  /**
   * پلاگینهای اضافه شده برای این محیط، از جمله پلاگینهایی که
   * مخصوص هر محیط ایجاد شدهاند `create` با استفاده از هوک
   */
  plugins: Plugin[]
  /**
   * امکان حل و فصل، بارگذاری و تبدیل کد را از طریق
   * مسیر پردازش پلاگین های محیط فراهم میکند
   */
  pluginContainer: EnvironmentPluginContainer
  /**
   * گزینه های تنظیمات اضافه شده برای این محیط. گزینههای موجود در
   * دامنهی کلی سرور بهعنوان پیشفرض برای تمام محیطها درنظر گرفته میشوند
   * optimizedDeps و external ، resolve conditions میتوانند بازنویسی شوند. مانند
   */
  config: ResolvedConfig & ResolvedDevEnvironmentOptions
  constructor(
    name: string,
    config: ResolvedConfig,
    context: DevEnvironmentContext,
  )
  /**
   * را به یک شناسه تبدیل میکند، آن را بارگذاری کرده و URL آدرس
   * کد را از طریق مسیر پردازش پلاگینها پردازش میکند
   * گراف ماژول نیز بهروزرسانی میشود
   */
  async transformRequest(url: string): Promise<TransformResult | null>
  /**
   * یک درخواست را برای پردازش با اولویت پایین ثبت میکند. این کار
   * اطلاعاتی Vite برای جلوگیری از وابستگیهای زنجیرهای مفید است. سرور
   * دربارهی ماژولهای ایمپورت شده توسط درخواستهای دیگر دارد، بنابراین میتواند
   * گراف ماژول را از پیش آماده کند تا ماژولها هنگام درخواست، پردازش شده باشند
   */
  async warmupRequest(url: string): Promise<void>
}با DevEnvironmentContext به صورت زیر است:
interface DevEnvironmentContext {
  hot: boolean
  transport?: HotChannel | WebSocketServer
  options?: EnvironmentOptions
  remoteRunner?: {
    inlineSourceMap?: boolean
  }
  depsOptimizer?: DepsOptimizer
}و با TransformResult به صورت زیر است:
interface TransformResult {
  code: string
  map: SourceMap | { mappings: '' } | null
  etag?: string
  deps?: string[]
  dynamicDeps?: string[]
}یک نمونه از محیط در سرور Vite به شما امکان میدهد که یک URL را با استفاده از متد environment.transformRequest(url) پردازش کنید. این تابع از خط پردازش پلاگینها برای تبدیل url به یک شناسهی ماژول (id) استفاده میکند، آن را بارگذاری میکند (با خواندن فایل از فایل سیستم یا از طریق پلاگینی که یک ماژول مجازی را پیادهسازی کرده است) و سپس کد را تبدیل میکند. در حین تبدیل ماژول،ایمپورتهای آن و دیگر اطلاعات متادیتا در گراف ماژول محیط ثبت میشوند، با ایجاد یا بهروزرسانی نود ماژول مربوطه. پس از اتمام پردازش، نتیجهی تبدیل نیز در ماژول ذخیره میشود.
نامگذاری transformRequest
در نسخهی کنونی این پیشنهاد، از transformRequest(url) و warmupRequest(url) استفاده میکنیم تا درک و بحث دربارهی آن برای کاربرانی که به API فعلی Vite عادت دارند، آسانتر باشد. پیش از انتشار، میتوانیم فرصت را برای بازبینی این نامها نیز غنیمت بشماریم. برای مثال، ممکن است نام آن را به environment.processModule(url) یا environment.loadModule(url) تغییر دهیم، مشابه context.load(id) در پلاگینهای Rollup. در حال حاضر، حفظ نامهای فعلی و به تعویق انداختن این بحث را بهتر میدانیم.
گرافهای ماژول مجزا 
هر محیط یک گراف ماژول ایزوله دارد. همه گرافهای ماژول امضای یکسانی دارند، بنابراین میتوان الگوریتمهای کلی برای پیمایش یا پیمایش گراف بدون وابستگی به محیط پیادهسازی کرد. مثال خوب آن hotUpdate است. وقتی یک فایل تغییر میکند، گراف ماژول هر محیط بررسی میشود تا ماژولهای تحت تأثیر را پیدا کند و HMR را به صورت مستقل برای هر محیط انجام دهد.
نکته
Vite نسخه ۵ یک گراف ماژول مشترک بین کلاینت و SSR داشت. اگر یک نود هنوز پردازش نشده یا باطل شده باشد، نمیتوان تشخیص داد که مربوط به محیط کلاینت، SSR، یا هر دو است. نودهای ماژول دارای برخی ویژگیهای پیشونددار هستند، مانند clientImportedModules و ssrImportedModules (بهعلاوه importedModules که اجتماع هر دو را برمیگرداند). فیلد importers همه ایمپورترهای مربوط به هر دو محیط کلاینت و SSR را برای هر نود ماژول شامل میشود. هر نود ماژول همچنین دارای transformResult و ssrTransformResult است. لایهای برای حفظ سازگاری به اکوسیستم اجازه میدهد تا از server.moduleGraph منسوخ شده به این مدل جدید مهاجرت کند.
هر ماژول توسط یک نمونه از EnvironmentModuleNode نشان داده میشود. ممکن است ماژولها در گراف بدون پردازش اولیه ثبت شوند (در این حالت، مقدار transformResult برابر null خواهد بود). فیلدهای importers و importedModules نیز پس از پردازش ماژول بهروزرسانی میشوند.
class EnvironmentModuleNode {
  environment: string
  url: string
  id: string | null = null
  file: string | null = null
  type: 'js' | 'css'
  importers = new Set<EnvironmentModuleNode>()
  importedModules = new Set<EnvironmentModuleNode>()
  importedBindings: Map<string, Set<string>> | null = null
  info?: ModuleInfo
  meta?: Record<string, any>
  transformResult: TransformResult | null = null
  acceptedHmrDeps = new Set<EnvironmentModuleNode>()
  acceptedHmrExports: Set<string> | null = null
  isSelfAccepting?: boolean
  lastHMRTimestamp = 0
  lastInvalidationTimestamp = 0
}environment.moduleGraph is an instance of EnvironmentModuleGraph:
export class EnvironmentModuleGraph {
  environment: string
  urlToModuleMap = new Map<string, EnvironmentModuleNode>()
  idToModuleMap = new Map<string, EnvironmentModuleNode>()
  etagToModuleMap = new Map<string, EnvironmentModuleNode>()
  fileToModulesMap = new Map<string, Set<EnvironmentModuleNode>>()
  constructor(
    environment: string,
    resolveId: (url: string) => Promise<PartialResolvedId | null>,
  )
  async getModuleByUrl(
    rawUrl: string,
  ): Promise<EnvironmentModuleNode | undefined>
  getModuleById(id: string): EnvironmentModuleNode | undefined
  getModulesByFile(file: string): Set<EnvironmentModuleNode> | undefined
  onFileChange(file: string): void
  onFileDelete(file: string): void
  invalidateModule(
    mod: EnvironmentModuleNode,
    seen: Set<EnvironmentModuleNode> = new Set(),
    timestamp: number = monotonicDateNow(),
    isHmr: boolean = false,
  ): void
  invalidateAll(): void
  async ensureEntryFromUrl(
    rawUrl: string,
    setIsSelfAccepting = true,
  ): Promise<EnvironmentModuleNode>
  createFileOnlyEntry(file: string): EnvironmentModuleNode
  async resolveUrl(url: string): Promise<ResolvedUrl>
  updateModuleTransformResult(
    mod: EnvironmentModuleNode,
    result: TransformResult | null,
  ): void
  getModuleByEtag(etag: string): EnvironmentModuleNode | undefined
}