株式会社クリアコード > ククログ

ククログ


redmine.tokyo第17回勉強会:Redmine検索の未来像 #redmineT

Redmineの全文検索プラグインを開発している須藤です。

2019年11月2日にredmine.tokyo第17回勉強会が開催されました。私は参加していないのですが、この半年一緒に全文検索プラグインを開発してきた島津製作所の赤羽根さんが全文検索プラグインの導入結果を報告しました。私はこれに合わせて技術面からの補足として次の資料を作成しました。

関連リンク:

内容

従来の検索システムのなにが課題でそれをどう解決したかについてまとめました。しかし、従来の課題を解決すればすごく明るい未来があるわけではありません。少し明るい未来があるだけです。すごく明るい未来にするためにはさらになにに取り組めばよいのかについてもまとめています。そして、その取り組みはすでに始まっています。

今はクリアコードと島津製作所さんで一緒に取り組んでいますが、できれば他の会社も巻き込んですごく明るい未来を目指したいと思っています。私たちの成果はRedmine本体同様ユーザーが自由に使えるソフトウェアとして公開しています。もし、他の会社も一緒に取り組んだ場合もその成果はユーザーが自由に使えるソフトウェアとして公開します。一緒に取り組まなくても使えるように公開しますが、一緒に取り組むことですごく明るい未来がより早く実現できます。

一緒にすごく明るい未来を目指したい方はお問い合わせください。

まとめ

クリアコードと島津製作所さんは一緒にRedmineの全文検索プラグインを開発していました。その成果を島津製作所の赤羽根さんがredmine.tokyo第17回勉強会で紹介しました。私も紹介する資料を用意しました。

Redmineの検索機能をよりよくして、Redmineに蓄積した知識をより活用するために一緒に取り組みたい企業を募集しています。興味が湧いてきた方はお問い合わせください。

タグ: Groonga
2019-11-05

他のチームの知見を活かす

はじめに

弊社では複数のチームがあり、それぞれのチームで日々案件をこなしています。
今回、あるチームで課題を解決した方法を別のチームでも使える可能性があるのでは?ということで、チーム間の情報共有を行う取り組みを始めました。

チーム間の情報共有がなされにくいという課題

弊社は、それぞれのチームで案件が独立しているため、チーム間で情報を交換する必要性をあまり感じません。各案件についての背景知識がないと課題解決できないと考えがちなためです。そのため、現状では、チーム間の情報共有はとても少ないです。

しかしながら、案件によらず、どのチームにも共通する課題は存在します。あるチームで解決した課題と同じような課題で、別のチームが悩んでいるということがありえるのです。

他のチームから知見を得る機会を作ってみた

これは、非常にもったいないので他のチームの知見を取り入れられないかと考えました。

チームミーティングへの参加

チーム内にどんな課題があって、それをどうやって解決しているかは、チーム内で情報を共有する場で話題になることなので、まず、手始めに、各チームの情報共有の場に参加することで、他のチームでは、どうやって問題解決しているのかなど、自分のチームにはない知見を探すことにしました。

チームはそれぞれ、定期的にチーム内でミーティングを実施しています。そこでは、チームの現状や課題等が共有されるはずです。この場に参加することで、情報を収集しようと考えました。

今回は、Mozillaのサポートをしているチーム(以下、Mozillaチームと呼びます)のミーティングへ参加しました。

Mozillaチームのミーティングのやり方

Mozillaチームのミーティングでは、現在動いている案件がどんな状況か、また、新しく来た案件はどれで、誰がどう進めるかなどについて各々がどう理解しているかが共有されていました。
これは、個々人のタスク管理力を過信してチェックをしなかった場合に、漏れが発生した時のダメージが大きくなるので、早めにリカバリーできるようにすることを優先しているためです。

このようにすると、情報を同期する時間を取らないといけないので効率は若干落ちますが、そのコストよりもタスク漏れによる対応にかかるコストの方が大きいと判断して、情報の同期する時間を設けているとのことでした。

Groongaチームの現状

私は、全文検索エンジンGroongaの開発、サポートを行うチーム(以下、Groongaチームと呼びます)に属しています。
Groongaチームでも、現状の案件の状況を把握し、新しい案件は担当を決めて進めていますが、各々が確認した内容をチーム間で共有はしていませんでした。

