RAKSUL TechBlog

ラクスルグループのエンジニアが技術トピックを発信するブログです

Hack Week 2021 オンライン開催します!!!

はじめまして。ラクスルでWebアプリケーションを開発している星野です。 例年、弊社ではこの時期に社内ハッカソン (Hack Week) を開催しています。今年もその時期がやってきました。

Hack Week とはエンジニア、デザイナ、PMなど、普段ラクスルの各事業部を支える開発チームが参加するハッカソンイベントです。自分たちでアイデアを出し合い、1週間かけて開発を行います。

今回で第4回目であるこの催しについてご紹介したいと思います。

Hack Week 2021 のテーマ

毎年なにかしらのテーマを設定している当催しですが、今年のテーマは

Going Beyond Borders - 境界を越える -

です!

一口に「境界」といっても、職務、事業部、専門分野などいろいろなものがあります。 ラクスルには海外拠点もあるため、国籍、言語、文化と言う意味での境界ももちろんあります。

時折「ボーダーレス」や「No Border」のような言葉を耳にしますが、境界をないものとするのではなく、境界があることを認識し、その境界を意思によって越えていく。 そんな思いがこのテーマにはあります。

今年はこの Hack Week にサマーインターンの学生の皆様も一緒に参加します。学生と社会人の境界も超えていく取り組みにできたらと考えています!

開催までの取り組み

アイデア募集

Slack の Workflow 機能で Hackweek 期間中に取り組むアイデアを Slack チャンネルに投稿できるフォームを作成しました。投稿は自動で Google Spreadsheet に追記されるようなっています。

去年も同じような仕組みを作ったのですが、当時は Spreadsheet への転記をするのに Zapier なども併用する必要があった記憶があります。 いつのまにか Workflow 単体で Spreadsheet への転記ができるようになっていて、進化を感じました。

 

チームビルディング

取り組むテーマについて集まったところで、チーム決めを行いました。

Google Meets で集まったテーマの紹介や、起案者からのチーム結成を呼びかける会を企画し、日頃は絡みのないメンバーとも交流できる催しを行いました。

試行錯誤しながらではありましたが、約 30 チーム、総勢 100 名超のイベントをこの度開催できることとなりました。

例年ですとチーム結成後から Hack Week 開催までの期間に、顔合わせや当日作戦会議をかねて各チームに費用会社負担での懇親会を推奨していました。しかし、今年は情勢的に行いませんでした。個人的にちょっと残念だったポイントです。

イベントクリエイティブ

リモートでのイベントだと、どうしても手応え感のようなものが薄くなりがちです。イベントが開催される実感を出すために、

  • 視覚: リモート会議用の背景、Slack icon
  • 触覚: イベントノベルティの作成

を、委員会のデザイナーにしてもらいました。

前述したチームビルディングイベントなどで参加者に背景を設定してもらうことで、「イベント近いぞ!」という雰囲気をだせてとても良かったと思います。

 

この記事を読んでくださっている方で、同じようにイベントノベルティを作りたい方がいたら是非弊社をご検討ください!

まとめ

ラクスルでは 8/30 - 9/3 にリモートで社内ハッカソンを開催します。

試行錯誤を多く要する取り組みですが、楽しいものにできればと実行委員の一人として邁進する毎日です。 後日また開催レポートを掲載できればと思っています。

 

これまでのレポートもありますのでご興味があればぜひ御覧ください。

Hack Week 2020 https://techblog.raksul.com/entry/2020/11/10/hackweek2020-report/

Hack Week 2019 https://techblog.raksul.com/entry/2019/06/20/raksul-hack-week-vo2/

Hack Week 2018 https://techblog.raksul.com/entry/2018/10/18/raksul-hack-week-report/

Macなら ビルド終了 声で知る

こんにちは。文字化けおじさんです。暑くなって参りましたが、皆さんお元気でしょうか? 最近は、私は社内業務で使うMacアプリ(時々Windowsアプリ)の開発を担当しており、Swiftを書いたり、TypeScript + React でElectronアプリとして作ったりしています。元気です。

さて、今回の記事は文字化けの話題ではなくて、Macにおける開発生産性を向上させるための小ネタをご紹介したいと思います。この記事のことを私が実践していたところ、若手の同僚の数名から「かわいい🥰」とお褒めの言葉を頂戴したので、改めて記事として紹介することにしました。

