いくつかのステップに分かれると思うので、ステップを分けるところから理解を深めるといいんじゃないかなと思います。
参照先を見つける
エントリーとなる最初のファイル(おそらく、bundlerのオプションで指定しているはず)から見ていき、参照先のファイルを見つけていきます。参照元から参照先のファイルを見つけて何が何に依存しているのか、というファイル間の結びつきを見つけます。木構造のようなグラフを作るようなイメージですね。
参照先を解決し、ファイルをまとめる
一個のファイルにするだけであれば、全ての参照先のファイルがわかっていれば、結合するファイルの全体が分かっているので、それをまとめるだけでいいです。まとめ方はものに寄りますが、webpackの場合は resolver と呼ばれる機能があり、それを介して参照先のオブジェクトを見つけて解決できるようにしています。
https://github.com/webpack/enhanced-resolve
ローダー/プラグインの仕組み
ただし、これはあくまでJSのファイルを一つにまとめる場合の方法です。webpackにせよviteにせよ CSS や画像などのJSではないファイルをロードする仕組みがあります。それを loader と呼んだり plugin と呼んだりします。ひとつ上で書いた参照解決する際に JS じゃないファイルは「こういう拡張子だったらこのloader/pluginを呼んでね」みたいに定義することができます。これを使って CSS のファイルであっても中で参照解決したりします。このあたりの仕組みはややこしいです。プラグインそれぞれの中身を見たほうが早いと思います。
最適化する
「一個のファイルにするだけであれば〜」と書きましたが、一個のファイルにしてしまうとファイルサイズが大きくなりすぎます。JSのファイルが大きくなると全体のロード時間に影響してしまうので小さくするほうが望まれており、それを最適化する仕組みがまた別なプラグインやデフォルトの機能として提供されています。
これを Code Splittingと呼びます。
https://web.dev/articles/reduce-javascript-payloads-with-code-splitting
https://web.dev
この他にもキャッシュして読み込みスピード上げてたり、色んな施策をbundlerは行っています。オプションを眺めてると色々あるので見てみると良いと思います。