网页加载缓慢可能是由于API请求造成的

问题描述 投票:0回答:1

我想快速解释一下情况。本质上,我创建了一个 Livewire 组件,它允许我从无线电 API 获取数据来获取歌曲。这些歌曲每 3 分钟更改一次,只要此 API 的属性发生更改,我就想更新我的 Blade 视图。

class TitleSong extends Component
{

    public $songTitle;
    public $songArtist;
    public $songImage;
    public $secondsTotal;
    public $secondsElapsed;
    public $elementToShow;
    public $remainingTime;

    public function render()
    {
        return view('livewire.title-song');
    }

    public function boot()
    {
        $this->fetchSongData();
    }


    public function fetchSongData()
    {
        try{
         $response = Http::get('MY API');
        $data = $response->json(); 

       $this->songArtist = $data['song']['artist'];
        $this->secondsElapsed = $data['song']['seconds_elapsed'];
        $this->secondsTotal = $data['song']['seconds_total'];
        $this->songImage = $data['song']['art']; 
         $this->songTitle = $data['song']['title'];

        $remainingTime = $this->secondsTotal - $this->secondsElapsed;
        $this->remainingTime = $remainingTime; 

    } catch (\Throwable $th) {
        dd($th->getMessage());
    }
    }

}

由于这些元素需要在整个文档中拆分,因此我使用新变量“$elementToShow”使其成为可能,这就是视图:

<div wire:poll.{{$remainingTime}}="fetchSongData">
    @if ($elementToShow === 'songTitle')
        <h1 id="songTitle" style="color: var(--quaternary-color); font-weight: 600" class="text-4xl">{{$songTitle}}</h1>
    @elseif ($elementToShow === 'songArtist')
        <p id="songArtist" class="mt-2 ml-1" style="color: var(--quinary-color); font-weight: 400; font-size: 15px">{{$songArtist}}</p>
    @elseif ($elementToShow === 'secondsElapsed')
        <span id="secondsElapsed" class="current-time">0:00</span>
    @elseif ($elementToShow === 'secondsTotal')
        <span id="secondsTotal" class="total-time"> {{substr($secondsTotal, 0, 1) . ':' . substr($secondsTotal, 1, 2)}}</span>
    @elseif($elementToShow === 'songImage')
    <img style="position: absolute; left: 12%; top: 2%; border-radius:20px; z-index: 1" width="220px" height="200px" src="{{$songImage}}" />
    @endif
</div>

现在我想问你是否有更好的方法来做到这一点而不使用wire:poll或其他东西。不幸的是,这给我带来了很多痛苦,因为它极大地影响了我网站的速度。该网站现在需要 5 秒才能加载 HTML 文档。

我不知道为什么这个 API 调用要花很长时间来加载,也许是 Livewire 组件的原因,但我尝试在这里和那里做一些优化,并使用 Laravel Debug。

php laravel performance lazy-loading laravel-livewire
1个回答
0
投票

好吧,所提供的代码中有一些不好的做法,所以我将解决这个问题以及您正在寻求帮助的原始问题。

TLDR

您只需将 Lazy 属性添加到带电线路附带的类中,或者添加到父视图或路由中。以下是如何向组件添加 Lazy 属性。

use Livewire\Component;
use Livewire\Attributes\Lazy; // Import The Attribute
 
#[Lazy]
class SongTitle extends Component
{

public function mount() {
 // Resolve Song From API HERE
}

您也不应该使用 Boot 方法。每次用户和服务器通信时(而不是首次渲染组件时)都会触发此方法。您最终可能会无缘无故地反复向 API 请求歌曲,这将锁定您的应用程序并极大地减慢您的应用程序速度。

官方文档中有更多详细信息 - Livewire Lazy Loading

API 请求使应用程序变慢

为了解决这个问题,我们可以延迟加载歌曲的数据。

你可能不应该使用 Boot

客户端和服务器之间的每个请求都会触发引导方法。您可以向此 API 端点发送许多请求来获取歌曲数据,并在不需要获取歌曲数据时阻止请求,因为所需的数据没有发生任何变化。

我们应该将此功能移至 Mount。这只会发送一次歌曲数据的 API 请求,但如果将来需要,您仍然可以手动发送另一个请求。

您可以在 Livewire 文档中阅读更多相关信息 - Lifecycle Hooks

为什么 API 请求会减慢我的应用程序

当您浏览非“单页应用程序”的标准网站时,您的 Web 浏览器(例如 Google Chrome)会向 Web 服务器发送页面请求。 有时,我们会遇到服务器需要一段时间才能响应的情况,因为它正在处理构建此 HTML 文件所需的所有内容。

为了解决这个问题,我们可以使用延迟加载,Livewire 本身就支持延迟加载。这在整个互联网上被广泛使用来解决您当前遇到的问题。简而言之,服务器将使用 HTML 文件进行响应,Javascript 将在客户端的 Web 浏览器中运行,它将处理获取这些额外数据并更新页面。

Livewire 特定上下文

由于 Livewire 在某种程度上模拟了您从非整体 SPA 获得的体验,因此您的 Web 浏览器可以与服务器来回通信,并且您实际上可能不会等待请求完成。相反,Livewire 安装或渲染方法需要一些时间来执行,并且需要在渲染方法返回视图之前完成。

如何在 Livewire 中延迟加载

在 Livewire 中,文档在这里很好地介绍了延迟加载:

Livewire - 延迟加载

尽管有几种方法可以实现此功能,但实现此功能很简单。我无法想象默认情况下我们不希望这种延迟加载,所以我建议的方法是将属性添加到组件类中,如下所示:

use Livewire\Component; use Livewire\Attributes\Lazy; // Import The Attribute #[Lazy] class SongTitle extends Component {

其他改进

我不确定您的示例代码与您的实现有多接近,但没有适当的类型提示。我们可能应该更多地分离代码,这样我们就不会有具有多重职责的类和方法。

这是类的改进示例,您可以在几分钟内将其实现到代码库中:

#[Lazy] class TitleSong extends Component { // set types on your variables public string $songTitle; public string $songArtist; public string $songImage; public int $secondsTotal; public int $secondsElapsed; public $elementToShow; public int $remainingTime; public function mount(): void { $this->resolveSong(); } public function resolveSong(): void { // Logic for API stuff here }

我建议研究的进一步改进包括创建一个服务来处理 API 通信以获取歌曲数据。

我创建了一个 GIST,其中包含一些适合您提供的上下文的示例类。它没有涉及很多细节,但我希望它可以直观地理解,所以这不是太大的问题。

歌曲标题清理 - Gist

© www.soinside.com 2019 - 2024. All rights reserved.