解決したい課題

何か時間のかかる処理が終了したときにはその通知が欲しいと、多くの開発者の方が思ったことがあると思います。ビルドしたとき、unit test を実行したとき、パッケージマネージャでインストール操作をしたとき、などです。この課題は、開発する言語やプラットフォームによらず、多くの環境で存在することでしょう。これらのタスクが短い時間で終わるように取り計らうというのはとても重要な取り組みなのですが、それには限界があります。 これらのタスクが動いている間ずっと画面を見つめていても良いのですが、自分自身の生産性のためには、待っている間はSlackのメッセージのチェックなどの他の作業を進めたいものです。この欲求を尊重した結果、画面を他のアプリに切り替えて作業していると、ビルド等の作業が終了したことに気付かないまま別の作業を継続してしまうという問題があります。

解決策の案

実現の難易度には一旦目を瞑りつつ、ぱっと思いつくところでは以下のような解決策(ビルド等終了の通知方法)が考えられます。

  • 音声で通知する
  • Notification Centre で通知を出す
  • Dockアイコンを跳ねさせる
  • Slack等のメッセージアプリ経由でmentionを飛ばす
  • ビルドが終了するとCPU使用率が下がって冷却ファンの回転が止まることを利用して、ファンの音に耳を澄ませつつ作業する(ファンのあるMacのみ)

様々なものがありますし、他にも手段があるかもしれませんが、この中で最も実現が簡単なのは、実は「音声で通知する」なのです! そう、Macならね😉

sayコマンド

ご存知の方も多いかもしれませんが、Macには say というコマンドが付属しており、引数として与えた文章を読み上げてくれます。このコマンドの詳しい使い方は、ターミナル等で man say を見て下さい。例えば日本語環境で say 東京特許許可局 とすると、噛むこと無く綺麗に読み上げてくれます。 この say コマンドの声の主は -v オプションで指定することができます。声の主ごとに対応している言語が異なり、例えば Kyoko さんは日本語、 Daniel さんはイギリス英語を喋ってくれます。デフォルトの音声は、OSの言語が日本語であれば Kyoko さんになっているはずですが、システム環境設定の「アクセシビリティ」の「読み上げコンテンツ」で変更することができます。このデフォルト設定を変えていたりOSが他の言語になっている場合は、先ほどのメッセージを読み上げるには say -v Kyoko 東京特許許可局 とする必要があるでしょう。 声の主のリストは say -v ? で得られますので、見てみて下さい。

コマンドの成否に応じて発言内容を変える

あるコマンドが終了したときにメッセージを読み上げてもらうには、ビルド用のコマンドの後にセミコロン ; を続けて、その後に say コマンドを呼び出すのが最も簡単です。例えばビルド用のコマンドが make build であるなら make build; say -v Kyoko 'ビルド終わったよ' とします。

これでも十分に有効に機能しますが、正常終了のときは喜ばしいメッセージを、そして異常終了の時は悲しいメッセージを読み上げて欲しいという需要もあります。そのような時は &&|| を用いて make build && say -v Kyoko 'ビルド終わったよ' || say -v Kyoko 'ビルド失敗しちゃったテヘペロ'

とするのが良いでしょう。ビルドのコマンドのstdout(標準出力)を破棄して良い場合は、こう書くこともできます。 say -v Kyoko $(make build > /dev/null && echo 'ビルド終わったよ' || echo 'ビルド失敗しちゃったテヘペロ')

Xcodeの Build Phases に組み込む

MacアプリやiOSアプリ等をXcodeでビルドする際は、終了したことは Notification Centre でも通知されますが、美しい声を聞きたいのであれば Build Phases の最後に Run Script を仕込むことで、ビルド終了時に say コマンドを動かすことができます。

Xcodeの Run Script 設定

私の手元では、ビルド失敗時の読み上げ手法を確立できておりませんが、もしかすると世の中の偉大なる先人たちの誰かが同様のことを確立済みかもしれません。 なお、CI環境など、手元のマシンではない場所でもビルドすることがある場合は、読み上げた結果として何が起きるのか?に気にかけておくと良いでしょう。

npm script に組み込む

