( environment: DevEnvironment, url: string, options: TransformOptionsInternal, )
| 76 | // but conceptually this is: `environment.transformRequest(url, options)` |
| 77 | |
| 78 | export function transformRequest( |
| 79 | environment: DevEnvironment, |
| 80 | url: string, |
| 81 | options: TransformOptionsInternal, |
| 82 | ): Promise<TransformResult | null> { |
| 83 | if (environment._closing && environment.config.dev.recoverable) |
| 84 | throwClosedServerError() |
| 85 | |
| 86 | // This module may get invalidated while we are processing it. For example |
| 87 | // when a full page reload is needed after the re-processing of pre-bundled |
| 88 | // dependencies when a missing dep is discovered. We save the current time |
| 89 | // to compare it to the last invalidation performed to know if we should |
| 90 | // cache the result of the transformation or we should discard it as stale. |
| 91 | // |
| 92 | // A module can be invalidated due to: |
| 93 | // 1. A full reload because of pre-bundling newly discovered deps |
| 94 | // 2. A full reload after a config change |
| 95 | // 3. The file that generated the module changed |
| 96 | // 4. Invalidation for a virtual module |
| 97 | // |
| 98 | // For 1 and 2, a new request for this module will be issued after |
| 99 | // the invalidation as part of the browser reloading the page. For 3 and 4 |
| 100 | // there may not be a new request right away because of HMR handling. |
| 101 | // In all cases, the next time this module is requested, it should be |
| 102 | // re-processed. |
| 103 | // |
| 104 | // We save the timestamp when we start processing and compare it with the |
| 105 | // last time this module is invalidated |
| 106 | const timestamp = monotonicDateNow() |
| 107 | |
| 108 | url = removeTimestampQuery(url) |
| 109 | |
| 110 | const pending = environment._pendingRequests.get(url) |
| 111 | if (pending) { |
| 112 | return environment.moduleGraph.getModuleByUrl(url).then((module) => { |
| 113 | if (!module || pending.timestamp > module.lastInvalidationTimestamp) { |
| 114 | // The pending request is still valid, we can safely reuse its result |
| 115 | return pending.request |
| 116 | } else { |
| 117 | // Request 1 for module A (pending.timestamp) |
| 118 | // Invalidate module A (module.lastInvalidationTimestamp) |
| 119 | // Request 2 for module A (timestamp) |
| 120 | |
| 121 | // First request has been invalidated, abort it to clear the cache, |
| 122 | // then perform a new doTransform. |
| 123 | pending.abort() |
| 124 | return transformRequest(environment, url, options) |
| 125 | } |
| 126 | }) |
| 127 | } |
| 128 | |
| 129 | const request = doTransform(environment, url, options, timestamp) |
| 130 | |
| 131 | // Avoid clearing the cache of future requests if aborted |
| 132 | let cleared = false |
| 133 | const clearCache = () => { |
| 134 | if (!cleared) { |
| 135 | environment._pendingRequests.delete(url) |
no test coverage detected