Valibot v0.31.0 is finally available

GitHub profile picture of fabian-hiller

After 3 months of hard work I am happy to announce that Valibot v0.31.0 is finally available. This is not a regular release as we have rewritten the whole library from scratch.

Based on your feedback and all the lessons learned from the past, we were able to drastically improve the mental model, bundle size, flexibility, type safety and stability of the library. I would like to highlight some of the major improvements and changes in this post.

Because this release introduces some breaking changes, we put a lot of effort into making the migration experience as smooth as possible. I worked closely with the open source community to create a detailed migration guide and two codemods to automatically update your schemas.

Mental model

We believe that Valibot will be easier to use because we have drastically improved the mental model. For a modular library like Valibot, this is crucial, as each functionality is imported as its own function.

The mental model is now reduced to schemas, methods and actions. Schemas are used to validate a specific data type like a string, object or date. They are the starting point for using Valibot.

Methods help you either modify or use a schema. For example, the new pipe method extends the functionality of a schema by adding additional validation and transformation rules. When using a method, you always pass a schema as the first argument.

Finally, there are actions. Actions are used exclusively in the pipeline of a schema. They can be used to further validate or transform a particular data type. For example, the following schema can be used to trim a string and check if it is a valid email address.

Code example with a schema, method and actions

We recommend using Valibot with a wildcard import as this improves the developer experience. Tree shaking still works when using v.. We tested it with various build-systems.

You can find a list of all schemas, methods and actions in our API reference.

Bundle Size

After increasing the initial bundle size by introducing new features to the core of Valibot in the past, I am pleased to announce that this release reduces the individual bundle size of your schemas by approximately 15 to 30% without losing any functionality. This has been achieved by simplifying and unifying the internal structure and implementation.

For example, the string schema required 800 bytes in the previous version, while the same schema now requires only 560 bytes. This is a reduction of 30%. As the library is optimized for compression, and most of these bytes are shared across all schemas and actions, the bundle size increases only slightly when adding more schemas or actions.

Comparison of string schema bundle size between v0.30.0 and v0.31.0

For example, adding the number schema increases the bundle size by only 40 bytes, resulting in a total bundle size of 600 bytes. This is a huge improvement and makes Valibot even more attractive when using schemas to validate unknown data in the browser, on the edge, or in serverless environments. A smaller bundle size can greatly improve the startup performance of your application by reducing the time it takes to download and parse the JavaScript code.

I am planning an experimental library with the same external API but slightly less functionality. If it works out, it could become a drop-in replacement if you do not need the full functionality of Valibot. I expect the initial bundle size of this library to start around 200 bytes. Stay tuned!

Flexibility

Another huge improvement is the flexibility gained by our new pipe method. Compared to the previous versions, we removed many limitation. For example, it is now possible to transform the data type inside of pipelines. This simplifies the usage and readability as it reduces function nesting.

// With the previous API
const BirthdaySchema = v.brand(
  v.transform(v.string([v.isoDate()]), (input) => new Date(input)),
  'birthday'
);

// With the brand new API
const BirthdaySchema = v.pipe(
  v.string(),
  v.isoDate(),
  v.transform((input) => new Date(input)),
  v.brand('birthday')
);

Furthermore, it is now possible to extend the pipeline of an existing schema by adding additional validation and transformation rules. This makes it possible to reuse already created schemas to construct more specific ones. Similar to how you extend a class in object-oriented programming to make it more specialized.

const EmailSchema = v.pipe(v.string(), v.email());
const GmailSchema = v.pipe(EmailSchema, v.endsWith('@gmail.com'));

Type safety

After I started working on a first draft in early March, I spent at least two weeks thinking about the structure and interplay of everything. I also thought a lot about the type safety of the library.

Previously, many parts were only typed generically. An example is the issues that a schema returns when parsing invalid data. Even though each issue contains very specific data depending on the schema or action, they were all previously typed as a generic SchemaIssue.

This changes with this release. Wherever possible, we have tried to achieve 100% type safety. You can even infer the issue type of any schema or action used. We expect this improvement to result in a better developer experience and fewer bugs.

Code example showing how the issue type of a schema is automatically inferred

Stability

Once most of the decisions were made, we spent a lot of time writing unit and type tests. This explains why it took us two and a half months to release the first release candidate. The tests have allowed us to fix some previously undetected bugs and enhance the stability of the library in the long run.