Electronアプリのビルドの際、そしてWebフロントエンドのアプリのビルドの終了通知にも、 say コマンドを用いることができます。package.jsonの scripts のところのコマンドに、前述の「コマンドの成否に応じて発言内容を変える」にあるようにコマンドを書けば良いでしょう。 こちらも CI に注意する必要があります。Mac以外の環境(WindowsやLinux等)で動かすことへの配慮が必要な場合は run-script-os を用いて、darwinの時とそれ以外の時とで実行するコマンドを切り替えるのも良いでしょう。

最後に

ラクスルでは、一緒に開発してくれる仲間を募集しています! say -v Daniel Rebuild the Industry. の声を在宅勤務中の自室、いえ、それだけではなく世界中に轟かせていきましょう! 詳しくはこちら

補足:動作確認環境

  • Xcode 12.5.1 on Big Sur 11.4
  • bash 3.2.57(1) on Big Sur 11.4 & Mojave 10.14.6
  • zsh 5.8 on Big Sur 11.4
  • NodeJS v14.17.2 / npm 6.14.13

新卒メンバーでAWS研修に参加しました!

こんにちは。21卒新卒エンジニアの山中です。今回は、6月1日〜3日に、新卒メンバー5人で、アマゾンウェブサービスジャパン株式会社様(以下 AWS Japan 様)主催の「AWS Jumpstart for NewGrads」という新卒向け研修に参加してきたので、そのレポートをしたいと思います。

AWS Jumpstart for NewGradsとは?

AWS Jumpstart for NewGrads とは、新卒エンジニア向けに AWS Japan 様が開催している研修イベントです。3日間にわたり、AWS のソリューションアーキテクト(以下SA)の方々と一緒に AWS について学ぶ研修です。今年に関しては、全日程 Amazon Chime や Slack を用いたオンライン開始となっていました。

おおよその研究内容は以下の通りでした。

  • AWS を用いた設計のベストプラクティスに関する講義(2時間)
  • ECS の入門ハンズオン(4時間)
  • Amplify の入門ハンズオン(3時間)
  • 架空のサービスを想定した AWS アーキテクチャ設計のグループワーク課題(10時間)
  • SA の方との座談会
  • 上記グループワークの成果発表会
  • 参加者同士の懇親会

時間配分を見るとわかるように、講義やハンズオンに加え、グループワーク課題にも多くの時間が割かれており、インプットとアウトプットの両方を意識した内容となっていました。また、弊社以外にも、多くの企業から新卒エンジニアが参加しており、私たちは、それぞれ別のチームに分かれて、他社の新卒エンジニアの方々3〜4人と一緒に課題に取り組みました。

この記事では、私たち5人が、どのような観点からグループワーク課題に取り組んだかご紹介したいと思います!各チームのアウトプットの違いにも注目して頂けると面白いと思います。

課題:大規模チャットツールを作ろう!

初日に発表されたグループワーク課題は、「新卒入社した会社でチャットサービスを立ち上げることになったので、そのアーキテクチャを考える」というものでした。なお、その会社の既存メンバーは全員退職予定ですが、全世界規模のサービスを半年後にリリースする計画はそのままであるという設定が付け加えられています。 AWS の各種サービスをうまく活用し、新卒メンバーだけで半年後のローンチを目指すことになりました。

サービスは日本・アメリカの2リージョンで展開し、Web ・ Android ・ iOS のマルチプラットフォーム展開を要求されています。必須機能として、チャット機能や動画・画像の送受信、アカウントや友達・グループ管理を実装する必要があり、それに加えて、Nice-to-have な機能として、通知・既読・スタンプ・検索といった機能が挙げられています。パフォーマンス要件としては、チャット流量が1秒あたり10000メッセージ、データ流量が1秒あたり 1GB と想定されています。また、データ保存期間は1年間となっています。

各チームの成果の紹介

グループワーク課題では、上記の要求を満たすようにアーキテクチャを設計する必要があります。ただし、アーキテクチャを設計する上では、実現可能性のみならず、開発容易性やコストなど、さまざまな観点から考える必要があり、どの観点を重視するのかによって、最終的に決定したアーキテクチャにも違いが出てきます。私たち5人のいたそれぞれのチームの成果をご紹介したいと思います。

