11import browserslist from "browserslist" ;
22import { findSuggestion } from "@babel/helper-validator-option" ;
33import browserModulesData from "@babel/compat-data/native-modules" ;
4+ import LruCache from "lru-cache" ;
45
56import {
67 semverify ,
@@ -45,7 +46,7 @@ function validateTargetNames(targets: Targets): TargetsTuple {
4546 }
4647 }
4748
48- return targets as any ;
49+ return targets ;
4950}
5051
5152export function isBrowsersQueryValid ( browsers : unknown ) : boolean {
@@ -70,7 +71,7 @@ function getLowestVersions(browsers: Array<string>): Targets {
7071 BrowserslistBrowserName ,
7172 string ,
7273 ] ;
73- const target : Target = browserNameMap [ browserName ] ;
74+ const target = browserNameMap [ browserName ] ;
7475
7576 if ( ! target ) {
7677 return all ;
@@ -108,7 +109,7 @@ function getLowestVersions(browsers: Array<string>): Targets {
108109
109110function outputDecimalWarning (
110111 decimalTargets : Array < { target : string ; value : number } > ,
111- ) : void {
112+ ) {
112113 if ( ! decimalTargets . length ) {
113114 return ;
114115 }
@@ -123,7 +124,7 @@ getting parsed as 6.1, which can lead to unexpected behavior.
123124` ) ;
124125}
125126
126- function semverifyTarget ( target : keyof Targets , value : string ) {
127+ function semverifyTarget ( target : Target , value : string ) {
127128 try {
128129 return semverify ( value ) ;
129130 } catch ( error ) {
@@ -141,7 +142,7 @@ function nodeTargetParser(value: true | string) {
141142 value === true || value === "current"
142143 ? process . versions . node
143144 : semverifyTarget ( "node" , value ) ;
144- return [ "node" as const , parsed ] as const ;
145+ return [ "node" , parsed ] as const ;
145146}
146147
147148function defaultTargetParser (
@@ -158,7 +159,7 @@ function generateTargets(inputTargets: InputTargets): Targets {
158159 const input = { ...inputTargets } ;
159160 delete input . esmodules ;
160161 delete input . browsers ;
161- return input as any as Targets ;
162+ return input ;
162163}
163164
164165function resolveTargets ( queries : Browsers , env ?: string ) : Targets {
@@ -169,6 +170,18 @@ function resolveTargets(queries: Browsers, env?: string): Targets {
169170 return getLowestVersions ( resolved ) ;
170171}
171172
173+ const targetsCache = new LruCache ( { max : 64 } ) ;
174+
175+ function resolveTargetsCached ( queries : Browsers , env ?: string ) : Targets {
176+ const cacheKey = typeof queries === "string" ? queries : queries . join ( ) + env ;
177+ let cached = targetsCache . get ( cacheKey ) as Targets | undefined ;
178+ if ( ! cached ) {
179+ cached = resolveTargets ( queries , env ) ;
180+ targetsCache . set ( cacheKey , cached ) ;
181+ }
182+ return { ...cached } ;
183+ }
184+
172185type GetTargetsOption = {
173186 // This is not the path of the config file, but the path where start searching it from
174187 configPath ?: string ;
@@ -181,7 +194,7 @@ type GetTargetsOption = {
181194} ;
182195
183196export default function getTargets (
184- inputTargets : InputTargets = { } as InputTargets ,
197+ inputTargets : InputTargets = { } ,
185198 options : GetTargetsOption = { } ,
186199) : Targets {
187200 let { browsers, esmodules } = inputTargets ;
@@ -190,7 +203,7 @@ export default function getTargets(
190203 validateBrowsers ( browsers ) ;
191204
192205 const input = generateTargets ( inputTargets ) ;
193- let targets : TargetsTuple = validateTargetNames ( input ) ;
206+ let targets = validateTargetNames ( input ) ;
194207
195208 const shouldParseBrowsers = ! ! browsers ;
196209 const hasTargets = shouldParseBrowsers || Object . keys ( targets ) . length > 0 ;
@@ -233,7 +246,10 @@ export default function getTargets(
233246 // or an empty array (without any user config, use default config),
234247 // we don't need to call `resolveTargets` to execute the related methods of `browserslist` library.
235248 if ( browsers ?. length ) {
236- const queryBrowsers = resolveTargets ( browsers , options . browserslistEnv ) ;
249+ const queryBrowsers = resolveTargetsCached (
250+ browsers ,
251+ options . browserslistEnv ,
252+ ) ;
237253
238254 if ( esmodules === "intersect" ) {
239255 for ( const browser of Object . keys ( queryBrowsers ) as Target [ ] ) {
@@ -258,7 +274,7 @@ export default function getTargets(
258274 }
259275
260276 // Parse remaining targets
261- const result : Targets = { } as Targets ;
277+ const result : Targets = { } ;
262278 const decimalWarnings = [ ] ;
263279 for ( const target of Object . keys ( targets ) . sort ( ) as Target [ ] ) {
264280 const value = targets [ target ] ;
0 commit comments