| | |

Parcel 06 ๐Ÿ“ฆ Browserslist Targets โ€” Opting into transpilation

โฑ๏ธ Estimated read: 9 min | |

Parcel 2 does not transpile JavaScript by default. A project without a browserslist field in package.json produces output that assumes a modern browser, and Parcel does not run @babel/preset-env or its Rust-based equivalent unless it knows which browsers to target. The browserslist field is the opt-in: declaring it tells Parcel to transpile the syntax that the listed browsers do not support, and to add the CSS vendor prefixes that those browsers require .

This chapter covers the browserslist field, the query syntax that defines a target set, the default behavior when the field is absent, and the difference between the dev server’s modern target and the production build’s use of the declared list.

Key point: Parcel does not transpile unless browserslist is declared. The field is the switch that enables the transpilation pipeline, and its queries determine which syntax is downleveled and which prefixes are added.


Why Parcel requires an explicit target

The no-transpilation default. Parcel 2’s design is to do less work when it has no reason to do more. Without a browserslist, there is no target to compile for, so the output preserves the source syntax. A project that wants to support older browsers must declare that intent. The Stack Overflow answer states it directly: “Parcel 2 doesn’t do transpilation by default and you need to specify targeted browsers in the browserslist field of the package.json and then parcel automatically transpiles code with @babel/preset-env to match the defined target” .

The automatic transform problem. Once browserslist is present, Parcel enables its internal transforms. For JavaScript, it applies the Babel-equivalent transformations for the target syntax. For CSS, it includes equivalents of Autoprefixer and PostCSS Preset Env, implemented in Rust for speed. The documentation notes that if these are the only transforms the project needs, PostCSS may not be necessary at all .

The dev server distinction. The dev server uses a development target that supports modern browsers by default, which is why HMR stays fast. To make the dev server respect the browserslist field, the --target default flag must be passed . The production build (parcel build) uses the declared browserslist without the flag.


a. The browserslist field and query syntax

The field lives at the top level of package.json. It accepts a string or an array of strings, each of which is a Browserslist query.

{
  "browserslist": [
    "> 0.25%",
    "not dead",
    "not IE 11"
  ]
}

The queries are the standard Browserslist syntax. > 0.25% selects browsers with more than 0.25% global usage. last 2 Chrome versions selects the two most recent Chrome releases. not dead excludes browsers without official support for more than 24 months. The full query syntax is documented on browserslist.dev .

The default that many tutorials cite is > 0.25%, which Parcel historically used as its implicit target. With that default, the output covers roughly 92% of internet users at the time the tutorial was written . But the default is not a fallback that applies when the field is absent; it is the value that the field commonly contains.


b. What the field enables

Declaring browserslist turns on two independent pipelines.

The JavaScript pipeline. Parcel reads the queries and determines which syntax features the target browsers support. A feature that is unsupported is downleveled. The transformations are the same ones that @babel/preset-env would apply, but Parcel does not require the developer to install or configure @babel/preset-env. The Stack Overflow answer is explicit: “there is no need to add babel/preset-env and parcel/babel-preset-env manually. just remove them” .

The CSS pipeline. Parcel adds vendor prefixes for the target browsers and transpiles modern CSS syntax. The documentation states that Parcel “automatically handles CSS transpiling for modern syntax features like lab() colors, logical properties, and CSS nesting syntax, as well as automatically adding the necessary vendor prefixes for your browser targets” . This is the equivalent of Autoprefixer running automatically, without a PostCSS configuration.


c. Targets and the browserslist default

The browserslist field sets the default engines.browsers for the browser target. Parcel’s target configuration maps the browser target’s engines.browsers to package.json#browserslist unless the browser field exists . The main target’s engines.browsers is also populated from browserslist if there is no browser field .

A project with custom targets can override the browserslist default per target. The targets object in package.json accepts an engines field, and the browsers value inside it can be a different query set. The top-level browserslist is the default, not a global override.

{
  "browserslist": ["> 0.25%", "not dead"],
  "targets": {
    "legacy": {
      "engines": {
        "browsers": ["IE 11"]
      }
    }
  }
}

The legacy target compiles for IE 11. The default target compiles for the broader browserslist set. Parcel builds both from the same source.


Complete Example Session

// ============================================
// PART 1: THE MINIMAL BROWSERSLIST
// ============================================
{
  "browserslist": ["> 0.25%", "not dead"]
}

// Parcel now transpiles JavaScript and CSS
// for the browsers matching these queries.
// ============================================
// PART 2: THE SPECIFIC QUERY SET
// ============================================
{
  "browserslist": [
    "last 2 Chrome versions",
    "last 2 Firefox versions",
    "last 2 Safari versions"
  ]
}