Groongaチームは全員別々の場所で働いているので、普段は顔を合わすことがありません。
やり取りは、チャット上(Zulipという自由なソフトウェアを使っています!)かRedmineのチケット上でやり取りしていて、チャットとチケットを確認してタスク漏れがないかを各自で判断しています。

Groongaチームはこまめに情報共有するというスタンスで作業しているため、基本的にまとまった時間をとって情報共有をしません。Groongaチームの作業は、GitHub、GitLab、Gitter、メール、Redmineのチケット等、様々な入り口から問合せがあり状況が刻々と変わっていくので、まとまった時間を取るより、各作業についてこまめに情報共有するほうが効率が良いためです。

ただ、この方法では、タスクを網羅しているかどうかを確認できません。
そのため、自分が気がついていない案件を見落とすということが起きてしまいますし、作業に集中しすぎて、こまめな情報共有をおろそかにすると、自分の理解が誤っていて、間違った作業や非効率的な作業をしてしまうことがあります。

他のチームの知見を活かすポイントの発見

このように効率が良いと思って、こまめに情報共有するスタイルにしていましたが、それだけでは不十分なのではないかと感じました。案件を見落としてしまうと、そのリカバリーのために多くの時間が必要になるので、結局効率を落としてしまいます。

Mozillaチームでは、各々自分が理解したことをまとまった時間を取って共有することで、その時点で、抜け、漏れ、誤りを指摘、修正できているので、GroongaチームもMozillaチームに倣って、まとまって情報を共有する時間が必要だと考えました。

別のチームの知見を活かすポイントを見つけられたのです。

まとめ

他のチームの知見を得るために、別のチームのミーティングに参加する取り組みを実行し、その内容を紹介しました。
実行した結果、自分のチームには無かった知見を得ることができました。

チーム間の情報共有があまり行われずに悩んでいる方は、他のチームのミーティングに混ざってみると、今回のようにミーティングのやり方等から意外な知見がえられるかもしれません。

2019-11-12

PostgreSQL Conference Japan 2019:Amazon RDS + Amazon EC2 + ロジカルレプリケーションを使った低コスト高速全文検索 #pgcon19j

2019年11月15日(金)にPostgreSQL Conference Japan 2019が開催されました。
私は、「Amazon RDS + Amazon EC2 + ロジカルレプリケーションを使った低コスト高速全文検索」という題名で、既存の技術を組み合わせて、なるべく楽に高速、高機能な全文検索ができる仕組みを紹介しました。

当日、使用した資料は以下に公開しています。

関連リンク:

内容

RDBMSのマネージドサービスにAmazon RDSがあります。Amazon RDSはマネージドサービスなので、RDBMSの管理や運用などのコストを大幅に下げるような機能(自動レプリケーション、自動フェイルオーバー、自動バックアップ、設定の最適化などなど)がたくさんあり、これらを使うことで、DBの管理、運用はとても楽になります。もちろん、PostgreSQLにも対応しておりPostgreSQLの管理、運用も大幅に楽になります。

Amazon RDSはとても便利なのですが、Amazon RDS上のPostgreSQLには決められた拡張しかインストールできません。
したがって、Amazon RDS上のPostgreSQLで全文検索をしたい場合、pg_trgmを使った全文検索をすることになります。(pg_trgmはAmazon RDS上で使用できます)
しかしながら、pg_trgmはアルファベットと数字にしか対応していません。日本語や中国語などの全文検索には使用できません。

PostgreSQLで使用できる全言語対応の全文検索の拡張には、PGroonga(ぴーじーるんが)があります。
PGroongaは、全言語対応の超高速全文検索機能をPostgreSQLで使えるようにする拡張で、安定して高速で、かつ高機能(同義語、表記ゆれや異体字への対応、類似文書検索など)ですが、前述の通り、Amazon RDS上では使用できません。

Amazon RDS上のPostgreSQLには直接PGroongaをインストールできないので、PostgreSQL10から追加されたロジカルレプリケーションと、Amazon EC2を使用してAmazon RDSのメリットである、管理、運用コストの低減を享受しつつ、高速、高機能な全文検索を実現する構成を紹介しました。

PostgreSQLでは、ストリーミングレプリケーションというレプリケーションがありますが、これは、複製元と複製先のDBはまったく同じものになります。
一方、ロジカルレプリケーションでは、複製元と複製先でテーブルの構造を一致させなくても良いという特徴があります。
この特徴を利用すると、複製先のテーブルにのみインデックスを設定するということができます。

