Skip to content

Commit 104d5ba

Browse files
authored
Support browserlists from package.json (#588)
1 parent dd0e484 commit 104d5ba

File tree

7 files changed

+74
-6
lines changed

7 files changed

+74
-6
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,20 @@ Bunchee offers a convenient watch mode for rebuilding your library whenever chan
470470
#### `target`
471471

472472
If you specify `target` option in `tsconfig.json`, then you don't have to pass it again through CLI.
473+
To target a range of browsers, you can use the `browserslist` field in `package.json`, bunchee will use it to determine the target browsers for the output bundle.
474+
475+
For example:
476+
477+
```json
478+
{
479+
"browserslist": [
480+
"last 1 version",
481+
"> 1%",
482+
"maintained node versions",
483+
"not dead"
484+
]
485+
}
486+
```
473487

474488
#### Package lint
475489

src/bundle.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import type { BundleConfig, BundleJobOptions } from './types'
1+
import type {
2+
BrowserslistConfig,
3+
BundleConfig,
4+
BundleJobOptions,
5+
} from './types'
26
import fsp from 'fs/promises'
37
import fs from 'fs'
48
import { resolve } from 'path'
@@ -134,13 +138,19 @@ async function bundle(
134138
hasTsConfig = true
135139
}
136140

141+
let browserslistConfig: BrowserslistConfig | undefined
142+
if (options.runtime === 'browser') {
143+
browserslistConfig = pkg.browserslist
144+
}
145+
137146
const outputState = createOutputState({ entries })
138147
const buildContext: BuildContext = {
139148
entries,
140149
pkg,
141150
cwd,
142151
tsOptions: defaultTsOptions,
143152
useTypeScript: hasTsConfig,
153+
browserslistConfig,
144154
pluginContext: {
145155
outputState,
146156
moduleDirectiveLayerMap: new Map(),

src/rollup/input.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { InputOptions, Plugin } from 'rollup'
2+
import { type Options as SwcOptions } from '@swc/core'
23
import { BuildContext, BundleOptions, ParsedExportCondition } from '../types'
34
import { isBinExportPath, isESModulePackage, isNotNull } from '../utils'
45
import { normalizeExportPath } from '../entries'
@@ -106,6 +107,7 @@ export async function buildInputConfig(
106107
pkg,
107108
cwd,
108109
tsOptions: { tsConfigPath, tsCompilerOptions },
110+
browserslistConfig,
109111
pluginContext,
110112
} = buildContext
111113
const isBinEntry = isBinExportPath(exportCondition.name)
@@ -145,11 +147,13 @@ export async function buildInputConfig(
145147
decorators: true,
146148
} as const
147149

148-
const swcOptions: import('@swc/types').Options = {
150+
const hasBrowserslistConfig = !!(browserslistConfig && !hasSpecifiedTsTarget)
151+
const swcOptions = {
149152
jsc: {
150-
...(!hasSpecifiedTsTarget && {
151-
target: jscTarget,
152-
}),
153+
...(!hasSpecifiedTsTarget &&
154+
!hasBrowserslistConfig && {
155+
target: jscTarget,
156+
}),
153157
loose: true, // Use loose mode
154158
externalHelpers: false,
155159
parser: swcParserConfig,
@@ -166,7 +170,12 @@ export async function buildInputConfig(
166170
sourceMaps: bundleConfig.sourcemap,
167171
inlineSourcesContent: false,
168172
isModule: true,
169-
} as const
173+
...(hasBrowserslistConfig && {
174+
env: {
175+
targets: browserslistConfig,
176+
},
177+
}),
178+
} satisfies SwcOptions
170179

171180
const sizePlugin = pluginContext.outputState.plugin(cwd)
172181

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type PackageMetadata = {
7272
exports?: string | Record<string, ExportCondition>
7373
types?: string
7474
typings?: string
75+
browserslist?: BrowserslistConfig
7576
}
7677

7778
type BuncheeRollupConfig = {
@@ -112,12 +113,15 @@ type ExportPaths = Record<string, FullExportCondition>
112113

113114
type Entries = Record<string, ParsedExportCondition>
114115

116+
type BrowserslistConfig = string | string[] | Record<string, string>
117+
115118
type BuildContext = {
116119
entries: Entries
117120
pkg: PackageMetadata
118121
cwd: string
119122
tsOptions: TypescriptOptions
120123
useTypeScript: boolean
124+
browserslistConfig: BrowserslistConfig | undefined
121125
pluginContext: {
122126
outputState: OutputState
123127
moduleDirectiveLayerMap: Map<string, Set<[string, string]>>
@@ -150,4 +154,5 @@ export type {
150154
BuildContext,
151155
BundleJobOptions,
152156
bundleEntryOptions,
157+
BrowserslistConfig,
153158
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { createIntegrationTest, assertFilesContent } from '../utils'
2+
3+
describe('browserslist', () => {
4+
it('should work with basic JSX format', async () => {
5+
await createIntegrationTest(
6+
{
7+
directory: __dirname,
8+
},
9+
({ distDir }) => {
10+
assertFilesContent(distDir, {
11+
'index.js': `_class_private_field_loose_key`,
12+
})
13+
},
14+
)
15+
})
16+
})
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"name": "browserslist",
3+
"main": "./dist/index.js",
4+
"browserslist": [
5+
"ie 9"
6+
]
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export class A {
2+
static prop = 'A-prop'
3+
4+
#foo() {
5+
return 'foo'
6+
}
7+
}

0 commit comments

Comments
 (0)