Answer
VeeValidate 4 does not remove validation rules at runtime. The loss happens during the production build: when NODE_ENV=production, bundlers such as Vite, Webpack, or Rollup enable minification and dead-code elimination. If a rule is referenced only by its string name in a schema and its implementation is never statically imported and executed, the bundler treats that module as unreachable and removes it. Development builds usually skip or relax this pruning, so the rules appear present locally but are absent after minification. The failure is silent because VeeValidate resolves an unknown rule name to no validation rather than throwing an error.
Confirmed facts vs likely explanation
Confirmed: VeeValidate 4 registers rules through defineRule and keeps them in an internal runtime registry. Production builds enable minification and dead-code elimination. Bundlers prune code that has no static import path from the application entry point.
Likely explanation: Your schema uses rule names as strings, for example rules="required|email", while the rule implementations are imported only for side effects or not imported at all. Because no static reference keeps the rule module alive, the bundler drops it in the production bundle.
Steps to preserve rules across builds
- Explicitly import every rule you use from @vee-validate/rules and register it with defineRule before the app mounts.
import { defineRule } from 'vee-validate'
import { required, email, min } from '@vee-validate/rules'
defineRule('required', required)
defineRule('email', email)
defineRule('min', min)
- Centralize this registration in one module imported by your application entry point so the side effect runs in both development and production bundles.
- Add a temporary verification check after registration. Log each imported rule to confirm it is a function before defineRule runs.
import { defineRule } from 'vee-validate'
import { required } from '@vee-validate/rules'
console.log('required is a function:', typeof required === 'function')
defineRule('required', required)
- Inspect the production bundle with a bundler analyzer such as webpack-bundle-analyzer or rollup-plugin-visualizer and confirm the @vee-validate/rules modules are present in the output.
There is no documented VeeValidate flag or plugin that disables tree-shaking or forces rule persistence. Stability is achieved by ensuring static imports and explicit defineRule calls.
Assumptions and uncertainty: This applies to VeeValidate 4.x with standard Vite, Webpack, or Rollup configurations. Exact registry behavior can vary by minor version, and the verification log should be removed or gated before shipping if it exposes internal module paths.
One diagnostic detail that changes the recommendation: Are your rules imported from @vee-validate/rules and explicitly registered with defineRule, or are they referenced only by string names with no static import? If the latter, the explicit import step above is required.