横山(チームA)

チームAでは、与えられていた背景をもとに、サービスをいかにして成り立たせるかということを意識しました。

今回のワークショップでは、既存社員が全員退職する中で新卒社員であるチームのメンバーだけで、半年でサービスをリリースしないといけないというタイトなスケジュールが与えられていました。チャット機能を実現するには双方向通信の実装が必要であるとわかりましたが、メンバーの多くは Web アプリケーション開発のエンジニアで Web での双方向通信の開発経験がありませんでした。

そのため、チャット機能は Lambda と API Gateway で実装し、一方で、今後のサービスの拡張性を考えてアカウント管理やチャット内検索などの機能は ECS 上に構築するようにしました。

また、サーバーのモニタリングや、Lambda の実行失敗、失敗したキューはデッドレターキューに流すなど実際にサービスの運用を想定した構築を意識しました。

ここまで大きな1つのサービスを構築することを考えて、アーキテクチャ検討を行ったことがなかったのでとても良い経験になりました。

山中(チームC)

チームCでは、必須機能に限定して、アーキテクチャを検討しました。基本的には AppSync を用いた GraphQL API を構築しました。また、特に工夫した点としては、次の2点を挙げました。

  • 直近2ヶ月のメッセージデータのみを DynamoDB に配置し、残りのデータは S3 に保管する
    • チャットのメッセージデータは、直近のものは頻繁に参照されるのに対して、過去のものはほとんど参照されないという特性があると考えられます。そのため、直近のデータのみを DynamoDB に配置し、残りは S3 などの安価なストレージに移すことでコスト削減を実現できます。私たちの試算では、直近2ヶ月分のみを DynamoDB に保管した場合、1年分のメッセージデータを全て DynamoDB に保存した場合に比べ、月2400万円のコスト削減になることが分かりました。
  • 動画変換に Elemental MediaConvert を利用する
    • AWS Elemental MediaConvert とは、動画データを各スマートフォンやタブレット端末に適した動画データや、ストリーミングデータに自動的に変換してくれるマネージドサービスです。マルチプラットフォームに対応する上では動画の変換処理が必須となるものの、処理を自分たちで実装するのは難しいと考えられたため、 MediaConvert を用いて楽をしようと考えました。

後者の工夫に関しては SA の方も想定していなかったようで、深いところまで検討できていると高評価をいただくことができました。他の企業の新卒のチームメンバーとともに、深いところまでアーキテクチャについてディスカッションでき、とても楽しむことができました。

原田(チームH)

チームHは全員 AWS 初心者だったため、既存のアーキテクチャをもとに各サービスがどんなものか調べ、必要に応じてサービスを加えたり構成を変更したりして進めました。例えば、一口に「チャットメッセージを DynamoDB に格納する」といっても、アメリカと日本でどのように同期を取るかは AWS のドキュメントを読みながら考えました。今回は Global Table という複数のリージョン間でデータベースを同期する機能を使うことにしました。

最終的なアーキテクチャはこのようになりました。認証機能は Cognito を利用し、ホスティング・デプロイ・ UI 開発は Amplify を使います。データについては、画像・動画といった静的ファイルは S3 の Intelligent Tiering で格納し、チャットメッセージは書き込みの速さを考慮し DynamoDB に格納します。自分たちのチームでは、アーキテクチャ以外に、実際に運用するにあたってクォータ制限に引っかからないかを検証しました。例えば、Dynamo DB は書き込みには 1テーブルあたり 40,000 write request units・読み込みには 1テーブルあたり 40,000 read request units というデフォルトのクォータがあります。この request unit とはデータの単位で、1 read request unit は「1秒あたり 4KB のデータを読み込める」というデータです。例えば、2KB のデータの read 操作は 1 read request unit に納まりますが、6KB のデータを読み込むときは 2 read request unit 必要です。今回は、 Read/Write 共に DynamoDB クォータ内に収まることがわかりました。

研修は3日間頭を使いっぱなしだったので大変でしたが、チームメンバーとたくさんディスカッションができて楽しかったです。 AWS についても、何がなんだかわからない状態からメジャーなサービスの概要が分かり、アーキテクチャ図の読み方もわかるようになり良かったです。

喜屋武(チームJ)

