ホームページ >ウェブフロントエンド >jsチュートリアル >ランタイムの作成
こんにちは、私の名前は Lucas Wasilewski です。NodeJS でプログラミングを始めて以来 (2021 年の初めに)、Github にプロジェクトの説明を入力したのと同じように、私は常にそうしたいと思っていました。ツールのようなものを書こうと思ったのですが、このプロジェクトに関するドキュメンタリーを観てからさらにその思いが高まりました。オープンソースの世界には紆余曲折があり、必要に応じて非常に歓迎してもらえることに驚きました。そして、一週間頭を悩ませた後、この挑戦を望んでいる将来の気の狂ったプログラマが私と同じ間違いを犯さないように、この記事を書くことにしました。
この用語は、この主題についてあまり理解していない人を簡単に誤解させる可能性があるため、適切な定義が必要です。
JavaScript ランタイムは、ブラウザの外部で言語を実行できるようにするツールです
現在、NodeJS、Deno (Node Killer)、Bun (Deno Killer) という 3 つの人気のあるランタイムがありますが、基本的に同じことを行います。ブラウザから JavaScript を使用したり、他のライブラリを使用して新しい機能を作成したりできます。どれもサーバーの構築、ライブラリの作成、さらにはモバイル アプリケーションやターミナル アプリケーションの作成に使用できるので、これは非常に優れています。
Node と Deno はどちらも同じ人、Ryan Dahl によって作成されました。2009 年に彼は、開発者が「非同期 IO」アプリケーションを作成できるようにするツールを作成しました。つまり、メインスレッドをブロックせず、引き続きこれを念頭に置いて、彼はまさにそれを行うライブラリである Libuv を作成しました。それまで、プロジェクトは単なる C の大きな山であり、より多くの人にこのツールを使ってもらいたいのであれば、より理解しやすく使いやすい言語が必要でした。偶然にも、同時に Google は V8 を発表しました。高速な JavaScript コンパイラを使用して、この 2 つを組み合わせて Node.
を作成しました。しばらくして (具体的には 9 年後)、Ryan はプロジェクトを離れ、より興味深いと考えた他のことに取り組み始めました。これにより、Node で修正できるいくつかのエラーに気づきましたが、コミュニティはすでに非常に大規模でしたそして、大きく後退することは不可能だったので、より良い仕事をしようと決意して、彼は Deno を作成しました。Deno は、Node よりもはるかに優れていることが期待される別の IO ランタイムです。今日 (2024 年) の時点で、Deno はバージョン 2.0 であり、非常に優れています。プロジェクトとコミュニティにとって安定しています。
この全体的なストーリーにより、より多くの人がランタイム コミュニティに参加するようになり、これが私たちの Bun の作成、そしてさらに良いことに、私のランタイムとあなたのランタイムの作成にもつながりました。それでは本題に入りましょう。
前述したように、V8 は Node エンジンであるため、ライブラリと ヘッダー にアクセスするには、実際に V8 をダウンロードして手動でコンパイルする必要があります。これは Google プロジェクトなので、ダウンロードとコンパイルには独自の方法があるため、このためにはマニュアルに従う必要があります: リンク。コピーして貼り付けるだけで最終的なコマンドに移動できます。
しかし、ここで私は間違いを犯し、自分のやり方がすべて間違っていたことに気づくまでに 3 日かかりました。以下を使用してビルド構成ファイルを生成した後:
tools/dev/v8gen.py x64.release
out.gn/x64.release/ フォルダー内の args.gn ファイルには、Ninja (コンパイル ツール) がライブラリ ファイルを生成するために使用するビルド構成が含まれているため、非常に注意する必要があります。 v8_monolithic = true パラメータを使用しますが、最近のバージョンではこれは使用されなくなりました。この StackOverflow コメントによると、is_component_build = true パラメータを使用して適切なファイルを生成し、ファイルのコンパイル時にフラグを変更する必要があります。非常に愚かなことで、注意を払わないと貴重な時間を無駄にする可能性があります。
残りのフラグを正しく配置したら、コマンドを実行してプロジェクトをコンパイルするだけです
忍者 -C out.gn/x64.release
それまでに、何か食べてください。V8 は無数のテストを含む非常に大規模なプロジェクトであるため、マシンによっては、このプロセスに 1 時間以上かかる場合があります。そのため、実行したままにして読み続けてください。
コンパイル後、v8/samples/hello-world.cc を見て、JavaScript のコンパイル方法のアイデアを得ることができますが、具体的には次の行です。
v8::Local<v8::String> source = v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'"); // Compile the source code. v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
「Hello World」を含む文字列を試してみて、関数、ループ、条件文を作成し、古典的な console.log() を含めると未定義のメッセージが返されることに気づき、混乱してしまいます。私は、コンソール オブジェクトは V8 自体の一部であると常に考えていましたが、実際には Node 自体にコンソール オブジェクトが含まれており、ブラウザーにも DOM の一部として含まれています (console.log はおそらくブラウザーでサポートされていないという 2012 年の投稿)。自分で作成する必要があります。
独自の関数を作成できるようにするには、まず V8 が複数のスコープで動作することを理解する必要があります。そのうちの 1 つはコンテキストであり、ランタイムはこれを通じて、スクリプトを個別に実行する場所と方法を認識します。他のすべての間で共有されるグローバル オブジェクトが存在する可能性があり、その中にカスタム関数を挿入します。
tools/dev/v8gen.py x64.release
これらの行により、global と呼ばれるオブジェクトを作成することができ、実行時に Print 関数を呼び出す「print」関数テンプレートを挿入しました。
v8::Local<v8::String> source = v8::String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'"); // Compile the source code. v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
Print 関数は、JavaScript 内の関数呼び出しに関する情報を含むこのクレイジーなパラメーターを受け取り、それを通じてその中のすべての項目を反復処理し、それらを C 文字列に変換し、非常に直接的に画面に表示します。非常にシンプルで、その役割を果たしています。ファイルに入れて読み取って V8 で再生するだけで十分です (それについては皆さんにお任せします)。
v8::Local<v8::ObjectTemplate> global = v8::ObjectTemplate::New(GetIsolate()); global->Set(GetIsolate(), "print", v8::FunctionTemplate::New(GetIsolate(), this->Print)); v8::Local<v8::Context> context = v8::Context::New(GetIsolate(), nullptr, global);
さて、もうこの内容を理解していただき、自家製 Node 用の独自の実装を作成するために読むのをやめていただけたと思いますが、V8 が私たちを連れて行ってくれるのはここまでで、プロフェッショナル ランタイムでは、JavaScript がより多くの操作を実行できるようにする必要があります。これを行うには、まさにこの目的のために作成された Libuv を使用します。
インストールしてコンパイルするためのチュートリアルはここにあります。ここで注意すべき重要な点は、非同期操作を自由に実行できる、つまりメインスレッドをブロックせずに実行できるため、より重い作業 (ファイルを開く、サーバーでのリクエストを待機するなど) を実行しながらプログラムの実行を継続できるということです。ソケット)。
それ自体には http サーバーを作成する機能がすでに組み込まれているため、V8 呼び出しと同期するだけで済みます。誤解しないでください。これは簡単な作業ではありません。2 つのライブラリのインターフェイスが大きく異なるため、両方を接続するのは困難ですが、方法は常にあり、ノードのソース コードはオープンなので、必ずアイデアを盗んでください。そこに
別の記事も終わりに達しましたので、実装中に気づいた詳細をいくつか見ていきます。 1 つ目は間違いなく複雑さです。もちろん、これは単純なプロジェクトではありませんが、V8 インターフェイスの操作方法を理解すると、作業は非常に早く進みます。
このプロジェクトにより、Node についての理解もさらに深まりました。ランタイムが通信するライブラリの単なる集合体であるという事実により、より複雑なもの (「イベント ループ」など) がどのように動作するかを非常に簡単に理解できます。
私が何を正しく行ったのか、あるいはおそらく非常に間違っていたのかを確認したい場合は、github のプロジェクトをご覧ください: 完了
話は簡単です、コードを見せてください - Linus Torvalds
## 参考資料
https://github.com/libuv/libuv
https://v8.dev/docs
https://stackoverflow.com/questions/71213580/cant-get-v8-monolith-to-genorate
https://github.com/ErickWendel/myownnode
https://github.com/WasixXD/done
以上がランタイムの作成の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。