20代後半エンジニアである私がこれから学ぶべきこと
私は、現在26歳のWebエンジニアです。これまでの技術に対する学び方と、これからの技術に対する学び方について、少し考えたいと思っています。
これまでの20代前半
新卒入社した当時の私は、業務上、PHP + MySQL on AWS の組み合わせでWebアプリケーション開発を学んでいました。 それとは別に、プライベートでは、Node.js + MongoDB on SAKURA レンタルサーバでWebアプリケーション開発もしていました。
当時、Webアプリケーション開発のフロントエンドとバックエンドをなんとなく動かせる程度で満足していたのですが、 先輩や同僚のエンジニアや、お勧めされた書籍から影響を受け、あらゆるものに興味を示しました。
- SQLや正規表現、文字コードといったエンジニアにとって欠かせない技術
- sedやawk, make といったshellscriptの扱い方
- 手続き型、オブジェクト指向、関数型といった考え方のパラダイムシフトを発生するような考え方
- MVC, MVVM, CleanArchtecture などのアプリケーション設計
- ユニットテストやE2Eテストなどを使ったTDD開発
- CI/CD を活用したDevOps開発
- インフラやミドルウェアの自動構築
- CloudNativeなアプリケーション開発
- SSRやSPA、SEOといったWeb設計
- インタプリタ言語やコンパイラ言語
- コンポーネントベースのフロントエンド開発
- Webゲーム開発
- ビッグデータを扱う技術
- 様々なクラウドサービス技術
- 強化学習
- Bot開発やスクレイプ技術、GASなどの業務改善
Webアプリケーションに関する幅広い領域をあらゆる角度で学んでいったのかなと思います。
これからの20代後半
これからも、興味を持った分野を見つけて、手あたり次第学んでいくのも1つのキャリアだと思います。 ただ、自信過剰という訳じゃないですが、多分やればある程度できるようになれると自負しています。
しかし、私としては、そろそろ広く浅くから、狭く深く学ぶ領域(専門性)を見つけたいと思っています。 どういった領域を突き詰めたいか、考える時がきたのかもしれません。
何を突き詰めたいか
単純にソフトウェア技術を突き詰め、テックリードを目指すか、 プロジェクトマネージャーやエンジニアリングマネージャーといった管理職を目指すか。 それでいうと、前者を目指したい。具体的には、Webに関わる専門性を突き詰めたいなと。 また、アーキテクトのような職業に憧れています。
VueやReactなど言語は違えど、Webアプリケーションの成果物はそう変わりません。 だとすると、あまり似たようなベクトルの言語を学んだところで、面白みが薄いのではと思っています。
それよりも、どのレイヤーにどういう役割を持たせるか、クラスをどのように設計するか、レスポンス速度をより早くするためにはどのようなシステム構成にすべきなのか、そういった視点を考える方が楽しいと最近感じています。
また、アーキテクト的な視点以外に、WebのNative(標準)部分の話やブラウザの話、W3Cの動向など、これからのWebについてキャッチアップし続けることにも、力を注ぎたいと思っています。
それらを踏まえると、『Webの専門性が高いアーキテクト』のような立ち位置を目指したいと思います。
最後に
ポエムみたいな話になってしまいました。以上、最近の悩み事でした。
技術におけるアンテナの張り方 (巨人の肩に乗れ!)
Photo by JESHOOTS.COM on Unsplash
エンジニアは、普段様々なところから技術をキャッチアップすると思います。それは、SNSであったり、ブログであったり、動画であったりです。 そこで、私の技術をキャッチアップするためのアンテナの張り方について、紹介しようと思います。
RSS
RSSは、良いです。不定期にお気に入りの企業やサービスのテクニカルな情報を知ることができます。 特に、大手の企業のブログや、自分自身の関心を持っているサービスのRSSがオススメです。
Tech Blog
- airbnb-engineering
- blog.twitter.com
- eng.uber.com
- engineering.atspotify.com
- engineering.fb.com
- engineering.linkedin.com
- github.blog
- instagram-engineering.com
- medium.engineering
- netflixtechblog.com
- slack.engineering
Web
- blog.chromium.org
- blog.google/products/chrome
- blog.whatwg.org
- discourse.wicg.io/latest
- discourse.wicg.io/posts
- tools.ietf.org
- www.w3.org
CDN
BBS
Book
News
Twitterの公式アカウントをフォローするのも良いです。 また、特定分野に長けているエンジニアの方であったり、コミュリティアカウントもフォローすると良いでしょう。
例えば、私の場合は、次のアカウントをフォローしていたりします。
- Michael Geers (@naltatis) / Twitter
- Micro Frontends in Action の著者
- 勉強会スライドbot (@tech_slideshare) / Twitter
- 日本における勉強会のスライド収集 Bot
- Web Incubator CG (@wicg_) / Twitter
- Web Incubator のコミュニティ
UseCotlin
私の独自ツールです。TwitterAPIを使って、SpeakerdeckやGoogleSlidesなどの技術スライドをSpreadsheetに収集しています。 勉強会やカンファレンスが開催されると、Twitterで宣伝されることが多いため、こちらのツールで自動的にキャッチアップできます。 また、日本だけではなく、世界各国のプレゼンテーションを知ることができます。
Medium
Mediumの有料会員です。Mediumは、Tech系の質の高い投稿が多く充実できます。 無料会員だと、一日の閲覧回数に制限があるため、ちょっとストレスに感じ、有料会員になりました。
Hatena Blog
今日のホットエントリを見て、何が流行りなのか、どういう分野に関心があるのかざっとななめ読みしています。
また、テクノロジだけではなく、総合分野を見ていたりします。
最後に
このネタを思いついたので、勢いで投稿してみました。 もしどなたかの参考になれば、幸いです。
Micro Frontends を調べたすべて
Micro Frontendsに関わる記事を100件以上読みました(参考記事に記載しています)。そこから得たMicro Frontendsについてこの投稿に記録します。 また、調査メモについて、次のリポジトリに残しています。 github.com
発端
実績企業
- Airbnb
- Allegro
- Amazon
- Beamery
- Bit.dev
- BuzzFeed
- CircleCI
- DAZN
- Elsevier
- Entando
- Fiverr
- Hello Fresh
- IKEA
- Klarna
- Microsoft
- Open Table
- OpenMRS
- Otto
- Paypal
- SAP
- Sixt
- Skyscanner
- Smapiot
- Spotify
- Starbucks
- Thalia
- Upwork
- Zalando
- ZEISS
Pros/Cons
Pros
観点 | 内容 |
---|---|
独立性 | ・任意のテクノロジーと任意のチームで開発可能 |
展開 | ・特定の機能をエンドツーエンド(バック、フロント、デプロイ)で確実に実行可能 |
俊敏性 | ・特定のドメインについて最高の知識を持つチーム間で作業を分散すると、リリースプロセスが確実にスピードアップして簡素化される。 ・フロントエンドとリリースが小さいということは、リグレッションテストの表面がはるかに小さいことを意味する。リリースごとの変更は少なく、理論的にはテストに費やす時間を短縮できる。 ・フロントエンドのアップグレード/変更にはコストが小さくなる |
Cons
観点 | 内容 |
---|---|
独立性 | ・独立できず、相互接続しているチームが存在しがち ・多くの機能で複数のマイクロフロントエンドにまたがる変更が必要になり、独立性や自律性が低下 ・ライブラリを共有すること自体は問題ないが、不適切な分割によって作成された任意の境界を回避するための包括的な場所として使用すると、問題が発生する。 ・コンポーネント間の通信の構築は、実装と維持が困難であるだけでなく、コンポーネントの独立性が取り除かれる ・横断的関心事への変更ですべてのマイクロフロントエンドを変更することは、独立性が低下する |
展開 | ・より大きな機能の部分的な実装が含まれているため、個別にリリースできない ・サイト全体の CI / CD プロセス |
俊敏性 | ・重複作業が発生する ・検出可能性が低下した結果、一部の標準コンポーネントを共有できず、個別のフロントエンド間で実装が重複してしまう。 ・共有キャッシュがないと、各コンポーネントは独自のデータセットをプルダウンする必要があり、大量の重複呼び出しが発生する。 |
パフォーマンス | ・マイクロフロントエンドの実装が不適切な場合、パフォーマンスが低下する可能性がある。 |
統合パターン
統合 | 選択基準 | 技術 |
---|---|---|
サーバーサイド統合 | 良好な読み込みパフォーマンスと検索エンジンのランキングがプロジェクトの優先事項であること | ・Podium ・Ara-Framework ・Tailor ・Micromono ・PuzzleJS ・namecheap/ilc |
エッジサイド統合 | サーバーサイド統合と同じ | ・Varnish EDI ・Edge Worker CDN ・ Akamai ・ Cloudfront ・ Fastly ・CloudFlare ・ Fly.io |
クライアント統合 | さまざまなチームのユーザーインターフェイスを 1 つの画面に統合する必要があるインタラクティブなアプリケーションを構築すること | ・Ajax ・Iframe ・Web Components ・Luigi ・Single-Spa ・FrintJS ・Hinclude ・Mashroom |
ビルド時統合 | 他の統合が非常に複雑に思われる場合に、 小さなプロジェクト(3 チーム以下)にのみ使用すること |
・ Bit.dev ・ Open Components ・ Piral |
機能
コミュニケーション
developer.mozilla.org github.com
データ共有
- ストレージ
- URL
- Cookie
- Local Storage/Session Storage
モジュール共有
- webpack
webpack.js.org webpack.js.org webpack.js.org
ルーティング
Vaddin router vaadin.com
キャッシュ
developer.mozilla.org developer.mozilla.org
認証
- JWT
計測
- Google Analytics
- Navigation Timing API
- Resource Timing API
- High Resolution Time API
- User Timing API
- Frame Timing API
- Server Timing API
- Performance Observer
Real User Monitoring
- SpeedCurve
- Catchpoint
- New Relic
- Boomerang.js
- Parfume.js
- sitespeed.io
Synthetics Monitoring
- Lighthouse
- WebpageTest
Proxy
コンポジションプロキシ。テンプレートを組み合わせる。 github.com
アクセス履歴
分割ポリシー
フロントエンドを分割する方針について
- 水平分割
- 画面内にある要素で分割
- ビジネス上の機能
- 垂直分割
- 画面毎に分割
Webサイト⇔Webアプリ
※ Microfrontends: An approach to building Scalable Web Apps
マイクロフロントエンドは、かなりのオーバーラップがあるバンドの中央部分の大部分に最も適しています。バンドの両極端に該当するプロジェクトにマイクロフロントエンドアーキテクチャを実装しようとすると、生産性に反するそうです。
リポジトリ
パターン | Pros | Cons | 技術 |
---|---|---|---|
モノリポ | コードベース全体に簡単にアクセスできる。 (検出可能性が高い) |
モノリポジトリは、特に大規模なチームで作業しているときに、 動作が遅くなる傾向があり、バージョン管理下のコミットとファイルの数が増加する。 |
・nx.dev ・lerna |
マルチリポ | ・マルチリポジトリは、非常に大規模なプロジェクトと それに取り組む非常に大規模なチームがある場合に最適。 |
マルチリポジトリ環境では、各マイクロアプリを 個別にビルドする必要がある。 |
他アーキテクチャ
アーキテクチャ名 | 関係リンク |
---|---|
Modular Monolith | ・Deconstructing the Monolith – Shopify Engineering ・kgrzybek/modular-monolith-with-ddd |
Enterprise Architecture (Clean Architecture) | ・Building an Enterprise Application with Vue ・soloschenko-grigoriy/vue-vuex-ts |
Jam Stack | Jam Stack |
App Shell | App Shell モデル |
書籍
参考記事
- https://blog.bitsrc.io/communication-between-micro-frontends-67a745c6cfbe
- https://medium.com/swlh/luigi-micro-fronteds-orchestrator-8c0eca710151
- https://medium.com/swlh/micro-frontends-in-action-221d4ed81c35
- https://medium.com/swlh/problems-with-micro-frontends-8a8fc32a7d58
- https://levelup.gitconnected.com/podium-easy-server-side-micro-frontends-385f3a4cd346
- https://levelup.gitconnected.com/micro-frontend-curry-506b98a4cfc0
- https://medium.com/javascript-in-plain-english/demystify-micro-frontends-using-component-libraries-53aa9a33cf5b
- https://medium.com/@areai51/microfrontends-an-approach-to-building-scalable-web-apps-e8678e2acdd6
- https://medium.com/@shubhranshutiwari07/micro-frontend-microfe-is-superman-part-1-basic-understanding-architectures-21970d3fc218
- https://medium.com/better-programming/5-steps-to-turn-a-random-react-application-into-a-micro-frontend-946718c147e7
- https://medium.com/@lucamezzalira/micro-frontends-decisions-framework-ebcd22256513
- https://medium.com/hacking-talent/two-years-of-micro-frontends-a-retrospective-522526f76df4
- https://medium.com/@sagiv.bengiat/integrate-react-with-other-applications-and-frameworks-94d443e3cc3f
- https://medium.com/js-dojo/serverless-micro-frontends-using-vue-js-aws-lambda-and-hypernova-835d6f2b3bc9
- https://medium.com/swlh/micro-frontend-using-web-components-e9faacfc101b
- https://medium.com/@tomsoderlund/micro-frontends-a-microservice-approach-to-front-end-web-development-f325ebdadc16
- https://medium.com/@PepsRyuu/micro-frontends-341defa8d1d4
- https://medium.com/hepsiburadatech/hepsiburada-micro-frontend-d%C3%B6n%C3%BC%C5%9F%C3%BCm%C3%BC-4c2f26b8dcae
- https://medium.com/javascript-in-plain-english/create-micro-frontends-using-web-components-with-support-for-angular-and-react-2d6db18f557a
- https://medium.com/hackernoon/understanding-micro-frontends-b1c11585a297
- https://medium.com/javascript-in-plain-english/micro-frontends-made-easy-e49acceea536
- https://itnext.io/building-micro-frontend-applications-with-angular-elements-34483da08bcb
- https://blog.pragmatists.com/independent-micro-frontends-with-single-spa-library-a829012dc5be
- https://blog.bitsrc.io/state-of-micro-frontends-9c0c604ed13a
- https://medium.com/stepstone-tech/microfrontends-extending-service-oriented-architecture-to-frontend-development-part-1-120b71c87b68
- https://medium.com/bb-tutorials-and-thoughts/6-different-ways-to-implement-micro-frontends-with-angular-298bc8d79f6b
- https://medium.com/@benjamin.d.johnson/exploring-micro-frontends-87a120b3f71c
- https://medium.com/hacking-talent/using-micro-frontends-to-permanently-solve-the-legacy-javascript-problem-5fba18b0ceac
- https://medium.com/dazn-tech/micro-frontends-the-future-of-frontend-architectures-5867ceded39a
- https://medium.com/swlh/build-micro-frontends-using-angular-elements-the-beginners-guide-75ffeae61b58
- https://medium.com/dazn-tech/adopting-a-micro-frontends-architecture-e283e6a3c4f3
- https://codeburst.io/breaking-a-large-angular-app-into-microfrontends-fb8f985d549f
- https://medium.com/dazn-tech/orchestrating-micro-frontends-a5d2674cbf33
- https://tech.buzzfeed.com/micro-frontends-at-buzzfeed-b8754b31d178
- https://blog.bitsrc.io/serverless-microfrontends-in-aws-999450ed3795
- https://medium.com/dazn-tech/identifying-micro-frontends-in-our-applications-4b4995f39257
- https://medium.com/@gilfink/avoiding-the-framework-catholic-wedding-using-stencil-compiler-3c2aa55bcaca
- https://medium.com/@lucamezzalira/building-micro-frontends-the-book-a2b531d0279a
- https://blog.bitsrc.io/tools-and-practices-for-microfrontends-dab0283393f2
- https://medium.com/better-programming/thoughts-about-micro-frontends-in-2020-dd95eb7216f
- https://medium.com/@rangleio/five-things-to-consider-before-choosing-micro-frontends-f685e71bdd76
- https://blog.bitsrc.io/how-we-achieved-smooth-navigation-across-micro-frontends-42130577924d
- https://eng.collectivehealth.com/gracefully-scaling-web-applications-with-micro-frontends-part-i-162b1e529074
- https://eng.collectivehealth.com/gracefully-scaling-web-applications-with-micro-frontends-part-ii-8fa730d05b14
- https://medium.com/bb-tutorials-and-thoughts/should-we-frameworks-for-micro-frontends-35f9f15b7821
- https://medium.com/javascript-in-plain-english/microfrontends-bringing-javascript-frameworks-together-react-angular-vue-etc-5d401cb0072b
- https://medium.com/@rchaves/building-microfrontends-part-i-creating-small-apps-710d709b48b7
- https://blog.bitsrc.io/6-patterns-for-microfrontends-347ae0017ec0
- https://medium.jonasbandi.net/frontend-monoliths-run-if-you-can-voxxed-day-zuerich-2019-d8d714ff361a
- https://medium.com/@gilfink/why-im-betting-on-web-components-and-you-should-think-about-using-them-too-8629396e27a
- https://medium.com/@ScriptedAlchemy/webpack-5-module-federation-stitching-two-simple-bundles-together-fe4e6a069716
- https://medium.com/passionate-people/my-experience-using-micro-frontends-e99a1ad6ed32
- https://engineering.contaazul.com/evolving-an-angularjs-application-using-microfrontends-2bbcac9c023a
- https://blog.bitsrc.io/11-popular-misconceptions-about-micro-frontends-d5daecc92efb
- https://medium.com/js-dojo/micro-frontends-using-vue-js-react-js-and-hypernova-af606a774602
- https://medium.com/linedevth/micro-frontends-the-new-era-of-front-end-edge-technology-cb981ad26eae
- https://blog.bitsrc.io/sharing-dependencies-in-micro-frontends-9da142296a2b
- https://medium.com/@pyaesonenyein/micro-frontends-part-one-95ea3d939bc6
- https://medium.com/outbrain-engineering/micro-front-ends-doing-it-angular-style-part-1-219c842fd02e
- https://levelup.gitconnected.com/brief-introduction-to-micro-frontends-architecture-ec928c587727
- https://itnext.io/prototyping-micro-frontends-d03397c5f770
- https://blog.bitsrc.io/mini-web-apps-a-bounded-context-for-microfrontends-with-microservices-f1482af9276f
- https://medium.com/trendyol-tech/micro-frontends-how-it-changed-our-development-process-a5cf667356da
- https://medium.embengineering.com/micro-front-end-and-web-components-ce6ae87c3b7f
- https://medium.com/@witek1902/ui-in-microservices-world-micro-frontends-pattern-and-web-components-23607a569363
- https://medium.com/stepstone-tech/microfrontends-part-2-integration-and-communication-3385bc242673
- https://blog.bitsrc.io/building-react-microfrontends-using-piral-c26eb206310e
- https://medium.com/js-dojo/implementing-microfrontends-in-nuxt-js-using-svelte-and-ara-framework-8c06b683472c
- https://itnext.io/implementing-microfrontends-in-gatsbyjs-using-ara-framework-a95ee79cc0e7
- https://itnext.io/strangling-a-monolith-to-micro-frontends-decoupling-presentation-layer-18a33ddf591b
- https://itnext.io/page-building-using-micro-frontends-c13c157958c8
- https://medium.com/notonlycss/micro-frontends-architecture-1407092403d5
- https://medium.com/soluto-nashville/not-so-micro-frontends-building-a-reverse-proxy-f41ab5cde81c
- https://medium.com/@armand1m_/why-micro-frontends-might-not-work-for-you-5a810b4687b0
- https://medium.embengineering.com/micro-front-ends-webpack-manifest-b05fc63a0d53
- https://medium.com/better-programming/you-dont-have-to-lose-optimization-for-micro-frontends-60a63d5f94fe
- https://medium.com/wix-engineering/3-ways-micro-frontends-could-improve-your-life-dev-velocity-and-product-97ff611881b5
- https://medium.com/oracledevs/microservice-approach-for-web-development-micro-frontends-1cba93d85021
- https://medium.com/@miki.lombi/micro-frontends-from-the-00s-to-20s-19b37efece6d
- https://medium.com/@soroushchehresa/deep-dive-into-the-micro-frontends-approach-c2ba1e5cd689
- https://medium.embengineering.com/micro-front-ends-server-side-rendering-2b515220a56e
- https://medium.com/wehkamp-techblog/sharing-server-code-between-micro-sites-4f23359101e5
- https://medium.com/@mikkanthrope/sso-with-jwt-and-react-micro-frontends-811f0fcc4121
- https://itnext.io/the-micro-frontends-journey-tech-agnostic-principle-b61414b19505
- https://medium.com/@singh.architsinghaim/micro-front-ends-dc105f5c0fea
- https://medium.embengineering.com/micro-front-ends-76171c02ab17
- https://medium.com/codingtown/micro-frontends-mystery-8b51b6e2f7f9
- https://medium.com/rangle-io/micro-frontends-and-the-rise-of-federated-applications-265171bcb346
- https://medium.com/@felipegaiacharly/the-micro-frontends-journey-tech-agnostic-principle-b61414b19505
- https://medium.com/better-practices/how-postman-engineering-does-microservices-aa026a3d682d
- https://medium.com/ergonode/create-your-own-vue-micro-frontend-architecture-with-vuems-library-f054233b97cb
- https://blog.bitsrc.io/how-to-develop-microfrontends-using-react-step-by-step-guide-47ebb479cacd
- https://medium.com/jit-team/microfrontends-should-i-care-12b871f70fa3
- https://medium.com/mailup-group-tech-blog/micro-frontends-in-the-mailup-console-82a81e712cfe
- https://towardsdatascience.com/looking-beyond-the-hype-is-modular-monolithic-software-architecture-really-dead-e386191610f8
- https://medium.com/swlh/developing-and-deploying-micro-frontends-with-single-spa-c8b49f2a1b1d
- https://levelup.gitconnected.com/easy-svelte-micro-frontends-with-podium-34aa949bed02
- https://medium.com/swlh/react-vue-svelte-on-one-page-with-micro-frontends-f740b3ee6979
- https://blog.bitsrc.io/using-es-modules-with-dynamic-imports-to-implement-micro-frontends-7c840a38890e
- https://medium.com/@jh.rossa/micro-frontend-federation-today-and-tomorrow-4eda3ab69409
- https://medium.com/design-and-tech-co/modular-monoliths-a-gateway-to-microservices-946f2cbdf382
- https://medium.com/swlh/implementing-micro-frontends-using-react-8d23b7e0a687
- https://medium.com/javascript-in-plain-english/javascript-monorepo-with-lerna-5729d6242302
- https://levelup.gitconnected.com/a-micro-frontend-solution-for-react-1914b19663b
- https://medium.com/@lucamezzalira/i-dont-understand-micro-frontends-88f7304799a9
- https://floqast.com/engineering-blog/post/implementing-a-micro-frontend-architecture-with-react/
- https://blog.bitsrc.io/how-we-build-micro-front-ends-d3eeeac0acfc
- https://medium.com/upwork-engineering/modernizing-upwork-with-micro-frontends-d5be5ec1d9a
- https://blog.bitsrc.io/implementing-micro-front-end-with-single-spa-and-react-eeb4364100f
- https://www.redhat.com/en/blog/5-benefits-using-micro-frontends-build-process-driven-applications
- https://medium.com/swlh/cross-app-bundling-a-different-approach-for-micro-frontends-e4f212b6a9a
- https://www.esentri.com/composing-micro-frontends-server-side
- https://dev.to/dabit3/building-micro-frontends-with-react-vue-and-single-spa-52op
- https://dev.to/florianrappl/11-popular-misconceptions-about-micro-frontends-463p
- https://dev.to/rsschouwenaar/thoughts-about-micro-frontends-in-2020-39ed
- https://dev.to/onerzafer/understanding-micro-frontends-1ied
- https://dev.to/aregee/breaking-down-the-last-monolith-micro-frontends-hd4
- https://dev.to/thejoin95/micro-frontends-from-the-00s-to-20s-5a2
- https://dev.to/florianrappl/communication-between-micro-frontends-41fe
- https://dev.to/phodal/micro-frontend-architecture-in-action-4n60
- https://dev.to/jondearaujo/the-approaches-and-challenges-of-micro-frontends-a-theoretical-introduction-176
- https://dev.to/scriptedalchemy/micro-frontend-architecture-replacing-a-monolith-from-the-inside-out-3ali
- https://dev.to/abhinavnigam2207/an-approach-to-micro-frontend-architecture-mvp-with-nextjs-2l84
- https://dev.to/jamesmh/using-micro-uis-to-extend-legacy-web-applications-166
- https://dev.to/jonisar/11-must-know-frontend-trends-for-2020-13e1
- https://dev.to/manfredsteyer/6-steps-to-your-angular-based-microfrontend-shell-1nei
- https://dev.to/coroutinedispatcher/working-on-modularising-android-app-314c
- https://dev.to/remast/my-software-architecture-resources-g38
- https://dev.to/open-wc/open-wc-scoped-elements-3e47
- https://medium.com/cdiscount-engineering/microservices-frontend-module-federation-an-handsome-promise-3b309944c215
- https://medium.com/@infoxicator/what-is-holocron-224255625241
- https://medium.com/paypal-engineering/how-micro-frontend-has-changed-our-team-dynamic-ba2f01597f48
- https://dev.to/kleeut/how-do-you-share-authentication-in-micro-frontends-5glc
- https://github.com/ChristianUlbrich/awesome-microfrontends
- https://github.com/rajasegar/awesome-micro-frontends
- https://github.com/MPankajArun/awesome-micro-frontends
- https://github.com/phodal/microfrontends
- https://martinfowler.com/articles/micro-frontends.html
- https://thenewstack.io/microfrontends-the-benefits-of-microservices-for-client-side-development
- https://allegro.tech/2016/03/Managing-Frontend-in-the-microservices-architecture.html
- https://engineering.hellofresh.com/front-end-microservices-at-hellofresh-23978a611b87
- http://tech.opentable.co.uk/blog/2016/04/27/opencomponents-microservices-in-the-front-end-world/
- http://tech.opentable.co.uk/blog/2015/02/09/dismantling-the-monolith-microsites-at-opentable/
- https://medium.com/@matteofigus/5-years-of-opencomponents-3114e6d6a35b
- https://blog.senacor.com/microfrontends/
- https://www.infoq.com/news/2018/08/experiences-micro-frontends/
- https://dzone.com/articles/building-micro-frontends-with-single-spa-and-react
- https://www.agilechamps.com/microservices-to-micro-frontends/
- https://gustafnk.github.io/microservice-websites/
- https://hub.packtpub.com/what-micro-frontend/
- https://www.thoughtworks.com/de/radar/techniques/micro-frontends
- http://blog.wolksoftware.com/microlibraries-the-future-of-web-development
- https://xebia.com/blog/the-monolithic-frontend-in-the-microservices-architecture/
- https://x-team.com/blog/micro-frontend/
- https://menelaos.dev/devweek-sf-2020/
- https://www.infoq.com/news/2020/07/microfrontends-vue-yoav-yanovski/
- https://www.infoq.com/articles/microfrontends-business-needs
- https://www.infoq.com/articles/architecture-trends-2020/
- https://www.infoq.com/news/2018/08/experiences-micro-frontends/
- https://www.infoq.com/news/2020/01/strategies-micro-frontends/
- https://speakerdeck.com/kimh/k8stotraefikdetukurumaikurohurontoendo
Zalando tailor で Micro Frontends with ( LitElement & etcetera)
Photo by Kenny Luo on Unsplash
Zalando社が開発したTailorを使って、サンプルWebアプリをMicro Frontendsで構築してみました。Tailorはサーバーサイドで統合するアーキテクチャです。クライアントサイドは、Web Componentsで作られているLit Elementを使って統合しました。どういった内容か、ここに投稿しようと思います。
作ったリポジトリは、下記に残しています。 github.com
全体構成
ざっくり説明すると、HTMLからTailorに対してフラグメント(コンポーネント)を取得・返却するようにします。各フラグメントは、LitElementでWebComponentsを定義させたJavascriptを指します。フラグメントを読み込むだけで、カスタムエレメントを使えるようになります。
Tailor
A streaming layout service for front-end microservices
tailorは、ストリーミングレイアウトサービスというだけあって、fragmentのloadをストリーミングするそうです。(こちらのライブラリは、FacebookのBigPipe に影響されたそう)
まず、tailor.jsのHTMLテンプレートは次のとおりです。
templates/index.html
<body> <div id="outlet"></div> <fragment src="http://localhost:7000" defer></fragment> <fragment src="http://localhost:8000" defer></fragment> <fragment src="http://localhost:9000" defer></fragment> </body>
これらのfragmentの取得は、tailor.jsを経由します。
tailor.js
const http = require('http') const Tailor = require('node-tailor') const tailor = new Tailor({ templatesPath: __dirname + '/templates' }) http .createServer((req, res) => { req.headers['x-request-uri'] = req.url req.url = '/index' tailor.requestHandler(req, res) }) .listen(8080)
x-request-uriは、後ろのフラグメントにURLを引き継ぐためのようです。 そして、フラグメントサーバーは、次のとおりです。
fragments.js
const http = require('http') const url = require('url') const fs = require('fs') const server = http.createServer((req, res) => { const pathname = url.parse(req.url).pathname const jsHeader = { 'Content-Type': 'application/javascript' } switch(pathname) { case '/public/bundle.js': res.writeHead(200, jsHeader) return fs.createReadStream('./public/bundle.js').pipe(res) default: res.writeHead(200, { 'Content-Type': 'text/html', 'Link': '<http://localhost:8000/public/bundle.js>; rel="fragment-script"' }) return res.end('') } }) server.listen(8000)
fragments.jsは、Response HeaderにLinkヘッダを追加するようにします。Tailorは、このヘッダのJavascriptを読み込むことになります。
さらに、fragments.jsは、Linkヘッダで指定されたリクエストを return fs.createReadStream('./public/bundle.js').pipe(res)
でストリームのパイプを返すそうです。
Lerna
それぞれのフラグメントをLernaで管理するようにします。 私は、下記のようなpackages分けをしました。
- common
- 共通する変数・ライブラリ
- fragment
- LitElementのカスタムエレメント定義
- function
- フラグメントと連携する関数 (ヒストリーやイベントなど)
具体的に言うと、次のようなものを用意しました。
directoy name | package name |
---|---|
packages/common-module | @type/common-module |
packages/common-variable | @type/common-variable |
packages/fragment-auth-components | @auth/fragment-auth-components |
packages/fragment-product-item | @product/fragment-product-item |
packages/fragment-search-box | @search/fragment-search-box |
packages/function-event-hub | @controller/function-event-hub |
packages/function-history-navigation | @controller/function-history-navigation |
packages/function-renderer-proxy | @controller/function-renderer-proxy |
packages/function-search-api | @search/function-search-api |
packages/function-service-worker | @type/function-service-worker |
どの名前も、その時の気分で雑に設定したので、気にしないでください。(笑) 伝えたいのは、@XXX が1チームで管理する領域みたいなことをしたかっただけです。
packageを使いたい場合は、次のような依存を設定します。
package.json
{ "dependencies": { "@controller/function-event-hub": "^0.0.0", "@type/common-variable": "^0.0.0", } }
LitElement
lit-element.polymer-project.org
LitElement A simple base class for creating fast, lightweight web components
純粋なWebComponentsだけを使えばよかったのですが、次のような理由で LitElementを使いました。
まあ、特にこだわりはないです。 書き方は、次のとおりです。
import {LitElement, html, customElement, css, property} from 'lit-element'; @customElement('product-item') export class ProductItem extends LitElement { static styles = css` :host { display: block; border: solid 1px gray; padding: 16px; max-width: 800px; } `; @property({type: String}) name = ``; render() { return html`<div>${this.name}</div>`; } } declare global { interface HTMLElementTagNameMap { 'product-item': ProductItem; } }
LitElement + Typescript では、open-testing を使ってテストすることができます。 github.com
また、jestでもテストができるようです。
DynamicRendering
このサンプルでは、カスタムエレメントを使って、ブラウザ側でレンダリングする 所謂SPAの動きで構築しています。 『SEOガー!』とSSRしなきゃと思う訳ですが、正直SSRを考えたくないです。(ハイドレーションなんて無駄なロードをブラウザにさせたくない) 次の記事のように、ボットのアクセスのみに、ダイナミックレンダリングした結果(SPAのレンダリング結果HTML)を返すようにしたいです。
技術的には、次のようなものを使えば良いです。
function-renderer-proxy/src/renderer.ts
... const page = await this.browser.newPage(); // browser: Puppeteer.Browser ... const result = await page.content() as string; // Puppeteerのレンダリング結果コンテンツ(HTML)
要は、Puppeteerで実際にレンダリングさせた結果をBotに返却しているだけです。
EventHub
フラグメント同士は、CustomEventを通して連携します。
https://developer.mozilla.org/ja/docs/Web/Guide/Events/Creating_and_triggering_eventsdeveloper.mozilla.org
全て、このCustomEventとAddEventListenerを管理するEventHub(packages名)を経由するようにします。(理想)
History
ページ全体のヒストリーは、HistoryNavigation(packages名)で管理したいと考えています。(理想)
また、ルーティングを制御する Web Components向けライブラリ vaadin/router も便利そうだったので導入してみました。
ShareModule
LitElementのようなどこでも使っているライブラリは、共通化してバンドルサイズを縮めたいです。 Webpackのようなバンドルツールには、ExternalやDLLPlugin、ModuleFederationなどの共通化機能があります。
今回は、externalを使っています。
common-module/common.js
exports['rxjs'] = require('rxjs') exports['lit-element'] = require('lit-element') exports['graphql-tag'] = require('graphql-tag') exports['graphql'] = require('graphql') exports['apollo-client'] = require('apollo-client') exports['apollo-cache-inmemory'] = require('apollo-cache-inmemory') exports['apollo-link-http'] = require('apollo-link-http')
common-module/webpack.config.js
module.exports = { entry: './common.js', output: { path: __dirname + '/public', publicPath: 'http://localhost:6006/public/', filename: 'bundle.js', libraryTarget: 'amd' } }
共通化したライブラリは、次のTailorのindex.htmlで読み込みます。
templates/index.html
<script> (function (d) { require(d); var arr = [ 'lit-element', 'rxjs', 'graphql-tag', 'apollo-client', 'apollo-cache-inmemory', 'apollo-link-http', 'graphql' ]; while (i = arr.pop()) (function (dep) { define(dep, d, function (b) { return b[dep]; }) })(i); }(['http://localhost:6006/public/bundle.js'])); </script>
そうすると、例えばsearchBoxのwebpackでは、次のようなことが使えます。
fragment-search-box/webpack.config.js
externals: { 'lit-element': 'lit-element', 'graphql-tag': 'graphql-tag', 'apollo-client': 'apollo-client', 'apollo-cache-inmemory': 'apollo-cache-inmemory', 'apollo-link-http': 'apollo-link-http', 'graphql': 'graphql' }
その他
その時の気分で導入したものを紹介します。(or 導入しようと考えたもの)
GraphQL
APIは、雑にGraphQLを採用しました。特に理由はありません。
SkeltonUI
Skelton UIも使ってみたいなと思っていました。
Reactを使わなくても、CSSの@keyframesを使えば良いでしょう。が、まあ使っていません。(笑)
Rxjs
typescriptの処理をリアクティブな雰囲気でコーディングしたかったので導入してみました。
(リアクティブに詳しい人には、怒られそうな理由ですね...笑)
所感
これまで、Podium、Ara-Framework, そして Tailor といったMicro Frontendsに関わるサーバーサイド統合ライブラリを使ってみました。
silverbirder180.hatenablog.com silverbirder180.hatenablog.com
これらは、どれも考え方が良いなと思っています。 Podiumのフラグメントのインターフェース設計、Ara-FrameworkのRenderとデータ取得の明確な分離、そしてTailorのストリーム統合です。 しかし、これらは良いライブラリではありますが、プロダクションとしてはあんまり採用したくない(依存したくない)と思っています。
むしろ、もっと昔から使われていた Edge Side Includeや Server Side Include などを使ったサーバーサイド統合の方が魅力的です。 例えば、Edge Worker とか良さそうです。(HTTP2やHTTP3も気になります)
まあ、まだ納得いくMicro Frontendsの設計が発見できていないので、これからも検証し続けようと思います。
Ara-Framework で Micro Frontends with SSR
みなさん、こんにちは。silverbirder です。 私の最近の興味として、Micro Frontends があります。 silverbirder180.hatenablog.com 今、Ara-Frameworkというフレームワークを使った Micro Frontends のアプローチ方法を学んでいます。
Ara-Framework とは
Build Micro-frontends easily using Airbnb Hypernova
※ https://ara-framework.github.io/website/
Ara-Frameworkは、Airbnbが開発したHypernovaというフレームワークを使って、Micro Frontendsを構築します。
Airbnb Hypernova とは
A service for server-side rendering your JavaScript views
※ https://github.com/airbnb/hypernova
簡単に説明すると、Hypernovaはデータを渡せばレンダリング結果(HTML)を返却してくれるライブラリです。 これにより、データ構築とレンダリングを明確に分離することができるメリットがあります。
Ara-Framework アーキテクチャ
Ara-Frameworkのアーキテクチャ図は、次のようなものです。
※ https://ara-framework.github.io/website/docs/nova-architecture
構成要素は、次のとおりです。(↑の公式ページにも説明があります)
- Nova Proxy
- Nova Directive (Layout)
- 全体のHTMLを構築します。Hypernovaのプレースホルダーを埋め込みます。
- Node.js, Laravel, Jinja2 が対応しています。
- Nova Cluster
- Nova Bindingを管理するクラスタです。
- Nova ProxyとNova Bindings の間に位置します。
- Nova Bindings (Hypernova)
- データを渡されて、HTMLをレンダリングした結果を返します。 (Hypernovaをここで使います)
- React, Vue.js, Angular, Svelte, Preact が対応しています。
このように、LayoutとRendering (Nova Bindings) を明確に分けることで、独立性、スケーラビリティ性が良いのかなと感じます。 各レイアの間にキャッシュレイヤを設けることでパフォーマンス向上も期待できます。
詳しくは、公式ページをご確認下さい。
Ara-Framework サンプルコード
Ara-Frameworkを実際に使ってみました。サンプルコードは下記にあげています。 github.com
package.json はこんな感じです。
package.json
"scripts": { "cluster": "cd cluster && PORT=5000 ara run:cluster --config ./views.json", "layout": "cd layout && PORT=8080 node ./bin/www", "proxy": "cd proxy && HYPERNOVA_BATCH=http://localhost:5000/batch PORT=8000 ara run:proxy --config ./nova-proxy.json", "search:dev": "cd search && PORT=3000 ./node_modules/webpack/bin/webpack.js --watch --mode development", "product:dev": "cd product && PORT=3001 ./node_modules/webpack/bin/webpack.js --watch --mode development", "dev": "concurrently -n cluster,layout,proxy,search,product \"npm run cluster\" \"npm run layout\" \"npm run proxy\" \"npm run search:dev\" \"npm run product:dev\"", }
作っていく手順は、次の流れです。
- Nova Proxy を作成
- Nova Directive (Layout) を作成
- Nova Cluster を作成
- Nova Bindings (Hypernova) を作成
Ara-Framework を使うためには、次の準備をしておく必要があります。
$ npm i -g ara-cli
Nova Proxy
Nova Proxyは、Nova DirectiveへProxyしますので、そのhostを書きます。
nova-proxy.json
{ "locations": [ { "path": "/", "host": "http://localhost:8080", "modifyResponse": true } ] }
また、Nova Proxyは、Nova Clusterへ問い合わせするため、HYPERNOVA_BATCH
という変数にURLを指定する必要があります。
Nova Proxyを動かすときは、次のコマンドを実行します。
$ HYPERNOVA_BATCH=http://localhost:5000/batch PORT=8000 ara run:proxy --config ./nova-proxy.json
Nova Directive (Layout)
Nova Directvieは、hypernova-handlebars-directive
を使います。
これは、Node.jsのhandlebarsテンプレートエンジン(hbs)で使えます。
Expressの雛形を生成します。
$ npx express-generator -v hbs layout
詳細は割愛しますが、次のHTMLファイル(hbs)を作成します。
※ 詳しくはこちら https://ara-framework.github.io/website/docs/render-on-page
layout/index.hbs
<h1>{{title}}</h1> <p>Welcome to {{title}}</p> {{>nova name="Search" data-title=title }} <script src="http://localhost:3000/public/client.js"></script> <script src="http://localhost:3001/public/client.js"></script>
{{>nova}}
がHypernovaのプレースホルダーである hypernova-handlebars-directive
です。
nameは、Nova Bindingsの名前 (後ほど説明します)、data-*は、Nova Bindingsに渡すデータです。
また、scriptでclient.jsをloadしているのは、CSRを実現するためです。
動かすのは、Expressを動かすときと同じで、次になります。
$ PORT=8080 node ./bin/www
Nova Cluster
Nova Clusterは、Nova Bindingsを管理します。
views.json
{ "Search": { "server": "http://localhost:3000/batch" }, "Product": { "server": "http://localhost:3001/batch" } }
SearchやProductは、後ほど作成するNova Bindingsの名前です。serverは、Nova Bindingsが動いているURLです。
Nova Clusterを動かすときは、次のコマンドを実行します。
$ PORT=5000 ara run:cluster --config ./views.json
Nova Bindings
Nova Bindings を作るために、次のコマンドを実行します。
$ ara new:nova search -t react $ ara new:nova product -t vue
そこから、自動生成されたディレクトリから、少し修正したものが次のとおりです。
search/Search.jsx
import React, { Component } from 'react' import { Nova } from 'nova-react-bridge' class Search extends Component { render() { <div> <div>Search Components!</div> <table> <tr> {['🐙', '🐳', '🐊', '🐍', '🐷', '🐶', '🐯'].map((emoji, key) => { return <td key={key}> <Nova name="Product" data={{title: emoji}}/> </td> })} </tr> </table> </div> } }
今までの説明ではなかったですが、Nova Bridge である nova-react-bridge
を使っています。
これは、Nova Directiveに似ているのですが、使えるファイルが ReactやVue.jsなどのJSフレームワークに対応しています。
そのため、Nuxt.jsやNext.js,Gatsby.js にも使えるようになります。
※ わかりにくいですが、このサンプルのNova Bridgeは、CSRで動作します。SSRで動作させるためには、Nova Proxyを挟む必要が (たぶん) あります。
product/Product.vue
<template> <div>{{title}}</div> </template> <script> export default { props: ['title'] } </script>
Nova Bindingsのこれらを動作させるためには、次のコマンドを実行します。
# search $ PORT=3000 ./node_modules/webpack/bin/webpack.js --watch --mode development # product $ PORT=3001 ./node_modules/webpack/bin/webpack.js --watch --mode development
動作確認
今まで紹介したものを同時に実行する必要があります。
そこで、concurrently
を使います。
$ concurrently -n cluster,layout,proxy,search,product "npm run cluster" "npm run layout" "npm run proxy" "npm run search:dev" "npm run product:dev"
動作として、次のような画像になります。
最後に
繰り返しますが、Ara-Framework を使うとデータ構築(Nova Directive)とレンダリング(Nova Bindings)を明確に分離できます。 また、レンダリング部分は、それぞれ独立できます。今回紹介していないAPI部分は、誰がどのように管理するのか考える必要があります。
ただ、Nova Bindingsで使用するCSR用javascriptは、重複するコードが含まれてしまい、ブラウザロード時間が長くなってしまいます。 そこで、webpack 5から使えるようになったFederation機能を使って解決するとった手段があります。
Ara-Frameworkの紹介でした!