チームJでは、主要な機能を重点的に考え、サービスとして成り立たせることを目標にアーキテクチャを考えました。そのためマルチリージョンなどは今回のアーキテクチャではスコープ外としました。

リアルタイム性を求められるようなチャット機能に関しては、 Lambda はコールドスタートした際に数100ms掛かる可能性があるため使わず、ECS ( on Fargate ) で常駐させることでリアルタイム性を損なわないようにしました。一方で、レスポンスの時間がある程度許容される過去のチャットへの参照などは Lambda を用いることでサーバのメンテナンスコストを下げるようにしました。このようにユースケースごとにアーキテクチャの選定をし構築を行いました。

今回の課題では大規模なアクセスを想定したアーキテクチャについて考えましたが、想像以上に考えることが多く難しかったです。ですが、学びも多く(新規接続数やデータ容量など)非常に良い経験が出来たと思います。

宮崎(チームL)

チームLでは、マルチリージョンで低レイテンシな通信を実現するインフラ構成をテーマにしました。SA の方々と密に会話できる貴重な機会でしたので、あえて難しい構成を目指しました。構成を議論するに当たって特に気を付けたことは、リージョンや VPC を跨いでも通信可能か、データの同期は問題なく行えるかということでしたが、認証で使用する Cognito や 画像などを保存する S3 はリージョン間でデータの同期がどのように行われるかを調べきれなかったため、片方のリージョンのみに配置することにしました。これにより、一方のリージョンがダウンしてももう一方のリージョンでサービスを継続できるようなアクティブ/アクティブ構成にできなかったのは個人的に悔いが残る点でした。また、 DynamoDB に全てのデータを入れる構成のため、金銭的なコストやパーティションキーの設計で困難を強いられる構成となってしまいました。

これほどクラウドのインフラ構成について考えたのはこの研修が初めてでした。何より SA の方と AWS 各サービスの細かな仕様について議論できたのは貴重な経験で、普段はフロントエンドのコードばかり書いている私にとってインフラ層に興味を持つ良いきっかけになりました。

まとめ

今回の研修では、ディスカッションを通じて、アーキテクティングの際に考慮しなければいけないポイントをおさえることができました。今後、システムアーキテクチャを検討する際に役立てていきたいと思います。

ECS や Amplify のハンズオンでは、簡単に Web アプリを構築できることに驚きました。 AWS をはじめとするクラウドサービスを賢く使いながら、ビジネスに貢献できるエンジニアを目指していきたいです。

また、今回の研修を企画していただいた AWS Japan 様、研修内で一緒になった他社エンジニアの皆様にもこの場を借りて御礼申し上げます。

 

 

