Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

フロントエンド開発にtextlintを導入して運用している話

 フロントエンド開発にtextlintを導入して運用している話

フロントエンド開発にtextlintを導入して運用している話
2021.07.13 Tue. SaaSプロダクトのフロントエンド最前線@オンライン

近藤 大介 @diescake
SmartHR プロダクトエンジニア
/年末調整チーム/主にWebフロントエンド(React + TypeScript)
2020年1月SmartHR入社
SmartHR年末調整チームを住処にして、2020年の年末調整の管理画面リニューアルから姿を現す
クラフトビールをポチっては冷蔵庫に積む習性を持つ

経緯・モチベーション

SmartHRの開発グループは、
フィーチャーチーム構想を掲げ、
クロスファンクショナル化の取り組みを進めています

クロスファンクショナル化の一環で
文言(UXライティング)と向き合い始めたdiescakeであったが…

単純な表記揺れ・ルールに起因する不備を一掃したい
PRでSuggested changesが飛び交う
個々単語の表記を覚えきれない
SmartHRの文言ガイドライン策定以前の文言もあわせたい
人間が本当に悩むべき点に注力したい
モチベーション・解決したい課題

textlintとは?

自然言語に対する静的チェックツール(linter)
デフォルトでplain text・Markdownをサポート
ルール・対象ファイル種別をライブラリで拡張可能
GitHub上に200以上のルールが公開されている
author: @azu_reさん

🔌 プラグイン
対象ファイルを追加(parser実装)
ライブラリ名は textlint-plugin-*
✅ ルール
文言に対するルールを追加
ライブラリ名は textlint-rule-*

kufu/textlint-rule-preset-smarthr
textlint-rule-preset-smarthr

SmartHRの文言ガイドラインに準拠したルールをまとめたプリセット
textlintを導入するプロダクト側では個々のルールを意識せずtextlint-rule-preset-smarthrをインポートすればよい
伸びしろに満ちあふれています😌

textlint-rule-ja-no-redundant-expression
「することができる」➔「できる」のように、なくてもいい・ないほうが読みやすい表現を検出する
textlint-rule-preset-ja-spacing
英語・日本語間のスペース有無を検出する
SmartHRの文言ガイドラインでは、半角英数字と日本語の間にはスペースを入れないルールを採用している
textlint-rule-ja-hiragana-keishikimeishi
ひらがなで表記したほうが読みやすい形式名詞を検出する
ex.) 明日やること、明日やる事

textlint-rule-prh
辞書を持ち、単語の期待値を登録することでゆらぎを検出する
正規表現による単語登録をサポート

textlintを
プロダクトに導入する

textlintの対象ファイルにフロントエンドのソースコードを追加する(*.js, *.ts, *.jsx, *.tsx)
プラグイン名こそjsxであるが、入力ファイルをtypescriptのparserを利用してASTに変換しているのでTypeScriptもサポート
🔌 textlint-plugin-jsx

textlintの設定ファイルにエラーを許容する文言を追加できる
正規表現の記述が可能
💡 導入・運用の要(後述)
✅ textlint-filter-rule-allowlist

⚙️ textlintの設定ファイルを記述する
https://textlint.github.io/docs/configuring.htmlより引用

設定ファイルは.textlintrc推奨とされているが.textlintrc.ymlを採用した
👍 拡張子が明示されているとsyntax highlightingやlinting、オートフォーマットが効く(大事)
👍 YAMLはコメントが書ける(超大事)
⚙️ textlintの設定ファイルを記述する

インストールしたルールとプラグインを有効化
詳しくは、公式ドキュメント参照
.textlintrc.ymlの素朴な設定

≒ textlintをCIに載せること
➔ textlintを通したい…!

textlintを既存プロダクトに導入した直後は大量のエラーがでるはず 🐛🐛🐛
ルールを緩めたり対象ファイルを限定してよいので、CIに載せてグリーンになることを目標にして修正していく
CIでtextlintが通る環境を作ってから、段階的に広げていく
small startでfalse-negativeな運用が大事
💪 textlintを通したい…!

ルールセットのインポート側で、部分的にルールをオーバーライドできる
無効化した理由をコメントとして残しておくと記憶喪失になっても大丈夫
textlint-rule-preset-smarthrの一部のルールを無効化

テストコードやモック等のダミーデータがエラーになる場合は除外しておく、みたいな使い方ができる
.textlintignoreで対象ディレクトリ・ファイルを限定する

ありふれた方法ではあるが誰の目にもわかりやすく有効
npm scriptsで対象ディレクトリ・ファイルを限定する

