|
1 | 1 | import colors from 'picocolors'
|
2 | 2 | import _debug from 'debug'
|
| 3 | +import glob from 'fast-glob' |
3 | 4 | import { getHash } from '../utils'
|
| 5 | +import { transformRequest } from '../server/transformRequest' |
4 | 6 | import type { ResolvedConfig, ViteDevServer } from '..'
|
5 | 7 | import {
|
6 | 8 | addOptimizedDepInfo,
|
@@ -65,6 +67,9 @@ export async function initDepsOptimizer(
|
65 | 67 | isOptimizedDepUrl: createIsOptimizedDepUrl(config),
|
66 | 68 | getOptimizedDepId: (depInfo: OptimizedDepInfo) =>
|
67 | 69 | isBuild ? depInfo.file : `${depInfo.file}?v=${depInfo.browserHash}`,
|
| 70 | + registerWorkersSource, |
| 71 | + delayDepsOptimizerUntil, |
| 72 | + resetRegisteredIds, |
68 | 73 | options: config.optimizeDeps
|
69 | 74 | }
|
70 | 75 |
|
@@ -101,8 +106,12 @@ export async function initDepsOptimizer(
|
101 | 106 | let enqueuedRerun: (() => void) | undefined
|
102 | 107 | let currentlyProcessing = false
|
103 | 108 |
|
| 109 | + // Only pretransform optimizeDeps.entries on cold start |
| 110 | + let optimizeDepsEntriesVisited = !!cachedMetadata |
| 111 | + |
104 | 112 | // If there wasn't a cache or it is outdated, we need to prepare a first run
|
105 | 113 | let firstRunCalled = !!cachedMetadata
|
| 114 | + |
106 | 115 | if (!cachedMetadata) {
|
107 | 116 | if (!scan) {
|
108 | 117 | // Initialize discovered deps with manually added optimizeDeps.include info
|
@@ -496,5 +505,85 @@ export async function initDepsOptimizer(
|
496 | 505 | }, timeout)
|
497 | 506 | }
|
498 | 507 |
|
| 508 | + const runOptimizerIfIdleAfterMs = 100 |
| 509 | + |
| 510 | + let registeredIds: { id: string; done: () => Promise<any> }[] = [] |
| 511 | + let seenIds = new Set<string>() |
| 512 | + let workersSources = new Set<string>() |
| 513 | + let waitingOn: string | undefined |
| 514 | + |
| 515 | + function resetRegisteredIds() { |
| 516 | + registeredIds = [] |
| 517 | + seenIds = new Set<string>() |
| 518 | + workersSources = new Set<string>() |
| 519 | + waitingOn = undefined |
| 520 | + } |
| 521 | + |
| 522 | + function registerWorkersSource(id: string): void { |
| 523 | + workersSources.add(id) |
| 524 | + if (waitingOn === id) { |
| 525 | + waitingOn = undefined |
| 526 | + } |
| 527 | + } |
| 528 | + |
| 529 | + function delayDepsOptimizerUntil(id: string, done: () => Promise<any>): void { |
| 530 | + if (!depsOptimizer.isOptimizedDepFile(id) && !seenIds.has(id)) { |
| 531 | + seenIds.add(id) |
| 532 | + registeredIds.push({ id, done }) |
| 533 | + runOptimizerWhenIdle() |
| 534 | + } |
| 535 | + if (server && !optimizeDepsEntriesVisited) { |
| 536 | + optimizeDepsEntriesVisited = true |
| 537 | + preTransformOptimizeDepsEntries(server) |
| 538 | + } |
| 539 | + } |
| 540 | + |
| 541 | + function runOptimizerWhenIdle() { |
| 542 | + if (!waitingOn) { |
| 543 | + const next = registeredIds.pop() |
| 544 | + if (next) { |
| 545 | + waitingOn = next.id |
| 546 | + const afterLoad = () => { |
| 547 | + waitingOn = undefined |
| 548 | + if (registeredIds.length > 0) { |
| 549 | + runOptimizerWhenIdle() |
| 550 | + } else if (!workersSources.has(next.id)) { |
| 551 | + getDepsOptimizer(config)?.run() |
| 552 | + } |
| 553 | + } |
| 554 | + next |
| 555 | + .done() |
| 556 | + .then(() => { |
| 557 | + setTimeout( |
| 558 | + afterLoad, |
| 559 | + registeredIds.length > 0 ? 0 : runOptimizerIfIdleAfterMs |
| 560 | + ) |
| 561 | + }) |
| 562 | + .catch(afterLoad) |
| 563 | + } |
| 564 | + } |
| 565 | + } |
| 566 | + |
499 | 567 | return depsOptimizer
|
500 | 568 | }
|
| 569 | + |
| 570 | +export async function preTransformOptimizeDepsEntries( |
| 571 | + server: ViteDevServer |
| 572 | +): Promise<void> { |
| 573 | + const { config } = server |
| 574 | + const { entries } = config.optimizeDeps |
| 575 | + if (entries) { |
| 576 | + const explicitEntries = await glob(entries, { |
| 577 | + cwd: config.root, |
| 578 | + ignore: ['**/node_modules/**', `**/${config.build.outDir}/**`], |
| 579 | + absolute: true |
| 580 | + }) |
| 581 | + // TODO: should we restrict the entries to JS and HTML like the |
| 582 | + // scanner did? I think we can let the user chose any entry |
| 583 | + for (const entry of explicitEntries) { |
| 584 | + transformRequest(entry, server, { ssr: false }).catch((e) => { |
| 585 | + config.logger.error(e.message) |
| 586 | + }) |
| 587 | + } |
| 588 | + } |
| 589 | +} |
0 commit comments