著者について Ctrip のフロントエンド開発者である Can は、現在ミニプログラムの開発に従事しており、コンパイルおよびパッケージ化技術とミニプログラムのクロスプラットフォーム ソリューションに強い関心を持っています。 1. 概要現在、私たちのチームのミニプログラムは、Taro クロスエンドソリューション React フレームワークを使用して開発されています。既存のスタイルソリューションに基づいて、コンパイルおよびパッケージ化後に大量のスタイルコードの冗長性が生成され、プロジェクトのコンパイル済み製品の大部分を占めます。 コンパイルされたスタイルのコードを分析した結果、冗長なコードは主に次の 2 つの側面に反映されていることがわかりました。
Taro プロジェクトの React フレームワーク アプレットが遭遇した上記の問題に対応して、この記事では新しいスタイルのソリューションを紹介します。このソリューションは、cssModules スタイル ソリューションの構文要件を採用し、Taro プラグインの利便性を利用して、既存の開発エクスペリエンスを変更せずに、対応するソリューションを提供することで、製品を「スリム化」します。最終的なスタイルファイルのスリム化効果は 50% ~ 70% に達し、公式パッケージのサイズ制限がさらに緩和され、ビジネスの急速な発展が促進されます。 2. cssModulesの簡単な紹介この記事のスタイル スキームは、スタイルの競合を解決するための cssModules の基本原則を学習し、これに基づいて改善することで、スタイル ファイルのサイズを縮小するという目的を達成します。したがって、このソリューションを正式に理解する前に、この記事ではまず Taro 公式サイトの cssModules ソリューションのサンプル コードを例として使用し、その構文要件と原則を簡単に理解します。 2.1 構文要件構成で cssModules を有効にすると、構文要件に従って、Taro プロジェクトに index.module.scss と index.js の 2 つのファイルが作成されます。ファイル コードは次のとおりです。デフォルトでは、cssModules はいくつかのカスタム モード変換を有効にします。ファイル名に .module. が含まれるスタイル ファイルのみが cssModules によって変換されます。次の index.module.scss スタイル ファイルでは、親子セレクターとクラス セレクターを通常どおり使用します。ただし、index.js ファイルでは、className 値は文字列ではなく、SCSS ファイルによってエクスポートされたオブジェクトのキーになります。キーは、SCSS ファイル内のクラス セレクターの名前です。 2.2 原則Taro プロジェクトは、cssModules 構成を有効にすると、コンパイルおよびパッケージ化中に cssModules 仕様を実装する css-loader を使用して SCSS およびその他のスタイル ファイルを処理します。まず、元の SCSS ファイル内のクラスセレクターを処理し、クラス名をハッシュして index-module__test___Bm2J6 などの新しいクラス名を取得し、新しいスタイルコードを生成して最終的な index.wxss に出力します。その際、ハッシュ後の元のクラス名と新しいクラス名とのマッピング関係を保存します。次に、元の SCSS ファイル index.module.scss を、元のクラス名とハッシュされた新しいクラス名をエクスポートするマッピング オブジェクトにコンパイルします。 JS ファイルの実行中、マッピング オブジェクトを通じて新しいハッシュ化されたクラス名を取得し、ファイルのクラス名が他のスタイル ファイルの同じクラス名と競合しないようにすることで、スタイルの競合の問題を解決できます。以下はコンパイルされたコード例です。styles.test は実行時に index-module__test___Bm2J6 になります。 3. 解決の原理の紹介3.1 基本原則3.1.1 現在のスタイルファイルサイズの分析 この記事のソリューションがスタイル ファイルのサイズをどのように削減するかを正式に紹介する前に、この記事では、次の 2 つの正規表現を使用して、パッケージ化された製品内のすべてのスタイル ファイルの 2 つのコア コンポーネントである ClassName と PropertyValue を照合し、サイズの統計分析を実行します。 注: この記事の .txt .tit {color: #red;} CssRule コードでは、ClassName は txt と tit を参照し、PropertyValue は color:#red; を参照します。 次の図は、コンパイルされパッケージ化されたミニプログラム プロジェクト全体のスタイル ファイルのサイズ分析を示しています。この図から、プロジェクトでパッケージ化およびコンパイルされたすべてのスタイル ファイルのうち、ClassName が約 5 分の 1 のスペースを占め、PropertyValue が 7 分の 1 のスペースを占めていることがわかります。残りのスペースは、スペースや疑似クラスの形で存在する可能性がありますが、この記事では考慮されていません。 3.1.2 解決策 前のセクションから、スタイル ファイルには ClassName と PropertyValue という 2 つの主要な部分があることがわかります。この記事のスタイル スキームでは、サイズを節約するという目標を達成するために、これら 2 つの部分を個別に処理します。 1) ClassNameの長さを短くする 核となるのは、元の ClassName をより短く一意の ClassName に置き換えることです。これにより、スタイルの競合が解決されるだけでなく、ClassName の長さが短くなるためサイズも節約されます。 cssModules を使用する場合、通常は、第 2 章の cssModules 紹介のサンプル コードのように、ClassName をハッシュして一意性を確保します。ただし、ハッシュ後の ClassName の長さは長くなり、スタイル コードのサイズを縮小するという目的を達成できません。 この解決策は、最も短い文字から始めて、徐々に文字数を増やし、プロジェクト全体で一意の ClassName を生成することです。これにより、ClassName の長さをできるだけ短く保ちながら一意性を確保します。たとえば、最初に解析された ClassName は -a に置き換えられ、2 番目に解析された ClassName は -b に置き換えられ、52 番目に解析された ClassName は -Z に置き換えられ、53 番目に解析された ClassName は -aa に置き換えられます。 ClassName の前の - は、新しく生成されたクラス名が変換されていないクラス名と競合するのを防ぐために使用されます。さらに、新しく生成された ClassName は規則に準拠する必要があります。このプラグイン アルゴリズムは、最初に prevString から文字を取得し、その後のすべての文字は charString 内の任意の文字にすることができます。 プロジェクト全体で宣言される ClassName が増えるにつれて、段階的に生成される ClassName がどんどん長くなり、合計 ClassName が長くなりすぎるのではないかと心配する人もいるかもしれません。上記のアルゴリズムにより、先頭に追加された - を含めて、3 文字のクラス名が使い果たされると、52 * 64 = 3328 個の ClassNames を置き換えることができます。4 文字のクラス名を使い切るには、52 * 64 * 64 = 212992 個の classNames が必要です。新しく生成された ClassName は 4 文字を超えないため、ほとんどのプロジェクトのニーズを満たすことができます。このスタイル スキームを使用する前に、プロジェクト内の ClassName の大きさを確認できます。 2) プロパティ値を減らす 上記の分析から、スタイル ファイルの最大サイズを占める部分は PropertyValue であることがわかります。したがって、PropertyValue を削減することが、このスタイル ソリューションでサイズを大幅に節約するための中核的な手段です。実際、開発プロセスで最もよく使用されるレイアウト属性 display:flex など、開発中に使用するスタイル属性値の多くは繰り返し使用されます。このプロパティが使用されるたびに新しいコピーを書き込む必要があり、互換性のために Autoprefixer プラグインが有効になっていると、 display:flex は display:-webkit-flex;display:-ms-flexbox;display:flex; になり、スタイル ファイルのサイズが大きくなります。このプラグインは、PropertyValue を可能な限り再利用することで削減します。 このプラグインは、クラス セレクターのみを使用するスタイル ファイル内の CssRule を PropertyValue に分割し、分割ごとに新しい PropertyValue ClassName を生成します。次のサンプル コードに示すように、クラス セレクター CssRule txt のみが 2 つの PropertyValue ClassNames: _a と _b に分割されます。後でクラスセレクターを持つ他の CssRule を分割に使用する場合、同じ PropertyValue があれば、_a または _b が直接再利用されます。 cssModules スタイルで記述された js ファイルでは、対応するマッピング処理も必要です。babel プラグインを使用して、コンパイル時に変換処理を行い、css ファイルの参照関係を判別して置き換えます。サンプルコードは次のとおりです。 このスタイル スキームは、クラス セレクターのみを使用する CssRule の PropertyValue を新しい PropertyValue ClassName に分割します。PropertyValue ClassName は、後続の分割場所で直接再利用できるため、繰り返される冗長な PropertyValue によって占有されるサイズが大幅に削減されます。 3) プラグイン処理フロー 上記の 2 つのセクションでは、2 つのコア サイズ削減ソリューションを紹介しました。このセクションでは、このプラグインがコンパイル時に上記の 2 つのソリューションを使用して、スタイル ファイルと JS ファイルを処理および変換する方法を示す、より包括的な例を示します。主に2つのステップがあります。 最初のステップは、クラス セレクターのみを使用する CssRule の PropertyValue を分割することです。次のサンプルコードでは、 .box{display:flex} が ._a {display: -webkit-flex;display: -ms-flexbox;display: flex;} に分割されています。その後、 .item1` `.item2 が分割されると、 ._a が直接再利用され、PropertyValue の重複が削減されます。 2 番目のステップは、クラス セレクターのみを使用しない CssRule を、グローバルに一意で短い ClassName に直接置き換えることです。次のサンプルコード .box .item2{color: red;} では、元のセレクターの ClassName が短い .-a .-b{ color: red;} に直接置き換えられ、マッピング関係のstyles = {box: "_a -a", item1: "_a _b _c", item2: "_a _b _d -b"} がコンパイル時に追加され、置き換えられます。 3.2 注意が必要な問題3.2.1 スタイルオブジェクトのプロパティは実行時にサポートされません cssModules ソリューションでは、次の例に示すように、JS ファイルに導入されたスタイル ファイル オブジェクトがプロパティの実行時計算をサポートします。これは、パッケージ化された JS ファイルには、ハッシュ後の元の ClassName と新しい ClassName のマッピング関係のオブジェクト データが存在するため、実行時にスタイルで属性をマッピングすることは可能ですが、この処理方法では JS ファイルのサイズが大きくなるためです。 プロジェクトのサイズを可能な限り小さくするために、このソリューションでは cssModules アプローチは使用しません。このソリューションでは、コンパイル中に PropertyValue を分割した後、元の CLassName を新しい ClassName に直接置き換えます。たとえば、 className={styles.txt} を className="_a _b" に直接置き換えます。 したがって、このソリューションのスタイル オブジェクトは、上記のサンプル コードのように実行時に計算される txt 属性をサポートしていません。スタイルを動的に調整する必要がある場合は、2 つのソリューションがあります。1 つは、インライン スタイルを直接使用することです。 2つ目は、className={value ?styles.txt1 :styles.txt2}}のように、連結するのではなく、新たにClassNameを記述することです。 3.2.2 クラスセレクタは順序に関係なく優先順位が付けられる 上記では、クラスセレクターのみを使用する CssRule を分割して、既存の PropertyValue ClassName を可能な限り再利用すると述べています。ただし、この再利用には欠陥があります。ClassName の順序が期待と一致しなくなる可能性があります。次のコードに示すように、通常、タイトルの色は灰色であると考えられます。 しかし、このプラグインが PropertyValue を再利用すると、 ._a{color:green;} の後に ._b{color:red;} が表示され、タイトルの色が赤になり、開発者の期待に応えられない可能性があります。 したがって、クラス セレクターのみを使用して CssRule の ClassName を記述する場合、クラス セレクターの順序に依存して優先順位を決定することはできないことに注意することが重要です。次のコード例に示すように、兄弟セレクターを使用して優先順位を高く設定し、順序の影響を受けないようにすることができます。これにより、タイトルの色が緑になります。 IV. ユーザーガイド4.1 使用4.1.1 プラグインのインストール このスタイル スキームは Taro プラグインtaro-plugin-split-classに統合されています。このプラグインをインストールしてください。ソースコードについては、リポジトリtaro-plugin-split-class を参照してください。 4.1.2 cssモジュールを無効にする 次のコードに示すように、Taro 構成ファイルで mini.posetcss.cssModules.enable = false を設定して、cssModules 関数がオフになっていることを確認します。 4.1.3 このプラグインを設定する Taro 構成ファイルで、このプラグイン taro-plugin-split-class をプラグイン構成に追加します。このプラグインは、クラス名変換ホワイトリスト(実装関数は global に似ています。2.4 を参照)classNameWhite の設定をサポートしています。たとえば、よく使用されるアイコンフォントは変換する必要はありません。 4.2 構文要件a. スタイル ファイル名は、このプラグインによって変換および処理できるように、index.module.scss のように .module.xxx で終わる必要があります。 b. JS ファイルで、スタイル ファイルをオブジェクトとしてインポートし、クラス名をオブジェクトのキーとして使用します。次のコードに示すように、 className="box" の代わりに className={styles.box} を使用します。ここで、 box はスタイル ファイルで定義されたクラス名です。 c. このソリューションは、親子セレクター、疑似クラスセレクター、兄弟セレクターなど、すべてのセレクターをサポートします。ただし、要素の配置にはできる限りクラス セレクターのみを使用してください。これにより、プラグインが PropertyValue をできるだけ再利用しやすくなり、サイズをより適切に削減できます。このソリューションはクラス名の競合の問題を解決するため、開発者は単純なクラス名によって発生するクラス名の競合を心配する必要がなくなります。 d. 特別クラス名は変更なし 場合によっては、特別な ClassNames を変更せずに残しておきたいことがあります。JS ファイルでは、次のコードの extra のように、スタイルからクラス名を取得する必要はありません。 ただし、スタイル ファイルでは、すべての ClassName がデフォルトで分割または圧縮されます。次のコード例では、 extra が -a に処理されます。 したがって、プラグインに ClasName を処理する必要がないことを知らせるための特別な識別子が必要です。このソリューションは、cssModules の :global に似たソリューションを提供します。これを使用するには 2 つの方法があります。1 つは :global(.extra) で、ラップされたクラス名は置き換えられません。 次に、:global で始まる場合、後続のクラス名はすべて置き換えられません。 4.3 パッケージ効果の表示4.3.1 開発環境 このプラグインを使用すると、元のクラス名が置き換えられるか、より短く新しいクラス名に分割されます。この処理後の新しいクラス名は非常に読みにくく、開発者は元のクラス名コードを見つけることができません。そのため、開発環境では、より短く一般的な新しいクラス名の前に [フォルダー_ファイル名_元のクラス名] が追加されます。開発者が元のクラス名を見つけやすくするために、元のクラス名に関連する情報が保持されます。以下のコードに示すように、元のクラス名は box です。プラグインによって分割および短縮された後、新しいクラス名は _a _g _h -c になります。新しいクラス名の前に Index_indes-module_box が追加されます。最終的に表示される完全なクラス名は index_index-module_box _a _g _h -c です。 4.3.2 実稼働環境 本番環境では、新しいクラス名の可読性を考慮する必要がないため、クラス名が完全に新しいクラス名に置き換えられます。以下のコードに示すように、box は _a _g _h -c に直接置き換えられます。 V. ソリューション分析5.1 実践結果5.1.1 ページ変換前と後の比較 このスタイル スキームを使用してページを変換すると、変換前と変換後のサイズの比較は次のようになります。スタイルファイルは44KB、約70%削減され、JSファイルは2KB増加していることがわかります。
使用前のコンパイル後のファイルサイズは次のとおりです。 コンパイルされたファイルのサイズは次のとおりです。 5.1.2 再構築ページの水平比較 最近、私たちのプロジェクトでは、2 つの大きな注文詳細ページを再構築しました。このセクションでは、これら 2 つのページの再構築されたコードを例として、コンパイルおよびパッケージ化の前後のサイズを分析し、横方向の比較を行います。 次の表が作成されます。
2 つの注文詳細ページのコード編成構造は類似しているため、水平に比較します。このスタイルスキームを採用していない注文詳細ページ 1 のスタイルコード文字数は 3620 で、パッケージ化後の実際のサイズは 86kb です。注文詳細ページ 2 がこのスタイル スキームを使用しない場合、梱包前のスタイル コードの文字数は 6615 で、梱包後の実際のサイズは 6615 / 3620 \* 86kb = 157kb と予想されます。ただし、注文詳細ページではこのスタイル スキームが使用され、梱包後の実際のサイズは 73kb で、157kb より約 50% 小さくなります。 以下は、このスタイル スキームを使用しない注文詳細ページ 1 です。このディレクトリ内のスタイル ファイルには、合計 3620 文字の 50 個のスタイル ファイルが含まれています。最終的にパッケージ化されたスタイル ファイルのサイズは 86kb です。 以下は、このスタイル スキームを使用した注文詳細ページ 2 です。このディレクトリ内のスタイル ファイルには、合計 6615 文字の 96 個のスタイル ファイルが含まれています。最終的にパッケージ化されたスタイル ファイルのサイズは 73kb です。 5.2 サイズ縮小効果分析プロジェクトの元の書き込みスキームと比較すると、このスキームを使用した後、上記の 2 つの実用的な効果により、次の 3 つの側面でサイズが節約されます。 a. このソリューションは、スタイルの競合の問題を解決します。スタイル コードを記述するときに、スタイル スコープを分離するために親子セレクター メソッドを使用する必要がなくなり、祖先セレクターの冗長性が軽減されます。 sass プリプロセッサを使用した次のスタイル コードに示すように、最終的にコンパイルされたコードでは、.box .item が 3 回冗長であり、.box .item の下に新しいリーフ ノード .item* が追加されると、.box .item が 1 回冗長になることがわかります。したがって、親子セレクターを使用してプロジェクト内のスコープを分離すると、冗長な祖先セレクターが多数生成されます。 b. 元の ClassName をより短い ClassName に短縮します。これにより、文字数が直接削減されます。この方法は比較的直接的ですが、最適化の効果は限られています。 c. このソリューションは、スタイル ファイル内のクラス セレクターのみの CssRule を可能な限り分割し、PropertyValue ClassName を生成して再利用し、PropertyValue の重複と冗長性を可能な限り削減します。 JS ファイル内の ClassName は、より短いが PropertyValue が多い ClassName に置き換えられますが、一定のサイズの増加があります。たとえば、練習効果 1 では、練習後に JS ファイルが 2KB 増加します。ただし、スタイルファイルのサイズの削減と比較すると、その効果はごくわずかです。 5.3 規模拡大分析このスタイル ソリューションを採用するプロジェクトでは、スタイル ファイルの数が増えるにつれて、スタイル ファイルのサイズの増加が緩やかになります。このソリューションでは、スタイル コードを主にクラス セレクターのみを使用して記述し、他のセレクターを少数のシナリオで補足として使用する必要があります。プロジェクト内のスタイル コードの数が増えると、クラス セレクター CssRules を処理および分割した後にこのプラグインによって生成される再利用可能な PropertyValue CssRules の数も増えます。このとき、特定の PropertyValue を使用するために新しいクラス セレクター CssRule を必要に応じて記述すると、再利用される可能性が高くなります。高い確率で再利用するたびにサイズの一部が節約されるため、最終的なコンパイルとパッケージ化後に生成されるスタイル ファイルのサイズ増加の曲線は徐々に緩やかになります。 VI. 結論この記事では、Taro プロジェクトの React フレームワーク アプレットの新しいスタイル ソリューションを紹介します。このソリューションは Taro プラグインに統合されており、既存の開発エクスペリエンスへの変更を少なくしながら、スタイル コードの冗長性を軽減できます。 このスタイル スキームは、cssModules スタイル スキームの構文規則と原則を借用して、スタイルの競合の問題を解決します。これに基づいて、ClassName と PropertyValue の長さを短縮することで、スタイル ファイルのサイズを縮小します。最終的なスタイル ファイルは 50% ~ 70% 縮小できます。これにより、公式パッケージのサイズ制限が緩和され、迅速なビジネス展開が可能になります。 7. vscodeプラグインの推奨このソリューションの基本的な構文は cssModules と一致しているため、既存の cssModules プラグインを直接使用して開発エクスペリエンスを向上させることができます。 7.1 CSS モジュール変換プラグイン このプラグインは、プロジェクトの既存の JS コードを cssModules 構文にすばやく変換し、元のクラス名の使用を、このソリューションに必要なクラス名の使用構文 ( classname="a1" => className={styles.a1} など) に 1 回のクリックで置き換えます。ワンクリック置換では非ランタイム構文のみがサポートされており、ランタイム構文は手動で置換する必要があることに注意してください。既存のスタイルソリューションの変換効率を効果的に向上できます。 7.2 CSS モジュール プラグイン CSS モジュール プラグインは、開発エクスペリエンスを向上させるために自動補完と型定義をサポートしています。 8. 論文の参照
|
<<: Ctrip列車チケットSMSリコールアルゴリズムの最適化の実践
>>: ジェネレーティブ AI に投資する前に CIO が答えるべき 11 の質問
自然言語処理 (NLP) の進歩により、データセンターの運用コストの削減や人材の維持率の向上など、デ...
製造業は過去 1 世紀にわたって大きく変化しました。 新しい高度なテクノロジーが業界を前進させるにつ...
[[379153]] [51CTO.com クイック翻訳] 研究によると、人工知能技術はさまざまな業...
AI は私たちの職業、働き方、そして企業文化を変えています。 AIを活用することで、本当に重要なスキ...
[[244829]]テクノロジー大手のHuaweiは最近かなり活発に活動している。 9月1日、ファ...
最近、清華大学コンピュータサイエンス学部の朱軍教授の研究グループが発表したシュレーディンガー橋[1]...
ここ数年、人工知能技術が徐々に発展するにつれ、社会の中で人工知能に対するさまざまな見方が現れ始めまし...
データ注釈は、ディープラーニングプロセスにおいて常に基本的かつ重要な役割を果たしてきました。高品質な...
文 | 李水清5月25日のZhidongxiの報道によると、Huawei Machine Visio...
[51CTO.com クイック翻訳] 機械学習には多くの利点があるのに、なぜ誰もが導入しないのでしょ...