ホームページ  >  記事  >  ウェブフロントエンド  >  焼き畑農業に別れを告げる: VisMooc_html/css_WEB-ITnose でのフロントエンド エンジニアリングの簡単な説明

焼き畑農業に別れを告げる: VisMooc_html/css_WEB-ITnose でのフロントエンド エンジニアリングの簡単な説明

WBOY
WBOYオリジナル
2016-06-24 11:24:54932ブラウズ

偶然にも、年の初めに先生から、VisMooc コードを引き継いでくれる先輩を探してほしいと頼まれました。プロジェクトがかなり面倒だったので、今年の期限までに関連開発を担当するだろうと思っていました。なので、春節前にシステム全体を書き直しました。その過程の記録は文書にまとめられます。交換や議論は歓迎です。

0. 背景を説明します

VisMooc は、主にオンライン教育 Web サイト上のさまざまなデータの視覚的分析ツールを提供する Web アプリです。元々は Cong Lei 兄弟によって設立され、バージョン 0.5 から現在の比較的安定したバージョン 2.0 まで開発され、Qu 先生と多くの兄弟姉妹の知恵と汗が集まり、数え切れないほどの栄誉と評判を獲得しました。グループにとって、それはチームの主力プロジェクトの1つであると言えます。

特殊な成長環境のため、VisMooc のさまざまな機能は基本的にさまざまな先輩たちによって次から次へと期限内に駆逐され、その後システム全体が毎年再構築され、さまざまな機能が統合されます。この特殊な「国家情勢」のもとで、VisMooc のコードは大きく成長し、プロジェクトのパフォーマンスは最適化されておらず、堅牢性も高くなく、多くの機能がハッキングされました。しかし実際には、パフォーマンスが良くなくても、堅牢性が高くなくても、結局はデモのためのデモプロジェクトにすぎず、同時訪問数や毎日の訪問数はそれほど多くありません。さまざまな視覚化テクノロジと概念を実証できる程度には十分です。

しかし、VisMooc には現在非常に大きな落とし穴があります。つまり、コードには保守性がまったくなく、致命的な保守性があり、多くの部分が非常に混乱しています。小屋でおいしいものを食べているような気分です。全然。正直に言うと、プログラマーとして、ある日開発効率が極端に低いことに気付いた場合、作業環境が十分に清潔ではないか、ナイフが研いでいないかを考えなければなりません。

VisMooc の保守性の低さは次の点に反映されています:

  1. コードの保守が難しい
    • 統一されたコーディング標準が存在せず、異なる機能が異なる先輩によって開発されているという事実により、それぞれのコードはプロジェクトの一部に非常に一貫性がありません。コードの各部分のスタイルが異なります。
    • 多くのコードの変数名は、var a、b、kkk; のようにランダムに選択されます。変数名は基本的に自明ではなく、変数と関数の意味は読む前にほとんど推測されます。コードを通して。
    • さらに、モジュール型およびコンポーネントベースの開発の機能は弱く、ディレクトリ構造と依存関係が乱雑であるため、あるコンポーネントの CSS ファイルが別のコンポーネントのディレクトリにある場合があります。オブジェクトの前にありますが、それがどのコンポーネントから来たのかわかりません。
    • 歴史的な負担が大きく、古いコードが多く、使われなくなったコードと今も使われているコードが混在しています。
  2. プロジェクトの維持が難しい
    • プロジェクト管理ツールの不足、小規模なワークショップ スタイルのプログラミング。 Bitbucket のチーム コラボレーション管理など、多くの管理ツールは楽しむだけで使用されていません。
    • npm と bower はサードパーティの依存関係パッケージを管理するために使用されますが、npm install と bower install が完了すると、基本的にプロジェクトを実行できなくなります。多くの場合、依存関係パッケージが欠落していますが、このパッケージは依存関係リストに含まれていません。コードを読むには人間が必要です。
    • Git はバージョン管理に使われますが、.gitignore は無造作に書かれていて、例えば自分が書いたコードは無視されるため、プロジェクトを他のマシンにクローンすると、特定の変数が存在しないというエラーが報告されることがよくあります。デバッグ後、最終的にコード ファイルが欠落していることがわかりました。
  3. デプロイメントの保守が難しい (これは実際には少し要求が多すぎます)
    • バージョン番号やコンテンツのフィンガープリントの概念がなく、キャッシュされたコンテンツを長期間キャッシュし、正確に制御することは不可能です。
    • 対象リリースですが、アップグレードは十分にスムーズではありません。