ルール違反となる固有名詞を登録してエラーを回避
textlintのルール不備によるエラーや一時的なエラー回避として活用できる
allowlistに単語を登録してエラー回避

困ったらallowlist 😌

自然言語を扱うため、予期せぬ誤検知が発生しやすい
しかし、共通ルールセットの修正➔リリースにはリードタイムがかかる
誤検知された文言はallowlistに追加することでCIのグリーンをキープして作業を継続できる
各リポジトリのallowlistを監視するとルールの問題点が集められそう
💡 textlintのルール誤検知回避のためのallowlist

VSCode連携

VSCode上でtextlintがリアルタイムに実行されている様子

taichi.vscode-textlintをインストールする
VSCodeの設定(settings.json)にvscode-textlintの対象とする言語を追加する

デフォルトでは*.js, *.jsx, *.ts, *.tsxは対象にならない
VSCode Extensionのvscode-textlintをインストール

振り返ってみる

単純な表記揺れ・ルールに起因する不備を一掃したい
PRでSuggested changesが飛び交う
個々単語の表記を覚えきれない
SmartHRの文言ガイドライン策定以前の文言もあわせたい
人間が本当に悩むべき点に注力したい
(再掲)モチベーション・解決したい課題

割とLGTM 🎉🎉

👍 よかったこと・実現できたこと
割れ窓を作らない継続的な運用
カジュアルにallowlistに突っ込む運用でも十分効果は得られる
文言ガイドラインのルールをスムーズにプロダクトに反映させるための土台作り
オンボーディングコストの低減
精神衛生の向上 🤗

ルールを拡充させて、文言ガイドラインのカバレッジを向上する
文言を持つのはフロントエンドのソースコードだけではない(*.rb, *.erb )
ファイルに対応するtextlint pluginの実装が必要になる
文言ガイドラインからtextlintのルールを更新するフローの整備
誤検知となった単語・ステートメントの根本解決
🤔 課題・やっていきたいこと

🤔 課題・やっていきたいこと
今回は、プロダクトのフロントエンドにフォーカスした話をしたが、サポートサイトや、オウンドメディアなどユーザとのタッチポイントはたくさんある
他職能のメンバーを巻き込みながら、クロスファンクショナルに活用の幅も広げていきたい…!

https://hello-world.smarthr.co.jp/
フロントエンドエンジニア積極採用中…!!
🙏

diescake

July 15, 2021
Tweet

More Decks by diescake

Other Decks in Programming

