UNPKG

vite-plugin-react-pages

Version:

<p> <a href="https://www.npmjs.com/package/vite-plugin-react-pages" target="_blank" rel="noopener"><img src="https://img.shields.io/npm/v/vite-plugin-react-pages.svg" alt="npm package" /></a> </p>

117 lines (105 loc) 3.06 kB
import { EventEmitter } from 'events' import { debounce } from 'mini-debounce' /** * Types of page data updates. * * add: * A new page is added. * The page list module will be updated. * update: * A page is updated. * The page list module will be updated if it is static data change * The page data module will be updated if it is runtime data change * delete: * A page is deleted. * The page list module will be updated. * Buffered update of the deleted page will be canceled. */ type Update = | { type: 'add' | 'delete' pageId: string } | { type: 'update' pageId: string dataType: 'runtime' | 'static' } export type ScheduleUpdate = (update: Update) => void /** * Buffer page data updates. * Can flush a batch of updates together * and cancel unnecessary updates */ export class PageUpdateBuffer extends EventEmitter { /** * which pages should be updated */ private pageUpdateBuffer = new Set<string>() /** * whether the page list should be updated */ private pageListUpdateBuffer = false private scheduleFlush: () => void constructor() { super() this.scheduleFlush = debounce(() => { let havePageUpdate = false if (this.pageUpdateBuffer.size > 0) { havePageUpdate = true const updates = [...this.pageUpdateBuffer.values()] this.emit('page', updates) this.pageUpdateBuffer.clear() } if (this.pageListUpdateBuffer) { // if we have just sent a page update, // we don't need to trigger page list update. // because during the page update hmr, the page list will automatically get updated // (because the whole import chain will get re-imported) if (!havePageUpdate) this.emit('page-list') this.pageListUpdateBuffer = false } }, 100) } scheduleUpdate(update: Update) { switch (update.type) { case 'add': this.pageListUpdateBuffer = true break case 'update': if (update.dataType === 'static') this.pageListUpdateBuffer = true else this.pageUpdateBuffer.add(update.pageId) break case 'delete': this.pageListUpdateBuffer = true this.pageUpdateBuffer.delete(update.pageId) break default: throw new Error(`invalid update type ${JSON.stringify(update)}`) } this.scheduleFlush() } async batchUpdate(exec: (scheduleUpdate: ScheduleUpdate) => Promise<void>) { let updates: Update[] | null = [] const _this = this try { await exec(scheduleUpdate) } finally { updates.forEach((update) => { _this.scheduleUpdate(update) }) updates = null this.scheduleFlush() } function scheduleUpdate(update: Update) { if (!updates) { // the batch lifetime has already expired // add it to buffer directly _this.scheduleUpdate(update) return } // store it, will flush these updates together later updates.push(update) } } }