これらの問題は、初期の小規模なワークショップ スタイルの開発では基本的にこのような問題が発生しており、これらの問題は基本的にエンジニアリング自動化手法を使用して解決できます。 VisMoocをケーススタディとして、フロントエンドエンジニアリングの考え方に基づいてシステム全体を再構築する方法を学び、実践しました。まず、要件を整理しましょう:

  • 開発
    1. コンポーネント開発。 Web アプリ全体はさまざまなコンポーネントで構成されており、コンポーネントの Js、CSS、および HTML は一緒に維持され、可能な限り緩やかに結合されています。
    2. モジュール開発。 Jsのモジュール化、CSSのモジュール化、HTMLのモジュール化、すべてのリソースはモジュールであり、使用する場所にインポートする原則が採用されており、同時にリソースの重複導入を防ぐ必要があります。
    3. リアルタイムのファイル監視とブラウザの自動更新。
    4. 依存関係パッケージ管理、バージョン管理。
    5. 標準エンコーディング。コーディング標準については、主に意識に依存する「メンテナンス可能なJavaScriptの書き方」を参照してください。
  • Build
    1. は中間言語をコンパイルできます。たとえば、Stylus、Less、Typescript などのコンパイルをサポートします。
    2. Js と CSS の圧縮と混合をサポートします。
    3. 画像を圧縮し、base64 エンコードで CSS、Js、または HTML に埋め込むことができます。
    4. オンデマンドでのコードの読み込みをサポートします。ページ要件に応じてコードを分割およびマージして、HTTP リクエストの数を最適化します。
  • 導入
    1. コードの内容に基づいてバージョン番号を生成し、キャッシュ制御を実装し、アクセス パフォーマンスを促進します。
    2. 自分で書いたコードからサードパーティライブラリの Js と CSS を分離することをサポートします。

整理すると、主な要件は 11 個ほどあり、現時点ではこのような実証プロジェクトには基本的に十分です。これらすべてをエレガントに実装するにはどうすればよいでしょうか?段階的に見ていきましょう。

1. テクノロジーの選択

フロントエンド ライブラリ

フロントエンド エンジニアリング構築の最初のタスクは、プロジェクトの特性に基づいてテクノロジーを選択することです。 VisMooc は、現在の機能に関しては、まだ 1 ページしかないシングル ページ アプリとしては比較的典型的な Web アプリと言えます。 VisMooc の対象プラットフォームは PC のみで、モバイル端末での使用はサポートされていません (おそらく将来的にはタブレット デバイスでの使用もサポートされるでしょう)。そのページ ロジックも、ダッシュボード アプリケーションと同様に比較的シンプルです。

フロントエンド レンダリング

VisMooc2.0 では、フロントエンドのモジュール性とさまざまな機能を実現するために Angular1 を使用します。しかし、VisMooc の場合、Angular はやや肥大化しており、Angular1 では性能が不足します。フロントエンド サークルの開発に伴い、Angular 開発チームは Angular2 の次のバージョンが Angular1 と互換性を持たなくなることを発表しました。これは明らかに、VisMooc を書き直すための新しいフレームワークを選択し、VisMooc をアップグレードする良い機会です。

フロントエンド フレームワークは日を追うごとに変化しており、VisMooc プロジェクトのフロントエンド フレームワークにはいくつかの特別な要件があります。 1. PC プラットフォームのみ。 2. 簡単に始められ、学習曲線が簡単である必要があります。スムーズ。これら 2 つの点により、人気のある React フレームワークは基本的に除外できます。 Angular2 の現在のエコシステムはまだかなり不完全 (エコシステムがほとんどない) ため、軽量の Vuejs が目に留まりました。 Vuejs は、非常に「小さいながらも美しい」フロントエンド レンダリング フレームワークです。シンプル、軽量、強力、データ駆動型、モジュールフレンドリーで、コンポーネント化をサポートしています。学習曲線は非常にスムーズで、それほど高くはありません。また、コミュニティはフレンドリーです。著者は中国人の元 Google エンジニアであり、既婚のプログラマです。このフレームワークに対する著者自身の評価を読むことができます。現在、国内外の多くの企業が実際の運用環境で Vus を使用しています。有名な企業には、Alibaba、Baidu、Sina、Xiaomi などが含まれます。

