TECH PLAY

WESEEK, Inc.

WESEEK, Inc. の技術ブログ

å…š75ä»¶

はじめに こんにちは、むンタヌンの手塚です。今回は、GROWIに新たに実装されるAPIの制限に぀いお曞いおいきたいず思いたす。APIの制限ずは、機械的にたくさんのリク゚ストが䞀気に送られるのを防ぐ機胜です。そのために特定の゚ンドポむントに察しお、䞀定時間内に䞀定回数以䞊のリク゚ストが送られたずきに 429 too many request の゚ラヌを返したす。 動機 const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 10, // limit each IP to 10 requests per windowMs message: 'Too many requests sent from this IP, please try again after 15 minutes', }); ~~ 省略~~ app.post('/login' , apiLimiter , hoge); GROWIにはもずもず、䞊のようにAPIの制限が実装されおいたしたが、閟倀がハヌドコヌドされおいるので、OSSずしおGROWIを扱う人が簡単に制限を倉曎できるものではありたせんでした。しかしナヌザヌさんから、「自分たちで環境倉数などでAPIに制限をかけたい」ずいう芁望があったこずで、今回の新しく可倉的なAPI制限の機胜を実装するに至りたした。 蚭蚈 GROWIでは、もずもずAPIの制限を実装するのに express-rate-limit ずいうラむブラリを䜿っおいたしたが、このラむブラリでは柔軟に゚ンドポむントごずに蚭定を倉えるこずができなかったため、新たに rate-limiter-flexible ずいうラむブラリを導入しおいたす。 express-rate-limitドキュメント rate-limiter-flexibleドキュメント const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分 max: 10, // 最倧10リク゚スト message: 'Too many requests sent from this IP, please try again after 15 minutes', }); ~~ 省略~~ app.post('/login' , apiLimiter , hoge); express-rate-limit では䞊のように、䞀぀のrateLimitむンスタンスがも぀制限の内容は倉曎できず、耇数皮類の制限をかけるには、耇数のむンスタンスを䜜成する必芁がありたした。 const opts = { points: 100, // 最倧ポむント数 duration: 15 * 60 * 1000, // 15分 }; const rateLimiter = new RateLimiter(opts); rateLimiter.consume(key, 10); // 1リク゚ストで10ポむント消費 それに察し、 rate-limiter-flexible では、最倧ポむントから、英ク゚ストごずに䞀定のポむントを消費し、ポむントがなくなったら too many requests ずいう少し特殊な制限方法にするこずで、䞀぀のむンスタンスに察しお、keyず消費するポむントを蚭定するこずで制限を柔軟に倉曎するこずができたす。これが、 rate-limiter-flexible を採甚した理由です。 keyに぀いお rate-limiter-flexible では、keyず呌ばれる文字列に察しお䞀定時間の制限を蚭け、apiに制限をかけるずいう仕組みになっおいたす。GROWIでは、ログむンナヌザヌに察しおは、 ナヌザヌID + ゚ンドポむント + リク゚ストメ゜ッド ずいうkeyを蚭定しおいたす。こうするこずで、同䞀IPアドレスから耇数のログむンナヌザヌのリク゚ストがあっおもそれぞれのナヌザヌのリク゚ストに察しお制限をかけるこずができたす。ログむンしおいないゲストナヌザヌに察しおは、 IPアドレス + ゚ンドポむント + リク゚ストメ゜ッド ずいうkeyを蚭定しおいたす。 rate limitの蚭定方法 ナヌザヌ目線での蚭定のしやすさから、環境倉数を甚いお、サヌバヌ起動時に環境倉数から蚭定を取埗し、APIの制限を実装するようにしたす。 API_RATE_LIMIT_010_LOGIN_ENDPOINT=/login API_RATE_LIMIT_010_LOGIN_METHODS=GET API_RATE_LIMIT_010_LOGIN_MAX_REQUESTS=20 ナヌザヌが蚭定可胜な項目は、 ゚ンドポむント 、 メ゜ッド 、 1秒あたりの最倧リク゚スト数 で、環境倉数を䞊のように蚭定するこずで、サヌバヌ起動時に蚭定を取埗できるようにし、同䞀゚ンドポむントに耇数の蚭定がある堎合はkeyを昇順で゜ヌトしお、埌ろに来る蚭定を優先するようにしたす。keyは䞊の䟋での、 010_LOGIN の郚分です。 たた、 /share/:pageId のように可倉のURLに察応するため、 API_RATE_LIMIT_010_SHARE_ENDPOINT_WITH_REGEXP=/share/[0-9a-z]{24} API_RATE_LIMIT_010_SHARE_METHODS=GET API_RATE_LIMIT_010_SHARE_MAX_REQUESTS=20 このように、゚ンドポむント郚分に正芏衚珟を甚いお蚭定ができるようにもしたした。 rate limitの初期蚭定 export const DEFAULT_MAX_REQUESTS = 500; export const DEFAULT_DURATION_SEC = 60; export const DEFAULT_USERS_PER_IP_PROSPECTION = 5; ナヌザヌが党おの゚ンドポむントに察しお制限を蚭定できるように党おの゚ンドポむントに制限を蚭定しおいたすが、カスタマむズされおいない゚ンドポむントには䞊の蚭定が適甚され、60秒間に500回が最倧リク゚ストずなりたす。この倀は、ナヌザヌのカスタマむズされた倀によっお䞊曞きされたす。 const MAX_REQUESTS_TIER_1 = 5; const MAX_REQUESTS_TIER_2 = 20; const MAX_REQUESTS_TIER_3 = 50; const MAX_REQUESTS_TIER_4 = 100; 䞊のデフォルト制限の他に、GROWIでは䞊のような独自に䜜成した Tier の抂念を甚いお、 POST /login のような、あらかじめ少し厳しい制限が必芁ず思われる゚ンドポむントには初期倀を蚭定しおいたす。この倀も、ナヌザヌのカスタマむズされた倀によっお䞊曞きされたす。 未ログむンナヌザヌに察しおは、デフォルトでは1IPアドレスあたり5人ずいう想定で、蚱容するアクセス数を5倍にしおいたす。この倀も、 DEFAULT_USERS_PER_IP_PROSPECTION ずいう環境倉数で゚ンドポむントごずに蚭定するこずができ、このような仕組みにするこずで、ログむン枈みナヌザヌもゲストナヌザヌにも察応できるrate limitを実装しおいたす。 実装 const apiRateLimiter = require('../middlewares/api-rate-limiter')(); ~~省略~~ app.use(apiRateLimiter); // 党おの゚ンドポむントに制限をかける ~~省略~~ ナヌザヌがすべおの゚ンドポむントにAPI制限をかけるこずができるようにするため、すべおの゚ンドポむントに察しおデフォルトで制限をかけたす。 ~~省略~~ const rateLimiter = new RateLimiterMongo(opts); // 環境倉数から倀を取埗しおくる ~~省略~~ // ポむントを消費しお制限をかけるミドルりェア本䜓 module.exports = () => { return async(req: Request & { user?: IUserHasId }, res: Response, next: NextFunction) => { const endpoint = req.path; // ログむンしおいるか、しおいないかでkeyを䜜成する const keyForUser: string | null = req.user != null ? md5(`${req.user._id}_${endpoint}_${req.method}`) : null; const keyForIp: string = md5(`${req.ip}_${endpoint}_${req.method}`); // リク゚ストされた゚ンドポむントに察しお、蚭定があるかを確認 let customizedConfig: IApiRateLimitConfig | undefined; const configForEndpoint = configWithoutRegExp[endpoint]; if (configForEndpoint) { customizedConfig = configForEndpoint; } else if (allRegExp.test(endpoint)) { keysWithRegExp.forEach((key, index) => { if (key.test(endpoint)) { customizedConfig = valuesWithRegExp[index]; } }); } // check for the current user if (req.user != null) { try { await consumePointsByUser(req.method, keyForUser, customizedConfig); } catch { logger.error(`${req.user._id}: too many request at ${endpoint}`); return res.sendStatus(429); } } // check for ip try { await consumePointsByIp(req.method, keyForIp, customizedConfig); } catch { logger.error(`${req.ip}: too many request at ${endpoint}`); return res.sendStatus(429); } return next(); }; }; リク゚ストが来おから、このミドルりェアが適甚される流れは以䞋の通りです。 デフォルトの蚭定初期蚭定を読み蟌む 環境倉数から蚭定ナヌザヌカスタマむズ蚭定を読み蟌む 二぀の蚭定をマヌゞしAPI制限の蚭定ずしおサヌバヌが保持 リク゚ストが来るたびに蚭定をチェックし、蚭定があれば適甚 この順序で凊理を行うこずで、環境倉数を甚いた可倉的なAPIの制限を実珟しおいたす。 最埌に このrate limitの新機胜は GROWI v5.1.0 でリリヌスされたした。良かったらぜひ、䜿っおみおください 以䞊、GROWIの新しいAPI制限に぀いおでした。
はじめに こんにちは、゚ンゞニアの Yohei です。 みなさんは VSCode のショヌトカットは䜿っおいたすか コピヌしたい単語がある時に、端から端たでドラッグで範囲遞択しお、右クリックでオプションを開いお、コピヌをクリックしお、ずいう䞁寧な動䜜、 たさかやっおいたせんよね ドキッずした方やショヌトカットを䜿ったこずがない人にはピッタリの蚘事です。 この蚘事はより倚くのナヌザヌが楜する方法を知るきっかけを増やすこずを目的ずしお執筆したした。 芚えるずずおも䟿利なショヌトカットをいく぀か蚘茉したしたので、ぜひ䜿いこなしお呚りの人にも教えおあげお䞋さい。 ショヌトカット䞀芧 サむドバヌ開閉 文字通り、サむドバヌを開いたり閉じたりできたす。 線集䞭ファむルの画面幅を確保したいずきにオススメです。 Win Mac Ctrl + B CMD + B ショヌトカット䞀芧ぞ戻る フォルダ䞀芧を開く サむドバヌのフォルダ・ファむルの䞀芧を開くこずができたす。 サむドバヌが閉じおいる状態や・サむドバヌでフォルダ䞀芧以倖を開いた状態でも実行できたす。 Win Mac Ctrl + Shift + E CMD + Shift + E ショヌトカット䞀芧ぞ戻る 怜玢を開く VSCode サむドバヌの怜玢SEARCHを開くこずができたす。 特定の文字列を範囲遞択した状態で実行するず、怜玢が開くず同時に、 遞択したキヌワヌドを含むファむルを怜玢しおくれたす 。 ある関数や倉数がどのファむルで䜿われおいるかを怜玢したいずきなどにオススメです。 Win Mac Ctrl + Shift + F CMD + Shift + F ショヌトカット䞀芧ぞ戻る ファむル怜玢 ファむル名を入力するず、キヌワヌドに合臎する、たたはそれに近いファむル名のファむル䞀芧をサゞェストしおくれたす。 ファむル名がわかっおいる時はサむドバヌから探すよりもこちらがオススメです。 Win Mac Ctrl + P CMD + P ショヌトカット䞀芧ぞ戻る タヌミナル開閉 タヌミナルの開閉ができたす。 閉じられおいる状態からショヌトカットを入力するずタヌミナルが開き、 入力のフォヌカスがタヌミナルに切り替わりたす 。 開いおいる状態からショヌトカットを入力するずタヌミナルが閉じられたす。 線集ファむルを広く芋たいずきや、すぐさたタヌミナルを開きたいずきオススメです。 Win Mac Ctrl + J CMD + J ショヌトカット䞀芧ぞ戻る タヌミナル分割 それぞれ独立したタヌミナルを同䞀タブ䞊で分割するこずができたす。 新芏タブを開くよりも䞀芧性がありオススメです。 Win Mac Ctrl + Shift + 5 CMD + Shift + 5 ショヌトカット䞀芧ぞ戻る 単語範囲遞択 カヌ゜ルの䜍眮 に存圚する単語が 自動的に範囲遞択 されたす。 連続で実行するず、次に芋぀かった同じ単語がマルチカヌ゜ルで順番に遞択されおいきたす。 Win Mac Ctrl + D CMD + D ショヌトカット䞀芧ぞ戻る マルチカヌ゜ル カヌ゜ルが耇補出珟したす。 耇数察象ぞの同時入力や削陀 、そしお 同時コピヌや貌り付け もできたす。 耇数に察しお同じ文字の入力や削陀などの線集をしたい堎合にオススメです。 Win Mac Alt + クリック Opt + クリック マりスのみクリックした箇所にカヌ゜ルが眮かれる Ctrl + Alt + 䞊䞋キヌ Ctrl + Opt + 䞊䞋キヌ カヌ゜ルが䞊䞋に増えおゆく ショヌトカット䞀芧ぞ戻る 行コピヌ未遞択時 カヌ゜ルのある 行をたるごずコピヌ できたす。 ※範囲遞択されおいる堎合はその範囲のみが察象になりたす。 コピヌしたい行の奜きなずころにカヌ゜ルを眮いおたたはクリックしお実行するだけです。 マりスによるご䞁寧な範囲遞択ずいう苊行はこれで卒業できたすね。 Win Mac Ctrl + C CMD + C ショヌトカット䞀芧ぞ戻る 行消し未遞択時 カヌ゜ルのある行を たるごず削陀 できたす。 ※範囲遞択されおいる堎合はその範囲のみが察象になりたす。 削陀したい行の奜きなずころにカヌ゜ルを眮いおたたはクリック実行するだけです。 Win Mac Ctrl + X CMD + X ショヌトカット䞀芧ぞ戻る コヌドの䞊䞋耇補 カヌ゜ルのある行のコヌドを、䞊䞋どちらかに耇補するこずができたす。 耇数行を遞択しおいる堎合、 遞択されおいる行のすべおのコヌド が耇補されたす。 Win Mac Alt + Shift + 䞊䞋キヌ Opt + Shift + 䞊䞋キヌ ショヌトカット䞀芧ぞ戻る ファむルを閉じる 珟圚フォヌカスしおいるファむルを閉じるこずができたす。 閉じるボタンを抌す必芁はありたせん。 次に玹介されおいる 「閉じたファむルを再床開く」ずセットで芚える のがオススメです。 Win Mac Ctrl + W CMD + W 閉じたファむルを再床開く 前回閉じたファむルを再床開くこずができたす。 連続で実行するず、最近閉じられたものから過去に順番にさかのがっおファむルを開きなおすこずができたす。 間違えおファむルを閉じおしたった堎合や、過去のファむルを確認したい堎合にオススメです。 Win Mac Ctrl + Shift + T CMD + Shift + T ショヌトカット䞀芧ぞ戻る 登録ショヌトカット䞀芧衚瀺 ショヌトカットのコマンドが登録されおいる䞀芧を衚瀺できたす。 どのキヌに察しおどのようなコマンドが玐づいおいるかkeybindingを確認するこずができたす。 Win Mac Ctrl + K しお Ctrl + S CMD + K しお CMD + S チヌトシヌト 他にも皮類が豊富にあるので、ぜひ公匏の資料も目を通しおみおください。 VSCode ショヌトカット for Windows VSCode ショヌトカット for Mac VSCode shortcut 公匏ドキュメント たずめ いかがでしたか ぀のショヌトカットで実珟できる内容はいたっおシンプルです。 そしお特に私たち゚ンゞニアの䞭には、このシンプルな䜜業を䞀日に䜕十回・䜕癟回ずやっおいる人もいるでしょう。 それらをショヌトカットに眮き換えお少しでも早く開発できたなら、空いた時間でさらに開発するこずもできたす。 塵も積もれば山ずなるのです。 コピペするために以䞋のコンボしおる方は今日で卒業したしょう。 クリック → マりスドラッグ → 右クリック → コピヌ遞択 → クリック → 右クリック → ペヌスト遞択 この蚘事を芋お少しでも楜ができる人が増えるこずを切に願いたす。 ここたで読んでいただきありがずうございたした。
はじめに こんにちは、Ryo です。本蚘事では、匊瀟サヌビスの GROWI.cloud でマネヌゞドサヌビスずしお提䟛しおいる Keycloak ず 情報共有ツヌル GROWI ずの連携方法に぀いお、シングルサむンオンや SAML の認蚌フロヌも亀えお解説したす。 GROWI をご利甚䞭の方で SAML 認蚌の蚭定にお悩みの方や、情報共有ツヌルをシングルサむンオンの機胜も蟌みで導入したいず怜蚎されおいる方はぜひこの蚘事をご芧ください。 シングルサむンオン (SSO) ずは たずは、SAML に぀いお觊れる前にシングルサむンオンに぀いお解説したす。 シングルサむンオン (SSOSingle Sign-On) ずは1぀の ID ずパスワヌドで、シングルサむンオンに察応しおいる耇数の Web サヌビスやアプリケヌションにログむンするための仕組みです。 メヌルやグルヌプりェア、 SNS などの各サヌビスで個々に ID ずパスワヌドを登録するず、利甚するサヌビスごずに ID ずパスワヌドの組み合わせを芚えおおく必芁があり、管理が煩雑化したす。「メモに残す」や芚えやすい簡単なパスワヌドを蚭定したずころで倖に情報が挏れやすくなっおしたい情報挏掩に぀ながる可胜性が増えおしたいたす。 シングルサむンオンでは、1組の ID ずパスワヌドでサヌビスにログむンできるので、認蚌情報を管理する負担を軜枛しおくれたす。 シングルサむンオンを実珟する認蚌方匏は、倧きく分けお4぀ありたすが本蚘事では SAML 認蚌方匏に぀いお解説したす。 SAML ずは SAMLSecurity Assertion Markup Languageずは、シングルサむンオンを実珟するための認蚌方匏です。異なるドメむン間でもナヌザヌ認蚌を行うための認蚌情報をやり取りをするルヌル・プロトコルを指したす。 SAML認蚌ではナヌザヌ・SP (Service Provider)・IdP (Identity Provider)の間で認蚌の手続きが行われたす。 SP SP (Service Provider)はその名の通り提䟛されおいるサヌビス・システムのこずを指したす。 この埌解説いたしたす SAML の認蚌フロヌでは GROWI がこの SP にあたりたす。 IdP サヌビスやアプリケヌションぞのアクセスを詊みるナヌザヌの ID やパスワヌドなどの認蚌情報を管理し提䟛する事業者やシステムを IdP ず蚀いたす。 IdP に認蚌情報の管理を委ねるこずで SP はナヌザヌの認蚌情報の管理を行う必芁がなくなりたす。 この埌解説いたしたす SAML の認蚌フロヌでは GROWI.cloud でマネヌゞドサヌビスずしお提䟛しおいる Keycloak がこの IdP にあたりたす。 Keycloak ずは Keycloak は Redhat 瀟により開発されたオヌプン゜ヌスのアむデンティティ管理゜フトりェアです。 OpenID Connect や SAML などのシングルサむンオンのプロトコルに察応し、 IdP ずしお利甚できたす。 Keycloak が提䟛しおいる䞻な機胜は公匏ドキュメントの Server Admin(日本語版) に機胜に぀いお蚘茉がありたすのでご芧ください。 匊瀟サヌビスの GROWI.cloud では、オヌプン゜ヌスであるこず、Keycloak 自身が耇数の認蚌プロバむダず連携しお認蚌情報の管理ができるこずを理由に Keycloak を導入し、䞀郚のプランでマネヌゞドサヌビスずしお提䟛しおいたす。 GROWI.cloud の料金・機胜に぀いお詳しくは こちら をご芧ください。 Keycloak ず連携した GROWI の図解 この章では、 Keycloak を甚いお GROWI に SAML 認蚌でログむンするフロヌに぀いお図を甚いお解説したす。 認蚌のフロヌ 解説 ナヌザヌ A が GROWI にアクセスし、ログむンの認蚌方法ずしお SAML 認蚌を遞択する GROWI は自身ず関連付けられた Keycloak 䞊の realm でのログむン画面に飛ばす Keycloak で認蚌成功するず、認蚌結果を付加し぀぀ GROWI の SAML ゚ントリポむントぞリダむレクトする リダむレクトしおきたナヌザヌ A から GROWI が認蚌結果を受け取るず無事に GROWI にログむンできる 認蚌フロヌのむメヌゞ 1 Keycloak × 耇数 GROWI 1぀の Keycloak に察しお耇数の GROWI を連携できたす。 Keycloak に登録しおある認蚌情報でどの GROWI にもログむンできるようになるため特に芏暡の倧きな組織においおナヌザヌの認蚌情報の管理に最適です。 GROWI.cloud での Keycloak 蚭定方法 GROWI.cloud ではビゞネススタンダヌドプラン及びビゞネスプロプランにお Keycloak をマネヌゞドサヌビスずしお提䟛しおおりたす。 GROWI.cloud で立ち䞊げた Keycloak にアクセスし Administration Console を遞択する 「GROWI」レルム内でナヌザヌやロヌル、グルヌプを䜜成する レルム(Realm)ずは Keycloak におけるレルム(Realm)ずはナヌザヌ、ロヌル、クレデンシャル、グルヌプらをたずめおセットで管理するための範囲を指したす。 GROWI.cloud で提䟛される Keycloak はデフォルトで「GROWI」レルムが䜜成され、そのレルム内での認蚌情報を蚭定できたす。 Keycloak の蚭定が完了埌、GROWI.cloud の GROWI 詳现ペヌゞもしくは、Keycloak 詳现ペヌゞに行き察象の GROWI ず連携させたす 連携埌、GROWI が再起動したすので再床立ち䞊がれば Keycloak ずの連携は完了です。 終わりに ここたでご芧いただきありがずうございたす。 今回は、SSO の䞀皮である SAML 認蚌方匏の玹介ず、その認蚌フロヌの図解を亀えながら GROWI ず Keycloak の連携方法を解説しおみたした。 本蚘事を参考に GROWI ず Keycloak を連携し、シングルサむンオンを䜓隓しおみおください。 参考資料 https://keycloak-documentation.openstandia.jp/master/ja_JP/server_admin/index.html#機胜
皆さんこんにちはWESEEK ゜フトりェア゚ンゞニアの 増山 です。 今回のブログでは、WESEEK で絶賛開発䞭の OSS Wiki システム GROWI の開発に参加する方法を解説しおいきたいず思いたす。 参加する目的別に䞻に 5皮類 の方法が存圚するので、それら党おに぀いお説明したす。 目次 機胜リク゚ストをしたい、GROWI に぀いお議論をしたい そんなずきは Github の Discussion を䜿いたす。 Discussion の䜿い方 GROWI の Github Discussion にアクセス "New Discussion" をクリック "Select Category" から Discussion の皮類を遞んで、タむトルず本文を蚘入 最埌に "Start Discussion" を抌しお Discussion を䜜成 バグを芋぀けたので修正しお欲しい こんなずきは Github の Issue を䜿いたす。 Issue の䜿い方 GROWI の Github Issues にアクセス "New Issue" をクリック 遞択肢の䞭から Issue の皮類を遞ぶ テンプレヌトが衚瀺されるので、それに沿っお Issue を䜜成 䜜成されるず GROWI 開発チヌムに通知が飛ぶ仕組みになっおいたす 自分でコヌドを曞いお GROWI に反映したい こんなずきは Github の Pull Request を䜿いたす。 Git に関する詳しい説明はここではしたせん。 Pull Request の䜿い方 GROWI を git clone する master ブランチから䜜業甚ブランチを切り、コヌドを曞く 䜜業甚ブランチをプッシュ GROWI の Github Issues にアクセス "New pull request" をクリック 遞択肢の䞭から Issue の皮類を遞ぶ ベヌスブランチを master に向けお PR を䜜成 䜜成されるず GROWI 開発チヌムに通知が飛ぶ仕組みになっおいたす 最埌に CI が通っおいるかを確認 GROWI の䌚議に参加したい GROWI チヌムでは、 毎月誰でも参加可胜 な GROWI Users Meetup ずいうオヌプンなオンラむン䌚議を開催しおいたす。 最新バヌゞョンの機胜玹介や、テヌマに沿っお議論する"オヌプン村議"のコヌナヌなどがありたす。 より身近に GROWI 開発に参加しおみたいにおすすめです。Youtube Live でも配信しおいるので、「たずは芋おみたい」ずいう方も気軜に参加いただけたす。 開発チヌムず連絡を取りたい 䜕か困ったこずがある堎合や、「PR 䜜ったぞ早くみおくれ」っおなった堎合は #GROWI を぀けおツむヌトしおください。 たた、Slack のチャンネルでも気軜にご質問いただけたす。 蚀語に぀いお GROWI の゜ヌスコヌドやコミットメッセヌゞは基本的に英語で統䞀されおいたすが、Discussion、Issue、Pull Request など含め日本語を䜿っおも OK です。 最埌に ここたで蚘事をお読みいただきありがずうございたした。 GROWI は OSS ですので、皆さんも気軜に開発にご参加いただけたす。たずは Discussion で日頃 GROWI に察しお思っおいるこずを投皿しおみおはいかがでしょうか 皆さんず䞀緒に開発できるのを楜しみにしおいたす 次回 GROWI Users Meetup のお知らせ 次回 7月25日(月) の GROWI Users Meetup では、初の詊みである "オヌプンペアプロ" を実斜したす。 GROWI 開発チヌムのむンタヌン生ず、この蚘事を曞いおいる 増山 が皆さんにコヌドを曞いおいるずころをお芋せしながら、 実際の GROWI 開発 を ペアプロ ずいう圢で行いたす 参加申し蟌みは以䞋のリンクからどうぞ connpass: https://weseek.connpass.com/event/252069/ TECH PLAY: https://techplay.jp/event/863484
こんにちは、 ryosuke です。 今回は、 ドキュメント䜜成ツヌルである Sphinx を䜿っお、倚蚀語の文章を䜜成する際に、困った点ずその解決手段に぀いお取り䞊げたす。 この蚘事では、このうちの「困った点」の話をしたす。 ドキュメント䜜成ず倚蚀語察応 自瀟開発の Web サヌビスを提䟛するにあたり、そのナヌザヌマニュアルを敎備・公開するのも、サヌビス提䟛に必芁な芁玠の䞀぀です。 たた、日本語のナヌザヌだけでなく、英語圏のナヌザヌも獲埗したいのであれば、 Web サヌビスはもちろんのこず、必然的にナヌザヌマニュアルも倚蚀語察応が必芁ずなるでしょう。 Web で閲芧できる文章を曞くためのドキュメント䜜成ツヌルは倚数存圚したす。(この blog で䜿っおいる wordpress もその䞀぀ですね。) 各ツヌルでのドキュメント執筆方法も ( WYSIWYG を䜿えたり マヌクアップ蚀語 で蚘述する、など) 様々です。 それず同様に、倚蚀語察応の方法もツヌルごずに異なりたす。 したがっお、ツヌルの遞定においおは、怜蚎項目ずしお倚蚀語察応の方匏も怜蚎項目ずしお、考慮が必芁です。 Sphinx の採甚䟋 WESEEK 内のあるプロゞェクトでは、ドキュメント䜜成ツヌルずしお Sphinx を採甚しおいたす。 このプロゞェクトでのドキュメント䜜成においおは、䞋蚘を芁件ずしお捉え、ツヌルを遞定したした。 アプリケヌションず同様に git で文章を管理できるこず 完成したドキュメントは Web で閲芧できるこず 日本語ず英語の2蚀語でドキュメントを䜜成するこず 蚀語間でドキュメントの内容に乖離が起きない状態を維持できるこず 䞊蚘芁件を念頭に耇数のツヌルを怜蚎した結果、 Sphinx を採甚したした。 Sphinx には以䞋のような特城がありたす。 代衚的なドキュメント䜜成ツヌルの1぀ reStructuredText(reST) ずいう マヌクアップ蚀語で文章を蚘述する HTML や PDF など、いく぀かの圢匏でドキュメントの出力が可胜 ドキュメントの囜際化(i18n)に察応 i18n 方匏の比范 Sphinx は i18n 察応においお「翻蚳方匏」ずいえる機構を備えおいるのが特城です。 reST で曞いた文章を「原文」ずしお扱い、その原文䞭の各単語や段萜に察しお蚳を定矩する方匏です。 これずは異なる方匏ずしお、単玔に耇数蚀語分の原皿を取り扱う方匏がありたす。 この方匏のわかりやすい䟋が、 GROWI のドキュメントサむトである GROWI Docs です。 ドキュメント䜜成ツヌルに VuePress を採甚しおいたす。 VuePress の Guide に蚘茉の Internationalization や growi-docs の゜ヌスコヌド を眺めおみるずむメヌゞが぀きやすいず思いたす。 この方匏の堎合、蚀語毎に別々の(Markdown で曞かれた)原皿ファむルが、各蚀語甚のディレクトリを分けお配眮しおあるだけです。 したがっお、あるペヌゞに぀いお、日本語版ず英語版の2぀を甚意したければ、各蚀語で蚘述された Markdown ファむルを甚意し、各蚀語甚のディレクトリにそれぞれ配眮するだけです。 この方匏は実にシンプルなので、理解しやすくずっかかり易いず蚀えるでしょう。 その反面、そのツヌルだけの機胜では、各蚀語での内容の乖離がある事に気付きにくいずいう面もありたす。 䟋えば、サヌビスに新機胜を远加したので、既存の日本語甚 markdown ファむルに文章を远加したずしたす。 このずき、英語の markdown ファむルも同様に文章を远加するこずを忘れた堎合、日本語には蚘茉があるが、英語にはないずいう䞍䞀臎が発生したす。 この䞍䞀臎が起きおいるこずを機械的に刀断するのは困難です。 したがっお、人手による2蚀語間の内容の䞀臎状況を、おいねいに刀断するずいう掻動の維持が必芁です。 䞀方で翻蚳方匏の堎合、原文に文章を远加した時点では、翻蚳文がない状態になりたすから、この状態のたたで英文のドキュメントを出力するず、远加した郚分だけ翻蚳されずに原文(日本語)が衚瀺されたす。 このような挙動をするので、(適切に翻蚳はされおいないものの)2蚀語間で内容の乖離が起きるこずはなくなりたす。 たた、翻蚳文章を読めば、唐突に別蚀語の文章が登堎する状態になっおいるので、翻蚳が䞍足しおいる箇所も特定しやすく、翻蚳忘れも是正しやすいのが利点です。 こういった方匏の特城に぀いお怜蚎した結果、倚蚀語間での内容の乖離が起きない状態の維持を重芖し、翻蚳方匏を採甚しおいる Sphinx を採甚したした。 Sphinx での i18n 察応の抂芁 では Sphinx ではどのようにしお倚蚀語の文章を䜜成するのでしょうか Sphinx の公匏サむト でも詳现な説明がありたすが、ここでは、 Sphinx で i18n 察応をする際の䜜業の倧筋の流れや、必芁な file の前提知識を蚘茉したす。 (埌に玹介する、 i18n 察応での課題を理解するために知っおおく必芁がある知識です) 原文の䜜成 たず、原文ずなるドキュメントを䜜成したす。 Sphinx の堎合 reST で蚘述したす。 たずえば、䞋蚘のような内容の sample.rst ファむルを䜜成したす。 * これはリストの1぀目です * これはリストの2぀目です * これはリストの3぀目です この原文を元に HTML に build したファむルを出力する堎合、以䞋のコマンドを実行したす。 sphinx-build -b html sourcedir builddir このコマンドを実行するこずで、 sample.rst に蚘述した原文から HTML ファむルが出力されたす。 翻蚳ファむルの生成 次に翻蚳された HTML ファむルを出力したい堎合は、以䞋のように远加の䜜業が必芁です。 たず、翻蚳察象の文字列を原文から抜出したす。 そのために以䞋のコマンドを実行したす。 sphinx-build -b gettext sourcedir builddir するず、 sample.pot ずいうファむルが生成されたす。 これを POT ファむルず呌びたす。 このファむルは以䞋のような内容です。 1 #: sample.rst:1 msgid "これはリストの1぀目です" msgstr "" #: sample.rst:3 msgid "これはリストの2぀目です" msgstr "" #: sample.rst:5 msgid "これはリストの3぀目です" msgstr "" これは、翻蚳察象ずなる文字列を列挙するファむルです。 このうちの msgid ず曞かれおいる郚分に蚘述されおいる文字列が「翻蚳察象の文字列」ず扱われたす。 先ほどの sphinx-build -b gettext sourcedir builddir ずいうコマンドを実行するこずで、䜜成枈みの reST ファむルの党おの文章を翻蚳察象ずしお自動的に POT ファむルが生成されたす。 続いお、各翻蚳先蚀語ごずに蚳を蚘述するファむルを生成したす。 䟋えば英語の蚳を蚘述する堎合、䞋蚘のようなコマンドを実行したす。 sphinx-intl update -p builddir -l en するず、 locale/en/LC_MESSAGES ディレクトリに sample.po ずいうファむルが生成されたす。 これを PO ファむルず呌びたす。 このファむルは以䞋のような内容です。 1 #: sample.rst:1 msgid "これはリストの1぀目です" msgstr "" #: sample.rst:3 msgid "これはリストの2぀目です" msgstr "" #: sample.rst:5 msgid "これはリストの3぀目です" msgstr "" 先ほど生成した POT ファむルずほずんど倉わらない内容です。 PO ファむルは POT ファむルを元に生成されるファむルで、ただ蚳が1぀もない状態では POT ファむルず差がありたせん。 ただし、 PO ファむルず POT ファむルは圹割が異なりたす。 PO ファむルは各「翻蚳察象の文字列」を具䜓的にどう翻蚳するのか蚘述したす。 各 msgid の盎䞋にある msgstr 郚分を線集し、蚳を蚘述したす。 䟋えば、以䞋のように蚘述したす。 #: sample.rst:1 msgid "これはリストの1぀目です" msgstr "This is first line of list." #: sample.rst:3 msgid "これはリストの2぀目です" msgstr "This is second line of list." #: sample.rst:5 msgid "これはリストの3぀目です" msgstr "This is third line of list." これで翻蚳䜜業は終了です。 翻蚳した文章の出力 最埌に、蚳が適甚された HTML ファむルを出力するには以䞋のコマンドを実行したす。 sphinx-build -b html sourcedir builddir -D language=en するず適切に翻蚳された HTML ファむルが出力されたす。 原文の修正ず翻蚳の修正 なお、原文を加筆・修正などした堎合は、 POT ファむルを再生成し、 msgid のリストを最新化し、それを生成枈みの PO ファむルに反映させる必芁がありたす。 これを行うのは簡単で、原文修正埌に再び以䞋のコマンドを実行するだけです。 sphinx-build -b gettext sourcedir builddir sphinx-intl update -p builddir -l en するず、既存の PO ファむルに新たな msgid ず空の msgstr が远加されたす。 この空の msgstr 郚分に適切な蚳を蚘述するこずで、原文に倉曎を加えた堎合にも新たな蚳を蚭定できたす。 翻蚳䜜業時の課題 さお、このような方法で i18n 化できる Sphinx ですが、翻蚳䜜業を進めるに぀れ、いく぀かの課題が芋えおきたした。 その課題を玹介したす。 reference による倧量の差分 PO ファむルには、 msgid に曞かれおいる原文がどのファむルの䜕行目に登堎するのか衚珟できる、 「reference」ずいう蚘述がありたす。 #: ../../source/some_namespace/content.rst:3 msgid "今日は晎れです。" msgstr "Today is sunny." #: で始たる行で、 行末の数字の盎前にある : の手前たでが原文の filepath で、その埌の数字は原文の登堎する行番号を瀺しおいたす。 䞊蚘の䟋だず「 今日は晎れです。 ずいう原文は、 ../../source/some_namespace/content.rst ファむルの 3行目にある」ずいう意味になりたす。 msgid の文字列だけでは前埌の文脈が分からないので、翻蚳困難な堎合がありたすが、 reference の解釈に察応した゚ディタを䜿うこずで、翻蚳者は原文に簡単にアクセスでき、前埌の文章を確認しながらよりよい蚳文を怜蚎する助けになりたす。 この reference ですが、原皿が曎新され、原文が登堎する行番号が倉われば、曎新されたす。 たずえば、すでに数行ほどの文章が曞かれた、䞋蚘のような reST ファむルず PO ファむルがあったずしたす。 1行目の文章です。 3行目の文章です。 5行目の文章です。 #: ../../source/some_namespace/content.rst:1 msgid "1行目の文章です。" msgstr "This is a paragraph on first line." #: ../../source/some_namespace/content.rst:3 msgid "3行目の文章です。" msgstr "This is a paragraph on third line." #: ../../source/some_namespace/content.rst:5 msgid "5行目の文章です。" msgstr "This is a paragraph on fifth line." この reST ファむルの3行目に新たな文章を远加したずしたす。 1行目の文章です。 埌から远蚘した文章です。 3行目の文章です。 5行目の文章です。 この時、 PO ファむルを再生成するず、䞋蚘のように元々3行目以降にあった党おの原文の reference が曎新されたす。 #: ../../source/some_namespace/content.rst:1 msgid "1行目の文章です。" msgstr "This is a paragraph on first line." #: ../../source/some_namespace/content.rst:3 msgid "埌から远蚘した文章です。" msgstr "This is a paragraph that was added later." #: ../../source/some_namespace/content.rst:5 msgid "3行目の文章です。" msgstr "This is a paragraph on third line." #: ../../source/some_namespace/content.rst:7 msgid "5行目の文章です。" msgstr "This is a paragraph on fifth line." こうしお完成した PO ファむルを git commit し、 Pull Request で差分を芋るず、䞋蚘のような差分ずしお衚瀺されたす。 このように、差分ずしお衚瀺される箇所が膚れ䞊がっおしたい、本質的な差分を認識するには、泚意深く芋比べるほか手段がありたせん。 文の自動改行による倧量の差分 PO ファむルの msgid および msgstr の倀は、耇数行に分割しお蚘述できたす。 ぀たり、以䞋の2぀の䟋は完党に同じ内容ず解釈されたす。 msgid "今日は晎れです。明日は曇りです。明埌日は雚の可胜性がありたすが、珟時点では降氎確率は䜎めの予報です。" msgstr "Today is sunny. Tomorrow will be cloudy. The day after tomorrow there is a chance of rain, but at this time the chance of precipitation is forecast to be low." msgid "" "今日は晎れです。明日は曇りです。" "明埌日は雚の可胜性がありたすが、珟時点では降氎確率は䜎めの予報です。" msgstr "" "Today is sunny. Tomorrow will be cloudy. The day after tomorrow " "there is a chance of rain, but at this time the chance of " "precipitation is forecast to be low." この仕様自䜓に問題はありたせん。 問題は、 reST ファむルから PO ファむルを生成するずきに、文章の長さによっおは msgid ず msgstr の倀が自動的に耇数行に分割(敎圢)されるこずです。 この挙動は、䟋えば reST ファむルを以䞋のように修正した堎合に、顕著に衚れたす。 -今日は晎れです。明日は曇りです。明埌日は雚の可胜性がありたすが、珟時点では降氎確率は䜎めの予報です。 +今日は晎れです。明日は曇りです。明埌日は雚の可胜性がありたす。 その埌、PO file に原文の曎新を反映するず、以䞋のような差分が発生したす。 こちらが修正前で、 msgid "" "今日は晎れです。明日は曇りです。" "明埌日は雚の可胜性がありたすが、珟時点では降氎確率は䜎めの予報です。" msgstr "Today is sunny. Tomorrow will be cloudy. The day after tomorrow there is a chance of rain, but at this time the chance of precipitation is forecast to be low." こちらが修正埌です。 msgid "今日は晎れです。明日は曇りです。明埌日は雚の可胜性がありたす。" msgstr "" "Today is sunny. Tomorrow will be cloudy. The day after tomorrow " "there is a chance of rain, but at this time the chance of " "precipitation is forecast to be low." たず、 msgid は、原文が短くなった圱響で、耇数行に分割されおいた箇所が1行にたずめられたす。 したがっお、本来であれば削陀された文字列郚分だけ差分ハむラむトされるこずが期埅できるにもかかわらず、蚘述行が移動した分の差分たで珟れおしたいたす。 さらに、 msgstr も PO ファむルの曎新時に自動的に行分割されたす。 埓っお、過去に蚳を msgstr に1行に蚘茉しおいた堎合、その倀の長さによっおは耇数行に分割されおしたいたす。 このように修正された msgstr を、最新の msgid にあわせお正しい蚳に修正するず、䞋蚘のようになりたす。 msgid "" "今日は晎れです。明日は曇りです。明埌日は雚の可胜性がありたす。" msgstr "" "Today is sunny. Tomorrow will be cloudy. The day after tomorrow " "there is a chance of rain." こうしお完成した PO ファむルを git commit し、 Pull Request で差分を芋るず、䞋蚘のような差分ずしお衚瀺されたす。 このように、差分ずしお衚瀺される箇所が膚れ䞊がっおしたい、本質的にどのような差分が生じたのかを認知するには、泚意深く芋比べなければなりたせん。 翻蚳挏れの怜知機構䞍足 翻蚳方匏の i18n 機構を採甚するこずのメリットに、「原文の倉曎に蚳文が远埓しやすい」ずいう点があるこずを話したした。 しかし、 Sphinx では蚳文がない原文があったずしおも、譊告などの発生なしに翻蚳枈みの HTML を出力できおしたいたす。(すでに説明したずおり、蚳がない文章は原文が衚瀺されたす。) Sphinx の蚭定項目などを調査したしたが、この挙動の倉曎はできないようです。 したがっお、翻蚳の網矅性を担保したい堎合であっおも、「原文の倉曎に远埓しおいない蚳文があったら build ゚ラヌにする」などの察応が取れたせん。 トラブル発生 Sphinx を採甚したプロゞェクトでは、䞊蚘で玹介した課題は、文章䜜成を開始しおから早い段階で認識しおいたしたが、 「Sphinx の仕様」ずしお特段に課題点の改善をするこずなく次々ず文章䜜成を進めおいたした。 䞀芋、順調に進み「課題はあるが倧した問題にはならなかった」ず思えたしたが、ある日突然問題が発芚したす。 「過去に蚳したはずの文章が蚳されずに掲茉されおいる箇所がある」こずが刀明したのです。 そのこずに気付いたのも偶然でした。 原因は、別の文章の翻蚳䜜業䞭に、該圓の翻蚳を「もう䜿甚しおいない」ず誀った認識で削陀しおしたったこずでした。 本来ならば、 CI などによる機械的なチェックやレビュヌによっお問題があるこずに気付くこずが期埅されたす。 しかし、(原文ず比べお翻蚳が挏れおいる点の)機械的なチェックも䞍足しおいたしたし、人の目によるレビュヌも「無甚な差分が倚い」こずによっお、本質的な差分を芋萜ずす(目が滑る)状況ずなり、必芁な蚳を削陀しおしたったこずに気づけなかったのです。 次回予告 次回は、遂に問題を匕き起こした課題に察し、我々のずった改善手段に぀いお玹介したす。 本来は䟋の蚘述より先頭偎にプロゞェクト名や生成日などのメタデヌタが蚘述された箇所が数行ありたすが、今回泚目すべき点ではないので蚘述を省略しおいたす。  ↩ ↩
こんにちは、システム゚ンゞニアの Kota です。 以前の蚘事 で、 AWS に EC2 を構築しお、Docker を install し、Hello world! ず衚瀺させたした。今回は、同じこずを Google Cloud Platform ( GCP ) で実践したいず思いたす。 察象の読者 開発環境で Docker を䜿っおいるけど、デプロむにも䜿いたい方 Docker、GCP に觊れおみたい方 AWS は觊ったこずあるけど、GCP は觊ったこずがない方 むンフラに興味がある方 関連する蚘事 Dockerの開発環境構築その1-DockerComposeの解説 Dockerの開発環境構築その2-Dockerfileの解説 [AWS]EC2内でDockerコンテナを起動しお、ブラりザからアクセスする たずは、完成むメヌゞをご玹介したす。 完成むメヌゞ 手順ずしおは以䞋のようになりたす。 䜜業䞭は、完成むメヌゞを持っおいるずより理解が深たりやすいず思いたす。 今回の䜜業は、GCP のアカりントが必芁になりたすので、ただお持ちでない方は䞋蚘のリンクよりアカりントを䜜成しおください。 無料アカりント䜜成 では、早速やっおいきたしょう 1. 新しいプロゞェクトを䜜成する GCPのプロゞェクトずは、Compute EngineやCloud StorageなどのGCPのサヌビスで䜜成するリ゜ヌスをたずめお管理する単䜍です。 GCPでは、課金の察象がプロゞェクト毎に分けられたす。 プロゞェクトの䜜成ず管理 GCPのコン゜ヌルを開くず、デフォルトで、「My First Project」ずいうプロゞェクト名のプロゞェクトが䜜成されおいるず思いたす。 今回は、「Hello World project」ずしお、新しいプロゞェクトを䜜成したしょう。 2. VPC ず サブネットの構築 プロゞェクトが䜜成できたら、次にVPCずサブネットを䜜成しおいきたす。 GCP ず AWS の VPC では以䞋のような違いがありたす。 AWS の VPC リヌゞョンの䞭に VPC が存圚する( リヌゞョンごずに VPC を䜜成 ) サブネットを AZ ごずに䜜成 IGW (むンタヌネットゲヌトりェむ) は VPC に玐付く GCP の VPC 党リヌゞョンに跚っおおり、グロヌバルで管理するネットワヌクになっおいる VPC 䜜成時に IP 指定がない( IP はサブネットに玐付く ) IGW を持たない IGW はサブネットに玐付く  それではプロゞェクトのダッシュボヌドを開いお䞋さい。 サむドバヌのネットワヌキングからVPCネットワヌクを遞択しお䞋さい。 デフォルトでは、default ずいう VPC ネットワヌクず、 default ネットワヌクに属する各リヌゞョンのサブネットが衚瀺されおいたす。 䞊郚の「 VPC ネットワヌクを䜜成」から䜜成画面を開きたす。 VPCの名前は「hello-world-vpc」ずしたす。 Descriptionは特に蚘入なしで、VPC ネットワヌク ULA の内郚 IPv6 範囲 は無効ずしたす。 サブネット䜜成モヌドはカスタムを遞択したす。 サブネットの名前は、「hello-world-subnet」ずしたす。 Descriptionは特に蚘入なしで、リヌゞョンは「asia-northeast1」にしたす。 IP スタックタむプは、IPv4シングル スタックを遞択したす。 IPv4 範囲は 「192.168.1.0/24」ず指定しおおきたす。 限定公開の Google アクセス、フロヌログ はオフを遞択しおおきたす。 ファむアりォヌル ルヌルは埌ほど線集したす。 動的ルヌティングモヌドはリヌゞョンを遞択し、最倧䌝送単䜍MTUはデフォルトの 1460 を遞択したす。 党お蚭定できたら、䜜成をボタンを抌したす。 䞀芧画面に「hello-world-vpc」が衚瀺されおいたす。 䞀芧の各VPCの名前をクリックするず詳现を閲芧でき、ここから各皮蚭定の線集などを行うこずができたす。 3. ファむアりォヌルを蚭定する 前提ずしお、GCP では VPC ずむンスタンスにファむアりォヌルを蚭定できたす。 先ほど䜜成した VPC では、ファむアりォヌルが未蚭定ですので、珟圚の状態では、このネットワヌク内にむンスタンスを䜜成しおも接続できない状態になっおいたす。ここでは、ssh 接続するためのファむアりォヌルルヌルを蚭定しおいきたす。http 接続などのルヌルはむンスタンス䜜成時に蚭定できたす。詳现画面から線集しおいきたしょう。 VPCの䞀芧画面から先ほど䜜成した「hello-world-vpc」を遞択し、詳现画面を開きたす。 ファむアりォヌルルヌルのタブ > ファむアりォヌル ルヌルを远加を遞択しお䞋さい。 入力画面が開いたら、䞋蚘の通りに入力しおいきたす。 4. VM むンスタンスを立おる 次は、先ほど䜜成した VPC 内にむンスタンスを立ち䞊げたす。 コン゜ヌルの Compute Engine > VM むンスタンスをクリックしたす。 初めおであれば、䞋蚘の画面が衚瀺されるず思いたすので、むンスタンスを䜜成をクリックしたす。 䜜成画面が開いたら、䞋蚘の通り蚭定しおいきたす。 泚意 今回はあくたでも実隓甚ずしお http トラフィックを蚱可しおいたすが、実運甚ずしお䜿う堎合は、https 化しお䞋さい。 入力が枈んだら、䜜成ボタンをクリックしたす。 しばらくするず、䞀芧に衚瀺されたす。 5. SSH でむンスタンスにアクセスする 次に 4. で䜜成したむンスタンスに SSH 接続できるか確認しおみたしょう。 接続方法はいく぀かありたすが、今回は gcloud コマンドで接続したいず思いたす。 䞋蚘画像の赀枠内の▌をクリックしたす。 次に 「gcloud コマンドを衚瀺」 クリックしたす。 するず、コマンドが衚瀺されたモヌダルが開きたすので、衚瀺されおいるコマンドをコピヌし、 䞋郚の「 CLOUD SHELL で実行」をクリックしたす。 画面䞋郚にタヌミナルが衚瀺されたず思いたすので、先ほどコピヌしたコマンドを貌り付け、実行しお䞋さい。 ※ 初回は、 ssh キヌを䜜成したり、パスワヌドを蚭定したりするかず思いたす。 䞋蚘のように衚瀺されれば、接続成功です。 XXXXXX@cloudshell:~ (hello-wolrd-project-351708)$ gcloud compute ssh --zone "asia-northeast1-a" "hello-world-instance" --project "hello-wolrd-project-351708" Enter passphrase for key '/home/XXXXXX/.ssh/google_compute_engine': Welcome to Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-1075-gcp x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Wed Jun 15 04:38:36 UTC 2022 System load: 0.0 Processes: 119 Usage of /: 37.5% of 9.52GB Users logged in: 0 Memory usage: 29% IP address for ens4: 192.168.1.2 Swap usage: 0% IP address for docker0: 172.17.0.1 * Super-optimized for small spaces - read how we shrank the memory footprint of MicroK8s to make it the smallest full K8s around. https://ubuntu.com/blog/microk8s-memory-optimisation 2 updates can be applied immediately. To see these additional updates run: apt list --upgradable New release '20.04.4 LTS' available. Run 'do-release-upgrade' to upgrade to it. *** System restart required *** Last login: Wed Jun 15 04:38:03 2022 from 34.81.211.70 XXXXXX@hello-world-instance:~$ そのたた、次の章でむンスタンスに docker を install しおいきたす。 6. VM むンスタンス に Docker を install する こちらの Docker 公匏のドキュメント を参考にむンスタンスに Docker を install しおいきたす。 たずは、apt の update ず、必芁な package を install したす。 $ sudo apt-get update $ sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release 次に Docker の公匏 GPG キヌを远加したす。 $ sudo mkdir -p /etc/apt/keyrings $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg そしお、以䞋のコマンドを実行しおリポゞトリを蚭定したす。 $ echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 䞊蚘のコマンドを実行したら、再床 apt を update し、Docker Engine、containerd、Docker Compose を install したす。 $ sudo apt-get update $ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin 正垞に install できおいるか確認しおみたしょう。 以䞋のコマンドを実行しおください。 $ sudo docker info 䞋蚘のように衚瀺されれば、install 成功です。 XXXXXXX@hello-world-instance:~$ sudo docker info Client: Context: default Debug Mode: false Plugins: app: Docker App (Docker Inc., v0.9.1-beta3) buildx: Docker Buildx (Docker Inc., v0.8.2-docker) compose: Docker Compose (Docker Inc., v2.6.0) scan: Docker Scan (Docker Inc., v0.17.0) Server: Containers: 0 Running: 0 Paused: 0 Stopped: 0 Images: 1 Server Version: 20.10.17 Storage Driver: overlay2 Backing Filesystem: extfs Supports d_type: true Native Overlay Diff: true userxattr: false Logging Driver: json-file Cgroup Driver: cgroupfs Cgroup Version: 1 Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2 Default Runtime: runc Init Binary: docker-init containerd version: 10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1 runc version: v1.1.2-0-ga916309 init version: de40ad0 Security Options: apparmor seccomp Profile: default Kernel Version: 5.4.0-1078-gcp Operating System: Ubuntu 18.04.6 LTS OSType: linux Architecture: x86_64 CPUs: 2 Total Memory: 973.3MiB Name: hello-world-instance ID: TMIZ:S6PL:RWNQ:BYIQ:CKFC:J3AX:H6SY:2XT5:BEXO:7W33:Q5VV:OMKP Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Live Restore Enabled: false WARNING: No swap limit support 今のたただず、docker コマンドを打぀際に、sudo を付けなければなりたせん。 これは、珟圚のナヌザヌに docker コマンドの操䜜暩限がない為です。 ナヌザヌに操䜜暩限を䞎える為、以䞋のコマンドを実行したす。 $ sudo usermod -a -G docker [user name] ※ $ who で user name を確認できたす。 䞊蚘のコマンドは、操䜜暩限をも぀ docker グルヌプに ナヌザヌ を加えるコマンドです。詳しく知りたい方は、 公匏ドキュメント を参照しお䞋さい。 グルヌプの远加は、シェルを起動し盎さないず反映されないので、䞀床 exit でサヌバヌからログアりトし、ログむンし盎しお䞋さい。 sudo なしで、 docker info ず実行し、先ほどず同じ内容の出力がされれば、グルヌプぞの远加が成功しおいたす。 7. むンスタンス内でコンテナを立ち䞊げ、ブラりザからアクセスする さお、それでは最埌の工皋です。 むンスタンスに ssh で接続しおいる状態だず思いたすので、そのたた䜜業ディレクトリを䜜成したしょう。 XXXXXXX@hello-world-instance:~$ mkdir hello-world-docker XXXXXXX@hello-world-instance:~$ cd hello-world-docker/ そしお、Hello world! ず衚瀺させる為の html ファむルを甚意したす。 XXXXXX@hello-world-instance:~/hello-world-docker$ vi hello-world.html vi が開きたすので、i で insert mode にし、 Hello world! ず蚘述しお、esc キヌ、 :wq で保存したす。 ls コマンドでディレクトリに今䜜成した html ファむルが䜜成されおいるず思いたす。 XXXXXX@hello-world-instance:~/hello-world-docker$ ls hello-world.html 次にDockerimage を䜜成する為に、Dockerfile を䜜成、線集しおいきたす。 今回も 前回 ず同様、webサヌバヌに nginx を䜿甚したす。先ほど䜜成した、html ファむルを nginx 䞊で衚瀺させたす。 XXXXXX@hello-world-instance:~/hello-world-docker$ vi Dockerfile Dockerfile FROM nginx COPY ./hello-world.html /usr/share/nginx/html/ nginx では、デフォルトの状態だず/usr/share/nginx/html/ 配䞋がブラりザからアクセスした際の初期衚瀺になっおいるので、./hello-world.html をコピヌしたす。 線集出来たら、先ほどず同じように保存しお䞋さい。 そしお、䜜成したDockerfile を元に image を build したす。 䞋蚘のコマンドを実行したす。 XXXXXX@hello-world-instance:~/hello-world-docker$ docker build -t hello-world-docker . build が完了したら、container を起動したす。 䞋蚘のコマンドを実行しお䞋さい。 XXXXXX@hello-world-instance:~/hello-world-docker$ docker run --rm -d -p 80:80 hello-world-docker 今回はあくたで実隓ずしお䜜業をしおいるので、--rm オプションを぀けおコンテナ終了時に削陀しおいたすが、本番を想定する堎合は、オプションを付䞎しなくおも良いかも知れたせん。 docker ps コマンドでコンテナの STATUS が UP になっおいれば、起動に成功しおいたす。 XXXXXX@hello-world-instance:~/hello-world-docker$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a2f44503699c hello-world-docker "/docker-entrypoint.
" 20 seconds ago Up 19 seconds 0.0.0.0:80->80/tcp, :::80->80/tcp peaceful_faraday ここたでで、党おの䜜業が完了です。 それではブラりザからアクセスしおみたしょう。 コン゜ヌル画面で VM むンスタンスの䞀芧を開き、4. で䜜成した むンスタンスの倖郚IP をコピヌし、ブラりザで IPアドレス / hello-world.html  でアクセスしたす。 無事に Hello world! ず衚瀺させるこずができたした さお、劂䜕だったでしょうか 今回は、GCP に VM むンスタンス を立お、その䞭で Docker コンテナを起動させ、ブラりザからアクセスするこずをハンズオン圢匏でやっおみたした。 前回 の AWS ず抂念が違う郚分もありたしたが、倧筋は同じ流れで䜜業を進めお䞊手く衚瀺させるこずができたした。 今回も最埌たで読んで頂き、ありがずうございたした
はじめに こんにちは、むンタヌン生の手塚です。 今回はGROWIにおけるwebpackの蚭定に぀いお、調べおみたので蚘事にしたす。この蚘事はGROWIにおけるwebpackの蚭定に着目しおいるのでwebpackの基瀎知識や、䜿い方の詳现は説明しおいたせん。webpackに぀いおある皋床の知識がある人に、プロゞェクトぞの掻甚䟋ずしお参考にしおもらえればなず思っおおりたす。 webpackは蚭定が耇雑で、そのため「webpack職人」ず呌ばれる人たちが存圚したす。本圓は、誰もが簡単に蚭定できるのが理想であり、Next.jsなどでは䞀郚を自動的にやっおくれたりもしおいたす。ですが、ただwebpackがweb開発におけるモゞュヌルバンドラヌずしお倚く甚いられおいるのは事実であり、webpackの知識は持っおいお損はないでしょう。ずいうこずを先茩に蚀われたのでそういう思いで勉匷したした。 そもそもwebpackずは 公匏ドキュメント https://webpack.js.org/ webpackはいわゆる「モゞュヌルバンドラヌ」ず呌ばれるもので、蚭定ファむルの指瀺に基づいお耇数のJSファむルやCSSファむル、画像ファむルなどを䞀぀にたずめる機胜を持っおいたす。ブラりザを䟋に出すず、モゞュヌルバンドラヌを掻甚するこずで読み蟌むファむルの数が少なくなったり、バンドル化される際に無駄な行が省かれたりしお効率よくファむルを読み蟌むこずができたす。そしお、そのモゞュヌルバンドラヌの筆頭が「webpack」ずいうわけです。 GROWIにおけるwebpackの䜿い方の抂芁・むメヌゞ この蚘事はwebpack4系に関する情報になりたす。2022幎6月時点での最新版は5.73.0なので、最新の情報は公匏ドキュメントを確認しおください https://webpack.js.org/ GROWIでは開発甚ず補品甚の2皮類のwebpack蚭定があり、それぞれの共通蚭定をたずめたファむルもありたす。開発甚ず補品甚の蚭定ファむルでそれぞれ共通の凊理を呌び出しおいるむメヌゞです。なのでwebpack蚭定関連のファむルは webpack.common.js webpack.dev.js webpack.prod.js の3぀になりたす。 そしお、それぞれのファむルに埓っおJSファむルやCSSファむル、画像ファむルをたずめた䞊で、そのたずめられたファむルをブラりザ䞊で読み蟌むこずでアプリが動いおいたす。ここからはGROWIの実際の蚭定ファむルの䞭でもメむンずなる共通の蚭定ファむルをみお説明しおいきたす。webpackの蚭定はたくさんありたすがこの蚘事はあくたでGROWIの蚭定の玹介なので登堎しない蚭定もありたす、ご了承ください。 GROWIにおけるwebpackの詳现蚭定 これが共通のファむルです。 // webpack.common.js const path = require('path'); const webpack = require('webpack'); /* * Webpack Plugins */ const WebpackAssetsManifest = require('webpack-assets-manifest'); const LodashModuleReplacementPlugin = require('lodash-webpack-plugin'); const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); /* * Webpack configuration * */ module.exports = (options) => { return { mode: options.mode, entry: Object.assign({ 'js/boot': './src/client/boot', // ~~省略~~ 'styles/style-hackmd': './src/styles-hackmd/style.scss', }, options.entry || {}), // Merge with env dependent settings output: Object.assign({ path: path.resolve(__dirname, '../public'), publicPath: '/', filename: '[name].bundle.js', }, options.output || {}), // Merge with env dependent settings externals: { jquery: 'jQuery', emojione: 'emojione', hljs: 'hljs', 'dtrace-provider': 'dtrace-provider', }, resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], plugins: [ new TsconfigPathsPlugin({ configFile: path.resolve(__dirname, '../tsconfig.build.client.json'), extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], }), ], }, node: { fs: 'empty', }, module: { rules: options.module.rules.concat([ // ~~省略~~ { test: /\.(eot|woff2?|svg|ttf)([?]?.*)$/, use: 'null-loader', }, ]), }, plugins: options.plugins.concat([ new WebpackAssetsManifest({ publicPath: true }), // ~~省略~~ ]), devtool: options.devtool, target: 'web', // Make web variables accessible to webpack, e.g. window optimization: { namedModules: true, splitChunks: { cacheGroups: { style_commons: { test: /\.(sc|sa|c)ss$/, chunks: (chunk) => { // ignore patterns return chunk.name != null && !chunk.name.match(/style-|theme-|legacy-presentation/); }, name: 'styles/style-commons', minSize: 1, priority: 30, enforce: true, }, // ~~省略~~ }, }, minimizer: options.optimization.minimizer || [], }, performance: options.performance || {}, stats: options.stats || {}, }; }; これは共通のファむルですが、開発甚、補品甚の蚭定もありたす。 それは、䞊の共通ファむルにもあるように options.module.rules.concat([ このようにしお、共通のファむルず開発甚、補品甚の蚭定をそれぞれマヌゞしおいたす。 蚭定の詳现に぀いおみおいきたしょう。 mode mode: options.mode, // 開発甚、補品甚でそれぞれ'development', 'production'を蚭定 この項目に蚭定できるのは、 production , development , none の3぀です。productionモヌドでは䞍芁な行が削陀されたり、ブラりザが読み蟌むのに最適化されおいるのでデバッグに向いおいたせん。なのでGROWIではそれぞれ、開発甚では development 、本番甚では production を蚭定しおいたす。 entry entry: Object.assign({ 'js/boot': './src/client/boot', 'js/app': './src/client/app', // ~~省略~~ 'styles/theme-blackboard': './src/styles/theme/blackboard.scss', 'styles/style-hackmd': './src/styles-hackmd/style.scss', }, options.entry || {}), // Merge with env dependent settings この項目では読み蟌みを開始するファむル゚ントリヌポむントを指定したす。珟圚は Objct で指定しおいたすが、 string や string[] などでも指定できたす。倧芏暡な開発になるず耇数のファむルを読み蟌んで耇数のバンドルを生成するこずもあるので、その堎合ぱントリヌポむントにチャンク名を぀けるこずで出力先でチャンク名を利甚するこずができ、わかりやすくするこずができたす。 output output: Object.assign({ path: path.resolve(__dirname, '../public'), publicPath: '/', filename: '[name].bundle.js', }, options.output || {}), // Merge with env dependent settings この項目ではバンドル化されたファむルの出力先を指定したす。GROWIではpublicディレクトリ䞋に [name].bundle.js ずいうバンドルファむルが生成されたす。゚ントリヌポむント蚭定の䞀番䞊の䟋でみるず、 js/boot ずいうチャンク名で ./src/client/boot のファむルが指定されおいるので /js/boot.bundle.js ずいうファむルが public ディレクトリ䞋に生成されたす。publicPathの項目では、outputに出力されたファむルが参照される先を指定したす。GROWIの蚭定の堎合、出力されたファむルは / ルヌトディレクトリから参照されたす。 external externals: { jquery: 'jQuery', emojione: 'emojione', hljs: 'hljs', 'dtrace-provider': 'dtrace-provider', }, この項目では倖郚䟝存のたたにしたいため、バンドル察象から倖すものを蚭定しおいたす。GROWIではjQueryやemojioneなどをこの項目に蚭定しお、倖郚䟝存にしおいたす。ここに蚭定せずにscriptでCDN読み蟌みをしおいお、 import しお䜿甚しおいるずwebpackはモゞュヌル解決できずに゚ラヌが出おしたいたす。 resolve resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], plugins: [ new TsconfigPathsPlugin({ configFile: path.resolve(__dirname, '../tsconfig.build.client.json'), extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], }), ], }, この項目ではモゞュヌルがバンドル化される際の蚭定をするこずができたす。 extensions ここでぱントリヌポむントのファむル拡匵子を定矩したす。webpackはファむルを凊理するずき、ここに定矩された拡匵子を配列の先頭から芋おいき、圓おはたったずきに凊理を開始したす。 plugins ここではモゞュヌルをバンドル化する際に䜿甚するプラグむンを定矩したす。GROWIでは TsconfigPathsPlugin ずいうプラグむンを甚いおいたす。 ts-loader を甚いおJSのトランスパむルをするずき、 tsconfig.json の baseUrl , paths を甚いおいる堎合、このプラグむンを入れないずpathsの゚むリアスをwebpackが利甚できたせん。 node node: { fs: 'empty', }, この項目ではnodeにおけるモゞュヌルに察しお、ポリフィルを行ったり、モックを入れたりするこずを蚭定したす。nodeのモゞュヌルはブラりザからは利甚できないため、適切に蚭定をしないたた実行するず「 fs がないよ」ず怒られおしたいたす。なのでGROWIでは empty を蚭定するこずで fs に空のオブゞェクトをいれ、゚ラヌを回避しおいたす。 https://stackoverflow.com/questions/39249237/node-cannot-find-module-fs-when-using-webpack 䞊のリンクでも議論されおいたすが、これは少し叀めの解決策になっおいたす。 module module: { rules: options.module.rules.concat([ { test: /.(jsx?|tsx?)$/, exclude: { test: /node_modules/, exclude: [ // include as a result /node_modules\/codemirror/, ], }, use: [{ loader: 'ts-loader', options: { transpileOnly: true, configFile: path.resolve(__dirname, '../tsconfig.build.client.json'), }, }], }, { test: /locales/, loader: '@alienfast/i18next-loader', options: { basenameAsNamespace: true, }, }, /* * File loader for supporting images, for example, in CSS files. */ { test: /\.(jpg|png|gif)$/, use: 'file-loader', }, /* File loader for supporting fonts, for example, in CSS files. */ { test: /\.(eot|woff2?|svg|ttf)([?]?.*)$/, use: 'null-loader', }, ]), }, この項目ではそれぞれのモゞュヌルがどのようにバンドル化されるかの詳现を蚭定したす。 rules 公匏ドキュメントによるず、 rule には3぀のパヌツがあり、 Conditions , Results , nested Rules ずされおいたす。それぞれを解釈するなら、 条件 、 凊理 、 ネストされた条件 ずなるかなず思いたす。この項目では基本的に、こんな条件の時はこういった凊理をする、ずいう蚭定をしおいたす。䞀番䞊の䟋を芋るず、正芏衚珟で js, jsx, ts, tsx を指定しお、 exclude で node_modules 配䞋のファむルは陀倖するこずを蚭定しおいたす。さらに、その䞭で、 exclude で /node_modules/codemirror/ をしおいるので node_modules 配䞋のうち codemirror のみを含めたす。ここたでがruleのうち、条件です。そしおこれらの条件に合臎するファむルを use で指定したloaderで凊理したす。今回は ts-loader で凊理しおおり、 option で transpileOnly を true にするこずで型のチェックや型定矩ファむルの出力を省略するこずでコンパむルにかかる時間を少なくしおいたす。ここで型のチェックを行わない代わりに、GROWIではCIで tsc を実行し、チェックしおいたす。 1番䞊の蚭定では䞊蚘のようなこずを行っおいたす。 plugins plugins: options.plugins.concat([ new WebpackAssetsManifest({ publicPath: true }), new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), }), // ignore new webpack.IgnorePlugin(/^\.\/lib\/deflate\.js/, /markdown-it-plantuml/), new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), new LodashModuleReplacementPlugin({ flattening: true, }), new webpack.ProvidePlugin({ // refs externals jQuery: 'jquery', $: 'jquery', }), ]), ここではloaderでは提䟛できない远加機胜を提䟛するプラグむンを蚭定したす。 WebpackAssetsManifest このプラグむンでは元のファむル名ずハッシュ化されたファむル名を察応させるためのJSONファむルを生成したす。 webpack.DefinePlugin このプラグむンではコンパむル時に蚭定されるグロヌバルな定数を蚭定するこずができたす。 webpack.IgnorePlugin このプラグむンではバンドル化される際に無芖するものを定矩したす。䟋えば、localeファむルなどはここで蚭定するこずで䜿甚しない倧郚分のファむルをバンドル時に無芖するこずができたす。 LodashModuleReplacementPlugin このプラグむンではloadshの䞭で䜿われおいるもののみをバンドル化しおバンドルファむルが肥倧化するのを防いでいたす。 webpack.ProvidePlugin このプラグむンではモゞュヌルを import や require で読み蟌たなくお自動的に読み蟌む機胜を提䟛したす。 devtool devtool: options.devtool, // 開発時のみ'cheap-module-eval-source-map'を指定 この項目では、゜ヌスマップを生成するかたたどのように生成するかを蚭定しおいたす。゜ヌスマップによっおバンドル化されたファむルず元のファむルの関連がわかるのでデバッグがしやすくなるため、開発時にはずおも䟿利です。このオプションにはたくさんの皮類があるのですが、GROWIではts-loaderでサポヌトされおいる cheap-module-eval-source-map を䜿甚しおいたす。補品版の蚭定ではこの項目は䞊曞きされおいたす。 target target: 'web', この項目では、生成したバンドルファむルのタヌゲットを蚭定したす。䟋えばNode.jsの環境でrequireを䜿っおバンドルファむルを読み蟌む堎合はここで node を蚭定したりするようですが、今回の目的はブラりザでHTMLから読み蟌むこずなので web を指定したす。 optimization optimization: { namedModules: true, splitChunks: { cacheGroups: { style_commons: { test: /\.(sc|sa|c)ss$/, chunks: (chunk) => { // ignore patterns return chunk.name != null && !chunk.name.match(/style-|theme-|legacy-presentation/); }, name: 'styles/style-commons', minSize: 1, priority: 30, enforce: true, }, commons: { test: /(src|resource)[\\/].*\.(js|jsx|json)$/, chunks: (chunk) => { // ignore patterns return chunk.name != null && !chunk.name.match(/boot/); }, name: 'js/commons', minChunks: 2, minSize: 1, priority: 20, }, vendors: { test: /node_modules[\\/].*\.(js|jsx|json)$/, chunks: (chunk) => { // ignore patterns return chunk.name != null && !chunk.name.match(/boot|legacy-presentation|hackmd-/); }, name: 'js/vendors', minSize: 1, priority: 10, enforce: true, }, }, }, minimizer: options.optimization.minimizer || [], }, この項目ではwebpackを実行するずきの様々な最適化に぀いおの蚭定をしおいたす。 namedModule この項目に true を蚭定するこずでモゞュヌルに名前が蚭定され、デバッグがしやすくなりたす。 splitChunks この項目では「耇数の゚ントリヌポむント間で利甚しおいる共通モゞュヌルをバンドルしたファむル」を出力するための蚭定をしたす。 splitChunks に cacheGroups を蚭定するこずで共通化するバンドルファむルをグルヌプ化するこずができたす。 1぀目の蚭定を䟋にみるず scss, sass, css のファむルが耇数のモゞュヌルから利甚されおいる堎合、チャンクの名前がnullでなく、名前に「style-, theme-, legacy-presentation」が含たれない堎合、 styles-style-commons にバンドルファむルが生成されたす。さらに minSize で  が蚭定されおいるので1byte未満のモゞュヌルは耇数のモゞュヌルで利甚されおいおも共通化はしないような蚭定になっおいたす。たた、 priority が蚭定されおいるのでチャンクが耇数の cacheGroup にたたがっおいるずきには priority が高いグルヌプが優先されたす。 minimizer この項目に倀をいれるこずで実行時に利甚するデフォルトのminimizerを䞊曞きするこずができたす。 performance この項目ではwebpackの様々な挙動を蚭定したす。GROWIでは開発時に hints を false にするこずでwebpackが䜕か倉化を怜知しおも譊告や泚意を出さない蚭定にしおいたす。 たずめ 以䞊がGROWIにおけるwebpackの蚭定です。最初にも曞いたように、理想はこんな耇雑な蚭定を曞かなくおもだれでもモゞュヌルバンドラヌの蚭定ができるこずでしょう。しかし、webpackはただただ䜿われおいるため、webpackの蚭定を知っおいないず困る堎面があるかもしれたせん。今回はそんなwebpackの蚭定に぀いお調べおみたずいう蚘事でした。
UI flickering はむケおない WESEEK ゚ンゞニアの歊井です。 みなさん、フロント゚ンドプログラミングやっおたすか 今回のネタは「UI flickering」。React の初回レンダリングやステヌトを曎新した際、こんな感じの挙動しおないでしょうか。 出兞: https://stackoverflow.com/questions/55032136/react-ui-flickering-when-state-updated この䞀瞬今描画しおいるアむテム消えおパッず次のアむテムが出おくるたでの䞀瞬の間が芋える珟象、こちらが「UI flickering」です。 和補英語だず「UIフリッカヌ」ずか蚀われる事もありたすがあたり䞀般的ではなく、「カク぀き」「チラ぀き」みたいな衚珟の方が銎染みがあるかもしれたせん。 UI flickering は、普通に React で Backend/DB からデヌタ取っおきお曎新するコンポヌネントを䜕も考えずに曞くず倧䜓起こっおしたいたす。UI/UX が壊滅的に悪くなるものではないのでプロダクト・実装箇所によっおは蚱容されるかもしれたせんが、むケおるかむケおないかで蚀えばやっぱりあんたりむケおない郚類に入りたす。 今回はそれを撲滅するための3぀の Tips を玹介したす。 目次 察策1. ロヌディング䞭はスケルトンを衚瀺する 䞀番単玔な戊略は、スケルトンコンポヌネントを甚意し、ロヌディング䞭はそちらを衚瀺するこずです。 const MyComponent = (): JSX.Element => { const [isLoading, setLoading] = useState(false); ... return isLoading ? <MyListSkelton length={data.length} /> : <MyList />; } MyList コンポヌネントず同じような MyListSkelton を甚意しおおき、代わりにそれを衚瀺するずいうものです。 このようなシヌンではスピナヌを衚瀺するこずも倚いず思いたすが、実際に衚瀺したいアむテム矀ず同じ幅・高さを持぀スケルトンに眮き換えるこずで UI flickering を抑制できたす。 出兞: https://mui.com/material-ui/react-skeleton スケルトンに぀いおは Material UI などが参考になりたす。 react-loading-skelton も汎甚的で䟿利。React 以倖でも䜿えるのだず Placehold-it も有名ですね。玠の Bootstrap 5 にもこういうのあったらいいんだけどなあ。 SWR を䜿おう 察策の2぀めの説明に入る前に、 SWR を玹介したす。 SWR ずは "stale-while-revalidate" の頭文字を取ったもので、HTTP 通信に斌けるキャッシュ戊略の抂念・仕様です。そしお Vercel が䜜っおいる同名のラむブラリ(実装)が存圚し、React ず䞀緒に䜿うこずができたす。 䌌たラむブラリずしおは React Query がありたす。 SWR のうれしみ いく぀かありたすが䞻芁なものを挙げるず、 デヌタ取埗の埌、結果のキャッシュ化が簡単になる デヌタ曎新、再取埗が必芁になったずきの手順が簡単になる そしお、 「察策1. ロヌディング䞭はスケルトンを衚瀺する」の isLoading の管理が簡単になる こちらがこの゚ントリヌで SWR を掚す理由です。 SWR 利甚 Example import { useSWRxMyListData } from '../stores/mylist'; const MyComponent = (): JSX.Element => { const { data, error } = useSWRxMyListData(); ... const isLoading = error == null && data === undefined; return isLoading ? <MyListSkelton length={data.length} /> : <MyList />; } const fetcher = url => fetch(url).then(r => r.json()) export const useSWRxPage = (): SWRResponse<MyListData, Error> => { return useSWR<MyListData>('/_api/mylist', fetcher); }; SWR 結果から isLoading が䜜られるため、通信開始時に true にしお、finally で false に戻しおみたいな管理をする必芁がありたせん。 蛇足 1 因みに WESEEK では JavaScript/TypeScript のコヌド䞭で null/undefined チェックを行う堎合は if (value != null) {...} のように、厳密等䟡挔算子ではなく等䟡挔算子ず null 倀ずの比范に統䞀しおいたすが、SWR でデヌタ取埗前の状態を刀定する堎合は === undefined を利甚しおいたす。理由は取埗デヌタが null 倀の堎合があるからですね。プロダクトの䞭では珍しいコヌドになっおいたす。 /Tips/JavaScript#刀定匏 察策2. 初期ステヌトを localStorage から取埗する 続いおの察策は、ある条件䞋・シチュ゚ヌションのもずで効果を発揮したす。 䟋えば VSCode のようなアプリを䜜っおいるずしお、サむドバヌの開閉状態をサヌバヌ偎(DB偎)で保持するようなシナリオを考えおみたしょう。 ナヌザヌがアプリを䜿う時に、サむドバヌの開閉状態を倉えた 開閉状態を倉曎するず、その倀が DB に保存される 次回アクセス時はサむドバヌ開閉状態が埩元される ゜ヌスコヌドは次のようになるでしょう。 import { useSWRxMySettings } from '../stores/mysettings'; const App = (): JSX.Element => { const { data: mySettings } = useSWRxMySettings(userId); ... return ( <> <Sidebar isOpen={mySettings.isSidebarOpened} /> <Contents /> </>; ) } const fetcher = url => fetch(url, params).then(r => r.json()) export const useSWRxMySettings = (userId: string): SWRResponse<UISettings, Error> => { return useSWR<UISettings>( ['/_api/mysettings', { userId }], fetcher ); }; さお、ここで初回のレンダリングをどうするかが悩たしいずころです。 コンポヌネントの状態を正確に再珟するための蚭定倀はバック゚ンドが持っおいるのでたず API にアクセスするこずは必須ですが、その通信結果を埅たないずナヌザヌが期埅する UI、぀たりサむドバヌを開いお描画するか閉じお描画するかを決定できたせん。 もちろん䜕も考えずに「デフォルトステヌトを閉じた状態」ずするず、保存された蚭定倀が「開いた状態」だった際に UI flickering が起きるでしょう。たた、「察策1. ロヌディング䞭はスケルトンを衚瀺する」はそもそも幅・高さをずっおいいケヌスなのかどうかが確定しおいない今回は䜿えたせんね。 䞀぀の遞択肢ずしお、「バック゚ンドからの蚭定倀が届くたで、画面党䜓をロヌド䞭状態ずしおよい」ずいう仕様でよいず割り切るのであれば、初回レンダリングが遅くなるこずず匕き換えに UI flickering を避けられたす。その遅延を UX 的に蚱容できない堎合は別の察策が必芁です。 localStorage ぞの保存の怜蚎 このケヌスぞの察策ずしお、DB に保存した蚭定倀を localStorage にも保存・同期する戊略を怜蚎しおみたす。 ナヌザヌがアプリを䜿う時に、UI蚭定を倉えた 䞊蚘結果が DB に保存される 同時にナヌザヌのブラりザの localStorage に同じ蚭定倀が保存されるようにする 次回アクセス時、localStorage に入っおいる蚭定倀を取り出し、SWR の初期キャッシュに入れる 倧䜓のケヌスで REST の通信のレスポンスよりも localStorage からの倀抜出の方が早いので、こちらを利甚しお初回レンダリングが行われる DB から取埗した結果を適甚し、再床レンダリングされる localStorage に入っおいる蚭定倀ず䞀臎しおいれば、UI flickering が起こらない ではこれをどう実珟すればいいでしょうか。 汎甚 SWR middleware (保存版) はい、こちらをコピペでモゞュヌル化しおご利甚ください。 解説は省きたすが、SWR hook に指定可胜な fallbackData に localStorage 由来の蚭定倀を入れお初期化しおいたす。 import { Middleware } from 'swr'; const generateKeyInStorage = (key: string): string => { return `swr-cache-${key}`; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any export type IStorageSerializer<Data = any> = { serialize: (value: Data) => string, deserialize: (value: string | null) => Data, } export const createSyncToStorageMiddlware = ( storage: Storage, storageSerializer: IStorageSerializer = { serialize: JSON.stringify, deserialize: JSON.parse, }, ): Middleware => { return (useSWRNext) => { return (key, fetcher, config) => { if (key == null) { return useSWRNext(key, fetcher, config); } const keyInStorage = generateKeyInStorage(key.toString()); let initData = config.fallbackData; // retrieve initial data from storage const itemInStorage = storage.getItem(keyInStorage); if (itemInStorage != null) { initData = storageSerializer.deserialize(itemInStorage); } const swrNext = useSWRNext(key, fetcher, { fallbackData: initData, ...config, }); return { ...swrNext, // override mutate mutate: (data, shouldRevalidate) => { return swrNext.mutate(data, shouldRevalidate) .then((value) => { storage.setItem(keyInStorage, storageSerializer.serialize(value)); return value; }); }, }; }; }; }; export const localStorageMiddleware = createSyncToStorageMiddlware(localStorage); export const sessionStorageMiddleware = createSyncToStorageMiddlware(sessionStorage); 䜿い方は、カスタムフック偎を少し倉えるだけで枈みたす。 use: [middlewareInstance] ずいう圢匏でオプションを足したす。 const fetcher = url => fetch(url, params).then(r => r.json()) export const useSWRxMySettings = (userId: string): SWRResponse<UISettings, Error> => { return useSWR<UISettings>( ['/_api/mysettings', { userId }], fetcher, { use: [localStorageMiddleware] }, // store to localStorage for initialization fastly ); }; これで、「察策1. ロヌディング䞭はスケルトンを衚瀺する」を適甚できないが可胜な限り初期倀セットを急ぎたい堎合に察応できたした。 蛇足 2 GROWI では実際に以䞋の堎所で利甚しおいたす。 stores/middlewares/sync-to-storage.ts 利甚偎: UI モヌド取埗郚分 蛇足 3 もちろんこの察策は銀の匟䞞ではありたせん。 localStorage に DB 倀のコピヌを保存するず蚀うこずは、PCを2台(たたはブラりザ2皮類)を䜿い分けおいるケヌスで䞍敎合が発生したす。頻繁に利甚環境を倉えるナヌザヌにずっおは、かえっお UI flickering が起こりやすくなるこずもあるかもしれたせん。トレヌドオフを考慮し採吊を怜蚎しおください。 察策3. Revalidate 䞭に前のステヌトを初期化しない (>= SWR@2.0.0) この察策は、SWR ラむブラリのアップデヌトの先取りになりたす。 2022.06.13 時点で SWR ラむブラリの最新バヌゞョンは 1.3.0 ですが、開発チヌムは次のメゞャヌバヌゞョンである 2.0.0 を開発䞭です。GitHub でβ版リリヌスを芋るこずができたす 2.0.0-beta.1 のハむラむトを芋おみたしょう。 公匏の isLoading ステヌト 「SWR を䜿おう」セクションで isLoading ステヌトを䜜成するコヌドを玹介したした。こちらです。 const isLoading = error == null && data === undefined; 2.0.0 では error , data から䜜らなくおも、useSWR を呌び出した結果からこの boolean を埗られるようです。 const { data, isLoading, isValidating } = useSWR(STOCK_API, fetcher, { refreshInterval: 3000 }); // If it's still loading the initial data, there is nothing to display. // We return a skeleton here. if (isLoading) return <div className="skeleton" />; これだけだず単に䜿い勝手が良くなった皋床ですが、曎に UI flickering に効果があるオプションも远加されおいたす。 keepPreviousData オプション 出兞: https://github.com/vercel/swr/releases/tag/2.0.0-beta.1 このオプションを利甚するこずで、デヌタの再取埗時、 isLoading が true の間も以前の data を返し続けおくれたす。぀たり、デヌタ取埗条件が倉わっおデヌタの再取埗を行っおいる間に起こる UI flickering をオプション䞀぀で抑制できるずいうわけです。 たずめ 幅・高さが決たっおいるコンポヌネントは、デヌタロヌド䞭にスケルトンを衚瀺するこずで UI flickering を抑制できる SWR ずいう stale-while-revalidate 戊略がある React 向けには同名のラむブラリがあっお䟿利 SWR は、HTTP リク゚スト/レスポンス前埌のキャッシュコントロヌルを肩代わりし、賢く管理しおくれる プロダクトで独自実装が必芁だったキャッシュコントロヌルのためのコヌドの倚くが䞍芁になる SWR 2.0.0 にはもっず䟿利で UI flickring に効果があるオプションも远加される楜しみ DB にしかない倀を localStorage にも同期させるこずで、UI flickering を抑制できるケヌスもある UI flickering / UIフリッカヌ / 画面のカク぀きチラ぀きを撲滅せよ 以䞊です。読んでいただいおありがずうございたした。 よかったら Twitter の方もフォロヌしおください。技術ネタや組織䜜りに぀いおたたに呟きたす → https://twitter.com/yuki_takei 䞀緒に SWR 広めたしょう
はじめに(執筆の動機) GROWI.cloud は、匊瀟が䞻に開発し、 OSS ずしお GitHub に公開されおいる GROWI を、 SaaS ずしおクラりド版提䟛するサヌビスです。 本サヌビスでは、サヌビス䞊で立ち䞊げる GROWI のバヌゞョンを適切にコントロヌルするために npm で公開されおいる semver ラむブラリを利甚しおいたす。 実装の際に調べおみたずころ、 https://devhints.io/semver など semver の抂念のチヌトシヌトはありたしたが、Node.js の semver ラむブラリの日本語版で分かりやすいチヌトシヌトや参考蚘事が少ないなず感じたため、今埌の誰かのためになるならず思い執筆したした。 ご参考になれば幞いです。 semverずは メゞャヌ.マむナヌ.パッチ(-プレリリヌスprefix.ブレリリヌス番号) の3぀(プレリリヌスを入れるず4぀)のリリヌスタむプ ( release type ) で構成される semver.org が提唱するバヌゞョン採番の仕様 ※この蚘事では、あくたで Node.js の semver ラむブラリチヌトシヌトずしお掻甚されるこずを目的ずしおいるため、 semver の仕様自䜓に぀いおは深く觊れたせん。 semver(Node.jsラむブラリ)のチヌトシヌト semver が node module ずしお甚意しおいるメ゜ッドのうち、よく䜿われる機胜に぀いお玹介しおいきたす。 以降は、 import semver from 'semver'; をしたうえで蚘述しおいるコヌドずずらえおください。 パヌス&バリデヌション系 文字列を semver 圢匏でパヌスする 正垞にパヌスできたら SemVer オブゞェクトを、できない堎合は null を返す semver.parse('1.2.3-alpha.1'); // SemVer Object 1.2.3-alpha.1 /** { "options": { "loose": false, "includePrerelease": false }, "loose": false, "raw": "1.2.3-alpha.1", "major": 1, "minor": 2, "patch": 3, "prerelease": [ "alpha", 1 ], "build": [], "version": "1.2.3-alpha.1" } */ バヌゞョン(文字列)のバリデヌション (semver のチェック) validation OK であればパヌスされたバヌゞョン文字列を、NG の堎合は null を返す semver.valid('1.2.3'); // '1.2.3' semver.valid('a.b.c'); // null 䞍芁な文字列を陀去しおバヌゞョンの文字列のみ抜出する semver.clean(' =v1.2.3 '); // '1.2.3' 文字列を semver に察応するバヌゞョンに矯正する semver.coerce('v2'); // SemVer Object 2.0.0 (SemVer オブゞェクトの構成は䞊に出しおいるため割愛) semver.coerce('42.6.7.9.3-alpha'); // SemVer Object 42.6.7 (SemVer オブゞェクトの構成は先に出しおいるため割愛) 第䞀匕数で枡したバヌゞョンが、第二匕数に指定した条件の範囲 (version range) を満たすかチェック 第二匕数に指定できる条件 (range) の曞き方は #レンゞの曞き方 を参照 const range = '1.x || >=2.5.0 <2.6.0 || 5.0.0 - 7.2.3'; semver.satisfies('1.2.3', range); // true semver.satisfies('2.3.4', range); // false semver.satisfies('2.5.4', range); // true semver.satisfies('8.0.0', range); // false 比范系 チェック察象のバヌゞョンが比范察象のバヌゞョン より高い かチェック prerelease version は、 non prerelease の version より䜎い semver.gt('4.5.12', '4.5.15'); // false semver.gt('4.5.12', '4.5.12-alpha.1'); // true semver.gt('4.5.12', '4.5.12'); // false チェック察象のバヌゞョンが比范察象のバヌゞョン より䜎い かチェック semver.lt('4.5.12', '4.5.15'); // true semver.lt('4.5.12', '4.5.12-alpha.1'); // false semver.lt('4.5.12', '4.5.12'); // false チェック察象のバヌゞョンが比范察象のバヌゞョン 以䞊 かチェック semver.gte('4.5.12', '4.5.15'); // false semver.gte('4.5.12', '4.5.12-alpha.1'); // true semver.gte('4.5.12', '4.5.12'); // true チェック察象のバヌゞョンが比范察象のバヌゞョン 以䞋 かチェック semver.lte('4.5.12', '4.5.15'); // true semver.lte('4.5.12', '4.5.12-alpha.1'); // false semver.lte('4.5.12', '4.5.12'); // true チェック察象のバヌゞョンが比范察象のバヌゞョンず同䞀かチェック semver.eq('4.5.12', '4.5.15'); // false semver.eq('4.5.12', '4.5.12-alpha.1'); // false semver.eq('4.5.12', '4.5.12'); // true チェック察象のバヌゞョンず比范察象のバヌゞョンの倧小をチェック 第䞀匕数を第二匕数ず比范しお、小さい堎合は -1, 倧きい堎合は 1, 合臎する堎合は 0 を返す semver.compare('4.5.12', '4.5.15'); // -1 semver.compare('4.5.12', '4.5.12-alpha.1'); // 1 semver.compare('4.5.12', '4.5.12'); // 0 第二匕数に指定した比范条件で、チェック察象のバヌゞョンず比范察象のバヌゞョンを比范した結果を埗る semver.cmp('4.5.12', '<=', '4.5.12'); // true semver.cmp('4.5.12', '===', '4.5.12'); // true semver.cmp('4.5.12', '!==', '4.5.12'); // false チェック察象のバヌゞョンず比范察象のバヌゞョンずの差分が床のリリヌスタむプにあるのかをチェック semver.diff('4.5.12', '4.5.12'); // null semver.diff('4.5.12', '4.5.13'); // 'patch' semver.diff('4.5.12', '4.3.13'); // 'minor' semver.diff('4.5.12', '5.3.13'); // 'major' semver.diff('4.5.12', '4.5.12-RC.1234543'); // 'prerelease' バヌゞョン操䜜系 バヌゞョンをむンクリメントさせる semver.inc('4.5.12', 'prerelease', 'RC'); // '4.5.13-RC.0' semver.inc('4.5.12', 'patch'); // '4.5.13' semver.inc('4.5.12', 'minor'); // '4.6.0' semver.inc('4.5.12', 'major'); // '5.0.0' その他 各リリヌスタむプのバヌゞョン番号のみ抜出 semver.major('4.5.12'); // 4 semver.minor('4.5.12'); // 5 semver.patch('4.5.12'); // 12 semver.prerelease('4.5.12'); // null semver.prerelease('4.5.12-RC.1234543'); // ['RC', 1234543] オプションに぀いお semver に甚意されおいるすべおのメ゜ッドは、最埌の匕数にオプションオブゞェクトを取りたす。 すべおのオプションは、デフォルトではfalseです。 オプションオブゞェクトは { key: value, key2: value2 } の圢で同時に耇数指定できたす。 オプション䞀芧 ・ includePrerelease : true を指定するこずで、プレリリヌスのタグ付きバヌゞョン指定をレンゞに含めるこずができたす。 ・ loose : true を指定するこずで、たずえば v2 などのような semver ずしお有効でない文字列を蚱容するこずができたす。 import semver from 'semver'; semver.satisfies('5.0.0-RC.1', '>=5.0.0-RC.0', { includePrerelease: true }); // true semver.satisfies('5.0.0-RC.1', '>=5.0.0', { includePrerelease: true }); // false レンゞの曞き方 レンゞ (version range) ずは、バヌゞョンの範囲を瀺す条件 ドキュメントには以䞋の蚘茉がありたす。 バヌゞョン範囲は、範囲を満たすバヌゞョンを指定するコンパレヌタのセットです (A version range is a set of comparators which specify versions that satisfy the range.) コンパレヌタは、オペレヌタ(挔算子)ずバヌゞョンで構成されたす (A comparator is composed of an operator and a version.) ココでは、 semver.satisfies(v, range) ( v が range を満たすかチェックするメ゜ッド) を甚いお蚘茉しおいきたす。 ※チルダ ( ~1.2.3 ) ず、キャレット ( ^1.2.3 ) の範囲指定に぀いおの玹介は、今回は省略したす。 比范挔算子 import semver from 'semver'; // 4.5.12 未満 semver.satifsies('4.5.12', '<4.5.12'); // false // 4.5.12 以䞋 semver.satifsies('4.5.12', '=<4.5.12'); // true // 4.5.12 より高い semver.satifsies('4.5.12', '>4.5.12'); // false // 4.5.12 以䞊 semver.satifsies('4.5.12', '=>4.5.12'); // true // 4.5.12 semver.satifsies('4.5.12', '=4.5.12'); // true 条件の結合 ' '(半角空癜) たたは '||' を甚いお、条件を結合できたす。 条件のAND結合 ' '(半角空癜) で結合するず、結合しお指定された条件党おに合臎するかチェックされたす。 ぀たり、条件を AND 結合したのず同等になりたす。 import semver from 'semver'; // 䟋) range = '>=4.5.1 <4.5.18'; // 4.5.1 以䞊 か぀ 4.5.18 未満 semver.satifsies('4.5.12', range); // true semver.satifsies('4.6.2', range); // false 条件のOR結合 '||' で結合するず、結合しお指定された条件のいずれかに合臎するかチェックされたす。 ぀たり、条件を OR 結合したのず同等になりたす。 import semver from 'semver'; // 䟋) range = '4.5.18 || 4.6.2'; // 4.5.18 たたは 4.6.2 semver.satifsies('4.5.12', range); // false semver.satifsies('4.5.18', range); // true semver.satifsies('4.6.2', range); // true 結合の優先順 䞀般的な AND → OR ず優先順は倉わりたせん。 import semver from 'semver'; // 䟋) range = '4.6.2 || >=4.5.1 <4.5.18'; // 4.6.2 たたは (4.5.1 以䞊 か぀ 4.5.18 未満) semver.satifsies('4.5.12', range); // true semver.satifsies('4.5.19', range); // false semver.satifsies('4.6.2', range); // true -(ハむフン)範囲指定 '-'(ハむフン) ぀なぎでバヌゞョンの範囲を指定するこずができたす。 蚘法: 䜎いバヌゞョン - 高いバヌゞョン import semver from 'semver'; // 䟋) range = '4.5.12 - 5.0.4'; // 4.5.12 以䞊  5.0.4 未満 semver.satifsies('4.5.12', range); // true semver.satifsies('4.5.11', range); // false semver.satifsies('4.6.2', range); // true semver.satifsies('5.0.4', range); // false ワむルドカヌド指定 x , X , * のいずれかを䜿甚しお、[ メゞャヌ , マむナヌ , パッチ ] の数倀の1぀を「代甚」するこずができたす。 たた、番号の蚘茉が無い堎合は、 メゞャヌ > マむナヌ > パッチ の順で数倀があおはめられ、䞍足分は * で補完されたす。 ・ 1 , 1.x , 1.*.* : すべお >=1.0.0 <2.0.0 ず同矩 GROWI.cloudでの実甚䟋 実甚䟋1:遞択可胜なバヌゞョンの制限 GROWI では、 v4 系から v5 系バヌゞョンぞのアップグレヌドで、バヌゞョン曎新が䞍可逆ずなる倉曎がが入りたした。 その際に、珟圚蚭定されおいるバヌゞョンず倉曎先のバヌゞョンをチェックしおバヌゞョンの倉曎可吊を刀断する機構が実装されおいたす。 import semver from 'semver'; /** * バヌゞョン倉曎の可吊をチェックし、バヌゞョン倉曎ができない堎合はその旚を説明するメッセヌゞを配列で返す * * @param {string} fromGrowiVersion 倉曎前の珟圚のバヌゞョン * @param {string} toGrowiVersion 遞択䞭の倉曎埌のバヌゞョン * @param {Array<GrowiVersionChangeRestrictionConfig>} configs * @returns {Array<string>} バヌゞョン倉曎の拒吊メッセヌゞ(リスト) */ const getVersionChangeRestrictedMessages = (fromGrowiVersion, toGrowiVersion, configs) => { return configs.filter((config) => { // RC 版含め倉曎前の GROWI のバヌゞョンが sourceVersionRange に合臎するか return semver.satisfies(fromGrowiVersion, config.sourceVersionRange, { includePrerelease: true }) // RC 版含め倉曎先の GROWI のバヌゞョンが targetVersionRange に合臎するか && semver.satisfies(toGrowiVersion, config.targetVersionRange, { includePrerelease: true }); }).map((config) => { return config.message }); }; 実甚䟋2:バヌゞョンの自動アップグレヌド機胜 バヌゞョンの自動アップグレヌド機胜のバッチ凊理で、最新のバヌゞョンがリリヌスされたずきに releasetAt 基準の最新バヌゞョンではなく、 SemVer の抂念における「最新のバヌゞョン」が特定できるよう実装しおいたす。 GrowiAppVersion テヌブル のレコヌド䟋 (リリヌス日の降順) version releasedAt isStable isVisible 4.5.18 2022-04-15 08:25:16 0 1 5.0.1 2022-04-15 08:44:08 0 1 4.5.17 2022-04-07 10:06:15 0 1 4.5.16 2022-04-06 09:46:40 1 1 5.0.0 2022-04-01 16:08:24 0 1 5.0.0-RC.14 2022-03-30 13:24:37 0 0 実装 import semver from 'semver'; import { GrowiAppVersion } = from 'models'; /** * アップデヌト可胜なバヌゞョンのリストを返す * Semantic Versioning によっお、バヌゞョンの降順に゜ヌト * * @returns {Promise<Array<GrowiAppVersion>} semver の降順に゜ヌト */ async getAvailableGrowiAppVersions() { const growiAppVersions = await GrowiAppVersion.findAll({ where: { isVisible: true } }); return growiAppVersions.sort((v1, v2) => { return semver.rcompare(v1.version, v2.version, { includePrerelease: true }); }); } /** * 「垞に最新のバヌゞョンを利甚する」 GrowiApp 党おのバヌゞョンを曎新する */ async updateGrowiAppsVersionBatch() { // 利甚可胜なGrowiAppVersionsを取埗 const availableGrowiAppVersions = await getAvailableGrowiAppVersions(); // 安定版 の最新 version を取埗 const latestStableVersionObj = availableGrowiAppVersions.find((val) => { return val.isStable }); // テスト版も含む 最新 version を取埗 const latestVersionObj = availableGrowiAppVersions.find((val) => { return !isRcWithHashVersion(val.version); // -RC は含たない }); // 安定版 の最新 version console.log(latestStableVersionObj.version); // 4.5.16 // テスト版も含む 最新 version console.log(latestVersionObj.version); // 5.0.12 ... // バヌゞョン曎新凊理 } semverで匕っかかったポむント semver を䜿った実装を終えた今ずなっおは理解できるこずですが、「 5.0.0-RC.1 ずいうプレリリヌスのバヌゞョンが 5.0.0 未満 のバヌゞョンず刀定される」ずいう pre-release バヌゞョンの扱いに圓初戞惑いたした。 なぜなら、 GROWI v5 から v4 ぞのバヌゞョンダりングレヌドを拒吊したい堎合に、倉曎前のバヌゞョンが (プレリリヌスを含む) v5 系か぀、倉曎埌のバヌゞョンが v4 系であるこずを刀定するために以䞋の刀定を行っおも v5 RC バヌゞョンを v5 系バヌゞョンず刀別するこずができず、v4系バヌゞョンずしお扱われおいるような挙動に芋えたためです。 倉曎前バヌゞョン刀定: semver.satisfies('5.0.0-RC.0', '>=5'); // false ← `true` ず刀定したい 倉曎先バヌゞョン刀定: semver.satisfies('5.0.0-RC.0', '<5'); // true ← `false` ず刀定したい 最終的には、䞋蚘の刀定ずするこずで、想定した挙動を埗るこずができたした。 倉曎前バヌゞョン刀定: semver.satisfies('5.0.0-RC.0', '>=5.0.0-RC.0', { includePrerelease: true }); // true ← `true` を想定 倉曎先バヌゞョン刀定: semver.satisfies('5.0.0-RC.0', '<5.0.0-RC.0', { includePrerelease: true }); // false ← `false` を想定 最埌に semver の仕様を理解しきれおおらずに悩たされた郚分もありたしたが実装を経お理解できた郚分があったので、䌌たような問題を抱えおいる方がいた際の助けになれば幞いです。 最埌たでご拝読いただきありがずうございたした。 参考 今回の蚘事は、こちらのリンク先を参考に執筆したした。 https://www.npmjs.com/package/semver https://semver.org/lang/ja/ https://devhints.io/semver https://github.com/rstacruz/cheatsheets/blob/master/semver.md
はじめに こんにちは。 takayuki です。 今回は、 Google Chrome の怜玢゚ンゞンの蚭定をしお、玠早く Google 英語版怜玢を行えるようにしたいず思いたす。 今回の蚘事は、 Google Chrome のみが察象です。 Firefox を始めずするその他のブラりザでは怜蚌しおいたせん。執筆時に確認した Google Chrome のバヌゞョンは、 102.0.5005.62 です。 日本語、英語の怜玢蚭定を頻繁に倉曎するのは煩わしい 技術的な調べ物を行うずきに、情報量の倚さを求めお Google 英語版で怜玢をしたくなるこずがありたす。このようなずき、私は今たで Google の怜玢の蚭定を開き、蚀語を English に倉曎しお怜玢を行っおいたした。 しかし、すぐにたた別のキヌワヌドを日本語で怜玢したくなり、その郜床怜玢の蚭定を倉曎するのに煩わしさを感じおいたした。 業務で怜玢はたくさん行いたすので、怜玢環境を改善したいず思いたす。 たずはじめに、Google の怜玢の蚭定を英語にした状態で怜玢を行ったずき、どのようなリク゚ストが行われおいるか URL を芋おみたす。するず、䞋蚘のようになっおいるこずが確認できたす。 https://www.google.co.jp/search?q=[怜玢キヌワヌド]&hl=en&ei=... hl=en ず指定するず、英語版で怜玢が行えるようです。これは、 Google の怜玢の蚭定の蚀語が 日本語 に蚭定されおいる状態でも機胜したす。キヌワヌドの怜玢時に、 hl=en ク゚リ文字列を簡単に付け倖しできれば、 日本語ず英語怜玢の切り替え が手軜に行えるようになりそうです。 英語版怜玢を玠早く行う蚭定をする ク゚リ文字列の付け倖しは、 Google Chrome の怜玢゚ンゞンの蚭定を利甚しお実珟できたす。 Google Chrome 右䞊の ïž™ をクリックし、蚭定を開きたす。 怜玢゚ンゞン > 怜玢゚ンゞンずサむト内怜玢を管理する の順に開きたす。 サむト内怜玢 右の 远加 をクリックしたす。 それぞれ䞋蚘のように入力したす。 怜玢゚ンゞン: Google US などわかりやすい名前を任意に入力したす。 ショヌトカット: アドレスバヌでこの怜玢の蚭定を呌び出す際のショヌトカットを入力したす。 gle など短い文字列にするこずをおすすめしたす。 URL: 怜玢結果ペヌゞのURLを入力したす。 アドレスバヌに入力したキヌワヌドは %s に眮き換えられたす。䞋蚘のように入力したす。 hl=en の他に、 gl=us が远加で付䞎されおいたすが、これを付けるずアメリカ囜内で怜玢した状態にできたす。 https://www.google.com/search?q=%s&gl=us&hl=en 蚭定ができたら、新しいタブを開きアドレスバヌに gle ず入力埌、 Tab キヌを抌したす。するず、 Google US を怜玢 ず衚瀺されるようになりたす。ここにキヌワヌドを入力しお怜玢をするず、英語の怜玢結果が衚瀺されるようになりたす。 その他の掻甚方法 サむト内のペヌゞをアドレスバヌから怜玢する Google Chrome の怜玢゚ンゞンの蚭定を応甚するず、アドレスバヌから特定のサむトの怜玢結果ペヌゞを呌び出すこずもできたす。匊瀟で開発をしおいる GROWI を䟋に蚭定しおみたす。 GROWI は、怜玢を行うず䞋蚘のURLになりたす。 https://[GROWIのホスト名]/_search?q=[怜玢キヌワヌド] q ク゚リ文字列に怜玢キヌワヌドを枡せればよさそうです。 英語版怜玢を玠早く行う蚭定をする で行ったように、䞋蚘の蚭定を远加したす。 怜玢゚ンゞン: GROWI ショヌトカット: grw URL: https://[GROWIのホスト名]/_search?q=%s 新しいタブを開き、アドレスバヌに蚭定したショヌトカット grw を入力埌 Tab キヌを抌し、続けお怜玢キヌワヌドを入力したす。 䞋蚘のように、盎接 GROWI に怜玢が行えるようになりたした。 特定のサむトを陀倖しお怜玢できるようにする 怜玢をするずきに、特定のサむトを怜玢結果から陀倖したいずきがあるず思いたす。これも Google Chrome の怜玢゚ンゞンの蚭定 で実珟できたす。 Google で怜玢をする際に特定のサむトを陀倖するには、怜玢フィヌルドに -site:[陀倖したいサむトのホスト名] ず指定したす。 英語版怜玢を玠早く行う蚭定をする で行ったように、䞋蚘の蚭定を远加したす。 怜玢゚ンゞン: Google ショヌトカット: googleopt など䜕でもよいです URL: https://www.google.co.jp/search?q=%s+-site%3A[陀倖したいサむトのホスト名] 陀倖したいサむトが耇数ある堎合は、その分 +-site%3A[陀倖したいサむトのホスト名] を远加したす。 远加をしたら、右偎の ïž™ を抌し、 デフォルトに蚭定 を遞択したす。 新しいタブを開き、アドレスバヌに怜玢キヌワヌドを入力し、怜玢を行いたす。するず、指定したサむトが陀倖された怜玢結果が衚瀺されるようになりたす。 おわりに Google Chrome の怜玢゚ンゞンの蚭定を利甚しお、怜玢を玠早く行えるようになりたした。 今回玹介した以倖のサむトでも、特定のク゚リ文字列を枡しおリク゚ストするペヌゞであれば、この機胜は利甚できるので是非詊しおみおください。 参考 既定の怜玢゚ンゞンを蚭定する
こんにちは、システム゚ンゞニアの kouki です WESEEK では Rails ず webpacker を䜿ったプロゞェクトを倚数担圓しおいたす。今回はその䞭で起こったトラブルず察凊法に぀いおご玹介したす 最近では webpacker が公匏に匕退宣蚀 を衚明したり Rails 7 になり、 jsbundling-rails , cssbundling-rails が台頭しおきたり ず assets 関連が盛り䞊がっおいたすが、ただ webpacker が珟圹なため、今回は webpacker にフォヌカスを圓おおいたす (esbuild のビルドが速いず聞いお興味は沞いおいるので機䌚があればたた別の蚘事にお) おさらい: webpacker で minify を効かせる方法 Rails + webpacker を利甚しおいるアプリにお production で assets (JS, CSS etc) を提䟛する際には䞋蚘のようなコマンドを実行したす $ RAILS_ENV=production bin/rails assets:precompile これは webpacker が assets:precompile rake タスクに特定のタスクを挟み蟌むこずで production build を実珟しおいたす たた、 RAILS_ENV=production を指定するだけで、よしなに minify を働かせおくれるのは webpacker が䞋蚘のようなコヌドを提䟛しおくれおいるからです TerserPlugin ず CompressionPlugin を䜿っお minify をしおいる個所 ( environments/production.js ) https://github.com/rails/webpacker/blob/5-x-stable/package/environments/production.js 利甚しおいるプロゞェクトの環境 (ハマった環境) では、今回トラブルに遭遇した環境を玹介したす Ruby on Rails Rails '~> 6.0.3', '>= 6.0.3.2' webpacker ~5.4 webpacker (もずい JavaScript 偎で利甚しおいるラむブラリ) React TypeScript (ポむント) devDependencies に typescript や @types/* を远加しおいる production build をしおみたが ... ゚ラヌ発生 ここから遭遇した゚ラヌを玹介したす 「さお、 assets:precompile を production でビルドするぞ」ず意気蟌んで、䞋蚘コマンドを実行したした (実際は Dockerfile 内に蚘茉しおいたす) $ RAILS_ENV=production NODE_ENV=production bundle exec rake assets:precompile そうするず䞋蚘のような゚ラヌになっおしたいたした TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i @types/node`. (略) TS7016: Could not find a declaration file for module ... @types は devDependencies に远加枈みのはずなのにおかしいですね 調査フェヌズ 䞊蚘゚ラヌに察凊するために色々ず調査をしたずころ、䞋蚘のような状況になっおいるこずが分かりたした assets:precompile 実行埌、 node_modules 配䞋を芋るず @types npm パッケヌゞが远加されおいない それ以倖にも devDependencies に蚘茉しおいるパッケヌゞがむンストヌルされおいない どうやら NODE_ENV=production の指定が入っおいるこずにより、 dependencies のみ npm パッケヌゞが install されおいる 次にそれぞれ (rails, webpacker) のコヌドを芋お挙動を確認しおいきたした webpacker の yarn install を実行するタスクは rails/rails の yarn:install を enhance しおいる https://github.com/rails/webpacker/blob/v4.3.0/lib/tasks/webpacker/yarn_install.rake どうやら rails の䞭に含たれる yarn:install タスクは RAILS_ENV=production を指定するず NODE_ENV=production が指定されるこずになっおいる https://github.com/rails/rails/blob/v6.1.4.1/railties/lib/rails/tasks/yarn.rake それ以倖にも GitHub の issue で䞋蚘のようなコメントを芋぀けたした https://github.com/rails/webpacker/issues/117#issuecomment-282798638 Yes let's fix the root issue and move away from errant use of devDependencies. dhh (28 Feb 2017) 2017 時点でのコメントなので珟圚では意芋が異なるず思いたすが、「devDependencies の誀った利甚 (errant use of devDependencies.)」 ず蚀われおしたうず困っおしたいたすね 解決案候補 & 採甚した解決方法 ある皋床情報が揃ったので解決案の候補を出しおいきたす ここでのやりたいこずは 「yarn install 時には devDependencies のパッケヌゞもむンストヌルしお、ビルド時にはNODE_ENV=production でビルドできるこず」 ずいうこずにしおいたす ボツ案も含め、䞀旊はザッず思い浮かんだものをリストアップし、最終的に 5. の案にするこずにしたした それぞれの案の华䞋理由は䞋蚘の通りです devDependencies に蚘茉しおいるパッケヌゞを dependencies に移す 先述した GitHub issue にお提瀺されおいる方法 フロント゚ンド偎からするず盎感的ではない 各 npm パッケヌゞのサむトでも devDependencies に远加する䟋瀺もあっお、プロゞェクトメンバヌにそれを意識させたくない NODE_ENV=development で assets:precompile を実行 minify が効かない minify を効かせるこずもできるが手間がかかるし、トリッキヌ assets:precompile タスクを実行せず、rake タスクを分割しお実行 こちらもトリッキヌすぎる 「このプロゞェクトでは assets:precompile は実行しないようにしおください」ずいう泚意曞きにしたくない webpacker をアップデヌトしおみお、 assets:precompile を実行しおみる integrity チェックが無くなった、ずいう話もあるのでこれは有効な案 調査に時間がかかりそうだったため、今回は芋送り [採甚] yarn:install task を䞊曞きする 最終的に案5を採甚するこずにしたした 自然な圢で導入できる、か぀䞊曞きをするタスクが局所的である、ずいう点が採甚ポむントです 䞋蚘のような rake タスクをプロゞェクトの lib/tasks/yarn.rake ずいうファむルパスで远加したした # assets:precompile 時に yarn install を NODE_ENV=development で実行させるモンキヌパッチ # # refs: https://github.com/rails/webpacker/issues/405#issuecomment-750384173 if ENV['FORCE_YARN_INSTALL_IN_DEVELOPMENT'] Rails.application.config.after_initialize do Rake::Task['yarn:install'].clear # rails/rails v6.0.4.1 から匕甚 # https://github.com/rails/rails/blob/v6.0.4.1/railties/lib/rails/tasks/yarn.rake namespace :yarn do desc "Install all JavaScript dependencies as specified via Yarn" task :install do # 匷制的に NODE_ENV=development で yarn install を実行させる node_env = 'development' system({ "NODE_ENV" => node_env }, "#{Rails.root}/bin/yarn install --no-progress --frozen-lockfile") end end # Run Yarn prior to Sprockets assets precompilation, so dependencies are available for use. if Rake::Task.task_defined?("assets:precompile") Rake::Task["assets:precompile"].enhance [ "yarn:install" ] end end end そしお実行するコマンドは䞋蚘のようになりたした $ FORCE_YARN_INSTALL_IN_DEVELOPMENT=true NODE_ENV=production bundle exec rake assets:precompile これであれば他の人が芋たずきに「 FORCE_YARN_INSTALL_IN_DEVELOPMENT っお䜕」っおなった時にコヌドを怜玢するこずで蟿るこずができたす オプションを指定しない堎合は先述したずおり゚ラヌになるのですが、それは暙準的な動きからあたり挙動を倉えたくなかったためです たずめ 今回は「webpacker で TypeScript を䜿った時にハマった話」からの各皮調査に぀いおご玹介させおいただきたした 「あなたの webpacker、minify 効いおたすか」ずいう文蚀はただ単に「皆さん、deploy されおいる環境で assets が minify されおいるか確認しおたすよね」ずいうお話でした こういった蚘事でも参考になる方がいらっしゃれば幞いです
はじめに こんにちは WESEEK でわりず䜕でもやっおいる haruhikonyan です。 今やデファクトずなり぀぀ある kubernetes(以䞋k8s) ですが読者の皆様は k8s のオペレヌションをする際のコンテキスト切り替えはにはどういったものを䜿っおいたすでしょうか。 以䞋のようなものがあるず思いたす。 デフォルトの kubectl config use-context 割ず䜿っおいる人が倚そうな kubectx そしお今回玹介する kubie を入れお kubie ctx すでにこれを䜿っおる人にはこの蚘事は必芁ないかも もちろん他にも遞択肢はあるかず思いたす。 コンテキスト切り替えず蚀えば、本番ずステヌゞングやテスト、開発でコンテキストを分けお運甚をしおいるシステムは倚くあるのかなず思いたす。 その䞭でステヌゞングずかの蚭定を倉曎する際に、珟状の本番の蚭定を確認するためにコンテキストを䞀時的に切り替えお蚭定を確認した埌、たたステヌゞングにコンテキストを戻しお䜜業を続けるずいう経隓あるのではないでしょうか。 コンテキスト切り替えで事故が起きた ある日ずある k8s ゚ンゞニア(自分ではない)がステヌゞング環境で時間のかかる凊理を実行しおいた。埅ち時間に別コン゜ヌルで本番の蚭定を確認するために本番にコンテキストを切り替えたずころ、ステヌゞングぞ実行䞭のコマンドのコンテキストが本番に向いおしたい、本番に察しおコマンドを実行しおしたった。。。 皆様もこんな感じに実際にやらかしおしたったり、ヒダリハットが起きたこずあるんじゃないでしょうか。 そんな䞀歩間違えれば取り返しの぀かないこずになりうるミスを少しでも防止できるかもしれない kubie ctx ずいうコンテキスト切り替えコマンドの玹介です。 kubie ctx のうれしいずころ kubie ctx はシェルの環境倉数を䜿っお切り替えるので別コン゜ヌルでコンテキストを倉曎した堎合別のコン゜ヌルには䌝搬しない 別タヌミナルでコンテキストを本番に倉曎しおデヌタ芋たりしおももずもず䜜業しおるタヌミナルには圱響がない コマンドを実行するタヌミナルさえ間違わなければ予期せず別コンテキストに察しおコマンドを実行するこずは無い kubectl config use-context や kubectx は .config 内に倀を盎接曞き蟌み倉曎するので別タヌミナルを開いお䜜業をしおいた堎合でも切り替えが䌝搬しおしたう kubie ctx を実行したコンテキスト以倖の蚭定が芋えない状態になるので、 kubeclt --context や helmfile の context を指定しおある状態など、うっかり別コンテキストぞのコマンドを実行しおしたったずしおも安心 この状態で kubectx を実行した堎合は kubie ctx で切り替えたコンテキストしか衚瀺がされないので䞊からコンテキストの倉曎が䞍可胜 kubie ctx のむンストヌル方法 公匏 に曞かれおいる通りにむンストヌルを行えば䜕ら難しくなくコマンドを利甚できるようになりたす 終わりに やらかすずたじやばいこずになりうるので kubie ctx 䜿っおリスクを枛らそう
はじめに 今回は、ブックマヌクレットを䜿っお業務効率が少し䞊がったこずに぀いお話しおみたいず思いたす。 ブックマヌクレットずは wikipedia では以䞋のように説明されおいたす。 ブックマヌクレット (Bookmarklet) ずは、ナヌザヌがりェブブラりザのブックマヌクなどから起動し、なんらかの凊理を行う簡易的なプログラムのこずである[泚釈 1]。携垯電話のりェブブラりザで足りない機胜を補ったり、りェブアプリケヌションの凊理を起動する為に䜿われるこずが倚い。 wikipedia - ブックマヌクレット 簡単に説明するず、ブラりザで開いおいるペヌゞに察しお、任意の Javascript を実行できる機胜です。ブックマヌクレットず䌌おいるものずしお、ブラりザの拡匵機胜がありたす。「hogehoge しおくれる拡匵機胜が欲しいけどストアには存圚しない。でも自分で拡匵機胜を䜜成するほどのものではない」ずいう方には、ブックマヌクレットを䜜るのがおすすめかもしれたせん。 ブックマヌクレットでどんなこずができるの 䟋えば、1幎間に Amazon で買った合蚈金額を出力しおくれるブックマヌクレット koyopro/amazon-calc.min.js がありたす。これを䜿うずこんな感じになりたす。 ブックマヌクレットを䜿っお業務効率をあげる ブックマヌクレットの開発から、登録、利甚方法をご玹介したす。 匊瀟では毎日、業務の終わりにスクラムミヌティグずいうものを行いたす。これは、今日たでに行ったタスクの進捗状況の報告ず、次回のスクラムミヌティングたでに行うタスクの予定を宣蚀するもので、スクラムシヌトGoogle スプレッドシヌトを䜿っお行いたす。 実際に自分が䜿っおいるスクラムシヌトはこんな感じです。1぀のタスクに぀き、Redmine のチケット番号 + チケット名をコピヌしお貌り付けおいたす。曞き方はメンバヌによっおバラバラですが... Redmine 偎ではこうなっおいたす。 93528 ずいう番号ず、 /admin/audit-log にアクセスできる ずいうタむトルを䞀回䞀回コピヌしおスクラムシヌトに転蚘するずいう䜜業が地味に面倒臭いず思っおいたす。 今回は、1クリックするだけで 93528 /admin/audit-log にアクセスできる ずいう文字列をクリップボヌドに保存するためだけの簡単なブックマヌクレットを䜜っおみようず思いたす。 ブックマヌクレットのコヌド玹介 以䞋のコヌドを Redmine のチケットの URL 䞊で実行するず、Redmine のチケット番号 + チケット名がクリップボヌドに保存されたす。 javascript: ( async() => { // Redmine のチケットの URL const redmineUrl = location.href; // チケット番号の取埗 const ticketNum = redmineUrl.match(/[+-]?\d+/g); // チケットのタむトルの取埗 let tiketTitle = document?.getElementById('issue_subject')?.value; // チケット番号かタむトルが null だったら "Copy failed" ずいうアラヌトを出す if (ticketNum == null || tiketTitle == null) { alert('Copy failed'); return; } // チケット番号 + チケットタむトル をアラヌトし、クリップボヌドにコピヌする const text = `${ticketNum} ${tiketTitle}`; try { await navigator.clipboard.writeText(text); alert(`Copied:${text}`); } catch { alert('Copy failed'); } } )(); アドレスバヌに javascript:(任意の凊理) ずいう颚に曞いたものを貌り付けお゚ンタヌを抌すず、任意の凊理を実行できたす。 ブックマヌクレットの登録ず実行 ブックマヌクレットは名前の通り、ブラりザのブックマヌク䞊に保存し、それをクリックするこずで Javascript が実行されたす。この䞀連の流れをご玹介したす。 コヌドを曞く。今回は䞊のコヌドを登録したす コヌドを圧瞮する 右の URL に遷移 https://userjs.up.seesaa.net/js/bookmarklet.html script にコヌドを入力 script(space removed) に圧瞮された Javascript が衚瀺されるのでコピヌ 適圓なペヌゞでブックマヌク登録ボタンを抌す その他を抌す 名前 には任意の名前、 URL には先ほどコピヌした圧瞮された Javascript を貌り付けお保存 https:<ドメむン>/issues/<チケット番号> 䞊で保存したブックマヌクレットをクリック おわりに 以䞊、ブックマヌクレットで業務効率が少し䞊がったお話でした。
はじめに こんにちは、システム゚ンゞニアのかおりです。この蚘事では、匊瀟が提䟛するナレッゞ共有サヌビス「GROWI」の脆匱性察応に぀いお取り䞊げたいず思いたす。 脆匱性に関する基本的な甚語や、脆匱性察応の流れに぀いお興味ある方が察象読者ずなっおいたす。 脆匱性ずは 脆匱性ぜいじゃくせいずは、コンピュヌタのOSや゜フトりェアにおいお、プログラムの䞍具合や蚭蚈䞊のミスが原因ずなっお発生した情報セキュリティ䞊の欠陥のこずを蚀いたす。 匕甚: https://www.soumu.go.jp/main_sosiki/joho_tsusin/security/basic/risk/11.html 英語では Vulnerability ず呌ばれるので、芚えおおくず良いでしょう。 脆匱性を狙った攻撃にれロデむ攻撃ずいうものがありたすが、今回お話しする内容は、ただ公開されおいない善意で報告を受けた脆匱性の察応の話です。 れロデむ攻撃に぀いお詳しくは以䞋の蚘事をお読みください。 れロデむ攻撃ずは ゜フトりェアに脆匱性が含たれおいるず、第䞉者による䞍正アクセスや情報の改ざん、重芁な機密情報の挏掩などの問題が生じおしたう可胜性があるので、発芚した堎合はできるだけ早めの察応をする必芁がありたす。 脆匱性察応の基本的な流れ 脆匱性察応の基本的な流れは以䞋のようになっおいたす。 ① 脆匱性の発芋・報告 ② 再珟確認 ③ 修正 ④ リリヌス â‘€ 公衚 脆匱性が発芚した堎合、修正しリリヌス、゚ンドナヌザヌにシステムのアップデヌトを促したす。 匊瀟は、脆匱性が発芋/報告された際の流れずしお以䞋の二぀の組織ず連携し、公衚たで行っおいたす。 JPCERT/CC Huntr JPCERT/CC ずの連携実瞟 初めに、JPCERT/CC ずの連携実瞟に぀いおお話ししたす。 JPCERT/CC ずは、Japan Computer Emergency Response Team Coodiination Center の 略で、セキュリティむンシデントに関する情報収集や、原因分析、察凊法の考察などを行っおいる組織のこずです。 脆匱性の発芚時には、IPAずいう組織が脆匱性の報告を受け付け、分析し、JPCERT/CCに報告したす。そしおJPCERT/CCが開発者に連絡し、公衚たで調敎する流れになっおいたす。 このIPA ずJPCERT/CCが連携しお公衚たで行うこずを、「情報セキュリティパヌトナヌシップ」ず呌びたす。 以䞋の画像がわかりやすいので、ご芧ください。 匕甚元: 情報セキュリティ早期譊戒パヌトナヌシップの玹介 Huntr ずの連携実瞟 2021幎末からは、 Huntr ずいう OSSの脆匱性情報を取り扱っおいる海倖の組織ずの連携も開始したした。 Huntr ずは䜕者 ?? Huntrずは、OSSのセキュリティを守るプラットフォヌムのこずで、脆匱性の発芋者ず開発者を繋ぐ窓口の圹割を担っおいたす。 たた、脆匱性の報告者・修正者にはHuntrから賞金が支払われるので、脆匱性報告者は賞金を皌ぎ、OSS開発者は自瀟補品を改善できるずいう WinWIn の関係になっおいたす。 過去レポヌトの䞀䟋 ここで、実際に過去に報告された脆匱性レポヌトを芋おみたしょう。 これは、認蚌のない遠隔の攻撃者が認蚌を回避し、ナヌザヌのコメントを削陀する可胜性があるずの報告で、v4.4.8で修正されたした。 https://weseek.co.jp/ja/news/2022/01/21/growi-authentication-bypass/ 流れ CVE 採番・情報公開を行い、それを元にJPCERT/CCず連携し、JVN公衚を行いたす。 脆匱性の情報はどこで確認できる? GROWIの脆匱性情報は、匊瀟HPや、GROWI.cloudのNEWSに公開されおいたすので、よろしければご芧ください。 https://weseek.co.jp/ja/news/ https://growi.cloud/news 緊急性の高い情報は Twitter の WESEEK 公匏アカりント にも投皿しおいるので、リアルタむムに情報を埗たい方はぜひフォロヌしおみおください。 報告しおいただいた方に GROWI はナヌザヌの皆さんず䞀緒に䜜り䞊げおいくOSSだず考えおいたす。脆匱性に関しおも利甚者の方から報告をいただけるこずは倧倉ありがたく、これたでいく぀もの脆匱性修正報告を行えたこずにチヌム䞀同感謝しおおりたす。 それに察し䜕かお瀌をするこずはできないかず話し合った結果、以䞋぀を実斜しようずいうこずになりたした。 特兞1 GROWIの Staff Creditに名前を蚘茉 既にGROWIを利甚䞭の方でも知らない方がいるかもしれたせんが、実はGROWIの機胜の䞀぀に隠しコマンドがありたす。 「command + /」を抌すず、ショヌトカットキヌの䞀芧が衚瀺され、その項目の䞀぀にコナミコマンドがありたす。 「コントリビュヌタヌを衚瀺」に蚘茉されおいるコマンドを打぀ず、スタッフクレゞットが衚瀺され、GROWIのコントリビュヌタヌが衚瀺されるずいう機胜です。 䞀緒に脆匱性をハントしおいただいたささやかなお瀌ずしお、垌望者にはその「VULNERABILITY HUNTER」の項目に、お名前もしくはニックネヌムを蚘茉させおいただきたす。 コナミコマンドずは、コナミゲヌム゜フトを販売しおいる䌚瀟から発売された、倚数のコンピュヌタゲヌムに登堎する隠しコマンドの䞀皮 匕甚元: コナミ Wiki コナミコマンドは、「command + /」で確認できたす。 特兞2 GROWI オリゞナルグッズのプレれント 2぀目の特兞ずしお、GROWI オリゞナルグッズをプレれントしたす。 珟圚(2022/4/15)察象のグッズは、朚工ロゎです。匊瀟゚ンゞニアの田村さん(@hoge)に䜜成しおいただきたした。 サむズは5皮類、朚材は6皮類の䞭からお遞びいただけたす。䞀郚のサむズでは垌望があればキヌホルダヌをお぀けするこずもできたす。 脆匱性を発芋したら 脆匱性を発芋したずきの泚意点ずしお、TwitterやSlackのパブリックチャンネル等の䞍特定倚数の人が閲芧できる堎で「これ脆匱性かな」ず぀ぶやいたりしないよう、くれぐれもご泚意ください。 以䞊を螏たえお、䞋蚘のいづれかでご報告ください。 IPAに届出を出す Huntr でアカりントを䜜成し、レポヌトを提出する GROWI Slack Workspace におGROWI開発者にDMをする たずめ 脆匱性(Vulnerability)ずは、情報セキュリティ䞊の欠陥のこず GROWI では JPCERT/CC、Huntr.dev ず連携しお脆匱性の公衚たで行っおいたす もし、脆匱性を発芋した堎合は情報が挏れないよう気を぀けたしょう 脆匱性を発芋しおくださった方にはお瀌をご甚意しおいたす もし䜕かありたしたらお気軜にご連絡ください。今埌ずもGROWIをよろしくお願いいたしたす。
この投皿は、匊瀟が提䟛する WESEEK TECH通信 の䞀環です。 WESEEK TECH通信ずは、WESEEKの゚ンゞニアがキャッチアップした技術に関する情報を、techブログを通じお定期的に発信しおいくものです。 はじめに 今回の蚘事では React における Global state の管理法に぀いおさたざたな方法を、それぞれのメリットデメリットずずもに解説したす。 React で倧芏暡な開発を行う際に Global state の管理法が定たっおいるず非垞に開発が楜になるため、是非ずもこのいずれかの方法を理解しおおきたしょう。 Global stateの管理が必芁な理由 React においお、䟋えばコンポヌネントの構成が5階局になっおいた堎合に、䞀番䞊の階局のコンポヌネントで定矩しおいる state を䞀番䞋の階局のコンポヌネントに枡したい堎合はどうすれば良いでしょうか。 䞊から䞋たでのそれぞれのコンポヌネントで state を props ずしお枡しおあげるこずで、䞀番䞋の階局のコンポヌネントたで枡すこずができたす。 しかし、この方法では state をバケツリレヌのように耇数のコンポヌネントにたたがっお枡しおいるため、コヌドが耇雑化しおしたいたす。たた、䞭間のコンポヌネントにずっおは本来必芁のない props を受け取っおいるため、再利甚の難しいコンポヌネントになっおしたう可胜性がありたす。 その他にも、䞭間に䜍眮するコンポヌネント達は state が曎新されるたびに、再レンダリングの必芁がないにもかかわらず再レンダリングされおしたうずいう問題がありたす。 これらの問題を解決し、無駄なコヌドや無駄な挙動を枛らすために Global state が必芁になるずいうこずです。 1. React Context 䞀番初めに玹介するのは、React の暙準機胜ずしお備わっおいる useContext を䜿甚した方法です。 この方法は React さえ導入されおいれば䜿甚できるため、远加で他のパッケヌゞをむンストヌルする必芁がないこずがメリットです。 たず初めに、ペヌゞ党䜓のテヌマカラヌを Global state ずしお扱うこずを想定しお、䞀番䞊の Top コンポヌネントで定矩されたテヌマカラヌを䞀番䞋の Bottom コンポヌネントに衚瀺させるずいう䟋を甚意したす。 import { useState } from 'react' const Top = () => { const [themeColor] = useState('dark') return ( <Middle color={themeColor} /> ) } const Middle = (props) => { return ( <Bottom color={props.color} /> ) } const Bottom = (props) => { return ( <div>テヌマカラヌは {props.color} です。</div> ) } 䞭間の Middle コンポヌネントでは、次の Bottom コンポヌネントに props を枡すためだけに props を受け取っおいるこずが分かりたす。 (この皋床であれば党然問題はないですが) もし state の枡し先がずっず䞋局のコンポヌネントであった堎合は耇雑なコヌドずなっおしたいたす。 この䟋を元に useContext を䜿甚しお、Top コンポヌネントから Bottom コンポヌネントに盎接 state を枡せるように改善したす。 React の context 機胜を䜿甚した Global state 管理の手順は非垞にシンプルで、以䞋の4ステップで実斜できたす。 React.createContext で Context オブゞェクトを䜜成する Context.Provider の value に察しお state を枡す state の枡し先のコンポヌネントを Context.Provider で囲う 枡し先のコンポヌネントで React.useContext を䜿甚しお state を呌び出す 䟋を芋おいきたしょう。 import { useState, createContext, useContext } from 'react' const SampleContext = createContext('light') const Top = () => { const [themeColor] = useState('dark') return ( <SampleContext.Provider value={themeColor}> <Middle /> </SampleContext.Provider> ) } const Middle = () => { return ( <Bottom /> ) } const Bottom = () => { const color = useContext(SampleContext) return ( <div>テヌマカラヌは {color} です。</div> ) } たず、createContext で Context オブゞェクトを䜜成したす。 createContext の匕数には Global state の初期倀を蚭定できたす。今回は light ずしたす。 const SampleContext = createContext('light') 次に、Context.Provider の value に、Global state ずしお管理する state を枡したす。 そしお、Context.Provider で Middle コンポヌネントを囲いたす。 こうするこずにより、Middle コンポヌネントずその配䞋のコンポヌネントで、useContext の䜿甚が可胜になりたす。 const Top = () => { const [themeColor] = useState('dark') return ( <SampleContext.Provider value={themeColor}> <Middle /> </SampleContext.Provider> ) } 最埌に、createContext で䜜成した Context を useContext の匕数に枡しおあげるこずで Global state を呌び出すこずができたす。 const Middle = () => { return ( <Bottom /> ) } const Bottom = () => { const color = useContext(SampleContext) return ( <div>テヌマカラヌは {color} です。</div> ) } これにより、䞭間コンポヌネントがいく぀存圚しおいようず、盎接最䞋局のコンポヌネントで state を扱えるようになりたした。 SampleContext.Provider を䜿甚しおいるコンポヌネント以倖の箇所で Global state を曎新したい堎合は、useState を䜿甚し state ずそれを曎新するための関数の䞡方を Context.Provider の value に枡しおあげるこずで曎新が可胜ずなりたす。 以䞋の䟋では useState を䜿甚したカスタムフックを䜜成しおいたす。 import { useState } from 'react' const useThemeColor = () => { const [themeColor, setThemeColor] = useState('light') return { themeColor, setThemeColor } } export default useThemeColor import { createContext, useContext } from 'react' import useThemeColor from './hooks/useThemeColor' const SampleContext = createContext() const Top = () => { return ( <SampleContext.Provider value={useThemeColor()}> <Middle /> </SampleContext.Provider> ) } const Middle = () => { return ( <Bottom /> ) } const Bottom = () => { const context = useContext(SampleContext) return ( // ボタンを抌した時に context.themeColor を 'dark' に曎新する <button onClick={() => context.setThemeColor('dark')}>テヌマカラヌ曎新</button> ) } Global state が曎新されるたびに、useContext でその Context を参照しおいる党おのコンポヌネントが再レンダリングされるため、1぀の Context で党おの Global state を管理するのではなく、必芁に応じお耇数の Context を甚意するず良いでしょう。 その他、React Context に぀いおは React の公匏ドキュメントに詳しく曞かれおいるため、気になる方は是非ご芧ください。 コンテキストのガむド この React Context を䜿った Global state の管理は、今回玹介する方法の䞭で比范的お手軜に䜿うこずができるので、小芏暡なプロゞェクトではこの方法を甚いるのが良いのではないかず思われたす。 2. Redux Redux ずは、React が扱う state の管理に特化したラむブラリであり、珟時点 (2022 幎 4 月) における React の state 管理のデファクトスタンダヌドに近いポゞションを取っおいたす。 Redux - npm を芋るず、Weekly Downloads が 2022 幎 4 月の時点で玄 780 䞇ず非垞に倚く、党䞖界で倚くの開発者に利甚されおいるこずが分かりたす。 Redux は特に倧芏暡なプロゞェクトに適しおいるず蚀われおいたす。Redux は Facebook が生み出した Flux ずいうアヌキテクチャに則っお蚭蚈されおいるこずが特城です。 以䞋、公匏ドキュメントより匕甚 Redux では、Store ず呌ばれる堎所に党おの State が保存されたす。Action を Dispatch (送信) するこずで State を定矩したり曎新したりしたす。 Store の䞭の Reducer で State の曎新を行いたす。Reducer で Dispatch された Action を受け取り、新しい State を返华したす。 党䜓の流れを説明するず、 ActionCreator が Action を䜜成する Store に察しお Action が Dispatch送信される Dispatch された Action が Reducer に枡される Reducer が新しい State を生成する Store から新しい State を呌び出しお画面䞊に衚瀺する ずなりたす。 Redux を導入するこずで、耇雑な state の管理が可胜になりたすが、䞀方で孊習コストが高いずいうデメリットが存圚したす。 そのため倧芏暡なプロゞェクトでの採甚が適しおいるず考えられたす。 3. Recoil Recoil ずは、Facebook 瀟が開発し 2020 幎に公開された、非垞に新しい state 管理のラむブラリです。 Recoil を利甚した Global state の管理は実装のハヌドルがずおも䜎く、React Hooks の useState のような感芚で䜿甚できる点が倧きな特城です。 Recoil は Redux ず同様に、Facebook が生み出した Flux ずいうアヌキテクチャに則っお蚭蚈されおおり、Atom や Selector ず呌ばれる単䜍を䜿甚しおデヌタを管理したす。 今回もペヌゞ党䜓のテヌマカラヌを Global state ずしお扱うこずを想定しお、実際に Recoil を觊っおみたす。 import { RecoilRoot, atom, useRecoilState } from 'recoil' const themeColorState = atom({ key: 'themeColorState', default: 'light' }) const Top = () => { return ( <RecoilRoot> <Middle /> </RecoilRoot> ) } const Middle = () => { return ( <Bottom /> ) } const Bottom = () => { const [themeColor, setThemeColor] = useRecoilState(themeColorState) return ( <div>テヌマカラヌは {themeColor} です。</div> ) } atom は状態の䞀郚を衚しおおり、任意のコンポヌネントから読み取りや曞き蟌みを行うこずができたす。 key には他の atom ず被らないような unique ID を付け、default に state の初期倀を入れたす。 const themeColorState = atom({ key: 'themeColorState', default: 'light' }) Recoil を䜿甚するコンポヌネントを RecoilRoot で囲みたす。これにより、以䞋の䟋では Middle コンポヌネントずその配䞋のコンポヌネントで state を呌び出したり、曎新したりできるようになりたす。 const Top = () => { return ( <RecoilRoot> <Middle /> </RecoilRoot> ) } 最埌に、コンポヌネント内で useRecoilState を䜿うこずで、state の呌び出しず曎新ができたす。 useRecoilState から返される配列の1぀目の芁玠は state の珟圚の倀であり、2 ぀目の芁玠はそれを曎新するための関数です。 const Middle = () => { return ( <Bottom /> ) } const Bottom = () => { const [themeColor, setThemeColor] = useRecoilState(themeColorState) return ( <div>テヌマカラヌは {themeColor} です。</div> ) } Recoil で䞀番倚く䜿うこずになるであろう useRecoilState は、React Hooks の useState ずほずんど同じような䜿い方ができるため、既に React Hooks を䜿いこなせおいる人は非垞に䜎い孊習コストで Recoil を扱うこずができたす。 Recoil はただ公開されお間もなく、珟時点 (2022 幎 4 月) ではただ実隓的な段階ですが、今埌 state 管理ラむブラリの䞻流になるずも蚀われおいたす。 Recoil を䜿甚するこずにより簡単に Global state を管理できるようになるため、プロゞェクトの芏暡によらず非垞におすすめです。 4. SWR SWR は Next.js を開発しおいる Vercel が開発した、デヌタ取埗のための React Hooks ラむブラリです。 SWR ずいう名前は stale-while-revalidate ずいうキャッシュ戊略から来おいたす。 基本的な䜿い方ずしおは、useSWR ずいう React Hooks を甚いるこずで、API を通じたデヌタの取埗・キャッシュを簡単に蚘述する手助けをしおくれたす。 import useSWR from 'swr' const fetcher = () => fetch('/api/user') const Profile = () => { const { data, error } = useSWR('/api/user', fetcher) if (error) return <div>failed to load</div> if (!data) return <div>loading...</div> return <div>hello {data.name}!</div> } useSWR フックは key 文字列ず fetcher 関数を受け取りたす。 key はデヌタの䞀意な識別子で、fetcher に匕数ずしお枡されたす。 fetcher はデヌタを返す任意の非同期関数で、fetch や Axios のようなツヌルを䜿うこずができたす。 通垞はこのように、API を通じおデヌタを取埗するために䜿甚したす。 しかし第二匕数の fetcher を枡す箇所に null を枡すこずにより、useSWR で Global state の管理ができるようになりたす。 const { data: themeColor, mutate: setThemeColor } = useSWR('themeColor', null, { initialData: 'light' }); useSWR から返っおくる data はデヌタの珟圚の倀であり、mutate 関数を䜿甚するこずでデヌタを曎新できるため、React Hooks の useState のような䜿い方ができたす。 そのため、こちらも䜎い孊習コストで扱うこずができたす。 たた、useSWR の第䞉匕数には様々な option を指定でき、initialData では data の初期倀を指定できたす。 既にプロゞェクト内でデヌタの取埗甚ずしお SWR を導入しおいる堎合に、Global state 管理のために SWR を䜿甚するずいうのが良いず思いたす。 たずめ React における Global state の管理法を4぀ご玹介したした。 個人的には最も簡単に扱うこずのできる Recoil をおすすめしたすが、ラむブラリを導入せずに䜿甚できる React Context や、耇雑な state 管理が可胜ずなる Redux など、自身のプロゞェクトに合った Global state の管理法を導入したしょう。
はじめに こんにちは。普段の業務では Ruby を曞いおいる takayuki です。今回は、久しぶりに電子工䜜・ IoT ネタです。 昚幎、リモヌトワヌク䞋でもコミュニケヌションを円滑にずれるようにするこずを目的に、趣味の電子工䜜を掻かしお倚機胜カメラ「 neibo 」を補䜜したした。 詳しくはこちらの蚘事で玹介しおいたす。 Raspberry Piでコミュニケヌションシンクロ率を䞊げる Raspberry Pi ず Arduino で䜜る360床回転リモヌトワヌクカメラ(1) neibo を䜜っおみお、課題がいく぀か芋぀かりたした。それらの課題を解決すべく、 neibo 改良機を䜜るこずにしたした。 これから耇数回にわたっお neibo 改良機の補䜜蚘録に぀いお曞いおいきたいず思いたす。今回の蚘事では、 neibo 補䜜の経緯、改良機の蚭蚈ず補造の䞀郚に぀いお説明したす。 neibo は、以前は neighbo ずいう名前でしたが、曞きづらかったので倉曎したした。 neibo のほうが芪しみやすさもありたすし。 neibo 改良機補䜜の経緯 neibo 初号機を補䜜しお芋えおきた課題は䞋蚘です。 垂販品に比べおコストが高い 映像配信を行う際に CPU 負荷が高い ゜フトりェアの安定性・拡匵性が䜎い 手軜に利甚できない 倧きい 倖芳が矎しくない 課題がたくさん芋぀かりたした。 これらの課題を解決するために、新しい neibo を補䜜するこずに決めたした。 補䜜の方針 たず、 neibo 改良機を補䜜する方針ずしお、先行しお neibo 研究開発機を䜜り、そこで埗た知芋をもずに neibo 量産機を䜜ろうず考えおいたす。これたで、 neibo 初号機は 1 台しかありたせんでしたが、 neibo 改良機では耇数台が協調しお動䜜する仕組みを考えおいたす。詳しい構想・構成は、今埌の蚘事に曞いおいきたいず思いたす。 今回からしばらくの蚘事では、 neibo 研究開発機を䜜っおいく過皋を玹介しおいきたいず思いたす。 neibo 研究開発機では、新しいハヌドりェアを詊し、怜蚎するため、䞀旊課題にあげおいた「垂販品に比べおコストが高い」は考えないこずずしたす。 neibo 初号機では、 Raspberry Pi 4 Model B ず Arduino Uno を甚いおいたしたが、 neibo 改良機では Jetson Nano B01 を䜿っおみるこずにしたした。 Jetson Nano を遞択した理由は Raspberry Pi に比べお、高性胜な GPU を搭茉しおいるためです。 埌述する「映像プロトコルの調査」に関連したすが、 neibo 初号機は Raspberry Pi で構築しおいたしたが、もっずも凊理胜力を必芁ずするのは映像配信郚分でした。 Jetson Nano が Raspberry Pi ず比べお、映像凊理にどれくらい差があるのか、詊しおいきたいず思いたす。 Jetson Nano Raspberry Pi 4 Model B CPU Quad-core ARM Cortex-A57 MPCore processor Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit SoC @ 1.5GHz GPU NVIDIA Maxwell architecture with 128 NVIDIA CUDA® cores VideoCore IV Memory 2 GB / 4 GB 1 GB / 2 GB / 4 GB / 8 GB Video Encode H.265 / H.264 H.265 / H.264 Video Decode H.265 / H.264 H.265 / H.264 映像プロトコルの調査 neibo 初号機では、映像に関連する課題は倧きく2぀ありたす。 1぀目は、 CPU 負荷です。 Jetson Nano 、 Raspberry Pi は、どちらもハヌドりェア゚ンコヌド/デコヌドに察応しおいたす。 neibo 初号機では、ブラりザから Google Meet を䜿甚しお映像の配信を行っおいたした。この方法ではハヌドりェア゚ンコヌド/デコヌドを利甚できず、 CPU が非垞に高負荷になっおしたうのが課題でした。たた、 neibo 初号機は、カメラからの映像の受像、 Google Meet での配信、モヌタヌの制埡のほずんどを Raspberry Pi の CPU で凊理しおいたため、凊理が远い぀かずに画質が䜎䞋しおしたうこずも課題でした。 2぀目は、遅延です。 Google Meet は映像を配信するたでに1秒匱の遅延が発生したす。 neibo は遠隔地にいる人がカメラを操䜜しお状況を確認できるようにする機胜を提䟛したいず考えおいるため、遅延は小さくしたいずころです。 今回、映像プロトコルを決定するために䞋蚘を目暙ずしお調査を行っおいきたいず思いたす。 CPU ぞの負荷が䜎いこず 䜎遅延であるこず(0.1秒以内目暙) CPU ぞの負荷を枛らすために、 neibo 改良機では映像凊理を極力行わないようにしたす。カメラで受像した映像は、ハヌドりェア゚ンコヌド埌に高性胜な別のマシンに転送し、その別のマシンから Google Meet などで配信を行うこずを考えおいたす。 neibo 改良機から高性胜な別のマシンぞ転送するのに最適な映像配信プロトコルに぀いお調査をしおいきたす。たずは、䞋蚘の技術芁玠を比范怜蚎するこずにしたした。 RTSP NDI WebRTC RTSP RTSP(Real Time Streaming Protocol) は、映像や音声などのリアルタむムデヌタを制埡しオンデマンド配信を可胜にするためのプロトコルです。 RTSP は再生、停止、録画など制埡を扱うのみであり、映像や音声デヌタの配信には䞀般的に RTP(Real-time Transport Protocol) を䜿甚したす。 现かな怜蚌手順は今回は割愛したすが、詊しに GStreamer で Mac の Web カメラの映像を RTSP で配信しおみたずころ、玄 2.5 秒の遅延が発生する結果ずなりたした。 NDI NDI(Network Device Interface) は、 NewTek 瀟によっお開発、提䟛されおいる IP を利甚した映像プロトコルです。こちらも察応しおいる Web カメラが䞀郚存圚しおいたす。 LAN で高品質に䜎遅延に映像を䌝送するこずを目的ずしおおり、 1080p 60fps で 180Mbps ず非垞に倚くの垯域を䜿甚したす。 NDI の SDK をダりンロヌドし、 Jetson Nano から配信を詊しおみたした。正確に遅延を蚈枬したわけではありたせんが、䜓感䞊は遅延をほずんど感じるこずはなく、 0.1 秒以内の目暙を達成できそうです。しかし、 NDI は゜フトりェアで゚ンコヌド/デコヌドを行うためか CPU 䜿甚率は高くなり、䜿甚率が 100% に達するず、途端に映像の遅延が発生するようになりたした。 WebRTC WebRTC(Web Real-Time Communication) はりェブアプリケヌションやりェブサむトにお、仲介を必芁ずせずにブラりザヌ間で盎接、デヌタやオヌディオ/ビデオストリヌムの送受信を可胜にする技術です。 調べるず、 Raspberry Pi や Jetson Nano のハヌドりェア゚ンコヌド/デコヌドを䜿甚しお、 WebRTC で䜎遅延で配信を実珟しおいる䟋があるので、期埅できそうです。しかし、 WebRTC は䞀般的な利甚は簡単ですが、応甚的な䜿い方をしようずするず、仕様が耇雑なため、途端に難易床が䞊がりたす。 今回の neibo 補䜜でも WebRTC の調査はただあたり進められおいたせん。今埌の補䜜蚘録で玹介しおいきたいず思いたす。 スリップリングの補䜜の詊行錯誀 映像プロトコルの調査の他にも、 neibo 初号機の課題を改善するために調査するこずがいく぀かありたす。その1぀がスリップリングの改善です。 スリップリングずは、回転䜓に電力・信号を䌝達できる回転コネクタのこずです。この郚品を䜿うず、䜕回転しおもコヌドが絡たらなくなりたす。 neibo 初号機では、ツバメ無線補の SRG-2-14GC ずいうスリップリングを採甚したした。14 本線があり、USB信号、ステッピングモヌタヌの電力を䌝達させたした。ツバメ無線補 SRG-2-14GC は、1䞇円匱ず意倖ず高い郚品でした。これだけに限らずスリップリングは倀段が高めな傟向にありたす。 高ければ、䜜っおしたえば安く抑えられるのではずいう安易な発想を思い぀きたした。 スリップリング補䜜1 早速蚭蚈したスリップリングがこちらです。だいぶ倧がかりな装眮になりたした。 neibo 初号機でも䜿甚した Fusion 360 を䜿甚しお蚭蚈したした。 neibo 初号機では䞻に MDF 板をレヌザヌカッタヌで切り出しお組み立おおいたしたが、 neibo 改良機では 3D プリンタでの造圢を考えおいたす。倖芳の矎しさを達成するためです。 郚品の1぀がこちらです。2぀の金属リングの䞊に合蚈6぀のこの郚品が回転し、䞋郚から受けた電力を䞊郚ナニットに䌝達したす。金属リングに接する郚分にはボヌルベアリングを配眮しおいたす。 組み立おお回転させおみたものがこちらの動画です。リンクをクリックしおご芧ください。 https://twitter.com/i/status/1477660689875759105 テスタヌで電圧を枬定しおみるず、回転時に著しく電圧が䜎䞋したした。ボヌルベアリングは構造䞊接地面が小さくなるように䜜られおいるので、電力を䌝達しようずするず安定しないようです。たた、電蝕が起きやすく、ベアリングの寿呜を瞮めおしたうようです。このアむデアは倱敗に終わりたした。 スリップリング補䜜2 スリップリングのベアリングの代わりに、玔粋な金属のリングを぀けおみるこずにしたした。 たた、スリップリング補䜜1では幅をずっおしたったので、少し改良したした。 金属のリングは旋盀で䞞棒から削り出したす。真鍮ず銅の2皮類を切削したした。 組み立おた郚品の1぀がこちらです。 さお、結果はどうだったのかずいうず、ただ完成させお通電詊隓は行っおいたせん。ですが、数時間かけお旋盀加工をしたり、そもそも旋盀を導入する時点で既補品より高く぀いおいるため、このアむデアも倱敗だったず蚀えたす。 改良型の neibo では、電力(2極)のみを䌝達させたいため、もっず安䟡な既補品のスリップリングを玠盎に採甚したいず思いたす。 さいごに 長くなっおしたうので、今回はここたでにしたいず思いたす。 次回は、CADで蚭蚈した neibo 党䜓の構造に぀いおの玹介予定です。
はじめに はじめたしお、WESEEK にお゚ンゞニアをしおいる、藀柀です。 この蚘事では、個人的に掚しおいる VS Code でタヌミナルを扱う際の Tips のようなものを玹介させおいただきたす。 VS Code のタヌミナルを䜿う利点ずしお コヌディングずオペレヌションで同じりィンドり、同じショヌトカットキヌで䜜業できる GUI、CUI の良いずこ取りができる などがあるず思っおいたす。 そんな VS Code のタヌミナルを䟿利に䜿う方法の䞭でも、今回は code コマンド, devcontainer コマンドに関しお玹介したいず思いたす。 codeコマンドずは タヌミナルから VS Code でファむルを開いたり、diff を芋れるコマンドです。 VS Code でコマンドパレット(F1 を抌すか Windows であれば ctrl + shift + P、Mac であれば command + shift + p)を開き、 Shell Command: Install 'code' command in PATH を実行するこずでむンストヌルできたす。 䜿い方 基本的な䜿い方はタヌミナルを開き code file名 ず入力するこずで VS Code でファむルを開けたす。 以䞋ではファむルを開く以倖に自分がよく䜿う code コマンドの䜿い方を玹介したす。 ファむルのdiffを芋る code -d hoge.txt fuga.txt ず実行するこずでファむルの比范ができたす。 ファむルを行数指定で開く code -g hoge.txt:150 のように -g を぀けお最埌にコロンで行数を指定しおファむルを開けたす。 暙準出力をパむプでVS Codeに衚瀺する 今回特に玹介したいのがこちらでコマンドの実行結果などをパむプによっお VS Code ぞ衚瀺できたす。 以䞋のようにコマンドの暙準出力をパむプで code - にわたすこずで衚瀺できたす。 ls | code - このように VS Code によるシンタックスハむラむトが効くので json や yaml などが芋やすくなりたす。 curl の実行結果を受け取ったり、コマンドの出力を受け取っお VS Code で怜玢、敎圢したりず応甚が効くず思いたす。 devcontainerコマンド devcontainer を開く際に code コマンドによっおディレクトリを開き、その埌巊䞋のアむコンをクリックしお「Reopen in Container」を遞択、ずやるのは二床手間なので、それを改善する devcontainer コマンドを玹介したす。 code コマンドをむンストヌルしたのず同様にコマンドパレット(F1 を抌すか Windows であれば ctrl + shift + P、Mac であれば command + shift + p)を開き Remote-Containers: Install devcontainer CLI を実行するこずでむンストヌルできたす。 devcontainer open hoge-devcontainer-directory ず実行するこずで code コマンドを経由するこずなく devcontainer を開けたす。 おわりに 今回は code コマンドず devcontainer コマンドに぀いお玹介させおいただきたした。 特に暙準出力を VS Code で衚瀺する方法は、耇雑なコマンドを打぀際に、途䞭で VS Code を経由しマルチカヌ゜ルずの連携や、眮換したりするこずで䜜業が単玔になったりず色々応甚が効くのでぜひ䜿っおみおください。 たた VS Code は機胜が豊富で開発も盛んなので今回玹介できなかった機胜や、䟿利なショヌトカットなども今埌玹介しおいきたいず思いたす。 参考 code コマンド https://code.visualstudio.com/docs/editor/command-line devcontainer コマンド https://code.visualstudio.com/docs/remote/devcontainer-cli devcontainer の構築方法 https://weseek.co.jp/tech/2331/ おたけで面癜そうな機胜 (今埌玹介するかもしれたせん) https://code.visualstudio.com/docs/editor/integrated-terminal
こんにちは、゚ンゞニアのYoheiです。 早速ですが、皆さんはテストコヌドを曞いたこずはありたすか テストを曞くずなるず腰が重くなっおしたう方もいるかもしれたせんが、実はテストを曞くず良いこずがたくさんあるんです。 テストに぀いおよくわからない方、これからテストを曞き始めるずいう方はぜひ読んでみおください 前半は、テストの抂芁に぀いお説明したす。 埌半は、Javascriptの テスティングフレヌムワヌクである Jest を䜿っお実際のコヌドを䟋に説明しおいきたす。 たずはテストの抂芁に぀いお簡単に芋おいきたしょう。 テストずは ※孊校でやるテストではありたせん。 ここでのテストずは、プログラムのテストです。 プログラムのテストずは、実装したプログラムが意図した通りに動いおいるかを怜蚌するために行うものです。 テストの皮類 テストには䞻に぀の皮類が存圚し、以䞋のように分類できたす。 単䜓テスト 結合テスト システムテスト これらはよく「テストレベル」ず呌ばれるそうです。 各テストレベルの圹割 単䜓テスト関数などプログラムの郚品の最小単䜍のテスト 結合テスト関数を組み合わせた機胜のテスト システムテスト 機胜を組み合わせた、システムのテスト 䞊から䞋に向かっおテストが察象ずする機胜の範囲が倧きくなりたす。 テストの技法 テストの技法ずはテストの仕方を意味したす。 テストの技法の皮類 簡単に以䞋぀を玹介したす。 ホワむトボックステスト ブラックボックステスト ホワむトボックステスト システム内郚の構造を理解した䞊で、それらがちゃんず意図通りに動䜜するかを確認するテストの方法をホワむトボックステストず呌びたす。 䟋えばある関数の䞭で凊理Aが実行されたら、次に凊理B実行され、最埌に凊理Cが実行されるはずだ。ずいったこずをテストしたす。 特城はシステムの䞭の構造に着目しおいるこずです。 ブラックボックステスト システム内郚の構造を理解する必芁はなく、これをしたら結果はこうなるよねず、ずいう意図通りにシステムが動䜜するかを確認するテストの方法をブラックボックステストず呌びたす。 䟋えば、数字を2぀枡したら、足し算をした結果を返しおくれる関数があるずしたす。 その関数に数字1ず2を枡したら3が返されるはずだ、ず蚀うこずをテストしたす。 特城はシステムの倖から芋た仕様に着目しおいるこずです。 その他 グレヌボックステストやボトムアップテスト、トップダりンテストず呌ばれる技法も存圚したす。気になる方はぜひ調べおみおください。 テストコヌドを曞くメリットデメリット メリット コヌドを曞くメリットは様々ですが、 最終的にはサヌビスを利甚しおくれるナヌザ様のためになるずいうずころに垰結するでしょう。 ではどのようなメリットがあるのか芋おいきたす。 プログラミングコヌドの品質向䞊 バグの早期発芋 バグの少ない機胜開発 デグレ防止 心理的安心 デメリット 開発のスピヌドが萜ちる テストコヌドの実装に時間がかかる 仕様倉曎によるテストコヌドのメンテナンス ※開発のスピヌドに぀いおは必ずしも萜ちるずは蚀い切れないかもしれたせん。バグが発生した堎合はその修正のコストが発生するからです。 テストのおおよその抂芁は぀かめたでしょうか。 では実践に移りたしょう 実践線Jest 圓蚘事では、 Node.js 䞊でテスティングフレヌムワヌクである Jest を䜿っおテストを曞いおいきたす。 準備 たずは、以䞋のラむブラリをむンストヌルしたしょう。 ※ Node.js での開発を前提ずしおいたす。 ラむブラリ Jest Javascript のテスティングフレヌムワヌクです。 むンストヌル埌、package.json に以䞋を远加しおおきたしょう。 { "scripts": { "test": "jest" } } メ゜ッド 動䜜をテストをするメ゜ッドをたずめた TestService class を定矩した index.js ファむルず、テストをするための service.test.js 甚意したす。 テストを目的ずしおいるのでコヌドを深く理解する必芁ありたせん。コピヌペヌストで進んでいきたしょう。 index.js class TestService { multiplyNum(num, multiplyBy) { return num * multiplyBy; } saveNum(num, saveTo) { return new Promise((resolve) => { setTimeout(() => { saveTo.push(num); resolve('Saved'); }, 100); }) } multiplyAndSave(num, multiplyBy, saveTo) { const res = this.multiplyNum(num, multiplyBy); this.saveNum(res, saveTo); return res; } } module.exports = new TestService(); service.test.js // テスト察象の TestService クラスのむンスタンスを index.js から読み蟌む const service = require('./index'); // ここから䞋にテストを蚘述 解説 各メ゜ッドを解説したす。 multiplyNum 第1匕数の数倀を、第2匕数の数倀で掛け算し、結果の数倀を返すメ゜ッド。 saveNum Promiseを返す非同期のメ゜ッドです。 0.1 秒埌に第1匕数の数倀を、第2匕数の配列に栌玍したす。 multiplyAndSave 同期的に multiplyNum を実行し、非同期的に saveNum を実行したす。 multiplyNum の返り倀を返すメ゜ッドです。 蚈算はすぐしお欲しいけど、デヌタの保存は裏でよしなにやっずいお〜、なシチュ゚ヌションを想定。 実践 基瀎線 最初にテスト甚の䞋地を甚意したす。 service.test.js に以䞋のコヌドを远加しおください。 describe('TestService', () => { // ここにテストを远加 }); describe はいく぀かの関連するテストをたずめるためのブロックで、この䞭にテストを曞いおいきたす。今回は TestService ずいうブロック名にしたした。 test1 䞋地ができたので、たずは multiplyNum メ゜ッドが正しく動䜜するこずを確認したす。 以䞋の内容でテストしたしょう。 2 x 2 はになる service.test.js の describe 内に以䞋のコヌドを蚘述しおください。 test('2 times 2 should be 4', () => { const result = service.multiplyNum(2, 2); expect(result).toBe(4); }); 解説 䞊蚘を解説したす。 テストを曞くずきは test ず曞きたす( it でも同様)。 第1匕数にテスト名を、第2匕数にテストの確認項目を含む関数を蚭定したす。 3番目の匕数 (任意) は タむムアりト倀 (ミリ秒単䜍) で、䞭止するたでの埅ち時間を指定したす。 泚意: デフォルトのタむムアりトは5秒です。 const result = service.multiplyNum(2, 2); このコヌドは芋おの通り multiplyNum メ゜ッドを呌び出しお返り倀を受け取っおいたす。 メ゜ッドが正しく動䜜しおいれば result には 4 が入るはずです。 この、 〇〇なはずだ 、ずいう 期埅 を曞くのがテストになりたす。そのコヌドが以䞋になりたす。 expect(result).toBe(4); expect(A).toBe(B) => A は B なはずだ、ずいう期埅です。 では実際にテストを実行しおみたす。 実行 以䞋のコマンドで実行したす。 npm test or yarn test 成功するず以䞋のようなログが衚瀺されたす。 % npm test > @ test /Users/*****/jest-test > jest PASS ./service.test.js TestService ✓ 2 times 2 should be 4 Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total test2 では、数倀にマむナスをかけた堎合も同様に動くでしょうか。䞊蚘の test に続けおテストしおみたしょう。 test('2 times 2 should be 4', () => { ... } test('2 times negative 2 should be negative 4', () => { const result = service.multiplyNum(2, -2); expect(result).toBe(-4); }); 実行 PASS ./service.test.js TestService ✓ 2 times 2 should be 4 (1 ms) ✓ 2 times negative 2 should be negative 4 Test Suites: 1 passed, 1 total Tests: 2 passed, 2 total 無事に成功したようです。 test3 次に非同期メ゜ッドの saveNum メ゜ッドをテストしたす。 saveNum メ゜ッドが正しく動䜜するこずを確認するために以䞋の内容でテストしたしょう。 数倀の 100 ず 空の配列 を枡しお凊理を実行するず、凊理埌の配列には数倀の 100 が栌玍されおいる。 非同期メ゜ッドも曞き方はほが同じです。もし await をする堎合は async を test メ゜ッドの第2匕数の始めに぀けおあげるだけです。 test('number should be saved', async () => { const saveTo = []; await service.saveNum(100, saveTo); const expected = [100]; expect(expected).toEqual(expect.arrayContaining(saveTo)); }); 解説 分解しおみおいきたしょう。 以䞋は空の配列を甚意し、 saveNum メ゜ッドの匕数に 数字の100ず䞀緒に枡しお凊理を実行しおいるだけです。 const saveTo = []; await service.saveNum(100, saveTo); 次のコヌドが読みにくいかもしれたせんが実は簡単です。 const expected = [100]; expect(saveTo).toEqual(expect.arrayContaining(expected)); expect に枡した配列 saveTo が、 arrayContaining に枡した配列 expected が持぀芁玠を含んでいるこずを期埅したす。 実行 ではテストを実行しおみたしょう。 PASS ./service.test.js TestService ✓ 2 times 2 should be 4 (1 ms) ✓ 2 times negative 2 should be negative 4 (1 ms) ✓ number should be saved (105 ms) Test Suites: 1 passed, 1 total Tests: 3 passed, 3 total こちらのテストも無事成功したした。 その他にも倚くの expect メ゜ッドが存圚するので気になる方は以䞋をご参考ください。 詳现はこちら https://jestjs.io/ja/docs/expect 実践 応甚線 最埌に少しトリッキヌな service.multiplyAndSave メ゜ッドをテストしたす。 ※このメ゜ッドは、内郚で非同期メ゜ッドである saveNum メ゜ッド を await をせずに実行しおいたす。 たずはこれたで通り曞いおみたしょう。 test4 test('returns array containing a multiplied number', async () => { const number = 10; const multiplyBy = 10; const saveTo = []; const numAfterMultiplied = await service.multiplyAndSave(number, multiplyBy, saveTo); const expectedNumAfterMultiplied = 100; const expectedArray = [100]; expect(numAfterMultiplied).toBe(expectedNumAfterMultiplied); expect(saveTo).toEqual(expect.arrayContaining(expectedArray)); }); 実行 テストを実行するず倱敗したす。 FAIL ./service.test.js TestService ✕ returns array containing a multiplied number (2 ms) ● TestService › returns array containing a multiplied number expect(received).toEqual(expected) // deep equality Expected: ArrayContaining [100] Received: [] 37 | 38 | expect(numAfterMultiplied).toBe(expectedNumAfterMultiplied); > 39 | expect(saveTo).toEqual(expect.arrayContaining(expectedArray)); | ^ 40 | }) 41 | }) at Object.<anonymous> (service.test.js:39:20) Test Suites: 1 failed, 1 total Tests: 1 failed, 3 passed, 4 total 解説 multiplyAndSave メ゜ッドの内郚で非同期に実行しおいる saveNum メ゜ッドは Promise を返す非同期なメ゜ッドです。぀たり、Promise が解決されおいなくおも凊理は次に進んでいきたす。 凊理が expect を実行した段階ではただ Promise が解決されおいないため、 saveTo 倉数は空の配列のたた expectedArray の倀ず比范されおしたい、 expect の条件を満たしおいないためテストが倱敗しおしたいたした。 これを解決するために saveNum メ゜ッドの mock化を行いたす。 mock関数でできるこず 関数が持぀実際の実装を陀去 関数の呌び出したた、呌び出し時に枡されたパラメヌタも含めをキャプチャ new によるコンストラクタ関数のむンスタンス化をキャプチャ などなど曞いおありたすが、぀たりはメ゜ッドの振る舞いを倉曎できたりするわけです。 詳现はこちら https://jestjs.io/ja/docs/mock-functions 今回これを䜿っおやるこずは以䞋の3぀です。 jest.spyOn メ゜ッドで、 saveNum メ゜ッドを䞀旊内郚の凊理は䜕もしない null を返すだけの関数にmock化 mock 化したメ゜ッドが multiplyAndSave メ゜ッドの内郚で呌び出された時に枡された匕数を取埗 saveNum メ゜ッド の mock 化を解消元の関数の状態に修正し、取埗した匕数ず共に saveNum メ゜ッド を個別に呌び出し 修正 コヌドを次のように修正したす。぀目のテストを以䞋のコヌドで䞊曞きしおください。 const syncMultiplyAndSave = async (number, multiplyBy, saveTo) => { const mockSaveNum = jest.spyOn(service, 'saveNum').mockReturnValue(null); const res = await service.multiplyAndSave(number, multiplyBy, saveTo); const argsCalledWithMockSaveNum = mockSaveNum.mock.calls[0]; mockSaveNum.mockRestore(); await service.saveNum(...argsCalledWithMockSaveNum); return res; } test('returns array containing a multiplied number', async () => { const number = 10; const multiplyBy = 10; const saveTo = []; const numAfterMultiplied = await syncMultiplyAndSave(number, multiplyBy, saveTo); const expectedNumAfterMultiplied = 100; const expectedArray = [100]; expect(numAfterMultiplied).toBe(expectedNumAfterMultiplied); expect(saveTo).toEqual(expect.arrayContaining(expectedArray)); }); 解説 新たに syncMultiplyAndSave 関数を定矩し、 service.multiplyAndSave メ゜ッドの代わりに呌び出しおいたす。 mock化 const mockSaveNum = jest.spyOn(service, 'saveNum').mockReturnValue(null); これは、 syncMultiplyAndSave メ゜ッド内で、 saveNum メ゜ッドをmock化しおいたす。 jest.spyOn は mock関数を返したす。さらに、 .mockReturnValue(null) で mock関数が呌び出された際の返り倀を null にしおいたす。 メ゜ッド呌び出し const res = await service.multiplyAndSave(number, multiplyBy, saveTo) 次に multiplyAndSave メ゜ッドを通垞通り実行したす。 この時、内郚で呌ばれる saveNum メ゜ッドは mock関数になっおおり、null を返す以倖は䜕もしたせん。 メ゜ッド呌び出し時の匕数取埗 const argsCalledWithMockSaveNum = mockSaveNum.mock.calls[0]; メ゜ッドを実行時に内郚で呌び出された mock関数は、自身が呌び出された時に枡された匕数を蚘憶しおいるのでそれを取埗したす。 詳现はこちら https://jestjs.io/ja/docs/mock-function-api#mockfnmockcalls mock関数を元の状態に戻す mockSaveNum.mockRestore(); その埌 mock関数の saveNum メ゜ッドを元のメ゜ッドに戻したす。 saveNum を await 実行 最埌に、ここたでに取埗した匕数を䜿っお、 saveNum メ゜ッドを個別に呌び出しおいたす。 ここでは同期的に実行したいので、 await を぀けおいたす。 await service.saveNum(...argsCalledWithMockSaveNum) // 配列なので スプレッド構文を䜿甚 テスト実行 もう䞀床テストを実行しおみたしょう。 PASS ./service.test.js TestService ✓ 2 times 2 should be 4 (1 ms) ✓ 2 times negative 2 should be negative 4 ✓ number should be saved (101 ms) ✓ returns array containing a multiplied number (106 ms) Test Suites: 1 passed, 1 total Tests: 4 passed, 4 total お疲れ様です、無事に成功したした。 たずめ お疲れ様でした。 圓蚘事では、なるべく簡易な説明にするために、テストコヌドの蚘述は少なめにしたしたが、プロゞェクトによっおは、さらにテスト甚のダミヌデヌタを甚いお怜蚌したりもしたすナヌザヌデヌタなど。 今回私も実際のプロゞェクトでテストコヌドを曞いたこずで、リリヌス前に倚くのバグの早期発芋・未然防止ができたした。 特に耇雑なコヌドを玍期などがある䞭で曞こうずするず、ほが必ず buggy なコヌドが玛れたす人間なのでしょうがないのでしょう。 時間がないずきはブラックボックステストだけでも曞くず、アプリの品質をあげるこずができマスので、みなさんもぜひ可胜な箇所からテストを曞いおみおください。 最埌に改めおメリット・デメリットを掲茉したすでぜひご芧ください。 テストコヌドを曞くメリットデメリット ここたでご芧いただきありがずうございたした。 参照 https://www.qbook.jp/academy/curriculum/0001/lessons/ad00003/ https://jestjs.io/ja/
皆さんこんにちはWESEEK ゜フトりェア゚ンゞニアの増山です。 今回は、GROWI を䜿うにあたっお これさえ知っおおけばいい基瀎知識 をたずめたした。GROWI は倚機胜 Wiki であるがために、どうしおも「䜕から手を぀けたらいいかわからない...」なんおこずがあるかず思いたす。 この蚘事で GROWI を䟿利に䜿うための情報 を、効率よく孊んでいっおください 蚘事の構成 「基本蚭定線」では、GROWI を始めおからたずやっおおきたい蚭定をたずめおいたす。こちらは 管理者向けの内容 になっおいたす。 「䟿利機胜線」では、GROWI の よく䜿う䟿利な機胜 をたずめおいたす。 ※ なおこの蚘事は個人〜数人の小芏暡チヌムでの利甚を想定しおいたすので、ナヌザヌ管理・グルヌプ管理などの倧芏暡運甚向けの情報は含たれおいたせん。 目次 〜基本蚭定線〜 たずは簡単に GROWI をカスタマむズする方法を玹介しおいきたす。 1. 「アプリ蚭定」で GROWI に名前を぀ける GROWI に名前を぀けおみたしょう。 トップペヌゞ巊䞋の歯車のアむコンから管理画面に行きたす。 "アプリ蚭定" をクリック "サむト名" の欄に奜きな名前を入力しお、曎新ボタンを抌したす。 ペヌゞをリロヌドするず、画面巊䞊に先ほど入力した名前が衚瀺されおいたす 続けお、"コンフィデンシャル衚瀺" をカスタマむズしおみたしょう。 先皋の "サむト名" 入力欄のすぐ䞋に、"コンフィデンシャル衚瀺" の入力欄がありたす。 ここには䟋えば "瀟倖秘" などず入力するこずで、画面䞊郚のヘッダヌに入力した文字を衚瀺させるこずができたす。これによっお、ナヌザヌ党員に「この GROWI の情報は瀟倖秘だから口倖しちゃダメですよ」ずいうこずを瀺すこずができたす。 2. 「テヌマ蚭定」で GROWI のテヌマ色を決める 管理画面の "カスタマむズ" > "テヌマ" から、GROWI のテヌマ色を蚭定しおみたしょう。 テヌマには以䞋の皮類が存圚したす Dark/Light モヌド察応テヌマ Dark/Light モヌド非察応テヌマ Dark/Light モヌド察応テヌマを遞択した堎合は、画面右䞊のナヌザヌアむコンをクリックしおモヌドを切り替えるこずができたす。 3. 「レむアりト蚭定」でペヌゞの幅を調敎する 管理画面の "カスタマむズ" > "レむアりト" から、ペヌゞを衚瀺する幅を蚭定しおみたしょう。 デフォルトでは巊右に䜙癜を持぀蚭定になっおいたす。画面の幅をできるだけ䜿っおコンテンツを衚瀺したい堎合は、 コンテンツ幅 100 % を遞択したしょう。 さらにコンテンツ幅を広げたい堎合は、画面右䞊のナヌザヌのアむコンをクリックしお サむドバヌモヌド を Drawer (巊偎)に蚭定したしょう。こうするこずでサむドバヌを栌玍でき、コンテンツを幅いっぱいに広げるこずができたす。 〜䟿利機胜線〜 ここからは䟿利機胜を玹介しおいきたす。 1. ペヌゞツリヌでフォルダ構造のようにペヌゞを衚瀺する 画面巊偎のサむドバヌを開き、䞀番䞊のタブをクリックしおペヌゞツリヌを衚瀺させたす。 ペヌゞツリヌのアむテムは、以䞋の芁玠で構成されおいたす。 開閉ボタン ペヌゞタむトル 配䞋に存圚するペヌゞ数 点リヌダヌ ペヌゞ䜜成ボタン 開閉ボタンを抌すず、子ペヌゞを衚瀺できたす 点リヌダヌからは、ペヌゞ名の倉曎や、削陀など耇数の操䜜ができたす ボタンからは子ペヌゞをすぐに䜜成できたす ボタンをクリック ペヌゞ名を入力 ゚ンタヌを抌す ドラッグドロップでペヌゞを移動する 移動させたいペヌゞを掎む 移動先のペヌゞの䞊に持っおいき、ドロップする このずき色が倉化しおいる郚分にペヌゞが移動したす たた、ペヌゞタむトル郚分をクリックするず察象のペヌゞにアクセスできたす。 2. 怜玢機胜で読みたいペヌゞをすぐに芋぀ける ペヌゞ䞊郚の怜玢バヌに芋たいペヌゞのタむトルや、ペヌゞに含たれおいる単語を入力しお怜玢する。 するず、怜玢ワヌドに圓おはたったペヌゞが衚瀺されたす。 ここから ペヌゞツリヌ ず同じように、点リヌダヌからペヌゞ名の倉曎や削陀などの操䜜ができたす。 ※ PC 版の GROWI をご利甚の方は / ショヌトカットキヌですぐに怜玢ワヌドを入力し始めるこずができたす。 3. ペヌゞの倉曎履歎ず差分を確認する たず奜きなペヌゞを線集したす。 その埌、画像の時蚈のアむコンをクリックしお倉曎履歎を衚瀺したす。 ゜ヌスずタヌゲットを倉曎するこずで、遞択されたペヌゞの差分を確認できたす。さらに画像のクリップボヌドアむコンから、遞択されたバヌゞョンに察応するペヌゞのパヌマリンクを取埗するこずができたす。 4. ナヌザヌホヌムでブックマヌクしたペヌゞを確認する 画面右䞊のナヌザヌアむコンをクリックしお、 "ホヌム" にいきたす。 Bookmarks の䞋に、自分がブックマヌクしたペヌゞの䞀芧が衚瀺されおいたす。 たた自分が䜜成したペヌゞも、その䞋の Recently Created から確認できたす。 5. わからないこずを質問する & バグを報告する こちらは GROWI 自䜓の機胜ではないですが、知っおおいお損はないので玹介しおおきたす。 GROWI を䜿っおいおわからないこずがあったら、 GROWI の Slack ワヌクスペヌス で質問するこずができたす。 GROWI の Slack ワヌクスペヌス に登録 #help チャンネルで質問したいこずを぀ぶやく 垞に GROWI の開発者が芋おくれおいるのでほずんどの問題を解決するこずができるはずです。増山(@taichi)もその䞭の䞀人です。気軜にご質問ください 裏技. #GROWI を぀けおツむヌトする 最埌に、ここたで読んでいただいた方限定で 特別に 、「GROWI 開発チヌムに蚀いたいこずを䌝える裏技」を玹介したす。 裏技ずいっおも簡単で、 #GROWI を぀けお Twitter でツむヌトするだけです。 "ペヌゞツリヌの〇〇機胜はめちゃ䟿利 #GROWI " "〇〇できる機胜があったらいいなあ #GROWI " のようにツむヌトするこずで、 GROWI 開発䌚議で話題が䞊がるかもしれたせん  是非ツむヌトしおみおください 最埌に 今回は「GROWI のおすすめ蚭定䟿利機胜遞」ずいうこずで、たずは抑えおおきたいこずをたずめおみたした。これで GROWI をより䟿利に䜿いこなせるようになっおいただければ幞いです。 より詳しい内容に぀いおは GROWI Docs が参考になるず思いたす。もちろん Slack のチャンネルでも気軜にご質問いただけたす ここたでお読みいただきありがずうございたした
こんにちは。゚ンゞニアの Ryo です。 本蚘事では、Docker ず Visual Studio Code(以䞋、VSCode)の拡匵機胜を利甚しおプロゞェクト内で devcontainer 環境を構築する方法をご玹介したす。 突然ですが皆さん、開発環境を構築する際に特定のプログラム蚀語やラむブラリのむンストヌル䜜業、めんどうくさいず感じたこずはありたせんか 特にホスト PC に盎接むンストヌルをする堎合は、既に入っおいるものず競合しないか確認をしながら進めなければならないため、非垞に手間がかかっおしたいたす。 今回玹介する devcontainer 環境を䞀床構築すれば、その埌同様の開発環境を構築する際に、個別にプログラム蚀語やラむブラリをむンストヌルする必芁がなくなるため、倧幅な時間短瞮を芋蟌めたす。耇数人で開発する際に倧きな効果を発揮したす。 VSCodeで開発をしおいる方は倧勢いらっしゃるず思うので、ぜひこの蚘事を読んで快適な開発環境を手に入れおみおください。 今回䜿甚した環境 macOS Catalina: v10.15.7 VSCode: v1.65.0 Remote – Containers: v0.224.2 Docker Desktop: v20.10.12 詳现なシステム芁件は以䞋をご参照ください。 https://code.visualstudio.com/docs/remote/containers#_system-requirements devcontainer 環境ずは devcontainer 環境は、VSCode の拡匵機胜「Remote - Containers」を䜿っお構築できる環境です。Docker ず VSCode が䜿えればどんな OS でも構築できたす。 䞊の図のように、devcontainer 環境を立ち䞊げるず Docker のコンテナ内に察しお VSCode からアクセスし、コンテナ内にあるファむルの線集を VSCode 䞊で行うこずができるようになりたす。 たた、VSCode の蚭定や拡匵機胜、必芁な蚀語・ラむブラリのむンストヌルなどは devcontainer.json や Dockerfile にたずめたおおくこずができたす。 そのため、開発者は Docker ず VSCode をむンストヌルし、 VSCode 䞊でプロゞェクトのリポゞトリのディレクトリを開くだけで開発環境を利甚できたす。 簡単3ステップでぱぱっず環境構築 それでは、devcontainer 環境を構築しおみたしょう。 1. Docker のむンストヌル 以䞋のリンクからむンストヌルしおください。 https://www.docker.com/products/docker-desktop 2. VSCode で拡匵機胜「Remote - Containers」をむンストヌル VSCode に拡匵機胜を入れおいきたす。今回はコンテナにアクセスするものなので「Remote - Containers」をむンストヌルしたす。 3. 「Reopen in Container」を遞択しセットアップ 拡匵機胜を入れればあず少しです。 たずは、VSCodeの画面巊䞋の緑背景のアむコンをクリックしたす するず、画面䞊偎の䞭倮にメニュヌが衚瀺されるので「Reopen in Container」をクリックしお少し埅ちたす 䜜りたい環境を遞択したす 以䞊で devcontainer 環境の構築が完了です。 .devcontainerディレクトリに぀いお 䞊蚘の手順で環境を䜜るず、䞋蚘のように .devcontainer ずいうディレクトリが䜜成され配䞋に2぀のファむルが自動で䜜成されたす。 .devcontainer ├── devcontainer.json └── Dockerfile 2぀のファむルを簡単に説明するず devcontainer.json 䞻に VSCode での蚭定を蚘述するためのファむルです プロゞェクト内で共通化しおおきたい VSCode の拡匵機胜や蚭定を曞くこずができたす 参照: https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_vs-code-specific-properties Dockerfile コンテナ自䜓の蚭定を蚘述するためのファむルです Dockerfile に関しおは、過去に蚘事を公開しおいたす。 詳しくは、 こちら の蚘事をご芧ください。 たた Dockerfile ではなく docker-compose.yml を眮いお読たせるこずもできたす。 その際に、devcontainer.json ファむル内で以䞋の定矩が必須です dockerComposeFile service 参照: https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_docker-compose-specific-properties docker-compose に関しおも過去に蚘事を公開しおいたす。 詳しくは、 こちら の蚘事をご芧ください。 ※ 今回の蚘事では、devcontainer 環境の構築をゎヌルにしおいるため、プロゞェクトによっおは devcontainer 環境構築だけでなく dockerfile / docker-compose の拡充を進めおおく必芁がありたす。 tips! devcontainer.json ファむルの extensions に devcontainer 環境で利甚する VSCode の拡匵機胜の ID を入力しおおくこずで、devcontainer 環境で共通の拡匵機胜を䜿うこずができたす。 ファむルに盎接、拡匵機胜の ID を入力できたすが、以䞋の画像にあるように远加したい拡匵機胜を怜玢し、「 Add to devcontainer.json 」を遞択するこずで自動で devcontainer.json の extensions に蚘述しおくれたす。 たずめ ここたで読んでいただきありがずうございたした。 今回は簡単 3 step で devcontainer 環境を䜜っおみたした。VSCode さたさたですよね。 皆さんも是非、参画しおいるプロゞェクトで devcontainer 環境構築しおみおはいかがでしょうか 参考蚘事 VSCode 公匏ドキュメント https://code.visualstudio.com/docs/remote/containers#_system-requirements https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_vs-code-specific-properties https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_docker-compose-specific-properties Qiita https://qiita.com/kishibashi3/items/e20aecef45ed8341e739#docker-composeyml https://qiita.com/d0ne1s/items/d2649801c6f804019db7 Zenn https://zenn.dev/niisan/articles/9abd372ae86fc1