Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Road to SPA #452

Open
lightnet328 opened this issue Jun 7, 2019 · 13 comments
Open

Road to SPA #452

lightnet328 opened this issue Jun 7, 2019 · 13 comments
Assignees

Comments

@lightnet328
Copy link
Member

@lightnet328 lightnet328 commented Jun 7, 2019

Overview

Currently, views are built with Template Engine (Swig), jQuery and React.
I propose migrating to SPA based on component orientation to achieve better user experience and development experience.

Why

Because I want to eliminate the waste of communication with the back-end and rendering at the time of page transition for migrating to SPA as a modern front-end application that runs at high speed.

Implementation flow

Let rendering responsibilities come near the front-end

First, rewrite templates written in Swig to React components with appropriate granularity.
If the target depends on jQuery, it also rewrites to React component.
From now on, React components create in Functional Component, define types in TypeScript, and define styles in styled-components.

Front-end holds global state

Adopt Redux to manage global state at front-end.
After being injected into HTML from back-end, the state managed by the Crowi instance, etc. will be managed by Redux at this point.

Recently, react-redux supported the hooks API in React v 7.1.0.
Adopt react-redux@v7.1.0 to connect to Store using hooks.

https://github.com/reduxjs/react-redux/releases/tag/v7.1.0

Front-end responsible for page routing and rendering

Introduce React Router and route components on front-end.
As a result, back-end has API, static file, fallback to SPA routing definitions only, and front-end is responsible for page routing.

In addition, global level state is not injected from back-end because the browser does not cause page transition.
At this point, all Swig templates are not present in back-end, and front-end is responsible for rendering the page.
Furthermore, almost all styles are migrated from SCSS to styled-components by componentizing even top-level elements.