ビルドとパッケージ化

コードをより適切に管理し、システムのパフォーマンスを向上させるために、システム構築タスクを完了するために、最近人気のあるモジュール構築システム Webpack を選択しました。正直に言うと、現在の Webpack は少し異なります。これはパッケージング ツールであり、構築ツールであり、モジュール読み込みツールでもありますが、完全なフロントエンド エンジニアリング ツールではありません。しかし、とにかく、Webpack は非常に強力です。 Webpack の助けを借りて、ノード側とブラウザ側の間でコードを共有したり、モジュールの依存関係の管理、コードの分割、プラグインを介した他のタイプのリソースのロードなどを行うことができます。 Webpack は、強力なローダー メカニズムとプラグイン メカニズムを提供します。ローダー メカニズムは、js スクリプトだけでなく、html、css、画像などのさまざまなリソースの読み込みをサポートし、依存関係の管理とパッケージ化に対応します。プラグインは、Webpack プロセス全体をある程度制御できます。たとえば、css-loader とless-loader をインストールして設定した後、require('./bootstrap.less') を使用して、必要に応じて、less で記述されたスタイル シートを Web ページにロードできます。Webpack CSS ファイルは、その実行中に自動的に生成されます。オンデマンドでビルドしてロードできるので、非常に便利です。

依存関係パッケージ管理

市場には多くのパッケージ管理ツールがあり、一般的なものは npm と bower です。一般に、人々は npm を使用して nodejs 関連のパッケージを管理し、bower を使用してフロントエンドが依存するクラス ライブラリを管理することに慣れています。フロントエンド エコシステムの急速な発展と、Browserify や Webpack などの CommonJS 仕様をサポートする構築ツールの人気により、npm は過去 1 年間で bower、component、spm などの多くのフロントエンド パッケージ管理ツールを基本的に廃止しました。 . の統一の可能性は大いにあります。これは、サードパーティ パッケージの依存関係を管理するために npm を使用することをためらわない、私のような「統合」を好む人々に最適です。

npm をサードパーティのパッケージ管理ツールとして使用するのは非常に簡単で、プロジェクト ディレクトリに package.json というファイルが自動的に作成され、プロジェクト関連の情報とプロジェクトが依存するさまざまなクラス ライブラリが記録されます。 npm で公開されているサードパーティ ライブラリ (super-lib と仮定すると) を使用する必要がある場合、プロジェクト フォルダーのコマンド ラインから npm install super-lib --save-dev と入力するだけで自動ダウンロードが完了します。このクラス ライブラリは、依存関係を package.json の依存関係に自動的に書き込みます。 Webpack を使用すると、require ステートメントやその他のステートメントを使用して、必要に応じてサードパーティのライブラリを導入できます。

//package.json file, which documents the dependent libs.{  "name": "example",  "version": "0.0.1",  "private": true,  "dependencies": {    "super-lib": "^0.4.5",    "beautiful-lib": "^0.22.0",    "smart-css": "^0.7.0"    "vuejs": "^3.4.0"  }}

npm を通じてダウンロードされたサードパーティ ライブラリを git サーバーにプッシュする必要はありません。他の開発者がプロ​​ジェクトが依存するサードパーティ クラス ライブラリを再ダウンロードする場合にのみ必要です。プロジェクト ディレクトリで npm install コマンドを実行すると、プロジェクトが依存するすべてのクラス ライブラリを自動的に完成させることができます。

npm と bower についての詳細な議論については、ここ (Zhihu) またはここ (github) を参照してください。

2. プロジェクト ディレクトリの設計

従来のフロントエンド プロジェクトはファイルの種類に応じてディレクトリ構造を編成するため、一般的なディレクトリ構造は次のようになります:

Project    |-src        |-HTML        |-CSS        |-JS        |-Images

この利点はシンプルであることです。 、大まかで非常に直接的なものですが、プログラミングの経験が少しあれば誰でも、プロジェクトがどのように構成されているかを一目で理解できます。ただし、これには明らかな欠点もあります。つまり、プロジェクトの保守コストが高く、肥大化したプロジェクトにエンジニアリング上のリスクが生じます。

  • プロジェクト内の機能に問題がある場合は、それを見つけなければなりません。メンテナンス中に js ディレクトリにある 対応するロジックを変更するには、css ディレクトリに移動して、対応するスタイル ファイルを見つけて変更します。画像が間違っている場合は、images ディレクトリに移動して、対応する開発リソースを見つけます。
  • CSS の下にあるファイルは、どの画像が使用されているのか、どの画像が放棄されたのかがわかりません。ファイルはますます増えています。 Js/HTML についても同様です。
  • 複数の人が共同作業する場合、複数の人が同じコード ファイルを変更し、競合が発生する可能性が非常に高くなります。