// The output targets only the most recent
// versions of the three major browsers.
// ============================================
// PART 3: THE ABSENT FIELD
// ============================================
{
  "name": "my-app",
  "dependencies": { "parcel": "^2.13.3" }
}

// No browserslist.
// No transpilation.
// The output uses the source syntax.
// ============================================
// PART 4: THE DEV SERVER FLAG
// ============================================
{
  "scripts": {
    "start": "parcel index.html --target default",
    "build": "parcel build index.html"
  }
}

// --target default makes the dev server
// respect the browserslist field.
// ============================================
// PART 5: THE PER-TARGET OVERRIDE
// ============================================
{
  "browserslist": ["> 0.25%", "not dead"],
  "targets": {
    "legacy": {
      "engines": {
        "browsers": ["IE 11"]
      }
    }
  }
}

// The default target uses the top-level list.
// The legacy target uses IE 11.
// ============================================
// PART 6: THE CSS PREFIX EXAMPLE
// ============================================
{
  "browserslist": ["IE 9"]
}

// display: flex;
// becomes:
// display: -ms-flexbox;
// display: flex;
// ============================================
// PART 7: THE SYNTAX EXAMPLE
// ============================================
{
  "browserslist": ["last 2 Chrome versions"]
}

// Optional chaining and nullish coalescing
// are preserved because Chrome supports them.
// ============================================
// PART 8: THE OLDER TARGET EXAMPLE
// ============================================
{
  "browserslist": ["IE 11"]
}

// Optional chaining and nullish coalescing
// are downleveled into conditional checks.
// ============================================
// PART 9: THE AUTOPREFIXER EQUIVALENT
// ============================================
{
  "browserslist": ["> 0.25%", "not dead"]
}

// Parcel adds the vendor prefixes that
// the target browsers require.
// No PostCSS configuration needed.
// ============================================
// PART 10: THE COMPLETE PACKAGE.JSON
// ============================================
{
  "name": "my-app",
  "browserslist": ["> 0.25%", "not dead"],
  "scripts": {
    "start": "parcel index.html --target default",
    "build": "parcel build index.html"
  },
  "devDependencies": {
    "parcel": "^2.13.3"
  }
}

The ten parts covered the minimal field, a specific query set, the absent-field behavior, the dev server flag, the per-target override, CSS prefixing, syntax preservation, syntax downleveling, the Autoprefixer equivalent, and the complete package.json.


Quick Reference

Browserslist field

PropertyDetail
LocationTop level of package.json
TypeString or array of strings
EffectEnables JS transpilation and CSS prefixing
AbsentNo transpilation
Dev serverUses modern target unless --target default

Common queries

QueryMeaning
> 0.25%Browsers with more than 0.25% usage
last 2 versionsTwo most recent versions of each browser
last 2 Chrome versionsTwo most recent Chrome releases
not deadExclude browsers without official support
IE 11Internet Explorer 11
defaultsBrowserslist’s recommended default set

Target configuration

FieldEffect
browserslistDefault engines.browsers for targets
targets.<name>.engines.browsersPer-target override
--target defaultDev server uses the browserslist field

What is enabled

PipelineBehavior
JavaScriptDownlevel syntax for target browsers
CSSAdd vendor prefixes, transpile modern syntax
PostCSSNot required for the built-in transforms

Best Practices

โœ… Do This:

// Declare browserslist explicitly
"browserslist": ["> 0.25%", "not dead"]                      // โœ…
// Use --target default for the dev server
"start": "parcel index.html --target default"                // โœ…
// Use a specific query set for a defined audience
"browserslist": ["last 2 Chrome versions"]                   // โœ…

โŒ Don’t Do This:

// Omit browserslist and expect transpilation
// No field means no transpilation                            // โŒ
// Install @babel/preset-env manually
// Parcel handles it when browserslist is present             // โŒ
// Use the dev server without --target default
// The dev target ignores browserslist                        // โŒ

Common Pitfalls

PitfallWhy It HappensFix
Output uses modern syntax despite browserslistDev server uses its own modern targetUse --target default for the dev server
Transpilation not happeningNo browserslist fieldAdd the field to package.json
@babel/preset-env conflictManually installed presetRemove it; Parcel handles it
CSS prefixes missingThe field is present but the query excludes the browserVerify the query matches the target browser
Build differs from devDev target and build target differUse --target default in dev

Real-World Examples

1. Broad audience

{ "browserslist": ["> 0.25%", "not dead"] }

2. Modern only

{ "browserslist": ["last 2 Chrome versions"] }

