kintone Advent Calendar 2021 23日目の記事です
今年は、kintone UI Component という「kintone ライクなパーツを提供する OSS ツール」の開発に取り組んでいるので、技術スタック・開発やテストでの工夫ポイントなどの裏側を少しお見せしたいなと思います!
実際に使っていただいているユーザーさんがいらしたら、開発の仕組みを知っていただくことで少しでも安心して使ってもらえるといいなとも思っています
どんなライブラリ?
これです...!笑
kintone アプリやプラグインカスタマイズをする際に、UI 周りのアレンジをしたいケースがあるかと思います。そんな時、デザインも kintone テイストにしたくなりますよね!
「CSS を色々いじったら寄せることはできるけど面倒だし、さらに挙動まで kintone ライクにするのはなかなか大変」。
そこで、簡単に呼び出してちょちょいとオプション設定を入れて使っていただけるのがこのライブラリです。
kintone カスタマイズあるあるを踏まえて各コンポーネントの仕様を考えるようにしているので、最低限の要件を満たすものをサクッと作っていただけるかなと思います。
(一方、汎用的に使ってもらえるものを目指していて、複雑な UI や動きを作り込むことは現状あまり想定していませんが、自由度はある程度持たせていきたいなと思っています!)
例えば npm パッケージ 利用の場合、Button コンポーネントはこんな風に呼び出して使うことができます。UMD ファイル, CDN, npm パッケージの3パターンで提供しているので、お好みに合わせてお使いください。
import { Button } from 'kintone-ui-component/lib/button';
(() => {
'use strict';
kintone.events.on('app.record.index.show', event => {
const header = kintone.app.getHeaderMenuSpaceElement();
const button = new Button({
text: 'Submit',
type: 'submit'
});
button.addEventListener('click', event => {
console.log(event);
});
header.appendChild(button);
return event;
});
})();
v0 シリーズを経て、2021年3月に v1 シリーズをリリースしまして、現在 Desktop と Mobile ver. 合わせて Button, Checkbox, Notification, Text など 17 コンポーネントを提供中です。
直近は DateTime シリーズや Dialog を作っていてもうすぐお披露目する予定です
あと、プラグイン設定画面などでよく使われる Table も計画中。
詳細はぜひドキュメントサイトをご覧ください。サンプルコード付きで書いておりますー
Quick Start はこちら。
では、ざっくり紹介が終わったところで、ここから仕組み的なところをお話ししていこうと思います
技術スタックはどんな感じ?
以下のように技術スタックを選択して実装しています!
- コンポーネント実装:Web Components の Lit, TypeScript
- 挙動や UI チェック:Storybook
- 開発ルールチェック:ESLint Custom Rule(以前は Sider 利用)
-
アクセシビリティチェック:Screen Reader
- 視覚的な障害がある方にとっては、キーボードで操作ができることや音声読み上げが正しくされることが重要です。内部的にはWAI-ARIAという技術を使って HTML だけでは表すことのできない構造や状態などを明示して、スクリーンリーダーで読み上げがされるように工夫していたり、キーボード動作もサポートしていたりします。障害がない方にとっても使い方の選択肢が広がり操作性がアップすることにも繋がりますね!
- 読み上げの確認には、スクリーンリーダーというツールを使っています。Chrome Extension もあったりするので比較的簡単にインストールして使うことができます。
-
ユニットテスト:Karma
- コードロジックのテストには、当初 Web Components のプロジェクトでおすすめされていた Karma を使っていますが、関連ライブラリがメンテナンスモードのため長期的には別のを探した方が良さそうだなと思っているところです。
- テスト自動化:WebdriverIO
- ドキュメント:docusaurus
-
サイトホスティング:Netlify
- docusaurus で作ったサイトをホスティングするのに使ってます。
- CI:GitHub Actions
- パッケージの脆弱性チェック:dependabot, Yamory
工夫ポイント
普段は、スクラム形式で毎週バックログ(要件リスト)の検討・タスクプランニング・進捗報告 & 成果発表というサイクルで開発を進めています。新規コンポーネントについては、ユーザーヒアリングもしながら PM, PG, QA メンバーで仕様を検討します。
プランニングは、こんな感じに kintone で
既に技術スタックの解説で触れたものも多いですが、フェーズごとに工夫していることをいくつかピックアップしてみました
開発フェーズ
共通クラスや関数を切り出し
メンテコスト削減のため、コンポーネント間で共通で使えるクラスや関数を切り出して、各コンポーネントスクリプトで呼び出すようにしています。(extends KucBase
や visiblePropConverter
などの部分)
import { html, PropertyValues, svg } from "lit";
import { property, state, queryAll, query } from "lit/decorators.js";
import {
KucBase,
generateGUID,
dispatchCustomEvent,
CustomEventDetail
} from "../base/kuc-base";
import { visiblePropConverter } from "../base/converter";
import {
validateProps,
validateItems,
validateValueString,
validateSelectedIndexNumber
} from "../base/validator";
type Item = {
label?: string;
value?: string;
};
type DropdownProps = {
className?: string;
error?: string;
id?: string;
label?: string;
value?: string;
selectedIndex?: number;
disabled?: boolean;
requiredIcon?: boolean;
visible?: boolean;
items?: Item[];
};
export class Dropdown extends KucBase {
@property({ type: String, reflect: true, attribute: "class" }) className = "";
@property({ type: String }) error = "";
@property({ type: String, reflect: true, attribute: "id" }) id = "";
@property({ type: String }) label = "";
@property({ type: String }) value = "";
@property({ type: Number }) selectedIndex = -1;
@property({ type: Boolean }) disabled = false;
@property({ type: Boolean }) requiredIcon = false;
@property({
type: Boolean,
attribute: "hidden",
reflect: true,
converter: visiblePropConverter
})
visible = true;
...
コミットごとにユニットテスト
ロジックのテストがうまく通っているか、コミットごとにチェックする CI を設定しているので、Pull Request 画面でレビュアーが結果を確認して問題があったときに早めに気づけるようにしています。
name: On commit v1
on:
push:
jobs:
Run_tests:
name: Run unit test
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Cache dependencies
uses: actions/cache@v2
with:
path: ~/.npm
key: npm-${{ hashFiles('package-lock.json') }}
restore-keys: npm-
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: npm run es-lint
- name: Run unit test
run: npm test
テストフェーズ
WebdriverIO や GitHub Actions self-hosted runner などでテスト自動化!
サポートしている提供方法(ESM/UMD)・ブラウザ(Safari, Google Chrome, Firefox, Edge)やモバイル端末(iOS, Android)が複数あって手動確認では埒があきません...
全てのテストケースをカバーできるわけではないですが、自動化の仕組みを入れることで大幅にコストカットできるようになりました。
- テストスクリプトを確認アプリに自動で適用(customize-uploader 利用)
- GitHub Actions でのテストワークフロー実行(複数環境を同時実行)
- ブラウザやモバイル画面を自動で立ち上げてテストケース実行
- テスト結果を出力
システム構成
仕組みについては大体こんな感じです ちょっと複雑なので簡単な紹介に留めておきます。
- 環境ごとの GitHub Actions ワークフローファイルを定義
- パラレルに実行されるように Job を設定
- GitHub Actions self-hosted runner を設置した Windows と Mac 端末にて Job を実行
- テスト環境を立ち上げてテスト実行
動き
QA や PG メンバーは以下のステップでテストして問題があるところを修正します。
リリースフェーズ
毎度作業が面倒なところは、できるだけ CI で自動化です!
- リリースチェック(バージョン, ESLint, ユニットテストなど)
- Release tag へのアーカイブファイルのアップロード
- ドキュメントのステージングとプロダクションサイトのデプロイ
この中で、一つだけ取り上げてみます。
ドキュメントサイトのステージングとプロダクションの使い分け
正式にリリースをする前にドキュメントだけオープンになっては困るので、タイミングによって Netlify 上の2つの環境を切り替えてデプロイし、内容確認をしています。
最後に
各トピック少しずつしか書けなかったので、需要があればもうちょっと詳しい内容もどこかでご紹介できればと思います!
また、kintone UI Component は OSS として公開しているので、ぜひ一緒に KAIZEN していけると嬉しいです。リクエストやお気づきのことがあれば、issue や Pull Request 登録などコントリビュートもお待ちしておりますー
それでは最後まで読んでいただきありがとうございました