プロジェクトのコード量が少なく、開発担当者が 1 人だけである場合を除き、このファイル タイプ ベースのプロジェクト構造は放棄する必要があります。コンポーネント開発を採用したいので、アプリ全体がコンポーネントで構成されているため、コードコンポーネントに従ってプロジェクトディレクトリを次のように分割できます。

Project    |-src        |-Components    // 存放组件资源        |-Static        // 存放非组件资源

サードパーティのクラスライブラリの管理に npm を使用しているため、デフォルトのフォルダーは、node_modules という名前ですが、すべての依存するサードパーティ ライブラリが npm でホストされているわけではありません。自分で管理する必要がある、謎のサードパーティ リソースがいくつかあります。ファイルの損失を避けるために、それらを src ディレクトリに置き、git サーバーにプッシュすることができます。このようにして、ディレクトリ構造は次のようになります:

Project    |-node_modules      // npm上的第三方资源    |-src        |-Components    // 存放组件资源        |-Static        // 存放非组件资源        |-lib           // 存放不在npm上的第三方资源

最後に、Vuejs を使用してフロントエンドを開発するため、コンポーネント、フィルター、ディレクティブなどの固有のコード コンポーネントがいくつかあります。コンポーネントを Components ディレクトリに置くのは非常に自然ですが、それ以外の部分は実際のコンポーネントではないため、Static に置くのは非常に違和感があります。開発ディレクトリをわかりやすくするために、これらを対応するディレクトリに分けて配置しました。最終的に、開発ディレクトリは次のようになりました。コードを書き始めます。最初の要件は

コンポーネントベース開発

まず、コンポーネントベース開発とは何かについて簡単に説明します。

コンポーネント開発の基本概念は上の図に示すとおりです。Zhang Yunlong の言葉と図を引用すると、いわゆるコンポーネント開発は次のように理解できます。

ページ上のそれぞれの独立したビジュアル/インタラクティブ領域は次のようになります。 1 つのコンポーネントとみなされます。 各コンポーネントはプロジェクト ディレクトリに対応し、コンポーネントが必要とするすべてのリソースは近くに維持されます。

各コンポーネントは比較的独立しており、ページはコンポーネントの単なるコンテナーです。自由に組み合わせて、完全に機能するインターフェイスを形成します。