つまり、複製元をAmazon RDSとし、複製先にはAmazon EC2を用意します。Amazon EC2にはPostgreSQLとPGroongaをインストールしておき、更新はAmazon RDS、検索はAmanzon EC2で行うという構成を取ることができます。

この構成では、Amazon RDSにさえデータがあれば、検索用のEC2はいくらでも作れるという特徴があります。
そのため、Amazon RDSのデータは大事に保護しなければなりませんが、DBの管理、運用に便利な機能があるAmazon RDSを使っているので、データの保護は今までよりも大幅に楽にできます。

一方で、Amazon EC2では、データをAmazon RDSからロジカルレプリケーションで同期するため、PGroongaを使ってAmazon RDSにあるデータを高速に全文検索できます。

このように、ロジカルレプリケーションの複製元と複製先のテーブル構造を一致させなくても良いという特徴を使って、Amazon RDSのメリットを享受しつつ、高速で高機能な全文検索を実現できるのです。

まとめ

Amazon RDSのメリットを活かしつつ、PGroongaを使った高速で高機能な全文検索を実現する構成を紹介しました。
Amazon RDSを使いたいけど、PGroongaが使えないので、しかたなく自前でサーバーを用意している。という方や、PGroongaを使って、高速で高機能な全文検索をしたいけど、Amazon RDSを使っているのでPGroongaが使えないとお悩みの方は、ここで紹介した構成を検討してみてはいかがでしょうか?

PGroongaを使った全文検索について、興味、疑問などございましたら、是非、お問い合わせください。

タグ: Groonga
2019-11-18

「Fluentd」のサポートサービスを開始しました。

クリアコードでは2015年からFluentdの開発コミュニティに参加し、Fluentd本体とプラグインの開発、サポート、各種ドキュメントの整備を行っています。
2016年以降、既存の取引先様に対してFluentdのサポートを提供していましが、この度満を持してサポートサービスの開始を宣言しました。
サービスの概要はこちらです。
先日プレスリリースも出しましたので、併せてご参照ください

Fluentdに関するお問い合わせはこちらまで。

タグ: Fluentd
2019-11-20

2019年、fat gemをやめる

fat gemを簡単に作れるようにするgemであるrake-compilerをメンテナンスしている須藤です。過去にfat gemの作り方をまとめたこともあります。

fat gemが有用な時代もあったのですが、今はメリットよりもデメリットの方が大きいのでfat gemをやめたらどうか、という話をします。

fat gemについて

fat gemとはビルド済みバイナリーが入ったgemのことです。Pythonで言えばwheelのようなものです。

RubyはC言語でRuby用のライブラリーを実装することができます。これを拡張ライブラリーと呼びます。拡張ライブラリーの用途は主に高速化(Rubyで実装したよりCで実装した方が速い)とバインディング(C・C++言語で実装されたライブラリーをRubyから使えるようにするライブラリー)です。

拡張ライブラリーをインストールするにはC言語のプログラムをビルドしなければいけません。ビルドするためにはインストール時にC言語のビルド環境が必要になります。ユーザーの環境にC言語のビルド環境がないとインストールできません。つまり、インストールの敷居が高くなります。

このインストールの敷居が高い問題を解決するものがfat gemです。fat gemにはビルド済みのバイナリーが含まれているためユーザーはC言語のビルド環境を用意しなくてもいいのです。やったー!

fat gemの問題点

fat gemのおかげでユーザーはハッピーになれそうですね。でも、本当にそうでしょうか?実際に、fat gemを作ってきた経験からfat gemの問題点を説明します。

新しいRubyを使えるまでにタイムラグがある

Rubyは毎年クリスマスに新しいバージョンがリリースされます。(メンテナンスリリースは必要に応じて随時行われています。)

fat gemにはビルド済みのバイナリーが含まれています。これは、だれかが事前にビルドしてくれているということです。だれかというのはgemの開発者です。

Rubyはバージョン間でのABIの互換性を保証していません。たとえば、Ruby 2.6用の拡張ライブラリーはRuby 2.7では使えません。そのため、新しいバージョンのRubyがリリースされたらそのバージョンのRuby用にビルドしないといけません。(メンテナンスリリースでは互換性があるのでRuby 2.6.0用の拡張ライブラリーはRuby 2.6.5でも使えます。)

