Skip to content

Commit c3405bd

Browse files
committed
Merge branch 'main' into ds.monorepo
2 parents db4b893 + 0dab332 commit c3405bd

File tree

12 files changed

+518
-34
lines changed

12 files changed

+518
-34
lines changed

LICENSE

Lines changed: 384 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Analyzes each PR's impact on your next.js app's bundle size and displays it usin
44

55
![screenshot of bundle analysis comment](https://p176.p0.n0.cdn.getcloudapp.com/items/BluKP76d/2b51f74a-9c0f-481f-b76a-9b36cf37d369.png?v=ddd23d0d9ee1ee9ad40487d181ed917f)
66

7-
### Installation
7+
## Installation
88

99
It's pretty simple to get this set up, just run the following command and answer the prompts. The command will create a `.github/workflows` directory in your project root and add a `next_bundle_analysis.yml` file to it - that's all it takes!
1010

@@ -14,20 +14,36 @@ $ npx -p nextjs-bundle-analysis generate
1414

1515
> **NOTE**: Due to github actions' lack of support for more complex actions, the experience of getting this set up is unusual in that it requires a generation script which copies most of the logic into your project directly. As soon as github adds support for the [features](https://github.com/actions/runner/pull/1144) [needed](https://github.com/actions/runner/pull/1144#discussion_r651087316) to properly package up this action, we'll put out an update that removes the extra boilerplate and makes usage much simpler. Until then, we all have no choice but to endure this unusual setup process.
1616
17-
### Configuration
17+
## Configuration
1818

1919
Config values are written to `package.json` under the key `nextBundleAnalysis`, and can be changed there any time. You can directly edit the workflow file if you want to adjust your default branch or the directory that your nextjs app lives in (especially if you are using a `srcDir` or something similar).
2020

21-
There is one config value, `showDetails`, that is set to "true" by default. This option renders a collapsed "details" section under each section of the bundle analysis comment explaining some of the finer details of the numbers provided. If you feel like this is not necessary and you and/or those working on your project understand the details, you can set this option to `false` and that section will not render.
21+
### `showDetails (boolean)`
2222

23-
If your application [builds to a custom directory](https://nextjs.org/docs/api-reference/next.config.js/setting-a-custom-build-directory), you can specify this with the key `buildOutputDirectory`. You will also need to replace all instances of `.next` in `next_bundle_analysis.yml` with your custom output directory.
23+
(Optional, defaults to `true`) This option renders a collapsed "details" section under each section of the bundle analysis comment explaining some of the finer details of the numbers provided. If you feel like this is not necessary and you and/or those working on your project understand the details, you can set this option to `false` and that section will not render.
24+
25+
### `buildOutputDirectory (string)`
26+
27+
(Optional, defaults to `.next`) If your application [builds to a custom directory](https://nextjs.org/docs/api-reference/next.config.js/setting-a-custom-build-directory), you can specify this with the key `buildOutputDirectory`. You will also need to replace all instances of `.next` in `next_bundle_analysis.yml` with your custom output directory.
2428

2529
For example, if you build to `dist`, you should:
2630

2731
- Set `package.json.nextBundleAnalysis.buildOutputDirectory` to `"dist"`.
2832
- In `nextjs_bundle_analysis`, replace all instances of `.next` with `dist`.
2933

30-
### Caveats
34+
### `budget (number)`
35+
36+
(Optional) The file size, in bytes, to budget for first page load size. For example, if `budget` was set to `358400` (350 KB) and a page's first load size was 248 KB, the report would list that page as having used 70% of the performance budget.
37+
38+
### `budgetPercentIncreaseRed (number)`
39+
40+
(Optional, but required if `budget` is specified) If a page's first load size has increased more than `budgetPercentIncreaseRed` percent, display a 🔴 to draw attention to the change.
41+
42+
### `minimumChangeThreshold (number)`
43+
44+
(Optional, defaults to `0`) The threshold under which pages will be considered unchanged. For example, if `minimumChangeThreshold` was set to `500` and a page's size increased by `300 B`, it will be considered unchanged.
45+
46+
## Caveats
3147

3248
- This plugin only analyzes the direct bundle output from next.js. If you have added any other scripts via the `<script>` tag, especially third party scripts and things like analytics or other tracking scripts, these are not included in the analysis. Scripts of this nature should _probably_ be loaded in behind a consent manager and should not make an impact on your initial load, and as long as this is how you handle them it should make no difference, but it's important to be aware of this and account for the extra size added by these scripts if they are present in your app.
3349
- Since this plugin works by comparing the base bundle against each PR, the first time it is run, it will fail since it has no base to compare against. This is expected - ideally you can just commit the changes directly to your default branch, where it will run to generate the base bundle, then anything that branches off after that will have a valid comparison point and the script will work as expected.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Copyright (c) HashiCorp, Inc.
3+
* SPDX-License-Identifier: MPL-2.0
4+
*/
5+
16
export default function IndexPage() {
27
return <p>hello world</p>
38
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Copyright (c) HashiCorp, Inc.
3+
* SPDX-License-Identifier: MPL-2.0
4+
*/
5+
16
module.exports = {
27
distDir: 'dist',
38
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Copyright (c) HashiCorp, Inc.
3+
* SPDX-License-Identifier: MPL-2.0
4+
*/
5+
16
export default function IndexPage() {
27
return <p>hello world</p>
38
}

__tests__/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Copyright (c) HashiCorp, Inc.
3+
* SPDX-License-Identifier: MPL-2.0
4+
*/
5+
16
const path = require('path')
27
const fs = require('fs')
38
const { execSync } = require('child_process')

compare.js

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
11
#!/usr/bin/env node
2+
/**
3+
* Copyright (c) HashiCorp, Inc.
4+
* SPDX-License-Identifier: MPL-2.0
5+
*/
26

3-
const filesize = require('filesize')
7+
8+
const originalFilesize = require('filesize')
49
const numberToWords = require('number-to-words')
510
const fs = require('fs')
611
const path = require('path')
712
const { getBuildOutputDirectory, getOptions } = require('./utils')
813

14+
// Override default filesize options to display a non-breakable space as a spacer.
15+
const filesize = (bytes, options) => {
16+
return originalFilesize(bytes, {
17+
spacer: ' ',
18+
...options,
19+
})
20+
}
21+
922
// Pull options from `package.json`
1023
const options = getOptions()
1124

@@ -43,17 +56,23 @@ delete currentBundle.__global
4356
delete baseBundle.__global
4457

4558
// calculate the difference between the current bundle and the base branch's
46-
const globalBundleChanges =
47-
globalBundleCurrent.gzip !== globalBundleBase.gzip
48-
? {
49-
page: 'global',
50-
raw: globalBundleCurrent.raw,
51-
gzip: globalBundleCurrent.gzip,
52-
gzipDiff: globalBundleCurrent.gzip - globalBundleBase.gzip,
53-
increase:
54-
Math.sign(globalBundleCurrent.gzip - globalBundleBase.gzip) > 0,
55-
}
56-
: false
59+
let globalBundleChanges = false
60+
const globalGzipDiff = globalBundleCurrent.gzip - globalBundleBase.gzip
61+
// only report a global bundle size change if we don't have a minimum change
62+
// threshold configured, or if the change is greater than the threshold
63+
if (
64+
globalGzipDiff !== 0 &&
65+
(!('minimumChangeThreshold' in options) ||
66+
Math.abs(globalGzipDiff) > options.minimumChangeThreshold)
67+
) {
68+
globalBundleChanges = {
69+
page: 'global',
70+
raw: globalBundleCurrent.raw,
71+
gzip: globalBundleCurrent.gzip,
72+
gzipDiff: globalGzipDiff,
73+
increase: Math.sign(globalGzipDiff) > 0,
74+
}
75+
}
5776

5877
// now we're going to go through each of the pages in the current bundle and
5978
// run analysis on each one.
@@ -75,7 +94,14 @@ for (let page in currentBundle) {
7594
const rawDiff = currentStats.raw - baseStats.raw
7695
const gzipDiff = currentStats.gzip - baseStats.gzip
7796
const increase = !!Math.sign(gzipDiff)
78-
changedPages.push({ page, ...currentStats, rawDiff, gzipDiff, increase })
97+
// only report a page size change if we don't have a minimum change
98+
// threshold configured, or if the change is greater than the threshold
99+
if (
100+
!('minimumChangeThreshold' in options) ||
101+
Math.abs(gzipDiff) > options.minimumChangeThreshold
102+
) {
103+
changedPages.push({ page, ...currentStats, rawDiff, gzipDiff, increase })
104+
}
79105
}
80106
}
81107

generate.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
#!/usr/bin/env node
2+
/**
3+
* Copyright (c) HashiCorp, Inc.
4+
* SPDX-License-Identifier: MPL-2.0
5+
*/
6+
27

38
const path = require('path')
49
const fs = require('fs')
@@ -28,6 +33,12 @@ inquirer
2833
'If you exceed this percentage of the budget or filesize, it will be highlighted in red',
2934
default: 20,
3035
},
36+
{
37+
type: 'number',
38+
name: 'minimumChangeThreshold',
39+
message: `If a page's size change is below this threshold (in bytes), it will be considered unchanged'`,
40+
default: 0,
41+
},
3142
])
3243
.then((answers) => {
3344
// write the config values to package.json
@@ -36,6 +47,7 @@ inquirer
3647
packageJsonContent.nextBundleAnalysis = {
3748
budget: answers.budget * 1024,
3849
budgetPercentIncreaseRed: answers.redIndicatorPercentage,
50+
minimumChangeThreshold: answers.minimumChangeThreshold,
3951
showDetails: true, // add a default "showDetails" argument
4052
}
4153
fs.writeFileSync(

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"action"
2828
],
2929
"author": "Jeff Escalante",
30-
"license": "GPL-2.0",
30+
"license": "MPL-2.0",
3131
"jest": {
3232
"testPathIgnorePatterns": [
3333
"/node_modules/",

report.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
#!/usr/bin/env node
2+
/**
3+
* Copyright (c) HashiCorp, Inc.
4+
* SPDX-License-Identifier: MPL-2.0
5+
*/
6+
27

38
const path = require('path')
49
const fs = require('fs')

0 commit comments

Comments
 (0)