3. Legacy support

{ "browserslist": ["IE 11"] }

4. Dev server flag

{ "start": "parcel index.html --target default" }

5. Production build

{ "build": "parcel build index.html" }

6. Per-target override

{ "targets": { "legacy": { "engines": { "browsers": ["IE 11"] } } } }

7. CSS prefix target

{ "browserslist": ["IE 9"] }

8. Syntax preservation

{ "browserslist": ["last 2 Chrome versions"] }

9. Syntax downleveling

{ "browserslist": ["IE 11"] }

10. The full package

{
  "browserslist": ["> 0.25%", "not dead"],
  "scripts": {
    "start": "parcel index.html --target default",
    "build": "parcel build index.html"
  }
}

Visual

The opt-in switch

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  NO BROWSERSLIST                                             โ”‚
โ”‚                                                              โ”‚
โ”‚  Source code โ”€โ”€โ–บ Parcel โ”€โ”€โ–บ Output                           โ”‚
โ”‚                                                              โ”‚
โ”‚  No transpilation.                                           โ”‚
โ”‚  No prefixing.                                               โ”‚
โ”‚  The output matches the source syntax.                       โ”‚
โ”‚                                                              โ”‚
โ”‚  WITH BROWSERSLIST                                           โ”‚
โ”‚                                                              โ”‚
โ”‚  Source code โ”€โ”€โ–บ Parcel โ”€โ”€โ–บ Transpile for targets โ”€โ”€โ–บ Output โ”‚
โ”‚                                                              โ”‚
โ”‚  JavaScript syntax downleveled.                              โ”‚
โ”‚  CSS vendor prefixes added.                                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The two pipelines

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  BROWSERSLIST                                                โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ”œโ”€โ”€ JavaScript pipeline                                โ”‚
โ”‚       โ”‚     โ””โ”€โ”€ syntax downleveling                          โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ””โ”€โ”€ CSS pipeline                                       โ”‚
โ”‚             โ”œโ”€โ”€ vendor prefixes                              โ”‚
โ”‚             โ””โ”€โ”€ modern syntax transpilation                  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Dev server vs build

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  DEV SERVER                          BUILD                    โ”‚
โ”‚                                                              โ”‚
โ”‚  Default: modern target              browserslist is used    โ”‚
โ”‚  Fast HMR                            Full transpilation      โ”‚
โ”‚                                                              โ”‚
โ”‚  --target default                    No flag needed          โ”‚
โ”‚    โ†’ uses browserslist                                       โ”‚
โ”‚    โ†’ slower, but matches build                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Target override

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  browserslist: ["> 0.25%", "not dead"]                       โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ”œโ”€โ”€ default target โ”€โ”€โ–บ broad audience                  โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ””โ”€โ”€ legacy target โ”€โ”€โ–บ engines.browsers: ["IE 11"]     โ”‚
โ”‚                              โ””โ”€โ”€ IE 11 output                โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Fieldbrowserslist in package.json
EffectEnables JS transpilation and CSS prefixing
DefaultNo transpilation without the field
Dev serverUses modern target unless --target default
BuildUses browserslist automatically
Query syntaxStandard Browserslist syntax
Per-target overridetargets.<name>.engines.browsers
Manual BabelNot required

Key takeaways:

  • Parcel does not transpile without browserslist. The field is the opt-in switch. A project that omits it gets output in the source syntax, which may fail in older browsers .
  • The field enables both JavaScript and CSS pipelines. JavaScript syntax is downleveled for the target browsers, and CSS vendor prefixes are added automatically. The built-in transforms are the equivalents of @babel/preset-env and Autoprefixer, implemented in Rust .
  • The dev server uses a modern target by default. To make the dev server respect the browserslist field, pass --target default. The production build uses the field without the flag .
  • Manual Babel configuration is unnecessary. Parcel handles the transpilation when the field is present. Installing @babel/preset-env or parcel/babel-preset-env manually is redundant and should be removed .
  • Per-target overrides are possible. The top-level browserslist sets the default, and a specific target can declare a different engines.browsers value. This allows a single project to build both a modern bundle and a legacy bundle .
  • The query syntax is standard Browserslist. > 0.25%, last 2 versions, not dead, and IE 11 are all valid queries. The full syntax is documented on browserslist.dev .

Remember: The browserslist field is the contract between the project and Parcel. It says “these are the browsers I support,” and Parcel does the work to make the code run in them. Without the field, Parcel does nothing. With the field, it transpiles JavaScript, prefixes CSS, and produces output that matches the declared audience. The dev server needs --target default to honor the field; the production build honors it by default.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!