Skip to content

Commit

Permalink
♻ Refactor to gather story snapshot dom without reloading the page
Browse files Browse the repository at this point in the history
When relying on the snapshot method to capture the DOM, each story is loaded from scratch. For some
larger Storybooks, this can create a lot of extra time repeatedly initializing all of Storybook's
JavaScript for each story.

By refactoring to gather DOM from a single page, this initial load time only happens once, and asset
discovery can be performed on the static DOM snapshot without needing JavaScript enabled. In
practice, this seems to speed up most Storybooks by roughly 20-40% depending on how well optimized
the stories are. For poorly optimized stories, we also automatically handle page crashes and will
only error if a page crashes on the same story more than once.

When testing large Storybooks of 800+ stories, it takes about 2 minutes (on my machine). However if
that is too slow for some (or if stories are slow to load), a few additional flags were added to
split snapshots into shards to allow parallel processes for the same Percy build. The new flags
`--shard-count` or `--shard-size` will determine how to split snapshots, and `--shard-index` will
determine which shard to use for the current process. Also the `--partial` flag from the exec
command was incorporated, which can mark a build as partial to hide missing snapshots in the UI.
  • Loading branch information
wwilsman committed Jun 25, 2022
1 parent 22f4b23 commit 26fc55a
Show file tree
Hide file tree
Showing 15 changed files with 1,885 additions and 1,280 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,11 @@ options](https://docs.percy.io/docs/cli-configuration#per-snapshot-configuration

- **skip** - Boolean indicating whether or not to skip this story.
- **name** - Snapshot name. (default: `${story.kind}: ${story.name}`)
- **args** - [Story args](https://storybook.js.org/docs/react/writing-stories/args) to use when snapshotting.
- **args** - [Story args](https://storybook.js.org/docs/react/writing-stories/args) to use when
taking the snapshot.
- **globals** - [Story
globals](https://storybook.js.org/docs/react/essentials/toolbars-and-globals#globals) to use when
taking the snapshot.
- **queryParams** - Query parameters to use when snapshotting.
- **waitForTimeout** - Wait for a timeout before taking the snapshot.
- **waitForSelector** - Wait for a selector to exist before taking the snapshot.
Expand All @@ -164,6 +168,7 @@ options](https://docs.percy.io/docs/cli-configuration#per-snapshot-configuration
- **suffix** - A suffix added to this additional snapshot's name.
- **name** - Snapshot name. Replaces the inherited name.
- **args** - Additional story args for this additional snapshot.
- **globals** - Additional story globals for this additional snapshot.
- **queryParams** - Additional query parameters for this additional snapshot.
- **include** - Only apply the additional snapshot to matching stories.
- **exclude** - Do not apply the additional snapshot to matching stories.
Expand Down Expand Up @@ -210,6 +215,7 @@ this SDK also adds the following Storybook specific options:
version: 2
storybook:
args: {}
globals: {}
queryParams: {}
waitForTimeout: 0
waitForSelector: ''
Expand Down
5 changes: 0 additions & 5 deletions babel.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ module.exports = {
}
}]
],
plugins: [
['@babel/proposal-class-properties', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
['@babel/plugin-proposal-private-property-in-object', { loose: true }]
],
env: {
test: {
plugins: [
Expand Down
29 changes: 14 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
"clean": "git clean -Xdf -e !node_modules -e !node_modules/**",
"lint": "eslint --ignore-path .gitignore .",
"readme": "percy-cli-readme",
"pretest": "build-storybook --config-dir=./test/.storybook --output-dir=./test/.storybook-build --loglevel error",
"test": "cross-env NODE_ENV=test jasmine --config=./test/jasmine.json",
"_pretest": "build-storybook --config-dir=./test/.storybook --output-dir=./test/.storybook-build --loglevel error",
"test": "yarn test:env jasmine --config=./test/jasmine.json",
"test:env": "cross-env NODE_ENV=test NODE_OPTIONS='--loader=./test/loader.js'",
"test:coverage": "nyc yarn test"
},
"@percy/cli": {
Expand All @@ -35,33 +36,31 @@
},
"dependencies": {
"@percy/cli-command": "^1.3.1",
"@storybook/router": "~6.4.22",
"cross-spawn": "^7.0.3",
"qs": "^6.10.5"
"@storybook/router": "^6.5.0",
"cross-spawn": "^7.0.3"
},
"devDependencies": {
"@babel/cli": "^7.17.10",
"@babel/core": "^7.18.5",
"@babel/eslint-parser": "^7.18.2",
"@babel/eslint-plugin": "^7.17.7",
"@babel/plugin-proposal-class-properties": "^7.17.12",
"@babel/preset-env": "^7.18.2",
"@babel/register": "^7.17.7",
"@storybook/react": "^6.4.22",
"@storybook/react": "^6.5.8",
"babel-eslint": "^10.0.3",
"babel-plugin-istanbul": "^6.1.1",
"cross-env": "^7.0.3",
"eslint": "^7.32.0",
"eslint-config-standard": "^16.0.3",
"eslint": "^8.17.0",
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^5.2.0",
"eslint-plugin-n": "^15.2.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0",
"jasmine": "^4.2.1",
"jasmine-spec-reporter": "^7.0.0",
"mock-require": "^3.0.3",
"nock": "^13.2.7",
"nyc": "^15.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"nyc": "^15.1.0",
"react": "^18.1.0",
"react-dom": "^18.1.0"
}
}
19 changes: 19 additions & 0 deletions src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,23 @@ export const flags = [{
type: 'pattern',
multiple: true,
short: 'e'
}, {
name: 'shard-count',
description: 'Number of shards to split snapshots into',
parse: v => parseInt(v, 10),
type: 'number'
}, {
name: 'shard-size',
description: 'Size of each shard to split snapshots into',
parse: v => parseInt(v, 10),
type: 'number'
}, {
name: 'shard-index',
description: 'Index of the shard to take snapshots of',
parse: v => (process.env.PERCY_PARALLEL_TOTAL ||= '-1') && parseInt(v, 10),
type: 'index'
}, {
name: 'partial',
description: 'Marks the build as a partial build',
parse: () => !!(process.env.PERCY_PARTIAL_BUILD ||= '1')
}];
4 changes: 4 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export const storybookSchema = {
type: 'object',
normalize: false
},
globals: {
type: 'object',
normalize: false
},
queryParams: {
type: 'object',
normalize: false
Expand Down
113 changes: 0 additions & 113 deletions src/eval.js

This file was deleted.

Loading

0 comments on commit 26fc55a

Please sign in to comment.