Skip to content

Commit 91831a3

Browse files
authored
feat: improve treeshaking (#463)
1 parent 8606a36 commit 91831a3

File tree

19 files changed

+117
-4
lines changed

19 files changed

+117
-4
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
},
2222
"license": "MIT",
2323
"author": "Sanity.io <[email protected]>",
24+
"sideEffects": false,
2425
"type": "module",
2526
"exports": {
2627
".": {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports.answer = 42
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export declare const answer: number
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const answer = 42
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "dummy-side-effects",
3+
"version": "1.0.0",
4+
"private": true,
5+
"license": "MIT",
6+
"type": "module",
7+
"sideEffects": ["./side-effect*"],
8+
"exports": {
9+
".": {
10+
"types": "./index.d.ts",
11+
"require": "./index.cjs",
12+
"default": "./index.js"
13+
},
14+
"./side-effect": {
15+
"types": "./side-effect.d.ts",
16+
"require": "./side-effect.cjs",
17+
"default": "./side-effect.js"
18+
},
19+
"./package.json": "./package.json"
20+
},
21+
"types": "./index.d.ts",
22+
"files": [
23+
"index.js",
24+
"index.cjs",
25+
"index.d.ts",
26+
"side-effect.js",
27+
"side-effect.cjs",
28+
"side-effect.d.ts"
29+
]
30+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// eslint-disable-next-line no-console
2+
console.log('side-effect.cjs')
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// eslint-disable-next-line no-console
2+
console.log('side-effect.js')

playground/multi-export/package.json

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"private": true,
55
"license": "MIT",
66
"type": "module",
7+
"sideEffects": ["./side-effect*"],
78
"exports": {
89
".": {
910
"types": "./dist/index.d.ts",
@@ -27,6 +28,27 @@
2728
"import": "./dist/plugin.js",
2829
"default": "./dist/plugin.js"
2930
},
31+
"./pure": {
32+
"types": "./dist/pure.d.ts",
33+
"source": "./src/pure.ts",
34+
"import": "./dist/pure.js",
35+
"require": "./dist/pure.cjs",
36+
"default": "./dist/pure.js"
37+
},
38+
"./side-effect": {
39+
"types": "./dist/side-effect.d.ts",
40+
"source": "./src/side-effect.ts",
41+
"import": "./dist/side-effect.js",
42+
"require": "./dist/side-effect.cjs",
43+
"default": "./dist/side-effect.js"
44+
},
45+
"./no-side-effect": {
46+
"types": "./dist/no-side-effect.d.ts",
47+
"source": "./src/no-side-effect.ts",
48+
"import": "./dist/no-side-effect.js",
49+
"require": "./dist/no-side-effect.cjs",
50+
"default": "./dist/no-side-effect.js"
51+
},
3052
"./package.json": "./package.json"
3153
},
3254
"main": "./dist/index.cjs",
@@ -37,11 +59,24 @@
3759
"*": {
3860
"plugin": [
3961
"./dist/plugin.d.ts"
62+
],
63+
"pure": [
64+
"./dist/pure.d.ts"
65+
],
66+
"side-effect": [
67+
"./dist/side-effect.d.ts"
68+
],
69+
"no-side-effect": [
70+
"./dist/no-side-effect.d.ts"
4071
]
4172
}
4273
},
4374
"scripts": {
4475
"build": "run-s clean && pkg build --strict && pkg check --strict",
4576
"clean": "rimraf dist"
77+
},
78+
"dependencies": {
79+
"dummy-side-effects": "workspace:*"
4680
}
4781
}
82+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Should be tree-shaken away as it's a side-effect free module
2+
import 'dummy-side-effects'
3+
4+
/** @public */
5+
export const answer = 42