つまり、新しいRubyがでてもgemの開発者が新しいRuby用のfat gemをビルドしてくれていなければ新しいRubyを使えません。すべてのgemがRubyのリリースにあわせて開発スケジュールを立てているわけではないので、クリスマスから数ヶ月遅れて新しいRuby用のfat gemをリリースすることも十分ありえます。

リリースされるならまだいいですが、メンテナンスモードになっているgemは重大な問題がなければ数ヶ月経ってもリリースされないかもしれません。もし、リリースされないgemが変更無しで新しいRubyでビルドできたとしてもユーザーは使えません。(RubyのC APIはそんなに劇的に変わらないのでだいたいビルドできます。)

もし、ユーザーが複数のfat gemに依存している場合はすべてのfat gemが新しいRubyに対応しなければ新しいRubyを使えません。1つでも新しいRubyに対応していないとインストールできないからです。

脆弱性対応までにタイムラグがある

バインディングをfat gemにするということはバインディング対象のライブラリーもfat gem内に入れていることになります。もし、バインディング対象のライブラリーに脆弱性があった場合は迅速に修正版をリリースするべきです。そうしないとユーザーが危険な状態が伸びてしまうからです。

しかし、すべてのfat gem開発者がそんなにタイミングよく作業できるわけではありません。そのため、脆弱性対応リリースが遅くなりがちです。

念のため補足しておくと、これはfat gemにしていない場合でも発生しえます。たとえば、Nokogiriのようにデフォルトで特定バージョンの依存ライブラリーをビルドするタイプのgemでも発生しえます。指定したバージョンのライブラリーに脆弱性があったらバージョンを更新してリリースしないと脆弱なバージョンを使ったままのユーザーが増えてしまいます。明示的に--use-system-librariesを指定すればNokogiriのバージョンを上げなくても対応できるのですが、残念ながら多くのユーザーはそこまで頑張ってくれないでしょう。

新しい依存ライブラリーを使えるまでにタイムラグがある

これもバインディングの場合ですが、バインディング対象のライブラリーが新しいバージョンをリリースしてもfat gemを更新しなければユーザーは新しいバージョンを使えません。

fat gemに対応するとrequireが遅くなる

fat gemに対応するには次のようなコードを入れる必要があります。2.6/io/console.so(ビルド済みバイナリー)があればそっちを優先し、なければio/console.so(自分でビルドしたバイナリー)を読み込むというロジックです。

begin
  require "#{RUBY_VERSION[/\d+\.\d+/]}/io/console.so"
rescue LoadError
  require 'io/console.so'
end

すべてのケースでfat gemを使うなら↓だけで大丈夫です。

require "#{RUBY_VERSION[/\d+\.\d+/]}/io/console.so"

しかし、それではユーザーが自分でビルドして使うという選択肢がなくなります。逆に言うと、開発者がすべてのプラットフォーム向けにfat gemを用意する覚悟を決める必要があります。

それは現実的ではないので、普通は前述のように自分でビルドしたバイナリーにフォールバックします。

そうすると、fat gemを提供していない環境では必ずfat gem用のrequireが失敗します。この分requireが遅くなるということです。$LOAD_PATHにたくさんのパスが入っている環境では無視できないくらい遅くなります。gemをたくさんインストールしているとその分$LOAD_PATHも大きくなります。たとえばRuby on Railsアプリケーションではたくさんのgemを使うことになるので影響が大きいです。

これを回避するために、fat gemを提供している環境でだけフォールバックする対策をとっているgemもあります。(ありました。)

fat gemのリリースを忘れる

多くのgemはrake releaseだけでgemをリリースできるようにしています。そしてこれはすぐに完了します。.gemファイルを作ってrubygems.orgにアップロードするだけだからです。(他にもgit tagをするとかちょろっとしたことをしています。)

しかし、fat gemをリリースするにはもう一手間必要です。各環境用のバイナリーをビルドしてそれぞれの環境毎にfat gemを作り、それらをrubygems.orgにアップロードします。

各環境用のバイナリーは大変です。rake-compiler-dockを使えば楽になりますが、それでも面倒です。

その結果どうなるかというとリリースが億劫になったり、fat gemのリリースを忘れたりします。たとえば、Ruby-GNOMEはリリースが億劫だなと思っていました。たとえば、io-console 0.4.8はfat gemのリリースを忘れていました