Before v1, I would like to further improve the test coverage to be able to fully guarantee the functionality of each function. This is an ambitious goal, but I am confident that we will reach it soon.

Thank you!

This release was a team effort! Because so many of you contributed to this release in so many different ways, I am not able to mention everyone. However, I have tried to link all of your GitHub profiles and highlight some very important contributions. Please ping me if your avatar is missing.

  • GitHub profile picture of Afsoon
  • GitHub profile picture of AlexXanderGrib
  • GitHub profile picture of Andarist
  • GitHub profile picture of AndreyYolkin
  • GitHub profile picture of ariskemper
  • GitHub profile picture of colinhacks
  • GitHub profile picture of Demivan
  • GitHub profile picture of DylanThomasFr
  • GitHub profile picture of EltonLobo07
  • GitHub profile picture of GabrielHangor
  • GitHub profile picture of Hugos68
  • GitHub profile picture of IlyaSemenov
  • GitHub profile picture of MohammedEsafi
  • GitHub profile picture of MrGeniusProgrammer
  • GitHub profile picture of Saeris
  • GitHub profile picture of Sandros94
  • GitHub profile picture of Sec-ant
  • GitHub profile picture of alexbit-codemod
  • GitHub profile picture of ammarriq
  • GitHub profile picture of anuraghazra
  • GitHub profile picture of arybitskiy
  • GitHub profile picture of bingtsingw
  • GitHub profile picture of brandonpittman
  • GitHub profile picture of brenelz
  • GitHub profile picture of chertik77
  • GitHub profile picture of chimame
  • GitHub profile picture of christophsturm
  • GitHub profile picture of dboune
  • GitHub profile picture of devcaeg
  • GitHub profile picture of dusty
  • GitHub profile picture of fredericoo
  • GitHub profile picture of gmaxlev
  • GitHub profile picture of homersimpsons
  • GitHub profile picture of jansedlon
  • GitHub profile picture of jchatard
  • GitHub profile picture of joshwashywash
  • GitHub profile picture of jsudelko
  • GitHub profile picture of juliusmarminge
  • GitHub profile picture of kovalchukq
  • GitHub profile picture of linkb15
  • GitHub profile picture of lukemorton
  • GitHub profile picture of macarie
  • GitHub profile picture of morgante
  • GitHub profile picture of mtt-artis
  • GitHub profile picture of mutewinter
  • GitHub profile picture of mxdvl
  • GitHub profile picture of nakanoasaservice
  • GitHub profile picture of naveen-bharathi
  • GitHub profile picture of sacrosanctic
  • GitHub profile picture of samualtnorman
  • GitHub profile picture of saturnonearth
  • GitHub profile picture of seren5240
  • GitHub profile picture of sillvva
  • GitHub profile picture of ssalbdivad
  • GitHub profile picture of vladshcherbin
  • GitHub profile picture of xcfox
  • GitHub profile picture of yudinmaxim
  • GitHub profile picture of znycheporuk

Thanks to @Demivan and @xcfox for their contributions to the new API design. @Demivan had the initial idea for the pipe method and helped me with many decisions along the way. Thanks to @ariskemper for influencing the new structure of our unit tests, thanks to @EltonLobo07 for porting over 25 actions to the new implementation and thanks to @anuraghazra for finding a TypeScript workaround that made the new pipe method possible in this way.

I would also like to thank our partners and sponsors who provide intellectual and financial support to the project. In particular, I would like to thank the Seidenberg School of Computer Science and Information Systems at Pace University. Without their support over the past few months, this release would not have been possible.

Please contact us if your organization is interested in becoming a partner of Valibot to help us ensure the long-term development and maintenance of the project.

Edit page

Contributors

Thanks to all the contributors who helped make this page better!

  • GitHub profile picture of fabian-hiller

Partners

Thanks to our partners who support the project ideally and financially.

Sponsors

Thanks to our GitHub sponsors who support the project financially.

  • GitHub profile picture of dailydotdev
  • GitHub profile picture of Thanaen
  • GitHub profile picture of KATT
  • GitHub profile picture of osdiab
  • GitHub profile picture of ruiaraujo012
  • GitHub profile picture of hyunbinseo
  • GitHub profile picture of F0rce
  • GitHub profile picture of caegdeveloper
  • GitHub profile picture of seahindeniz