Tasks

  • Introduce and migrate to TypeScript (@lightnet328, @otofune) (#402, #486)
  • Upgrade React to v16.8 (@lightnet328) (#420)
    • To be able to use Hooks
  • Introduce styled-components (@lightnet328) (#538)
  • Make Swig templates to React components
    • Page creation modal (@saitoeku3) (#606)
    • Page deletion modal
    • Help modal
    • Page name tips modal
    • Portalization modal
    • Page name change modal
    • Unportalization modal
    • Sign in / Sign up modal
    • What is a portal (@okonomi) (#604)
    • User page
    • Installer page
    • Presentation page
    • Invitation page
    • User settings page
    • External share pages (@lightnet328)
    • Admin pages (@lightnet328) (#423)
    • Comments (@lightnet328) (#424)
    • Page edit page (Editor) (@sotarok)
  • Introduce react-helmet
  • Introduce react-redux@v7.1.0
  • Migrate existing the global state to Redux
    • Manage state related to auth
    • Manage state related to search
  • Introduce React Router
  • Route on front-end
    • User page
    • List / Portal page
    • Page
    • Shared page
    • Bookmark page
    • Recent created page list page
    • Search result page
    • Installer page
    • Presentation page
    • Invitation page
    • User settings page
    • Sign in / Sign up page
    • Admin pages
    • Page edit page (Editor)

Contributing

I created this proposal to more people be able to participate in the discussion and implementation by writing down and publish the specification and implementation flow before implementing a architecture or function that requires bold changes.

Please provide review or feedback on this proposal in this Issue comment. I look forward to your contribution🙏

Japanese

概要

現在のCrowiのビューはTemplate Engine (Swig)とjQueryとReactで構築されています。
より良いユーザー体験と開発体験を実現するためにコンポーネント指向に基づいてSPAに移行することを提案します。

何故やるか

ページ遷移時の通信やレンダリングの無駄を無くし、高速に動作するモダンフロントエンドアプリケーションとして実装をSPAに移行していきたいから。

実装の流れ

レンダリングの責務をフロントエンドに寄せる

まず、Swig で書かれたテンプレートを適切な粒度でReact コンポーネントに書き換えます。
書き換えた対象がjQueryに依存されていた場合はjQueryのコードもReact コンポーネントに書き換えます。
これから作成するReact コンポーネントはFunctional Componentで作成し、型をTypeScriptで、スタイルをstyled-componentsで定義します。

フロントエンドがグローバルレベルの状態を保持する

フロントエンドでグローバルレベルの状態を管理するためにReduxを採用します。
バックエンドからHTMLに注入された後、Crowiインスタンスなどで管理されていた状態はこの時点でReduxで管理されるようになります。

最近、react-reduxはReactのv7.1.0でhooks APIをサポートしました。
hooksを使ってStoreに接続するために、react-redux@v7.1.0を採用します。

https://github.com/reduxjs/react-redux/releases/tag/v7.1.0

フロントエンドがページのルーティングとレンダリングの責務を持つ

React Routerを導入し、フロントエンドでコンポーネントのルーティングを行います。
結果として、バックエンドはAPI、静的ファイル、SPAへのフォールバックのルーティングのみの定義を持ち、、フロントエンドがページのルーティングの責務を持つようになります。

また、ブラウザによるページ遷移が発生しなくなるため、グローバルレベルのステートはバックエンドから注入されなくなります。
この時点で、全てのSwig テンプレートはバックエンドに存在しなくなり、フロントエンドがページのレンダリングの責任を持つようになります。
更に、トップレベルの要素までがコンポーネント化されることで、ほぼ全てのスタイルがSCSSからstyled-componentsに移行されます。

タスク

  • TypeScript の導入と移行 (@lightnet328, @otofune) (#402, #486)
  • React 16.8 の導入 (@lightnet328) (#420)
    • Hooks を使用できるようにするため
  • styled-components の導入 (@lightnet328) (#538)
  • Swig テンプレートのReact コンポーネント化
    • ページ作成モーダル (@saitoeku3) (#606)
    • ページ削除モーダル
    • ヘルプモーダル
    • ページ名に関するヒント
    • ポータル化モーダル
    • ページ名変更モーダル
    • ポータル解除モーダル
    • ログイン/新規登録ページ
    • ポータルとは (@okonomi) (#604)
    • ユーザーページ
    • インストーラー
    • プレゼンテーション
    • 招待ページ
    • ユーザー設定ページ
    • 外部共有ページ (@lightnet328)
    • 管理者ページ (@lightnet328)
    • ページ編集ページ (Editor)
  • react-redux@v7.1.0の導入
  • 既に持っているグローバルレベルの状態を Redux で管理する
    • 認証の状態管理
    • 検索の状態管理
  • React Router の導入
  • フロントエンドでルーティングする
    • ユーザーページ
    • リストページ・ポータル
    • ページ
    • 共有されたページ
    • ブックマークページ
    • 最近作成したページ
    • 検索結果ページ
    • インストーラー
    • プレゼンテーションページ
    • 招待ページ
    • ユーザー設定ページ
    • ログイン・新規登録ページ
    • 管理ページ (@lightnet328) (#423)
    • コメント (@lightnet328) (#424)
    • ページ編集ページ (Editor) (@sotarok)

貢献する

大胆な変更を要する機構や機能を実装する前にその仕様と実装の流れを書き下してオープンにすることでより多くの人が議論や実装に加われるようにするために、この提案を作成しました。
この提案に対する意見をこのIssueのコメントで教えてください。あなたの貢献をお待ちしています🙏

@lightnet328 lightnet328 added the Proposal label Jun 7, 2019
@sotarok

This comment has been minimized.

Copy link
Member

@sotarok sotarok commented Jun 7, 2019

I totally agree with you and your proposal and it definitely follows my idea of Crowi's long term roadmap.

I'd like to open ideas wether Redux is good for state and data flow management library or any other options at this moment?
(I don't have strong opinion on this point, just want to know options.)

@lightnet328

This comment has been minimized.

Copy link
Member Author

@lightnet328 lightnet328 commented Jun 10, 2019

IMO:

There are two reasons for choosing Redux:

  1. To communicate between components that are not in a parent-child relationship
  2. To divide files by domain or processing type

If need to satistfy only 1, React's Context API is enough.
I think Redux is useful when need to satistfy 2, that is, when scalability is required.

@sotarok

This comment has been minimized.

Copy link
Member

@sotarok sotarok commented Jun 13, 2019

Thank you :)
I agree with choosing Redux at this moment.

@sotarok

This comment has been minimized.

Copy link
Member

@sotarok sotarok commented Jun 16, 2019

📝 We can change the status of this proposal to be approved if we don't have any other ideas or opinions for it until the end of this week (Jun 24).

@sotarok

This comment has been minimized.

Copy link
Member

@sotarok sotarok commented Jun 25, 2019

Go on to be approved status :)

@sotarok sotarok added the Approved label Jun 25, 2019
@lightnet328

This comment has been minimized.

Copy link
Member Author

@lightnet328 lightnet328 commented Aug 21, 2019

Finally, converting codes to TypeScript and introducing styled-components have been completed!
And we are now ready to start making Swig templates into React components.
If you can help, please tell us the task you want to take charge of!

@saitoeku3

This comment has been minimized.

Copy link
Contributor

@saitoeku3 saitoeku3 commented Aug 21, 2019

May I take Page creation modal?

@lightnet328

This comment has been minimized.

Copy link
Member Author

@lightnet328 lightnet328 commented Aug 22, 2019

@saitoeku3 Yes, please! Thank you

@lightnet328

This comment has been minimized.

Copy link
Member Author

@lightnet328 lightnet328 commented Aug 22, 2019

Implementation guideline for migrating to React components

Since not all of the existing codes are implemented with the same policy, I'd like to show you the basic policy here.

Basic policy

  • Use styled-components and don't add new styles to scss as much as possible
  • Use Hooks and Functional Component
  • Use reactstrap, not use bootstrap's class name directly

FYI

  • Migrate admin pages to React (#423)
  • Migrate comment to React (#424)
  • Introduce styled components and replace some scss with styled-components (#538)
@okonomi

This comment has been minimized.

Copy link
Contributor

@okonomi okonomi commented Sep 15, 2019

I want to do What is a portal!

@lightnet328

This comment has been minimized.

Copy link
Member Author

@lightnet328 lightnet328 commented Sep 27, 2019

@okonomi Sorry for the late reply🙇
Yes, please! Thanks🙏

@saitoeku3 saitoeku3 mentioned this issue Oct 3, 2019
4 of 4 tasks complete
@saitoeku3

This comment has been minimized.

Copy link
Contributor

@saitoeku3 saitoeku3 commented Nov 30, 2019

I want to work on Page deletion modal.

@lightnet328

This comment has been minimized.

Copy link
Member Author

@lightnet328 lightnet328 commented Dec 3, 2019

Please! Thanks❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.