fat gemのリリースが大変

fat gemのリリースは大変なんです。特にバインディングのfat gemのリリースは大変です。

私はRuby-GNOMEでWindows用のfat gemを作っていました。バインディング対象のGTKなどのライブラリーはLinux上でMinGWを使ってクロスコンパイルしていました。これがすごく大変です。というのは、クロスコンパイルしている人がほとんどいないので、バインディング対象のライブラリーのバージョンを上げるとビルドエラーになることがよくあるからです。Ruby-GNOMEをリリースするたびにアップストリームにパッチを送っていたものです。ただ、librsvgがRustを使うようになってクロスコンパイルできなくなったときにfat gemをやめる決心をしました。

fat gemはそんなにポータブルじゃない(気がする)

fat gemは主にWindows向けに提供されていますが、Linux向けに提供している野心的なgemもあります。たとえば、sasscです。

Windowsはバージョンが限られていますし、後方互換性があるので古いWindows向けにビルドしていればいろんなWindowsでもだいたい大丈夫です。

しかし、Linuxディストリビューションはたくさんあり、使っているlibcも違います。スタティックリンクしたバイナリーを用意すれば大丈夫なのかというとそうでもない気がします。どうなんでしょうか。。。?

Pythonのwheelではmanylinuxという(だいたいの)Linux環境で動く仕組み(?)を用意しているので、このくらい頑張れば大丈夫なのかもしれません。が、私としては、この方向で頑張っちゃうの。。。?という気持ちになります。RubyGemsはそうなって欲しくないなという気持ちです。

fat gemの問題点の解決方法

ここまででfat gemの問題点をまとめました。それではfat gemの問題点を解決する方法を示します。それはfat gemをやめることです。どーん!

そもそもfat gemが必要だったのはユーザーがビルド環境を持っていないことが多かったからです。しかし、今は状況が変わっています。ユーザーがビルド環境を持っていないプラットフォームの代表はWindowsでしたが、今はRubyInstaller for Windowsがほぼ標準でDevKitを提供しています。Ruby 2.3以前はそうではなかったですが、Ruby 2.3がEOLになったので、今はWindowsユーザーでもビルド環境があるのです。

Linuxではパッケージをインストールすればすぐにビルド環境を整えられます。

macOSでもXcodeをインストールすればビルド環境を整えられます。Homebrewを使っている人はすでに整っているはずです。

他の環境(たとえば*BSD)でもビルド環境はすぐに整えられるでしょう。

つまり、今はユーザーがビルド環境を持っていると仮定してもよい状態になっています。そのため、fat gemを提供しなくてもユーザーがインストールできる状態が整っています。実際、私はWindowsユーザーがいるRuby-GNOMEでfat gemをやめましたが、最近はWindowsでのインストールトラブルはほとんど報告されていません。

それではfat gemをやめるとうれしいことをまとめます。

新しいRubyをすぐに使える

新しいバージョンのRubyは以前のバージョンのRubyとC APIが変わっている可能性があります。たとえば、Ruby 2.7ではrb_f_notimplement()が変わります。(Ruby 2.7の対応が必要な例)

しかし、多くのC APIは互換性があるのでなにも変更しなくても新しいRubyで動くことが多いです。その場合は、特になにもしなくてもすぐに新しいRubyを使えます。ユーザーは単に新しいRubyを使ってgemをインストールすればよいだけだからです。

また、もしRuby 2.7で動かない場合でも事前にプレビュー版で動作確認し、Ruby 2.7より前にRuby 2.7対応版をリリースしておくこともできます。こうすればクリスマス後にリリースしなくてもよくなるのでgem開発者に余裕があります。

fat gemを使った場合でも、プレビュー版でバイナリーを作ってリリースしておくことができなくはありませんが、rake-compiler-dockなど各種ツールが事前に対応していないと難しいです。

脆弱性対応をシステムに任せられる

バインディングをシステムのライブラリーを使ってビルドするようにしていた場合、バインディング対象のライブラリーに脆弱性があってもシステムのライブラリーを更新すれば対策できます。gemの開発チームよりシステムのライブラリーをメンテナンスしている人たちの方が層が厚いいので迅速に脆弱性に対応してもらえます。

なお、Nokogiriのようにデフォルトで依存ライブラリーを自前で管理するタイプのgemはfat gemでもそうでなくても関係ありません。

