Reactのようなフレームワークをゼロから作成する

Reactのようなフレームワークをゼロから作成する

最近、インターネットで「Build your own React」という記事を見ました。著者は、シンプルなReact風のフレームワークをゼロから実装しました。最適化はあまり行われていませんでしたが、Concurrent ModeやFiber Reconcilerなど、Reactのコアとなるアイデアはすべて実装されていました。読んだ後、Reactの理解に非常に役立ちました。そこで、「Build your own React」に基づいてコードを分割し、独自のフレームワークプロジェクトを構築してから、チュートリアルで完了しなかった他の機能を改善したいと思います。コードはracにあります。

プロジェクト構築

技術スタックとしては、開発には TypeScript、パッケージングには Rollup を使用することにしました。これらはあまり使わない技術なので、一緒に練習します。webpack と比較すると、rollup の設定は簡単です。プロジェクトに tsconfig.json と rollup.config.js を作成し、rollup-plugin-typescript2、rollup-plugin-terser などの必要なロールアップ プラグインをインストールします。また、サンプルフォルダを用意し、小さなデモプロジェクトを作成し、tsxを使用して開発します。

jsxをサポート

TypeScript で jsx をサポートするには、tsconfig で jsx を有効にする必要があります。TypeScript には、preserve、react、react-native の 3 つのモードがあります。react に設定すると、TypeScript はコード内の jsx を React.createElement に変換します。これが、jsx を使用するときに React をスコープ内に含めなければならない理由です。

しかし、React のようなフレームワークを独自に実装したい場合は、React.createElement の名前を変更するだけです。 Build your own React では、/** @jsx Didact.createElement */ コメントを使用して、コンパイラに jsx の出力関数を Didact.createElement に変更するように指示しています。この方法は、現在のファイルに対してのみ有効です。プロジェクトで使用する場合は、ファイルごとにコメント行を追加するのが面倒になります。 tsconfig の jsxFactory 属性 (ここでは h と呼びます) を通じて指定する別の方法を使用します。React.createEmenent に加えて、特別な要素である Fragment もあります。TypeScript はデフォルトでこれを React.Fragment に変換します。jsxFragmentFactory を通じてこれを直接 Fragment に変更します。

tsconfig.json:

{
  "コンパイラオプション": {
    "ターゲット": "esnext",
    "モジュール": "commonjs",
    "モジュール解像度": "ノード",
    "jsx": "react", // jsx を有効にする
    "jsxFactory": "h", // React.createElement => h
    "jsxFragmentFactory": "Fragment", // React.Fragment => Fragment
    "ルートディレクトリ": "./src",
    "lib": ["dom", "es2015"]
  }
}

ロールアップ構成

Rollup の設定は比較的簡単です。入力と出力に加えて、いくつかのプラグインを追加できます。

定数パス = require('path')
定数typescript = require('rollup-plugin-typescript2')
const { terser } = require('rollup-plugin-terser')
const eslint = require('@rollup/plugin-eslint')

エクスポートデフォルト{
  入力: 'src/index.ts',
  出力: [
    { ファイル: 'dist/rac.umd.js'、形式: 'umd'、名前: 'rac' }
  ]、
  プラグイン: [
    簡潔(),
    エスリント({
      throwOnError: true、
      インクルード: ['src/**/*.ts']
    })、
    タイプスクリプト({
      詳細度: 0,
      tsconfig: path.resolve(__dirname, 'tsconfig.json'),
      useTsconfigDeclarationDir: true
    })
  ]
}

TypeScript での Eslint

Eslint が TypeScript をサポートできるようにするには、Eslint にいくつかの追加設定が必要です。

モジュール.エクスポート = {
  パーサー: '@typescript-eslint/parser',
  環境: {
    es6: 本当、
    ブラウザ: true
  },
  プラグイン: [
    '@typescript-eslint'
  ]、
  拡張: [
    'eslint:推奨',
  ]、
  パーサーオプション: {
    ソースタイプ: 'モジュール'
  },
  ルール:
    ...
  }
}

プロジェクト構造

Reactの新しいFiberアーキテクチャにはいくつかのコアコンセプトがあります。Build your own Reactでは、著者は次のように説明しています。

  • ステップ I: createElement 関数
  • ステップ II: レンダリング機能
  • ステップ III: 並行モード
  • ステップIV: 繊維
  • ステップ V: レンダリングとコミットのフェーズ
  • ステップ VI: 和解
  • ステップ VII: 関数コンポーネント
  • ステップ VIII: フック

これらの手順により、ミニ React が徐々に実装されます。コードの可読性と保守性を向上させるために、これらの関数は異なるファイルに分割されます。

