ajvはNode.jsとブラウザ用のバリデーションライブラリ。
Typescriptで利用できるバリデーションライブラリといえば、yup, zod, joiあたりが候補に上がるが、ajvを採用した。
理由はバックエンド・クライアント両方で使えること、スキーマファイルを使えること、そしてIE11対応が可能であることが決め手となった。
ajvはスキーマファイルを使ってもいいし、コードで書いてもいいしで使いやすそうであった。
動作確認環境
- next: 12.1.0
- ajv: 8.8.2
- ajv-formats: 2.1.1
インストール
yarn add ajv
基本的な使い方
1. バリデーションファイルを作成
login.validator.ts
import Ajv from 'ajv' const ajv = new Ajv() const schema = { type: 'object', properties: { username: { type: 'string' }, }, required: ['username'], additionalProperties: true, // username以外のパラメータがあっても許容する } export const validate = ajv.compile(schema)
2. バックエンド(Node.js)で利用する
先程作ったvalidate
メソッドを呼び出して値を検証するだけ。
api/login.ts
import { validate } from '@/validators/login.validator' export default function handler(req, res) { const isValid = validate(req.body) res.status(200).json({ result: isValid }) }
3. クライアント(ブラウザ)で利用する
ブラウザで利用するときも同じ。
pages/users.tsx
import { validate } from '@/validators/login.validator' import { useRef } from 'react' const Users = () => { const ref = useRef(null) const onClick = () => { const username = ref.current.value const isValid = validate({ username }) } return ( <div> ユーザー名: <input ref={ref} type="text" name="username" /> <button onClick={onClick}>送信</button> </div> ) } export default Users
自作のバリデーションルールを適用
例えば'hoge'
という文字列しか受け付けないようなルールを適用したい場合
import Ajv from 'ajv' const ajv = new Ajv() + function isHoge(schema, data) { + return data === 'hoge' + } + + ajv.addKeyword({ + keyword: 'isHogeValue', + validate: isHoge, + }) const schema = { type: 'object', properties: { + username: { type: 'string', isHogeValue: isHoge }, }, required: ['username'], additionalProperties: true, } export const validate = ajv.compile(schema)
keywordとvalidatorの名前を同じにしておけばもうちょっとシンプルになる。
import Ajv from 'ajv' const ajv = new Ajv() function isHoge(schema, data) { return data === 'hoge' } ajv.addKeyword({ + keyword: 'isHoge', validate: isHoge, }) const schema = { type: 'object', properties: { + username: { type: 'string', isHoge }, }, required: ['username'], additionalProperties: true, } export const validate = ajv.compile(schema)
IE11 対応
next.config.js
を下記のようにする。ajv-formats
を使っている場合はajv-formats
も対象にする。
module.exports = { webpack(config, options) { config.module.rules.push({ test: /node\_modules\/.*(ajv|ajv-formats)\/.*\.js$/, // ajvをIE11対応させる use: [ options.defaultLoaders.babel, { loader: 'babel-loader?cacheDirectory', options: { presets: ['next/babel'] }, }, ], }) return config }, }
終わりに
今回はシンプルにコードベースでバリデーションを書いていったが、スキーマファイルを使った例も試したい。
スキーマファイルを使う場合はスキーマファイルを自動生成してajvで使うといったことができると開発体験が良くなりそうだ。