[{"data":1,"prerenderedAt":1044},["ShallowReactive",2],{"content:\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fremoving-unneeded-polyfills-with-browserslist":3,"surroundings:\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fremoving-unneeded-polyfills-with-browserslist":1035},{"id":4,"title":5,"body":6,"description":1015,"extension":1016,"meta":1017,"navigation":1029,"path":1030,"seo":1031,"stem":1033,"__hash__":1034},"content\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fremoving-unneeded-polyfills-with-browserslist\u002Findex.md","Removing Unneeded Polyfills with Browserslist",{"type":7,"value":8,"toc":1000},"minimark",[9,14,34,37,188,193,266,270,280,286,299,309,384,388,393,396,463,466,470,473,480,561,564,568,595,611,614,745,749,759,822,825,829,839,843,872,876,890,894,906,919,932,949,958,962,985,990,993,996],[10,11,13],"h1",{"id":12},"how-to-remove-unneeded-polyfills-with-browserslist","How to Remove Unneeded Polyfills with Browserslist",[15,16,17,18,23,24,28,29,33],"p",{},"This guide is part of ",[19,20,22],"a",{"href":21},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002F","Polyfills & Differential Serving"," in ",[19,25,27],{"href":26},"\u002Fjavascript-bundle-optimization-code-splitting\u002F","JavaScript Bundle Optimization & Code Splitting",". Browserslist is the shared configuration that Babel's preset-env, SWC, ",[30,31,32],"code",{},"core-js"," (through Babel), Autoprefixer, Lightning CSS and many other tools read to decide what to transform. One outdated query — often copied from a project template years ago — quietly instructs all of them to support browsers your visitors abandoned long ago.",[15,35,36],{},"The fix is to replace a guessed query with one derived from your own traffic, then verify that each tool actually honours it. On typical single-page apps this removes 20–60KB of compressed JavaScript and a matching amount of CSS prefixes, with no change in behaviour for the browsers people actually use.",[15,38,39],{},[40,41,47,48,47,55,47,59,47,62,47,80,47,88,47,94,47,102,47,109,47,114,47,118,47,121,47,125,47,128,47,131,47,137,47,141,47,144,47,147,47,151,47,154,47,157,47,160,47,164,47,167,47,176,47,180,47,184,47],"svg",{"viewBox":42,"width":43,"role":44,"ariaLabel":45,"style":46},"0 0 760 149","100%","img","Steps from exporting browser usage data to a Browserslist query consumed by every build tool.","height:auto;max-width:760px;display:block;margin:1.75rem auto;font-family:inherit;color:var(--fp-svg-ink)"," ",[49,50],"rect",{"className":51,"x":53,"y":53,"width":43,"height":43,"fill":54},[52],"svg-canvas","0","#ffffff",[56,57,58],"title",{},"From analytics to a lean bundle",[60,61,45],"desc",{},[63,64,65],"defs",{},[66,67,74],"marker",{"id":68,"viewBox":69,"refX":70,"refY":71,"markerWidth":72,"markerHeight":72,"orient":73},"fa17f9c221","0 0 10 10","9","5","7","auto-start-reverse",[75,76],"path",{"d":77,"fill":78,"style":79},"M0 0 L10 5 L0 10 z","currentColor","fill-opacity:0.7",[49,81],{"x":82,"y":82,"width":83,"height":84,"rx":85,"fill":86,"stroke":78,"style":87},"1","758","147","10","none","stroke-opacity:0.18",[89,90,58],"text",{"x":91,"y":92,"fill":78,"style":93},"28.0","34.0","font-size:16px;font-weight:700",[49,95],{"x":91,"y":96,"width":97,"height":98,"rx":99,"fill":100,"stroke":100,"style":101},"56.0","108.8","71.0","6","#0466c8","fill-opacity:0.14;stroke-opacity:0.9",[89,103,108],{"x":104,"y":105,"fill":78,"style":106,"textAnchor":107},"82.4","78.0","font-size:13px;font-weight:700","middle","Export usage",[89,110,113],{"x":104,"y":111,"fill":78,"style":112,"textAnchor":107},"96.0","font-size:12px","90 days of",[89,115,117],{"x":104,"y":116,"fill":78,"style":112,"textAnchor":107},"112.0","browser versions",[49,119],{"x":120,"y":96,"width":97,"height":98,"rx":99,"fill":100,"stroke":100,"style":101},"176.8",[89,122,124],{"x":123,"y":105,"fill":78,"style":106,"textAnchor":107},"231.2","Define policy",[89,126,127],{"x":123,"y":111,"fill":78,"style":112,"textAnchor":107},"e.g. 99%",[89,129,130],{"x":123,"y":116,"fill":78,"style":112,"textAnchor":107},"coverage",[49,132],{"x":133,"y":96,"width":97,"height":98,"rx":99,"fill":134,"stroke":135,"style":136},"325.6","#ffc300","#b8860b","fill-opacity:0.24;stroke-opacity:0.9",[89,138,140],{"x":139,"y":105,"fill":78,"style":106,"textAnchor":107},"380.0","Write query",[89,142,143],{"x":139,"y":111,"fill":78,"style":112,"textAnchor":107},".browserslistrc",[49,145],{"x":146,"y":96,"width":97,"height":98,"rx":99,"fill":100,"stroke":100,"style":101},"474.4",[89,148,150],{"x":149,"y":105,"fill":78,"style":106,"textAnchor":107},"528.8","Tools read it",[89,152,153],{"x":149,"y":111,"fill":78,"style":112,"textAnchor":107},"Babel, SWC,",[89,155,156],{"x":149,"y":116,"fill":78,"style":112,"textAnchor":107},"PostCSS",[49,158],{"x":159,"y":96,"width":97,"height":98,"rx":99,"fill":100,"stroke":100,"style":101},"623.2",[89,161,163],{"x":162,"y":105,"fill":78,"style":106,"textAnchor":107},"677.6","Verify output",[89,165,166],{"x":162,"y":111,"fill":78,"style":112,"textAnchor":107},"treemap + grep",[168,169],"line",{"x1":170,"y1":171,"x2":172,"y2":171,"stroke":78,"strokeWidth":173,"style":174,"markerEnd":175},"136.8","91.5","174.8","1.5","stroke-opacity:0.6","url(#fa17f9c221)",[168,177],{"x1":178,"y1":171,"x2":179,"y2":171,"stroke":78,"strokeWidth":173,"style":174,"markerEnd":175},"285.6","323.6",[168,181],{"x1":182,"y1":171,"x2":183,"y2":171,"stroke":78,"strokeWidth":173,"style":174,"markerEnd":175},"434.4","472.4",[168,185],{"x1":186,"y1":171,"x2":187,"y2":171,"stroke":78,"strokeWidth":173,"style":174,"markerEnd":175},"583.2","621.2",[189,190,192],"h2",{"id":191},"rapid-diagnosis","Rapid Diagnosis",[194,195,196,207,228,252],"ul",{},[197,198,199,47,203,206],"li",{},[200,201,202],"strong",{},"Print the current matrix:",[30,204,205],{},"npx browserslist",". If it lists Internet Explorer, very old Safari, Opera Mini or Android 4.x browsers, the query is outdated.",[197,208,209,212,213,216,217,220,221,223,224,227],{},[200,210,211],{},"Check for multiple sources of truth."," A ",[30,214,215],{},"browserslist"," key in ",[30,218,219],{},"package.json"," and a ",[30,222,143],{}," file, or per-tool ",[30,225,226],{},"targets"," options in Babel config, can disagree.",[197,229,230,47,233,236,237,240,241,243,244,247,248,251],{},[200,231,232],{},"Check environment sections.",[30,234,235],{},"[production]"," and ",[30,238,239],{},"[development]"," sections in ",[30,242,143],{}," apply depending on ",[30,245,246],{},"BROWSERSLIST_ENV"," or ",[30,249,250],{},"NODE_ENV","; production may still use an old list.",[197,253,254,257,258,261,262,265],{},[200,255,256],{},"Look for polyfills in the treemap"," (",[30,259,260],{},"core-js\u002Fmodules\u002F...",") and helpers (",[30,263,264],{},"regenerator-runtime",").",[189,267,269],{"id":268},"root-cause-analysis","Root Cause Analysis",[15,271,272,275,276,279],{},[200,273,274],{},"1. Template defaults."," Starters shipped years ago with queries like ",[30,277,278],{},"> 0.25%, not dead, ie 11"," that persist unexamined.",[15,281,282,285],{},[200,283,284],{},"2. Global usage instead of your usage."," Queries based on global percentages include browsers that are popular somewhere but absent from your audience.",[15,287,288,291,292,294,295,298],{},[200,289,290],{},"3. Tool-specific overrides."," A Babel ",[30,293,226],{}," option overrides Browserslist for Babel only, so CSS and JS disagree; or SWC is configured with an explicit ",[30,296,297],{},"env.targets"," that nobody updates.",[15,300,301,304,305,308],{},[200,302,303],{},"4. Stale caniuse data."," Browserslist resolves queries using the ",[30,306,307],{},"caniuse-lite"," database installed in your project. Old data makes \"last 2 versions\" mean versions from the past.",[15,310,311],{},[40,312,47,315,47,318,47,321,47,323,47,326,47,328,47,335,47,342,47,347,47,351,47,356,47,360,47,364,47,368,47,372,47,376,47,380,47],{"viewBox":313,"width":43,"role":44,"ariaLabel":314,"style":46},"0 0 760 194","Bar chart of production JavaScript and CSS before and after replacing a template Browserslist query with one derived from traffic.",[49,316],{"className":317,"x":53,"y":53,"width":43,"height":43,"fill":54},[52],[56,319,320],{},"Output size change from tightening Browserslist",[60,322,314],{},[49,324],{"x":82,"y":82,"width":83,"height":325,"rx":85,"fill":86,"stroke":78,"style":87},"192",[89,327,320],{"x":91,"y":92,"fill":78,"style":93},[89,329,334],{"x":330,"y":331,"fill":78,"style":332,"textAnchor":333},"181.1","70.0","font-size:13px","end","JS before (template query)",[49,336],{"x":337,"y":96,"width":338,"height":339,"rx":340,"fill":134,"stroke":135,"style":341},"193.1","474.9","19","3","fill-opacity:0.7;stroke-opacity:0.9",[89,343,346],{"x":344,"y":331,"fill":78,"style":345},"674.0","font-size:12px;font-weight:600","296KB",[89,348,350],{"x":330,"y":349,"fill":78,"style":332,"textAnchor":333},"101.0","JS after (traffic query)",[49,352],{"x":337,"y":353,"width":354,"height":339,"rx":340,"fill":100,"stroke":100,"style":355},"87.0","391.5","fill-opacity:0.55;stroke-opacity:0.9",[89,357,359],{"x":358,"y":349,"fill":78,"style":345},"590.6","244KB",[89,361,363],{"x":330,"y":362,"fill":78,"style":332,"textAnchor":333},"132.0","CSS before",[49,365],{"x":337,"y":366,"width":367,"height":339,"rx":340,"fill":134,"stroke":135,"style":341},"118.0","97.9",[89,369,371],{"x":370,"y":362,"fill":78,"style":345},"297.0","61KB",[89,373,375],{"x":330,"y":374,"fill":78,"style":332,"textAnchor":333},"163.0","CSS after",[49,377],{"x":337,"y":378,"width":379,"height":339,"rx":340,"fill":100,"stroke":100,"style":355},"149.0","83.4",[89,381,383],{"x":382,"y":374,"fill":78,"style":345},"282.5","52KB",[189,385,387],{"id":386},"step-by-step-resolution","Step-by-Step Resolution",[389,390,392],"h3",{"id":391},"_1-build-a-usage-based-query","1. Build a usage-based query",[15,394,395],{},"Export browser versions from your analytics, convert them to a Browserslist stats file, and query against it.",[397,398,403],"pre",{"className":399,"code":400,"language":401,"meta":402,"style":402},"language-bash shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","# browserslist-ga or similar tools convert analytics exports into browserslist-stats.json.\nnpx browserslist-ga-export --reportPath report.csv   # produces browserslist-stats.json\nnpx browserslist \"> 0.2% in my stats, last 2 Chrome versions, last 2 Safari versions, Firefox ESR, not dead\"\n# trade-off: \"in my stats\" reflects past traffic. Browsers you do not support\n# today will not appear in your analytics because their users already left —\n# decide policy deliberately rather than following the data in a loop.\n","bash","",[30,404,405,413,434,445,451,457],{"__ignoreMap":402},[406,407,409],"span",{"class":168,"line":408},1,[406,410,412],{"class":411},"sjfSM","# browserslist-ga or similar tools convert analytics exports into browserslist-stats.json.\n",[406,414,416,420,424,428,431],{"class":168,"line":415},2,[406,417,419],{"class":418},"sQw3B","npx",[406,421,423],{"class":422},"sZ8jY"," browserslist-ga-export",[406,425,427],{"class":426},"sPXB4"," --reportPath",[406,429,430],{"class":422}," report.csv",[406,432,433],{"class":411},"   # produces browserslist-stats.json\n",[406,435,437,439,442],{"class":168,"line":436},3,[406,438,419],{"class":418},[406,440,441],{"class":422}," browserslist",[406,443,444],{"class":422}," \"> 0.2% in my stats, last 2 Chrome versions, last 2 Safari versions, Firefox ESR, not dead\"\n",[406,446,448],{"class":168,"line":447},4,[406,449,450],{"class":411},"# trade-off: \"in my stats\" reflects past traffic. Browsers you do not support\n",[406,452,454],{"class":168,"line":453},5,[406,455,456],{"class":411},"# today will not appear in your analytics because their users already left —\n",[406,458,460],{"class":168,"line":459},6,[406,461,462],{"class":411},"# decide policy deliberately rather than following the data in a loop.\n",[15,464,465],{},"Expected outcome: a matrix covering your chosen share of traffic, typically far more modern than the template.",[389,467,469],{"id":468},"_2-make-browserslist-the-single-source-of-truth","2. Make Browserslist the single source of truth",[15,471,472],{},"Remove per-tool targets so every tool reads the same matrix.",[397,474,478],{"className":475,"code":477,"language":89,"meta":402},[476],"language-text","# .browserslistrc\n[production]\n> 0.2% in my stats\nlast 2 Chrome versions\nlast 2 Safari versions\nlast 2 iOS versions\nFirefox ESR\nnot dead\n\n[development]\nlast 1 Chrome version\nlast 1 Firefox version\n",[30,479,477],{"__ignoreMap":402},[397,481,485],{"className":482,"code":483,"language":484,"meta":402,"style":402},"language-javascript shiki shiki-themes github-light-high-contrast github-dark-high-contrast github-light-high-contrast","\u002F\u002F babel.config.js — no \"targets\" here; preset-env reads .browserslistrc.\nmodule.exports = {\n  presets: [['@babel\u002Fpreset-env', { useBuiltIns: 'usage', corejs: '3.40', bugfixes: true }]],\n};\n\u002F\u002F trade-off: useBuiltIns 'usage' injects polyfills per file based on what that\n\u002F\u002F file uses, which is precise but can miss APIs used by un-transpiled\n\u002F\u002F dependencies. If a dependency needs a polyfill, add it explicitly in the entry.\n","javascript",[30,486,487,492,511,540,545,550,555],{"__ignoreMap":402},[406,488,489],{"class":168,"line":408},[406,490,491],{"class":411},"\u002F\u002F babel.config.js — no \"targets\" here; preset-env reads .browserslistrc.\n",[406,493,494,497,501,504,508],{"class":168,"line":415},[406,495,496],{"class":426},"module",[406,498,500],{"class":499},"saISM",".",[406,502,503],{"class":426},"exports",[406,505,507],{"class":506},"sPARh"," =",[406,509,510],{"class":499}," {\n",[406,512,513,516,519,522,525,528,531,534,537],{"class":168,"line":436},[406,514,515],{"class":499},"  presets: [[",[406,517,518],{"class":422},"'@babel\u002Fpreset-env'",[406,520,521],{"class":499},", { useBuiltIns: ",[406,523,524],{"class":422},"'usage'",[406,526,527],{"class":499},", corejs: ",[406,529,530],{"class":422},"'3.40'",[406,532,533],{"class":499},", bugfixes: ",[406,535,536],{"class":426},"true",[406,538,539],{"class":499}," }]],\n",[406,541,542],{"class":168,"line":447},[406,543,544],{"class":499},"};\n",[406,546,547],{"class":168,"line":453},[406,548,549],{"class":411},"\u002F\u002F trade-off: useBuiltIns 'usage' injects polyfills per file based on what that\n",[406,551,552],{"class":168,"line":459},[406,553,554],{"class":411},"\u002F\u002F file uses, which is precise but can miss APIs used by un-transpiled\n",[406,556,558],{"class":168,"line":557},7,[406,559,560],{"class":411},"\u002F\u002F dependencies. If a dependency needs a polyfill, add it explicitly in the entry.\n",[15,562,563],{},"Expected outcome: Babel, PostCSS and other tools produce output for one consistent matrix.",[389,565,567],{"id":566},"_3-update-caniuse-lite-and-pin-corejs","3. Update caniuse-lite and pin corejs",[397,569,571],{"className":399,"code":570,"language":401,"meta":402,"style":402},"npx update-browserslist-db@latest\n# trade-off: updating the database can change what \"last 2 versions\" means and\n# therefore your output. Commit the lockfile change in its own PR so any output\n# difference is reviewable.\n",[30,572,573,580,585,590],{"__ignoreMap":402},[406,574,575,577],{"class":168,"line":408},[406,576,419],{"class":418},[406,578,579],{"class":422}," update-browserslist-db@latest\n",[406,581,582],{"class":168,"line":415},[406,583,584],{"class":411},"# trade-off: updating the database can change what \"last 2 versions\" means and\n",[406,586,587],{"class":168,"line":436},[406,588,589],{"class":411},"# therefore your output. Commit the lockfile change in its own PR so any output\n",[406,591,592],{"class":168,"line":447},[406,593,594],{"class":411},"# difference is reviewable.\n",[15,596,597,598,601,602,604,605,607,608,610],{},"Set ",[30,599,600],{},"corejs"," to the installed minor version (for example ",[30,603,530],{},") so ",[30,606,32],{}," knows which polyfills exist and which browsers need them; a bare ",[30,609,340],{}," assumes an old feature set.",[15,612,613],{},"Expected outcome: polyfill decisions use current browser data.",[15,615,616],{},[40,617,47,620,47,623,47,626,47,628,47,631,47,633,47,638,47,645,47,649,47,653,47,656,47,660,47,664,47,668,47,670,47,673,47,675,47,678,47,681,47,685,47,687,47,690,47,692,47,695,47,698,47,702,47,704,47,706,47,708,47,711,47,714,47,718,47,720,47,723,47,725,47,728,47,731,47,735,47,737,47,740,47,742,47],{"viewBox":618,"width":43,"role":44,"ariaLabel":619,"style":46},"0 0 760 258","Common build tools, whether they read Browserslist by default, and the override that can silently bypass it.",[49,621],{"className":622,"x":53,"y":53,"width":43,"height":43,"fill":54},[52],[56,624,625],{},"Which tools read Browserslist",[60,627,619],{},[49,629],{"x":82,"y":82,"width":83,"height":630,"rx":85,"fill":86,"stroke":78,"style":87},"256",[89,632,625],{"x":91,"y":92,"fill":78,"style":93},[49,634],{"x":91,"y":96,"width":635,"height":636,"rx":53,"fill":78,"stroke":78,"style":637},"163.6","30.0","fill-opacity:0.06;stroke-opacity:0.4",[89,639,644],{"x":640,"y":641,"fill":78,"style":642,"textAnchor":643},"38.0","75.5","font-size:12.5px;font-weight:700","start","Tool",[49,646],{"x":647,"y":96,"width":648,"height":636,"rx":53,"fill":78,"stroke":78,"style":637},"191.6","270.2",[89,650,652],{"x":651,"y":641,"fill":78,"style":642,"textAnchor":107},"326.7","Reads Browserslist",[49,654],{"x":655,"y":96,"width":648,"height":636,"rx":53,"fill":78,"stroke":78,"style":637},"461.8",[89,657,659],{"x":658,"y":641,"fill":78,"style":642,"textAnchor":107},"596.9","Override to watch",[49,661],{"x":91,"y":662,"width":635,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},"86.0","stroke-opacity:0.35",[89,665,667],{"x":640,"y":666,"fill":78,"style":642,"textAnchor":643},"105.5","@babel\u002Fpreset-env",[49,669],{"x":647,"y":662,"width":648,"height":636,"rx":53,"fill":100,"stroke":100,"style":101},[89,671,672],{"x":651,"y":666,"fill":78,"style":112,"textAnchor":107},"yes",[49,674],{"x":655,"y":662,"width":648,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},[89,676,677],{"x":658,"y":666,"fill":78,"style":112,"textAnchor":107},"targets option",[49,679],{"x":91,"y":680,"width":635,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},"116.0",[89,682,684],{"x":640,"y":683,"fill":78,"style":642,"textAnchor":643},"135.5","SWC",[49,686],{"x":647,"y":680,"width":648,"height":636,"rx":53,"fill":78,"stroke":78,"style":637},[89,688,689],{"x":651,"y":683,"fill":78,"style":112,"textAnchor":107},"when env.targets unset",[49,691],{"x":655,"y":680,"width":648,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},[89,693,694],{"x":658,"y":683,"fill":78,"style":112,"textAnchor":107},"env.targets \u002F jsc.target",[49,696],{"x":91,"y":697,"width":635,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},"146.0",[89,699,701],{"x":640,"y":700,"fill":78,"style":642,"textAnchor":643},"165.5","Autoprefixer \u002F PostCSS",[49,703],{"x":647,"y":697,"width":648,"height":636,"rx":53,"fill":100,"stroke":100,"style":101},[89,705,672],{"x":651,"y":700,"fill":78,"style":112,"textAnchor":107},[49,707],{"x":655,"y":697,"width":648,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},[89,709,710],{"x":658,"y":700,"fill":78,"style":112,"textAnchor":107},"overrideBrowserslist",[49,712],{"x":91,"y":713,"width":635,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},"176.0",[89,715,717],{"x":640,"y":716,"fill":78,"style":642,"textAnchor":643},"195.5","Lightning CSS",[49,719],{"x":647,"y":713,"width":648,"height":636,"rx":53,"fill":78,"stroke":78,"style":637},[89,721,722],{"x":651,"y":716,"fill":78,"style":112,"textAnchor":107},"via browserslistToTargets",[49,724],{"x":655,"y":713,"width":648,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},[89,726,727],{"x":658,"y":716,"fill":78,"style":112,"textAnchor":107},"explicit targets",[49,729],{"x":91,"y":730,"width":635,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},"206.0",[89,732,734],{"x":640,"y":733,"fill":78,"style":642,"textAnchor":643},"225.5","esbuild \u002F Vite build.target",[49,736],{"x":647,"y":730,"width":648,"height":636,"rx":53,"fill":134,"stroke":135,"style":136},[89,738,739],{"x":651,"y":733,"fill":78,"style":112,"textAnchor":107},"no, own target list",[49,741],{"x":655,"y":730,"width":648,"height":636,"rx":53,"fill":86,"stroke":78,"style":663},[89,743,744],{"x":658,"y":733,"fill":78,"style":112,"textAnchor":107},"build.target",[389,746,748],{"id":747},"_4-align-esbuild-based-tools-manually","4. Align esbuild-based tools manually",[15,750,751,752,754,755,758],{},"esbuild (and therefore Vite's ",[30,753,744],{},") does not read Browserslist. Convert your query with ",[30,756,757],{},"browserslist-to-esbuild"," so syntax lowering matches.",[397,760,762],{"className":482,"code":761,"language":484,"meta":402,"style":402},"\u002F\u002F vite.config.js\nimport browserslistToEsbuild from 'browserslist-to-esbuild';\nexport default { build: { target: browserslistToEsbuild() } };\n\u002F\u002F trade-off: esbuild lowers syntax but never adds polyfills. If you need\n\u002F\u002F runtime polyfills with Vite, add them explicitly or use @vitejs\u002Fplugin-legacy.\n",[30,763,764,769,786,812,817],{"__ignoreMap":402},[406,765,766],{"class":168,"line":408},[406,767,768],{"class":411},"\u002F\u002F vite.config.js\n",[406,770,771,774,777,780,783],{"class":168,"line":415},[406,772,773],{"class":506},"import",[406,775,776],{"class":499}," browserslistToEsbuild ",[406,778,779],{"class":506},"from",[406,781,782],{"class":422}," 'browserslist-to-esbuild'",[406,784,785],{"class":499},";\n",[406,787,788,791,794,797,800,804,807,810],{"class":168,"line":436},[406,789,790],{"class":506},"export",[406,792,793],{"class":506}," default",[406,795,796],{"class":418}," { ",[406,798,799],{"class":499},"build: { target: ",[406,801,803],{"class":802},"smZ65","browserslistToEsbuild",[406,805,806],{"class":499},"() } ",[406,808,809],{"class":418},"}",[406,811,785],{"class":499},[406,813,814],{"class":168,"line":447},[406,815,816],{"class":411},"\u002F\u002F trade-off: esbuild lowers syntax but never adds polyfills. If you need\n",[406,818,819],{"class":168,"line":453},[406,820,821],{"class":411},"\u002F\u002F runtime polyfills with Vite, add them explicitly or use @vitejs\u002Fplugin-legacy.\n",[15,823,824],{},"Expected outcome: syntax lowering and polyfilling are both driven by the same matrix.",[189,826,828],{"id":827},"verification","Verification",[15,830,831,832,834,835,838],{},"Rebuild and compare: the treemap should show far fewer ",[30,833,32],{}," modules, and ",[30,836,837],{},"regeneratorRuntime"," should be absent if your matrix supports native async functions. Run your end-to-end tests in the oldest browser the new matrix includes (via BrowserStack, Sauce Labs or Playwright's WebKit\u002FFirefox builds) to confirm nothing broke. Measure TBT on a throttled run; expect a modest but real improvement proportional to the bytes removed.",[189,840,842],{"id":841},"common-mistakes","Common Mistakes",[194,844,845,851,857,866],{},[197,846,847,850],{},[200,848,849],{},"Deriving the query from desktop analytics only."," Mobile Safari versions lag desktop ones; make sure iOS versions are represented.",[197,852,853,856],{},[200,854,855],{},"Excluding embedded browsers."," In-app browsers (social apps' webviews) report as Chrome or Safari variants with their own version lag; check them in your stats.",[197,858,859,865],{},[200,860,861,862,500],{},"Forgetting ",[30,863,864],{},"not dead"," Without it, a percentage-based query can include discontinued browsers that still have residual traffic.",[197,867,868,871],{},[200,869,870],{},"Changing the matrix without telling support."," Users of newly unsupported browsers may see broken features; give support teams the list and a recommended upgrade path.",[189,873,875],{"id":874},"worked-example-one-query-change-three-tools","Worked Example: One Query Change, Three Tools",[15,877,878,879,882,883,885,886,889],{},"A documentation site used ",[30,880,881],{},"> 0.25%, not dead"," as its query. Running ",[30,884,205],{}," showed it included Opera Mini, UC Browser and several old Android WebViews because of their global share — none of which appeared in the site's own analytics, where 99.6% of sessions came from Chromium 110+, Safari 16+ and Firefox 115+. Replacing the query with one based on the site's stats changed three outputs at once: Babel stopped injecting 31 polyfills, Autoprefixer removed about 4KB of prefixed CSS, and Lightning CSS stopped emitting fallbacks for ",[30,887,888],{},"color-mix()"," and nesting. The pull request was a two-line configuration change; the review consisted mostly of running the end-to-end tests in Safari 16, which passed.",[189,891,893],{"id":892},"faq","FAQ",[895,896,899,903],"details",{"className":897},[898],"faq-item",[900,901,902],"summary",{},"How much traffic coverage is reasonable?",[15,904,905],{},"Most consumer sites settle between 98% and 99.5% of sessions. The remaining sessions are often bots, very old devices, or browsers that would struggle with the site regardless. For B2B products with known customer environments, use customer requirements rather than percentages.",[895,907,909,912],{"className":908},[898],[900,910,911],{},"Does a tighter matrix break old browsers completely?",[15,913,914,915,918],{},"It can, if modern syntax reaches a browser that cannot parse it — the whole script fails. Decide how unsupported browsers should behave: a server-rendered page that works without JavaScript, a feature-detected notice, or a legacy build served via ",[30,916,917],{},"nomodule",". Silently broken pages are the one outcome to avoid.",[895,920,922,925],{"className":921},[898],[900,923,924],{},"Should Browserslist differ between client and server bundles?",[15,926,927,928,931],{},"Yes. Server code should target your Node version (",[30,929,930],{},"node 20"," or similar), which every server-side tool understands. Keep the browser matrix for client builds only.",[895,933,935,938],{"className":934},[898],[900,936,937],{},"Can I check a query's effect before changing the build?",[15,939,940,941,944,945,948],{},"Yes. Run ",[30,942,943],{},"npx browserslist \"\u003Cnew query>\""," to see the resolved browsers, then build once with ",[30,946,947],{},"BROWSERSLIST=\"\u003Cnew query>\""," set in the environment, which overrides the config file for that run. Compare the output treemap with the current build before committing to the change.",[895,950,952,955],{"className":951},[898],[900,953,954],{},"What about browsers on smart TVs and consoles?",[15,956,957],{},"Some audiences — streaming and media sites in particular — have meaningful traffic from TV and console browsers based on older engine versions. They appear in analytics with distinctive user-agent strings; include them in the policy decision explicitly, since a global query will usually exclude them and a tightened one certainly will.",[189,959,961],{"id":960},"related","Related",[194,963,964,971,978],{},[197,965,966,970],{},[19,967,969],{"href":968},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fauditing-core-js-polyfill-weight\u002F","Auditing core-js polyfill weight"," — checking what remains after tightening.",[197,972,973,977],{},[19,974,976],{"href":975},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Ftargeting-baseline-browsers-with-esbuild-and-swc\u002F","Targeting baseline browsers with esbuild and SWC"," — syntax targets without Babel.",[197,979,980,984],{},[19,981,983],{"href":982},"\u002Fjavascript-bundle-optimization-code-splitting\u002Ftree-shaking-and-dead-code-elimination\u002Fesbuild-vs-terser-for-production-minification\u002F","esbuild vs Terser for production minification"," — the next step in shrinking output.",[986,987,989],"script",{"type":988},"application\u002Fld+json","\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"HowTo\",\n  \"name\": \"How to Remove Unneeded Polyfills with Browserslist\",\n  \"description\": \"Build a data-driven Browserslist configuration and use it to strip polyfills and down-levelled syntax from production bundles.\",\n  \"step\": [\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 1,\n      \"name\": \"Build a usage-based query\",\n      \"text\": \"Export browser versions from your analytics, convert them to a Browserslist stats file, and query against it.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 2,\n      \"name\": \"Make Browserslist the single source of truth\",\n      \"text\": \"Remove per-tool targets so every tool reads the same matrix.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 3,\n      \"name\": \"Update caniuse-lite and pin corejs\",\n      \"text\": \"Set corejs to the installed minor version (for example '3.40') so core-js knows which polyfills exist and which browsers need them; a bare 3 assumes an old feature set.\"\n    },\n    {\n      \"@type\": \"HowToStep\",\n      \"position\": 4,\n      \"name\": \"Align esbuild-based tools manually\",\n      \"text\": \"esbuild (and therefore Vite's build.target) does not read Browserslist.\"\n    }\n  ]\n}\n",[986,991,992],{"type":988},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"TechArticle\",\n  \"headline\": \"How to Remove Unneeded Polyfills with Browserslist\",\n  \"description\": \"Build a data-driven Browserslist configuration and use it to strip polyfills and down-levelled syntax from production bundles.\",\n  \"datePublished\": \"2026-10-06\",\n  \"dateModified\": \"2026-10-06\",\n  \"author\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": \"frontend-performance.com\"\n  },\n  \"mainEntityOfPage\": {\n    \"@type\": \"WebPage\",\n    \"@id\": \"https:\u002F\u002Ffrontend-performance.com\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fremoving-unneeded-polyfills-with-browserslist\u002F\"\n  }\n}\n",[986,994,995],{"type":988},"\n{\n  \"@context\": \"https:\u002F\u002Fschema.org\",\n  \"@type\": \"BreadcrumbList\",\n  \"itemListElement\": [\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 1,\n      \"name\": \"Home\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 2,\n      \"name\": \"JavaScript Bundle Optimization & Code Splitting\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fjavascript-bundle-optimization-code-splitting\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 3,\n      \"name\": \"Polyfills & Differential Serving\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002F\"\n    },\n    {\n      \"@type\": \"ListItem\",\n      \"position\": 4,\n      \"name\": \"Removing Unneeded Polyfills with Browserslist\",\n      \"item\": \"https:\u002F\u002Ffrontend-performance.com\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fremoving-unneeded-polyfills-with-browserslist\u002F\"\n    }\n  ]\n}\n",[997,998,999],"style",{},"html pre.shiki code .sjfSM, html code.shiki .sjfSM{--shiki-default:#66707B;--shiki-dark:#BDC4CC;--shiki-light:#66707B}html pre.shiki code .sQw3B, html code.shiki .sQw3B{--shiki-default:#702C00;--shiki-dark:#FFB757;--shiki-light:#702C00}html pre.shiki code .sZ8jY, html code.shiki .sZ8jY{--shiki-default:#032563;--shiki-dark:#ADDCFF;--shiki-light:#032563}html pre.shiki code .sPXB4, html code.shiki .sPXB4{--shiki-default:#023B95;--shiki-dark:#91CBFF;--shiki-light:#023B95}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .saISM, html code.shiki .saISM{--shiki-default:#0E1116;--shiki-dark:#F0F3F6;--shiki-light:#0E1116}html pre.shiki code .sPARh, html code.shiki .sPARh{--shiki-default:#A0111F;--shiki-dark:#FF9492;--shiki-light:#A0111F}html pre.shiki code .smZ65, html code.shiki .smZ65{--shiki-default:#622CBC;--shiki-dark:#DBB7FF;--shiki-light:#622CBC}",{"title":402,"searchDepth":415,"depth":415,"links":1001},[1002,1003,1004,1010,1011,1012,1013,1014],{"id":191,"depth":415,"text":192},{"id":268,"depth":415,"text":269},{"id":386,"depth":415,"text":387,"children":1005},[1006,1007,1008,1009],{"id":391,"depth":436,"text":392},{"id":468,"depth":436,"text":469},{"id":566,"depth":436,"text":567},{"id":747,"depth":436,"text":748},{"id":827,"depth":415,"text":828},{"id":841,"depth":415,"text":842},{"id":874,"depth":415,"text":875},{"id":892,"depth":415,"text":893},{"id":960,"depth":415,"text":961},"Build a data-driven Browserslist configuration and use it to strip polyfills and down-levelled syntax from production bundles.","md",{"slug":1018,"type":1019,"breadcrumb":1020,"datePublished":1028,"dateModified":1028},"removing-unneeded-polyfills-with-browserslist","article",[1021,1024,1025,1026],{"name":1022,"url":1023},"Home","\u002F",{"name":27,"url":26},{"name":22,"url":21},{"name":5,"url":1027},"\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fremoving-unneeded-polyfills-with-browserslist\u002F","2026-10-06",true,"\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fremoving-unneeded-polyfills-with-browserslist",{"title":5,"description":1032},"Derive a Browserslist query from real traffic, wire it into Babel, SWC and core-js, and remove tens of kilobytes of polyfills modern visitors never needed.","javascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fremoving-unneeded-polyfills-with-browserslist\u002Findex","h0gOhRo9cMnGx0YGblzRzlhXFiPPk92SQCjrtOdzhO8",[1036,1040],{"title":1037,"path":1038,"stem":1039,"children":-1},"Is module\u002Fnomodule Differential Serving Still Worth It?","\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fis-module-nomodule-differential-serving-still-worth-it","javascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Fis-module-nomodule-differential-serving-still-worth-it\u002Findex",{"title":1041,"path":1042,"stem":1043,"children":-1},"Targeting Baseline Browsers with esbuild and SWC","\u002Fjavascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Ftargeting-baseline-browsers-with-esbuild-and-swc","javascript-bundle-optimization-code-splitting\u002Fpolyfills-and-differential-serving\u002Ftargeting-baseline-browsers-with-esbuild-and-swc\u002Findex",1791308076733]