ラクスルでは、AWS を利用して Web サービスを展開しており、モブプロなどを通じチームメンバーとディスカッションする環境も豊富にあります。また、技術書買いホーダイ制度など、エンジニアの学習を支援する環境も整備されています!ラクスルで一緒に働いてみたいと思ってくださった方は、こちらのページ (https://recruit.raksul.com/) をご覧いただければ幸いです!

 

 

※本記事で使用されているアーキテクチャ図ではAWS提供のアーキテクチャアイコンを使用しております。また、アーキテクチャ図は他社エンジニアの皆様との共同作成したものを掲載させていただいております。

モブプログラミングへのいざない

こんにちは。ラクスルです。

今回はAMチームで導入している「モブプログラミング(以下モブプロ)」を紹介したいと思います。

モブプログラミングとは

チームのみんなで集まって - 同じ時間に - 同じ場所で - 同じコンピュータを使って - 同じ課題に一緒に取り組む 開発手法です。 ( https://www.slideshare.net/couger2010/at-agile-japan-2017 より )

モブプロの流れ

AMチームでは以下のような流れでモブプロを行なっています。

  • チームメンバーが1か所に集まる(AMチームは全員がリモートワークのため、Slackの通話機能と画面共有機能を利用しています)
  • 実際に手を動かす「ドライバー」を一人決める(残りのメンバーは指示・相談役の「ナビゲーター」になります)
  • タスクに着手する前に、タスクのゴールの共有と、タスクを終了させるためのTODOリストを作成する
  • ドライバーとナビゲーターとで相談しながらコードを書き進める
  • 25分たったら1コマ終了、ドライバーを交代する
    • (ドライバー交代の間に5分ほど休憩を入れてます)
  • 3コマ目が終わったらちょっと長めに30分休憩
  • (上記を繰り返す)

朝の作業開始時間がチームメンバー間でバラバラなので午前中はソロでできそうな作業や個人的な作業を行い、午後から必要があればモブプロを行う、という流れになっています。

モブプロを行うタスク・行わないタスク

タスクによってはモブプロを行わない事もあります。

単純作業や小さなタスクはモブプログラミングするメリットがうすいのでソロで作業することが多いです。逆に技術的難易度が高いものや、不確実性の高いタスクは積極的にモブプログラミングするようにしています。

また、事前に調査が必要なタスクなどは、モブで調査するのは時間の無駄なため、事前にソロで調査を行ってからモブプログラミングするようにしています。

良かった点

(1) 合意と意思決定がその場で行われることによるスピード感

開発の方針に悩んだ時の「相談」から「意思決定」までのスピードがものすごく速い。不確実性の高いタスクをモブプロすることで「相談」から「意思決定」のサイクルを素早く回せて良さそうです。

(2) 「ハマり」時間が減少

書いたコードが思うように動かず、動かない原因も分からない、いわゆる「ハマる」状況におちいることがよくありますが、モブプログラミング中に「ハマり」が発生した際、チームメンバーの誰かが解決策を持っていたおかげで問題が一瞬で解決することが何度もありました。

(3) レビューに費やす時間が減少

モブプログラミングを行うことでレビューに費やす時間を減らすことができましたし、仕様の解釈ミスによる手戻りも減らすことができました。

(4) 個人の効率化テクニックが皆に共有される

ドライバーがどんどん交代するため、各メンバーのちょっとした効率化テクニックを知ることができたのが新鮮で面白かったです。

困った点

モブプログラミングをしていく中でいくつか困った点もありました。

(1) めちゃくちゃ疲れる

モブプログラミングは疲れます。

開発中はチームメンバーとコミュニケーションをとりつづけるので頭を常にフル回転させる必要があります。そのせいか一人でプログラミングしてる時の数倍疲れます(個人の感想です)。1日中モブプログラミングをしてると、終業時間の頃にはもうグッタリです。

「モブプロ疲れ」に対しては、モブプログラミングの時間に上限を設けたりることで対応しているチームがあるようなので ( https://cabi99.hatenablog.com/entry/2019/11/26/145242 ) 今度試してみたいです。

(2) ドライバーの切り替えが辛い

チーム全員がリモートで作業しているため、ドライバー切り替える際に現時点の変更を一度リポジトリへコミットし、次のドライバーのPCへ反映する必要があります。これが地味に辛い…。

まだ試してはいないのですがVisual Studio CodeのLive Share機能を使えばこのへんを解決できるかもしれません。

 

ペアプロとモブプロ

モブプロと似たアプローチとしてペアプログラミング(以下ペアプロ)があります。

ペアプロとモブプロはどちらも同じようなメリットをチームにもたらしますが、モブプロの方がメリットがより強く現れるように感じました。

ペアプロ(2×2) VS モブプロ(4×1)

では、ペアプロ2チーム(2×2)と4人のモブプロ1チーム(4×1)とで、どちらの方が生産性が高いでしょうか?

モブプロ(4×1)とペアプロ(2x2)のどちらを選ぶかは、プロジェクトの不確実性の高さとチームメンバーの習熟度によって変わってくるのではないかと考えています。

プロジェクト開始直後のようにプロジェクト全体の不確実性が高く、チームメンバーの習熟度が低い状態では、モブプロの「意思決定の速さ」や「ハマりの解決速度」がペアプロよりも有効に働くように思います。

逆にプロジェクトの終盤、プロジェクトの不確実性が低下し、チームメンバーの習熟度が上がった状態では、ペアプロやソロプロの方が生産性が上がる気がしています。

おわりに

以上モブプログラミングのご紹介でした。なかなか面白い開発のアプローチなので、みなさんのチームでもぜひ一度お試しください。

また、ラクスルでは一緒に働くエンジニアを募集しています。一緒にモブプロしましょう!

https://recruit.raksul.com/guideline/

参考

 

Apply code-splitting in Novelty front-end side

Hi, I am Nuong, working as a Front-End (FE) developer for the Novelty team. Novelty is an e-commerce website that allows small and medium businesses to do on-demand printing for novelty items. At Novelty, we care a lot about delivering the best user experiences and we are always improving the performance of our website, to make it as fast as possible. In this post, I would like to share how we implement code-splitting for our Javascript on the frontend side to speed up our website.

In the Novelty project, We build our frontend using the VueJs framework. As a typical Vue project, there are many modules with components that represent many features on the UI. However, Novelty is slightly different from other common Vue single page application (SPA) projects, instead of having the FE handling all routing, we still rely on Rails to do our routing for us, and only mounted the necessary components on each page load. Each module on the FE side will be in charge of supporting rendering data for a corresponding web page that is returned from the server-side. The practical approach we applied in integrating the FE code to Rails is quite straightforward, the FE code will be bundled into JS files and those files will be added to the web page similar to other Javascript sprinkles.

Our FE code's bundling pipeline:

Insert to every web page:

The problem

In the beginning, the FE code was bundled into one single file app.jsand this file was added to every webpage that is using FE code for rendering data. As time passed, the project became larger, more features were added, and the FE code size increased as well. As a result, we had to think about the potential issues that could happen with the current bundling method:

  • The size of app.jsbecomes too large: The whole FE code turns into a single file, its size soon be enormous network payload when loaded in the webpage, and increasing the loading time of the page. ( Https://web.dev/total- byte-weight / ).
  • Unused code is included in every page: Each page just needs one corresponding part of code but we always load others along with that.
  • app.js cannot be cached since its contents keep changing every time we change the source code hence the app becomes much slower right after any deployment.
  • Unscoped error: One error while initiating code will affect all pages even if some pages don't even use this block of code.

        Solution

        To solve the above-mentioned problems, we decided to go with code-splitting. This method is not a new technique, it is strongly recommended to apply widely in websites building with ReactJs, VueJs, and other JS frameworks. Code-splitting is a feature supported by bundler Webpack, which we are currently using in the Novelty project, so why don't we take advantage of it? After our plan is clear, we are going to separate code for each router path instead of putting everything in one file as before:

        Then we will add those output assets to corresponding web pages. But at this time, the output assets from FE are still added to the web page templates manually. It did not really matter with only one app.jsfile but manually adding many assets to many templates. And managing the changes is a big challenge. We needed to think about automating this process, and it could need more comprehensive work to achieve this goal, including server-side and FE side work. For that reason, we decided to implement it step by step.

        After analyzing the FE bundle code, we decided to separate only the code for editor page for several reasons:
        • The editor page is using a different template on our server-side code, so it is easy to change from adding app.jsto adding others.
        • The editor page requires the huge fabric.jslib, its size is more than 900KB, which accounts for a significant proportion of the bundled file while it is only useful for the editorpage, not others.

          And what we finally implemented:

          • Created two entries file for webpack
            • editor.entry.ts for editor page.
            • app.entry.ts for the rest pages.
          • Optimized bundle for each entry using optimization option:
            ...
            optimization: { 
              splitChunks: { 
                chunks: 'all', //Optimize for all types of chunks. 
                maxInitialRequests: 2, //Expect maximum number of parallel requests at an entry point is 2 
                minSize: 0,// No restriction 
                maxSize: 0, //No restriction 
                cacheGroups: { 
                  fabric: { // bundle fabric to separated chunk so we can apply longer cache for this file. 
                    test: /[\\/]node_modules[\\/](fabric)[\\/]/, 
                    name: 'fabric', 
                    enforce: true 
                  } 
                } 
              }
            }
            ...

            Output assets:

          • Added output assets to the web page templates.

          After implemented code-splitting, we used Chrome's development tool to measure the effects :

          💡
          Testing environment: Server: Novelty QA2. Date: Sep 28th, 2020. Minify: Unminified

          The file size that we need to deliver through the network is considerably reduced:

          And the performance reported by the Lighthouse tool is positive as well: Editor page:

          Other pages:

          Conclusion

          The result of splitting js code for the editor page is quite positive, even though it is limited to only parts of the site this step inspires us to take more actions to improve the performance of Novelty as much as possible.