。
├── README.md
├── examples // デモディレクトリ├── package.json
├── rollup.config.js
├── 出典
│ ├── ドム.ts
│ ├── h.ts
│ ├── hooks.ts
│ ├── index.ts
│ ├── reconciler.ts
│ ├── スケジューラ.ts
│ └── type.ts
└── tsconfig.json
  • dom.ts で DOM 関連の作業を処理する
  • h.tsはjsxFactoryとjsxFragmentFactoryの実装です
  • hooks.tsはフックの実装です
  • reconciler.tsは、調整フェーズとコミットフェーズの実装です。
  • shceduler.tsはタスクスケジューラの実装です
  • type.tsは何らかの型定義である

この時点で、プロジェクトは構築されています。プロジェクト全体の構造と一部のコード実装は、fre フレームワークに基づいています。

これで、ゼロから書いたReactライクなフレームワークのプロジェクト構築と実装に関するこの記事は終了です。Reactライクな構築に関するより関連性の高いコンテンツについては、123WORDPRESS.COMの過去の記事を検索するか、以下の関連記事を引き続き閲覧してください。今後とも123WORDPRESS.COMを応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Amap を使用した React 実装例 (react-amap)
  • Reactの仮想DOMとdiffアルゴリズムの詳細な説明
  • ファイルのアップロードの進行状況を示す React の例
  • React で遅延読み込みを使用して最初の画面の読み込み時間を短縮する方法
  • WeChat公式アカウントでReactプロジェクトを実行する方法
  • ReactでCSSをエレガントに書く方法
  • 最も単純な ErrorBoundary コンポーネントをカプセル化して、React 例外を処理する
  • React Fiber構造の作成手順
  • React の 3 つの主要属性における Ref の使用に関する詳細な説明
  • React useEffect の理解と使用

<<:  nginxのシンプル転送リクエストのサーバーとロケーション設定の詳しい説明

>>:  Java で ffmpeg を呼び出してビデオ形式を flv に変換する方法の詳細な説明

推薦する

Nest.js 環境変数の設定とシリアル化の詳細な説明

環境変数の設定の簡単な説明プログラムは、環境によって異なる環境変数を必要とします。たとえば、実稼働環...

MySQL では SQL ステートメントはどのように実行されますか?

目次1. MySQLアーキテクチャの分析1.1 コネクタ1.2 クエリキャッシュ1.3 アナライザー...

win10 で mysql8.0.23 をインストールし、「サービスが制御機能に応答しません」という問題を解決する方法

Windows10にmysqlをインストールする1. 公式サイトからMySQLをダウンロードするウェ...

JS ベースのページフローティングボックスを実装するためのサンプルコード

スクロール バーを下に引くと、主にposition:fixed;スタイルにより、フローティング ボッ...

Nginx転送マッチングルールの実装

1. 正規表現マッチング大文字と小文字を区別するマッチングの場合 ~ ~*は大文字と小文字を区別しな...

テキストエリアタグはサイズ変更できず、マウスでドラッグすることもできません

テキストエリアタグのサイズは不変ですコードをコピーコードは次のとおりです。 <textarea...

Linux プラットフォームでの Zabbix エージェントのインストールと設定方法

ここでは、Linux プラットフォームでの Zabbix エージェントのインストールと構成について簡...

コンテンツ領域の周囲を回転する CSS 動的グラデーション ボーダーの効果 (サンプル コード)

レンダリング ネットで関連情報を調べたところ、現在のダイナミックグラデーションボーダーの実装方法のほ...

HTML フォームタグチュートリアル (2):

このチュートリアルでは、ウェブデザインにおけるFORMフォームタグのさまざまな属性の応用を紹介します...

MySQLは数百万のシミュレーションデータ操作コードを自動的に挿入します

私はデータベースツールとして Navicat を使用しています。他のものも同様です。 1. Navi...

LeetCode の SQL 実装 (182. 重複するメールボックス)

[LeetCode] 182.重複メールPerson という名前のテーブル内のすべての重複メールを...

ウェブ開発者はIE7とIE8の共存を懸念している

今日、IE8 をインストールしました。ダウンロードするために Microsoft の Web サイト...

テーブルセルの幅tdの設定は無効であり、内部コンテンツによって常に引き伸ばされます

テーブルページを作成するときに、td に設定された幅が無効になることがあります。td の幅は常に内部...

CSS3 で作成したホバーズーム効果

結果:実装コード: html <link href='https://fonts.go...

ベースリンクタグの使用の紹介ベース

<br />リンクをクリックすると、ポップアップ表示される Web ページ アドレスは ...