新しい依存ライブラリーをすぐに使える。。。こともある

バインディングをシステムのライブラリーを使ってビルドするようにしていた場合、バインディング対象のライブラリーの更新はシステムのパッケージシステムが面倒をみてくれます。Debian GNU/Linux sid、Fedora Rawhide、ArchLinux、Homebrew、MSYS2などのように最新のバージョンに随時アップデートされるシステムではgemの更新を待たずに新しいライブラリーを使えます。

ただし、ライブラリーのバージョンアップでAPIが変わった場合はgemの更新が必要です。

requireが遅くならない

fat gem用のrequireがいらなくなるので失敗するrequireを実行しなくてもよくなります。これによりrequireが遅くなりません。

bigdecimalがfat gemのサポートをやめたのはこれが理由です。

開発コストが下がる

面倒なfat gemのリリースをしなくてよくなるので開発者は本来の開発にリソースを注力できます。

最適化ビルドできる

fat gemは事前にビルドしたバイナリーをすべてのユーザーが共通で使うことになるので最大公約数の最適化しかできません。

しかし、fat gemをやめて各ユーザーごとにインストールする場合はその環境毎に最適化できません。たとえば、速度が非常に重要な拡張ライブラリーをGCCでビルドする場合は-O3 -march=nativeというオプションをつけてビルドするとその環境向けに最適化されます。たとえば、CPUがSIMDをサポートしていればSIMDを使ったバイナリーを生成することもあります。

fat gemをやめたときの問題点と解決策

fat gemをやめるとユーザーも開発者もハッピーになれそうですね。でも、本当にそうでしょうか?fat gemをやめたときの問題点とその解決策をまとめます。

インストール時間が長くなる

fat gemの場合はビルド済みのバイナリーをコピーするだけなのですぐにインストールは完了します。しかし、fat gemをやめるとインストールするたびにビルドすることになるので時間がかかります。

解決策は。。。特にありません。。。

依存ライブラリーがなくてインストールが失敗しやすくなる

バインディングはバインディング対象のライブラリーがないとインストールに失敗します。たとえば、RMagickはImageMagickがないとインストールに失敗します。Nokogiriがデフォルトで自分で依存ライブラリーをビルドするようになっているのはこの失敗を防ぐためです。

たしかに、自分でビルドしてしまうというのはこの問題の解決策の1つではあります。ただ、そんなに筋がよいとは思えません。脆弱性があったときの対応に関する問題があるからです。

私がオススメする方法はシステムのパッケージシステムを使って自動で足りない依存ライブラリーをインストールする方法です。このための便利gemがnative-package-installerです。私が開発しています。

native-package-installerはpkg-config gemと一緒に使うことを想定していて、extconf.rbに次のように書いておけば、cairoがインストールされていなければ自動でインストールします。

require "pkg-config"
require "native-package-installer"

unless PKGConfig.have_package("cairo")
  unless NativePackageInstaller.install(:arch_linux => "cairo",
                                        :debian => "libcairo2-dev",
                                        :homebrew => "cairo",
                                        :macports => "cairo",
                                        :msys2 => "cairo",
                                        :redhat => "cairo-devel")
    exit(false)
  end
  unless PKGConfig.have_package("cairo")
    exit(false)
  end
end

なお、RubyInstaller for Windows用のRubyではgemのメタデータにMSYS2のパッケージを指定しておくことで同じ機能(自動で依存ライブラリーをインストールする機能)を実現できます。以下はcairo.gemspecでの例です。

gemspec.metadata["msys2_mingw_dependencies"] = "cairo"

参考:MSYS2 library dependencies - For gem developers - onclick/rubyinstaller2 Wiki

ビルドに失敗してインストールが失敗しやすくなる

fat gemではすでにビルド済みなのでビルドが失敗することはありません。開発者が用意した環境でビルドが成功すればOKです。

一方、ユーザーの環境でビルドする場合は、開発者の環境では成功しているのにユーザーの環境では失敗することがあります。

解決策は、CIでサポートしている環境を常にテストすることです。Travis CIやGitHub Actionsなどを使えば、いろんな環境でテストできます。Linuxの亜種はDockerを使うとよいでしょう。

まとめ

検討するべき項目が他にもある気がしますが、一通りまとめたので公開します。fat gemをやめたくなりましたか?それともfat gemはやめないで!という気持ちになりましたか?