Transcript

  1. ۙ౻ େհ SmartHR ϓϩμΫτΤϯδχΞ ʗ೥຤ௐ੔νʔϜʗओʹWebϑϩϯτΤϯυʢReact + TypeScriptʣ • 2020೥1݄SmartHRೖࣾ •

    SmartHR೥຤ௐ੔νʔϜΛॅॲʹͯ͠ɺ2020೥ͷ೥຤ௐ੔ ͷ؅ཧը໘ϦχϡʔΞϧ͔Β࢟Λݱ͢ • ΫϥϑτϏʔϧΛϙνͬͯ͸ྫྷଂݿʹੵΉशੑΛ࣋ͭ @diescake
  2. textlintͱϧʔϧɾϓϥάΠϯͱͷؔ܎ 🔌 ϓϥάΠϯ - ର৅ϑΝΠϧΛ௥Ճʢparser࣮૷ʣ - ϥΠϒϥϦ໊͸ textlint-plugin-* ✅ ϧʔϧ

    - จݴʹର͢ΔϧʔϧΛ௥Ճ - ϥΠϒϥϦ໊͸ textlint-rule-* textlintຊମ - plain text parser - Markdown parser ઃఆϑΝΠϧͰ Πϯϙʔτ ઃఆϑΝΠϧͰ Πϯϙʔτ
  3. textlintͱϧʔϧɾϓϥάΠϯͱͷؔ܎ʢReal-worldʣ textlintຊମ - plain text parser - Markdown parser ✅

    ϧʔϧAɿ textlint-rule-hoge ઃఆϑΝΠϧͰ Πϯϙʔτ ✅ ϧʔϧBɿ textlint-rule-foo ✅ ϧʔϧCɿ textlint-rule-piyo ✅ ϧʔϧDɿ textlint-rule-buz … 🔌 ϓϥάΠϯAɿ textlint-plugin-waga 🔌 ϓϥάΠϯBɿ textlint-plugin-hai 🔌 ϓϥάΠϯCɿ textlint-plugin-neko 🔌 ϓϥάΠϯDɿ textlint-plugin-dayo … … …
  4. textlintͱϧʔϧɾϓϥάΠϯͱͷؔ܎ʢReal-worldʣ textlintຊମ - plain text parser - Markdown parser ✅

    ϧʔϧAɿ textlint-rule-hoge ઃఆϑΝΠϧͰ Πϯϙʔτ ✅ ϧʔϧBɿ textlint-rule-foo ✅ ϧʔϧCɿ textlint-rule-piyo ✅ ϧʔϧDɿ textlint-rule-buz … 🔌 ϓϥάΠϯAɿ textlint-plugin-waga 🔌 ϓϥάΠϯBɿ textlint-plugin-hai 🔌 ϓϥάΠϯCɿ textlint-plugin-neko 🔌 ϓϥάΠϯDɿ textlint-plugin-dayo … … …
  5. textlintͱϧʔϧɾϓϥάΠϯͱͷؔ܎ʢReal-worldʣ textlintຊମ - plain text parser - Markdown parser ઃఆϑΝΠϧͰ

    Πϯϙʔτ ✅ ϧʔϧηοτɿ textlint-rule-preset-smarthr 🔌 ϓϥάΠϯAɿ textlint-plugin-waga 🔌 ϓϥάΠϯBɿ textlint-plugin-hai 🔌 ϓϥάΠϯCɿ textlint-plugin-neko 🔌 ϓϥάΠϯDɿ textlint-plugin-dayo … … 🤗
  6. - textlint-rule-ja-no-redundant-expression - ʮ͢Δ͜ͱ͕Ͱ͖Δʯ➔ʮͰ͖ΔʯͷΑ͏ʹɺͳͯ͘΋͍͍ɾͳ͍΄͏͕ ಡΈ΍͍͢දݱΛݕग़͢Δ - textlint-rule-preset-ja-spacing - ӳޠɾ೔ຊޠؒͷεϖʔε༗ແΛݕग़͢Δ -

    SmartHRͷจݴΨΠυϥΠϯͰ͸ɺ൒֯ӳ਺ࣈͱ೔ຊޠͷؒʹ͸εϖʔε ΛೖΕͳ͍ϧʔϧΛ࠾༻͍ͯ͠Δ - textlint-rule-ja-hiragana-keishikimeishi - ͻΒ͕ͳͰදهͨ͠΄͏͕ಡΈ΍͍͢ܗ໊ࣜࢺΛݕग़͢Δ - ex.) ໌೔΍Δ͜ͱɺ໌೔΍Δࣄ ✅ ࠾༻͍ͯ͠Δ୅දతͳϧʔϧ
  7. ʢ࠶ܝʣtextlintͱϧʔϧɾϓϥάΠϯͱͷؔ܎ʢReal-worldʣ textlintຊମ - plain text parser - Markdown parser ઃఆϑΝΠϧͰ

    Πϯϙʔτ ✅ ϧʔϧηοτɿ textlint-rule-preset-smarthr 🔌 ϓϥάΠϯAɿ textlint-plugin-waga 🔌 ϓϥάΠϯBɿ textlint-plugin-hai 🔌 ϓϥάΠϯCɿ textlint-plugin-neko 🔌 ϓϥάΠϯDɿ textlint-plugin-dayo … …
  8. textlintͱϓϩμΫτͱͷؔ܎ ✅ ϧʔϧηοτɿ textlint-rule-preset-smarthr 🔌 ϓϥάΠϯAɿ textlint-plugin-waga 🔌 ϓϥάΠϯBɿ textlint-plugin-hai

    🔌 ϓϥάΠϯCɿ textlint-plugin-neko 🔌 ϓϥάΠϯDɿ textlint-plugin-dayo … … textlintຊମ package.json ϓϩμΫτʢ΢ΣϒϑϩϯτΤϯυɾSlackbotɾChrome Extension ͳͲʣ
  9. - ϧʔϧΛ֦ॆͤͯ͞ɺจݴΨΠυϥΠϯͷΧόϨοδΛ޲্͢ Δ - จݴΛ࣋ͭͷ͸ϑϩϯτΤϯυͷιʔείʔυ͚ͩͰ͸ͳ͍ ʢ*.rb, *.erb ʣ - ϑΝΠϧʹରԠ͢Δtextlint

    pluginͷ࣮૷͕ඞཁʹͳΔ - จݴΨΠυϥΠϯ͔ΒtextlintͷϧʔϧΛߋ৽͢Δϑϩʔͷ੔උ - ޡݕ஌ͱͳͬͨ୯ޠɾεςʔτϝϯτͷࠜຊղܾ 🤔 ՝୊ɾ΍͍͖͍ͬͯͨ͜ͱ