FormKit ships with a lot of functionality out of the box. This is great for getting started, but the defaultConfig
may include features and inputs you aren’t using. In this guide, we'll learn how to slim down our FormKit installation for production.
Most FormKit users get started by using the provided defaultConfig
— but what does this actually include?
@formkit/validation
plugin with all rules.@formkit/i18n
plugin with the en
locale (plus any additional locales you've added).@formkit/inputs
plugin with all non-pro inputs.@formkit/theme
plugin with CDN-loaded icons, or any explicitly loaded icons.@formkit/vue
bindings to allow FormKit to interface with Vue.@formkit/dev
error interpreter (gives human-readable error messages in development).The defaultConfig
also exposes a convenient object syntax to provide configuration options for all the plugins above. For example, to provide an input to the @formkit/inputs
plugin instantiation, the default config allows you to pass an inputs
property:
app.use(plugin, defaultConfig({
inputs: {
myInput: createInput(/* input options */)
}
}))
For more details, check out the source code of the defaultConfig
.
When optimizing your FormKit installation for production, you may want to create a custom configuration. This will allow you to only include the features, inputs, rules, and messages you are actually using.
For example, consider a project with a simple form that only uses a text input and the required
rule. Something like this:
<script setup>
async function submit () {
// ... submit the things
}
</script>
<template>
<FormKit
type="form"
@submit="submit"
>
<FormKit
type="text"
name="name"
label="Name"
help="What do people call you?"
validation="required"
/>
</FormKit>
</template>
In this case, we only want to use the singular required
rule, only the text
input, and only the required
message in English and German. We can create this tree-shakable custom configuration by not using the defaultConfig
and instead performing our own plugin instantiations:
// file: main.ts
import { createApp } from 'vue'
import App from './App.vue'
import type { FormKitOptions } from '@formkit/core'
import { plugin, bindings } from '@formkit/vue'
import { createValidationPlugin } from '@formkit/validation'
import { required } from '@formkit/rules'
import { createI18nPlugin, en, de } from '@formkit/i18n'
import { createLibraryPlugin, text, form, submit } from '@formkit/inputs'
const library = createLibraryPlugin({ text, form, submit })
const validation = createValidationPlugin({ required })
const i18n = createI18nPlugin({ en, de })
const app = createApp(App)
app.use(plugin, {
plugins: [library, validation, i18n, bindings]
})
If you are using the @formkit/nuxt
module, you can opt out of the defaultConfig
by providing the defaultConfig: false
option to the module:
export default defineNuxtConfig({
modules: ['@formkit/nuxt'],
formkit: {
autoImport: true,
defaultConfig: false
}
})
Then your formkit.config.ts
is expected to provide a full custom configuration:
import type { FormKitOptions } from '@formkit/core'
import { bindings } from '@formkit/vue'
import { createValidationPlugin } from '@formkit/validation'
import { required } from '@formkit/rules'
import { createI18nPlugin, en, de } from '@formkit/i18n'
import { createLibraryPlugin, text, form, submit } from '@formkit/inputs'
const library = createLibraryPlugin({ text, form, submit })
const validation = createValidationPlugin({ required })
const i18n = createI18nPlugin({ en, de })
export default {
plugins: [library, validation, i18n, bindings]
} satisfies FormKitOptions
In the above examples, we import the en
and de
locales. These include messages that are not used in our example. Instead, we could have provided our own custom messages directly:
createI18nPlugin({
en: {
validation: {
required: 'This field is required'
},
ui: {
submit: 'Submit'
}
},
de: {
validation: {
required: 'Dieses Feld ist erforderlich'
},
ui: {
submit: 'Einreichen'
}
}
})
Vue’s plugin architecture is inherently global. The plugin
in @formkit/vue
is no different; however, this convenience comes with a cost — FormKit will be loaded wherever Vue is loaded, even if it is not used on the page.
Fortunately for Nuxt users, the @formkit/nuxt
module provides a solution to this problem: autoImport: true
. This option will automatically inject FormKit and its configuration only on pages where it is used.
Vite users can also leverage automatic injection by using unplugin-formkit.
For users of other build tools or for use cases that don’t fit well within the supported features of unplugin-formkit
, using the <FormKitProvider>
component allows you to provide global configuration to your FormKit inputs at the point of use. Simply wrap your components in <FormKitProvider>
and provide a config
prop:
<script setup>
import { FormKitProvider } from '@formkit/vue'
import type { FormKitOptions } from "@formkit/core"
const formKitConfig: FormKitOptions = {
// ... your custom config
}
</script>
<template>
<FormKitProvider :config="formKitConfig">
<!-- your FormKit components (can be deeply nested) -->
</FormKitProvider>
</template>