コンポーネントが不要になった場合、またはコンポーネントを置き換えたい場合は、ディレクトリ全体を削除/置き換えることができます。

  • コンポーネント ベースの開発の中核的な利点は、分割統治戦略にあります。エンジニアリングの観点から見ると、開発タスクを適切な粒度に分割して、異なる開発者へのタスクの割り当てを容易にします。開発の観点から見ると、各コンポーネントが相対的に独立しているため、開発中に競合が発生した場合でも開発者は依存関係を持たなくなります。メンテナンスの観点から開発効率を向上させるために独自のモジュール開発にのみ集中する必要があり、モジュール関連のリソースがまとめて整理されているため、メンテナンスと整理が非常に簡単です。
  • モジュール化のサポートにより、プロジェクトの開発は次のように組織されることが考えられます (写真は Yunlong Master から引用):
  • 令人愉快的是,Vuejs的作者提供了一个插件vue-loader,可以将Vuejs的代码整合进Webpage的构建系统中,从而漂亮的实现了组件化开发的需求。通过使用Vuejs+Webpack这样的组合,我们可以把每一个组件的样式、模板和脚本集合成一个文件里。 一个组件就是一个文件,麻雀虽小五脏俱全,里面包含了组件之间的依赖关系,整个组件从外观到结构到特性再到依赖关系都一览无余。

    如上图所示,在一个example.vue文件里,包含了该example组件的Template(HTML)/JS/CSS。当然如果每个部分很长,也可以将内容分别写至对应的HTML/JS/CSS文件下,再引用到vue文件里。

    同时,我们的第二个需求 模块化开发 也在此一并实现了。在Webpack的帮助下,该组件所依赖的所有第三方资源都可以当作模块,直接就近引用(图中采用了ES6语法)—— 需要bootstrap的css,import进来,需要d3的js,也import进来,这个组件要什么,就在这里import就好,至于重复引入的问题Webpack会帮你解决。

    有了组件化和模块化开发,像往常的 “之前用过但是现在不用的第三方类库由于不知道别人还要不要用所以不敢删除只能留着” 这样的问题就能彻底解决了,还有像上文图中出现的 “引用的js类库长达一脸” 的情况也能大为改善。

    此外,如上图所示,我们还引入了一个less文件,只要我们在Webpack里开启了less-loader,任何less代码在最终输出的时候,会自动被Webpack预编译成CSS代码并插入到合适的地方。在Vue文件中,只要你开启了Webpack的各种loader,各种预编译方言都不是问题(比如sass、jade、typescript等):

    这样,支持中间语言的编译的需求也搞定了。

    这样再大的系统、再复杂的界面,也可以用这样的方式庖丁解牛,分成一件一件的模块来写。并且就像你能看到的, 相当易于维护和适合多人共同开发

    4. 潇洒的构建与部署

    • 开发
      1. 组件化开发。整个webapp由各个组件构成,一个组件的Js、CSS和HTML维护在一起,尽量松耦合。
      2. 模块化开发。Js模块化,CSS模块化,HTML模块化,所有资源都是模块,并采取就近引入原则,哪里用哪里引,同时要做到防止资源重复引入。
      3. 文件实时监听、浏览器自动刷新。
      4. 依赖包管理,版本控制。
      5. 规范编码。编码规范的事可以参考 《编写可维护的JavaScript》 ,主要靠自觉。
    • 构建
      1. 可以编译中间语言。比如支持Stylus、Less、Typescript等的编译。
      2. 支持Js、CSS的压缩和混肴。
      3. 允许图片压缩后以base64编码形式嵌入到CSS、Js或HTML中。
      4. 支持代码按需加载。将代码根据页面需求进行分割与合并,优化Http请求数。
    • 部署
      1. 根据代码内容生成版本号,实现缓存控制,提示访问性能。
      2. 支持第三方类库的Js、CSS与自己所写的代码分离。

    到这里,剩下的任务主要都是构建和部署部分了,这些都将依靠Webpack来实现,而我们所需要做的,仅仅是配置Webpack的配置文件即可搞定一切。Webpack的配置文件是一个js文件 webpack.config.js ,但是内容就像 package.json 一样,基本就是一个 javascript 对象,所需要的一切都在里面。

    一些常规任务,比如支持文件实时监听、浏览器自动刷新,可以通过安装Webpack的官方配套的调试用服务器 webpack-dev-server 解决,而支持 JS/CSS/图片压缩混肴等任务可谓老生常谈,只需直接开启Webpack自带的优化插件即可解决:

    {    //webpack.config.js    ...    plugins:{        new webpack.optimize.UglifyJsPlugin(),        new webpack.optimize.OccurenceOrderPlugin(),        new webpack.optimize.DedupePlugin()    }}

    现代浏览器一般都默认开启本地缓存功能,当第二次打开同一个网站的时候,会根据网站内请求的链接来决定是否读取缓存,比如上回打开网页请求了一个 "/plugin.js" ,下一次打开依然请求 /plugin.js 的话,浏览器会优先查找本地是缓存,从而提高了网页的加载速度。如果文件的内容发生了改变而文件名没有变化的话,便会导致读取缓存,加载过时的代码文件,造成网页显示错误。解决这个问题的方法有很多,其中一个相当不错的方法就是根据文件内容给文件名打上hash指纹。这样每当文件内容发送变化,文件名就会发生对应的改变。这里有一篇超赞的文章讲这个问题 《大公司里怎样开发和部署前端代码?》 ,作者还是云龙大神。

    在Webpack里实现打hash指纹简单飞起,只需在Output选项里进行如下配置即可:

    {    //webpack.config.js    ...    output: {        ...        filename: './js/[name].[hash].js'    },}

    上面配置的意思就是输出一个文件,它的名字叫 [name].[hash].js ,其中 [name] 是文件的本命,Webpack会给你自动替换上, [hash] 是文件的hash指纹,Webpack也会给你自动给计算出来替换上。

    Webpack那么强大,它有没有什么令人无语的地方呢?有一点可能算是不太好的地方,那就是Webpack默认会把引入的第三方代码和你自己写的代码一起打包成一个文件,这显然是不太好的:首先第三方库的代码往往并不会经常修改,用户缓存了一次之后很长一段时间内都不会再需要下载新的版本;其次第三方库的代码很可能会利用CDN渠道分发,你上别的网站缓存的第三方库,在下一个网站可能还能用,大大提高了整体浏览速度,而跟自己的代码打包在一起,就放弃了CDN的优势。

    想要将第三方类库的代码跟自己的代码分离依然很简单,也是配置一行就搞定,比如你想把引入的 Bootstrap 、 d3js 资源抽出来,可以进行如下配置:

    {    //webpack.config.js    ...    entry:{        app:'index.js',        vendors:['bootstrap','d3js']    }}

    上面的意思就是说,最终生成的文件的代码入口点有两个,其中一个是自己的代码入口点 app.js ,由自己的代码 index.js 及其中引用的资源文件组成,如果这些被引用的文件出现在 vendors 列表里的话,会被自动抽出来放到 vendors.js 里。

    这样一来,所有你想单独抽出来的代码或者资源模块,你只需把他们添加进 vendors 数组就好了。由于支持模块化开发,如果是通过 npm 下载的模块资源,直接把模块的名字填进 vendors 数组即可,Webpack会自动解析。

    此时此刻,我们还剩最后一个需求就搞定了,即支持代码按需加载,根据页面将代码进行分割与合并。这个也是Webpack的主打卖点之一,涉及一个 CommonsChunk 的概念,可以讲上好久。可惜的是我们的VisMooc中目前只有一个页面,是彻彻底底的单页应用,并不需要分割代码,暂时还用不上。目前因为缺乏实操经验,我对这个功能的理解也并不深,以后如果有机会用到,再讲讲好了。

    5. 总结&后记

    • 开发
      1. 组件化开发。整个webapp由各个组件构成,一个组件的Js、CSS和HTML维护在一起,尽量松耦合。
      2. 模块化开发。Js模块化,CSS模块化,HTML模块化,所有资源都是模块,并采取就近引入原则,哪里用哪里引,同时要做到防止资源重复引入。
      3. 文件实时监听、浏览器自动刷新。
      4. 依赖包管理,版本控制。
      5. 规范编码。编码规范的事可以参考 《编写可维护的JavaScript》 ,主要靠自觉。
    • 构建
      1. 可以编译中间语言。比如支持Stylus、Less、Typescript等的编译。
      2. 支持Js、CSS的压缩和混肴。
      3. 允许图片压缩后以base64编码形式嵌入到CSS、Js或HTML中。
      4. 支持代码按需加载。将代码根据页面需求进行分割与合并,优化Http请求数。
    • 部署
      1. 根据代码内容生成版本号,实现缓存控制,提示访问性能。
      2. 支持第三方类库的Js、CSS与自己所写的代码分离。

    到这里,所有的需求算是都已经实现了。经过这轮重写,整个项目变得无比清爽,开发起来顺畅自然,Linus有句名言叫 “Talk is cheap,show me the code” ,对比重写之前有多好,谁上谁知道。

    今回のリライトで、テクノロジー選択の重要性を痛感しました。カニを食べるには8個のカニが必要で、クルミを食べるにはクルミクリップを着用する必要があります。テクノロジースタックを適切に選択すると、問題は迅速かつ効果的に解決されます。

    エンジニアリングコードを記述するときは、パフォーマンス効率、拡張性、保守性などをすべて考慮する必要があります。科学研究を行うには、提示できるデモのみが必要な場合が多いため、要件が高すぎることはできません。しかし、良い習慣を身につければ、コードがどれほど小さくても、それは美しくエレガントになりますが、悪い習慣を身につければ、プロジェクトがどんなに大きくても、どれだけの時間を費やしても耐えられないものになります。プロジェクトと最終出力は同じではありません。実はこれも姿勢の問題なのです。

    フロントエンド エンジニアリングにはまだ長い道のりがあります。結局のところ、マスター ユンロンはこの分野で多大な貢献をした中国のフロントエンド エンジニアリングの第一人者です。フロントエンドサークルがもっともっと盛り上がって、より良くなることを願っています。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。