もし、これはどうなの?という項目があったらなんらかの手段で私に聞いてください。回答します。

タグ: Ruby
2019-11-22

FirefoxでInternet Explorerのwindow.open()周りの挙動を再現する

日本におけるFirefoxの法人利用の代表的なニーズは「Internet Explorer向けに作られた古いWebベースの社内システムがあるためにIEを捨てられず、社外のWebを見に行くためにFirefoxを使いたい」というものです。しかし、それとは逆のパターンとして、「IE向けに作られたWebベースのシステムをFirefoxで使いたい」という場面もあります。後者の場合にはIEとFirefoxの細かな挙動の違いが問題となることがあり、window.open() でウィンドウを開くときの挙動の違いもその一つです。

名前付きの子ウィンドウ(タブ)の挙動の違い

window.open() はJavaScriptから利用できるブラウザの機能(いわゆるDOM0)で、子ウィンドウ(タブ)を開く物です。第2引数には「子ウィンドウの名前」を指定することができ、この方法を使って名前を付けて開かれた子ウィンドウ(タブ)は、<a target="ウィンドウ名" href="..."> のようにtarget属性を明示したリンクの読み込み先や、window.open() で同じウィンドウ名を指定した場合の読み込み先として再利用されることになります。

Internet Explorerでは、このような場面で以下のような挙動を取ります。

  • すでにその名前の子ウィンドウ(タブ)が開かれていた場合、とにかくそれを読み込み先として使う。
  • 読み込み先の子ウィンドウが最小化状態であれば、通常の状態に復帰させる。他のウィンドウの背後に隠れている場合であれば、最前面に持ってくる。

他方、Firefoxでは同じ場面で以下のような挙動を取ります。

  • 子ウィンドウはそれぞれのタブに対して個別に管理される。2つのタブそれぞれで子ウィンドウを名前を指定して開いた場合、それぞれのタブに対して別々の子ウィンドウが開かれる。その後のウィンドウ名を指定した読み込みも同様に取り扱われる。
    • →IEの挙動を前提に作られたWebアプリだと、無駄にたくさん子ウィンドウが開かれてしまう。
  • 読み込み先の子ウィンドウが最小化状態や他のウィンドウの背後に隠れている場合でも、そのままの状態で読み込みを行う。
    • →IEの挙動を前提に作られたWebアプリだと、「リンクやボタンをクリックしても(最小化された、または背後にあるウィンドウの中に読み込まれる場合があり)結果を画面上で確認できないという事が起こる。

Firefoxアドオンでの解決

Webアプリとしては、このような挙動の違いを吸収したり、Firefoxのような挙動でも問題が起こらないようにしたりと対策を取れればそれに越したことはありません。しかし、様々な事情からそれができない場合もあります。

そのようなお客さまからのご相談を受けて、Firefox上でIEの上記の挙動を再現するためのアドオンを開発しました。以下のリンクからインストールできます。

  • Merge Named Browser Windows:ウィンドウ名を指定して子ウィンドウ(タブ)が開かれた場合に、親ウィンドウ(タブ)を問わずその名前の既存のタブを探して閉じ、特定の名前のタブが1つだけ開かれているという状態を維持する。
  • Unminimize Browser Window On Load:最小化状態や背面にあるウィンドウにコンテンツが読み込まれた場合に、ウィンドウを復帰させフォーカスを与える。

主にセキュリティ向上のために、現代のWebブラウザはウィンドウ(タブ)間での情報の分離を徹底する方向で進化しています。また、迷惑な広告やいわゆるブラクラの類にユーザーが煩わされる事が無いよう、コンテンツ側からの操作によるウィンドウのフォーカス制御も制限されるようになっています。それらの変化は一般的なWebサイトを閲覧するユーザーにとって好ましいものですが、特定のWebアプリの使用頻度が高くなる法人利用では却って困った結果になる事もあります。

そのような特殊な場面での暫定的な対処のための方法として、一般的なWebアプリよりも強力な権限が与えられているアドオン(拡張機能)は有用な選択肢となる場合があります。Firefoxの法人利用で似たような事にお悩みの企業担当者さまがいらっしゃいましたら、お問い合わせフォームより是非ご連絡下さい。

タグ: Mozilla
2019-11-26

«前月 最新記事
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|