playground/multi-export/src/pure.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import {answer} from 'dummy-side-effects'
2+
3+
/** @public */
4+
export function getAnswer() {
5+
return answer
6+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Should not be tree-shaken away as it's a side-effect module
2+
import 'dummy-side-effects/side-effect'

pnpm-lock.yaml

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/node/core/config/types.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import {type PluginItem as BabelPluginItem} from '@babel/core'
2-
import {NormalizedOutputOptions, type Plugin as RollupPlugin} from 'rollup'
1+
import type {PluginItem as BabelPluginItem} from '@babel/core'
2+
import type {NormalizedOutputOptions, Plugin as RollupPlugin, TreeshakingOptions} from 'rollup'
33

44
// re-export
55
export type {RollupPlugin}
@@ -120,6 +120,13 @@ export interface PkgConfigOptions {
120120
rollup?: {
121121
plugins?: PkgConfigProperty<RollupPlugin[]>
122122
output?: Partial<NormalizedOutputOptions>
123+
/**
124+
* Default options are `preset: 'recommended'` and `propertyReadSideEffects: false`
125+
* @alpha
126+
*/
127+
treeshake?: TreeshakingOptions
128+
/** @alpha */
129+
experimentalLogSideEffects?: boolean
123130
}
124131
/**
125132
* Default runtime of package exports

src/node/core/pkg/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export interface PackageJSON {
4242
files?: string[]
4343
scripts?: Record<string, string | undefined>
4444
browserslist?: string | string[]
45+
sideEffects?: boolean | string[]
4546
engines?: {
4647
node?: string
4748
npm?: string

src/node/core/pkg/validatePkg.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const pkgSchema = z.object({
4747
),
4848
),
4949
browserslist: z.optional(z.union([z.string(), z.array(z.string())])),
50+
sideEffects: z.optional(z.union([z.boolean(), z.array(z.string())])),
5051
})
5152

5253
export function validatePkg(input: unknown): PackageJSON {

src/node/resolveBuildContext.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export async function resolveBuildContext(options: {
4242

4343
/* eslint-disable padding-line-between-statements */
4444
let browserslist = pkg.browserslist
45-
if (!browserslist) {
45+
if (strict && !browserslist) {
4646
logger.warn(
4747
'Could not detect a `browserslist` property in `package.json`, using default configuration. Add `"browserslist": "extends @sanity/browserslist-config"` to silence this warning.',
4848
)
@@ -51,6 +51,12 @@ export async function resolveBuildContext(options: {
5151
const targetVersions = browserslistToEsbuild(browserslist)
5252
/* eslint-enable padding-line-between-statements */
5353

54+
if (strict && typeof pkg.sideEffects === 'undefined') {
55+
logger.error(
56+
'No `sideEffects` field in `package.json`, assuming all files are side-effectful. Add `"sideEffects": true` to silence this warning. See https://webpack.js.org/guides/tree-shaking/#clarifying-tree-shaking-and-sideeffects for how to define `sideEffects`.',
57+
)
58+
}
59+
5460
const nodeTarget = resolveNodeTarget(targetVersions)
5561
const webTarget = resolveBrowserTarget(targetVersions)
5662

src/node/tasks/rollup/resolveRollupConfig.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,11 @@ export function resolveRollupConfig(
180180
plugins,
181181

182182
treeshake: {
183+
preset: 'recommended',
183184
propertyReadSideEffects: false,
185+
...config?.rollup?.treeshake,
184186
},
187+
experimentalLogSideEffects: config?.rollup?.experimentalLogSideEffects,
185188
},
186189
outputOptions: {
187190
chunkFileNames: () => {

src/node/templates/default/template.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ export const defaultTemplate: PkgTemplate = async ({cwd, logger, packagePath}) =
159159
'repository': undefined,
160160
'license': options.license,
161161
author,
162+
'sideEffects': false,
162163
'type': 'module',
163164
'exports': {
164165
'.': {
@@ -188,6 +189,7 @@ export const defaultTemplate: PkgTemplate = async ({cwd, logger, packagePath}) =
188189
}
189190
: undefined,
190191
// prettier: prettierConfig,
192+
'browserslist': 'extends @sanity/browserslist-config',
191193
'dependencies': {},
192194
'devDependencies': {
193195
'@sanity/pkg-utils': '*',

0 commit comments

Comments
 (0)