Skip to content

perf: validate options with a precompiled check - #756

Merged
alexander-akait merged 2 commits into
mainfrom
perf/precompiled-options-check
Oct 18, 2026
Merged

alexander-akait merged 2 commits into
mainfrom
perf/precompiled-options-check

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Summary

webpack adds this plugin as its default minimizer in production mode. Validating its options with compiler.validate(schema, options, configuration) loads ajv and compiles options.json, about 200 ms on every production build start.

src/options.check.js is that schema precompiled with schema-utils precompile (schema-utils 4.6.0, webpack/schema-utils#231). It's passed as the check argument to compiler.validate and to the schema-utils validate fallback for older webpack versions:

  • Valid options go through the check only, so ajv never loads.
  • Invalid options still get the full ajv validation, so the error messages stay the same.

Measurements

Production webpack(config) with new MinimizerPlugin() as the minimizer, in a fresh Node 22 process, median of 5:

Before After
webpack(config) 563 ms 356 ms (−207 ms, −37%)
ajv loaded yes no

Changes

  • src/index.js passes require("./options.check.js") to both validation paths.
  • Keeping the check in sync:
    • npm run fix:schema regenerates the check.
    • lint:schema (run by npm run lint) fails when the check is out of date with options.json. A change to a description doesn't trigger it, because annotations are stripped before compiling.
  • Build: Babel now skips the check and copies it as is. It's already written for Node 10.13.0, and transpiling it tripled it from 77 KB to 248 KB. Jest gets the matching transformIgnorePatterns, and ESLint, Prettier, cspell and coverage ignore the generated file.
  • types/options.check.d.ts is generated by build:types like the other declarations.
  • schema-utils goes to ^4.6.0, because the check loads its ucs2length helper from schema-utils/dist/runtime. The lockfile was on 4.3.3, and later versions print property types in error messages. That changes two snapshots, e.g. object { path, export? } becomes object { path: non-empty string, export?: non-empty string }.

Tests

  • Parity: createCompiler in test/validate-options.test.js now also asserts that the precompiled check accepts or rejects the options exactly as the full schema-utils validation does, across every valid and invalid case in that file. webpack's compiler.validate never runs the schema when a check says the options are valid, so a check that disagrees would let invalid options through.
  • npm run lint and the full suite (781 tests, 837 snapshots) pass locally. dist/options.check.js is byte-identical to the source and works under Node.

Generated by Claude Code

Summary by CodeRabbit

  • Performance
    • Option validation now uses a precompiled validator, avoiding schema compilation for valid configurations and helping the plugin initialize more efficiently.
  • Bug Fixes
    • Invalid configurations continue to be rejected, including unsupported options and values outside the allowed formats. Validation results remain consistent across the plugin’s supported validation paths.

webpack validates the plugin options with `compiler.validate`, which
without a check loads `ajv` and compiles `options.json`: about 200ms of
every production build start, since webpack adds this plugin as its
default minimizer.

`src/options.check.js` is that schema precompiled with `schema-utils
precompile`, passed as the fourth argument to `compiler.validate` and to
the `schema-utils` fallback. Valid options are only checked; `ajv` still
reports what is wrong with invalid ones, so the errors stay the same.

`npm run fix:schema` regenerates the check and `lint:schema` fails when
it is out of date with the schema. Babel copies it as is, it is already
written for Node.js 10.13.0 and the transforms made it three times the
size. Every case of the validation tests now also asserts that the check
agrees with the schema. `schema-utils` goes to 4.6.0 for the runtime
helpers the check loads, which also changes how two error messages print
the property types.
@changeset-bot

changeset-bot Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5a1e8da

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
minimizer-webpack-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@socket-security

socket-security Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedschema-utils@​4.3.3 ⏵ 4.6.099 +110010089100

View full report

@codecov

codecov Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.67%. Comparing base (f185baa) to head (5a1e8da).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #756   +/-   ##
=======================================
  Coverage   97.67%   97.67%           
=======================================
  Files           5        5           
  Lines        1718     1718           
  Branches      664      668    +4     
=======================================
  Hits         1678     1678           
  Misses         39       39           
  Partials        1        1           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 214b8804-64a5-4003-bd91-3db7b8becc07
📥 Commits

Reviewing files that changed from the base of the PR and between 69ce2e4 and 5a1e8da.

📒 Files selected for processing: 1
  • test/embedded-source.test.js

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.

Walkthrough

The plugin adds a generated validator for its options schema and passes it to the webpack compiler validation path and the schema-utils fallback. Tests compare the precompiled validator with schema-based validation. Package scripts and tool configurations support generating and handling the generated file. Nested data stylesheet tests sort CSS declarations before comparing them.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 5a1e8

The change uses a precompiled check for option validation and makes CSS tests tolerant of declaration-order differences. No actionable merge-blocking risk remains; the PR is ready subject to normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 8 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the primary change: improving option-validation performance by using a precompiled check.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

test/embedded-source.test.js

Oops! Something went wrong! :(

ESLint: 10.13.0

Error: Error while loading rule 'jest/no-deprecated-functions': Unable to detect Jest version - please ensure jest package is installed, or otherwise set version explicitly
Occurred while linting /test/embedded-source.test.js
at detectJestVersion (/.eslint-tmp/node_modules/eslint-plugin-jest/lib/rules/utils/detectJestVersion.js:22:9)
at create (/.eslint-tmp/node_modules/eslint-plugin-jest/lib/rules/no-deprecated-functions.js:31:107)
at Object.create (/.eslint-tmp/node_modules/@typescript-eslint/utils/dist/eslint-utils/RuleCreator.js:39:20)
at createRuleListeners (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:502:15)
at /.eslint-tmp/node_modules/eslint/lib/linter/linter.js:628:7
at Array.forEach ()
at runRules (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:562:31)
at #flatVerifyWithoutProcessors (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:1297:4)
at Linter._verifyWithFlatConfigArrayAndWithoutProcessors (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:1382:43)
at Linter._verifyWithFlatConfigArray (/.eslint-tmp/node_modules/eslint/lib/linter/linter.js:1449:15)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Member Author

The failing Test - * - Node v10.x/v12.x/v14.x, Webpack latest rows don't come from this PR. Each fails two tests in test/embedded-source.test.js: webpack 5.112.0 (released Oct 15) emits CSS declarations in a different order (color:red before background), and those tests compare the stylesheet verbatim. Those rows install webpack@latest, because their npm can't read the v3 lockfile; every other row stays on the locked 5.109.2, where the file is skipped. main fails the same way.

Fix: #760. Once it's merged, I'll merge main into this branch.


Generated by Claude Code

webpack 5.112's CSS minimizer emits declarations in a different order, so
the two embedded-source tests that compared the stylesheet verbatim failed
on the rows that install webpack@latest (Node 10/12/14).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYPkbvwyRWt2SHgXDoYRdo
@alexander-akait
alexander-akait merged commit 4def5f4 into main Oct 18, 2026
31 checks passed
@alexander-akait
alexander-akait deleted the perf/precompiled-options-check branch October 18, 2026 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant