Widget grafik butuh stylesheet, library chart, dan script inisialisasi sendiri. Meletakkan ketiganya di layout berarti layout memuat aset semua widget — mubazir di halaman tanpa widget itu. Meletakkannya di tengah <body> pun tidak selalu boleh, karena CSS wajib berada di <head>. Blade menyelesaikan dilema ini dengan stack: layout menyiapkan titik kumpul bernama lewat @stack, lalu view mana pun — partial, halaman anak, bahkan component — mengirimkan asetnya dari jauh lewat @push. Chapter ini menguji urutan pengumpulannya dengan halaman statistik sungguhan yang dirender lewat HTTP.

Dua Sisi: @stack di Layout, @push di View #

Layout layouts/app.blade.php dari chapter Layouts dan Sections sudah menyediakan dua stack — satu untuk stylesheet di <head>, satu untuk script menjelang </body>:

blade
<head>
    <meta charset="utf-8">
    <title>@yield('title', 'TugasKu')</title>
    @stack('styles')
</head>
<body>
    {{-- ... kerangka halaman ... --}}

    @stack('scripts')
</body>
</html>

Directive @stack('nama') adalah titik parkir: kosong saat tidak ada yang mengirim, terisi berurutan saat ada. Pengirimnya adalah @push('nama') ... @endpush yang bisa ditulis di view mana pun yang ikut dirender.

Partial yang Membawa Asetnya Sendiri #

Partial grafik mengirim tiga hal sekaligus. Stylesheet dan library chart cukup sekali berapa pun jumlah grafiknya, jadi keduanya memakai @pushOnce; script inisialisasi justru harus berbeda per instance, jadi memakai @push biasa dengan parameter $jenis:

blade
{{-- resources/views/partials/grafik.blade.php --}}
@pushOnce('styles')
    <link rel="stylesheet" href="/css/grafik.css">
@endpushOnce

@pushOnce('scripts')
    <script src="/js/chart.min.js"></script>
@endpushOnce

@push('scripts')
    <script>new Grafik('.grafik-{{ $jenis }}').init();</script>
@endpush

<div class="grafik grafik-{{ $jenis }}">Grafik {{ $jenis }} dimuat.</div>

Halaman resources/views/statistik.blade.php memasukkan partial dua kali dengan jenis berbeda, plus satu @prepend untuk utilitas yang harus dimuat paling awal:

blade
@extends('layouts.app')

@section('title', 'Statistik')

@push('styles')
    <link rel="stylesheet" href="/css/statistik.css">
@endpush

@prepend('scripts')
    <script src="/js/util.js"></script>
@endprepend

@section('konten')
    <h2>Dashboard Grafik</h2>
    @include('partials.grafik', ['jenis' => 'batang'])
    @include('partials.grafik', ['jenis' => 'garis'])
@endsection

Hasil Render: Urutan Head dan Body #

Route::view('/statistik', 'statistik') dan satu request GET menghasilkan:

text
=== GET /statistik → HTTP 200 ===
<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="utf-8">
    <title>Statistik</title>
        <link rel="stylesheet" href="/css/statistik.css">
    <link rel="stylesheet" href="/css/grafik.css">
</head>
<body>
    <header>
        <strong>TugasKu</strong> &mdash; Beranda    </header>

    <div class="layout">

        <main>
                <h2>Dashboard Grafik</h2>
    <div class="grafik grafik-batang">Grafik batang dimuat.</div>
    <div class="grafik grafik-garis">Grafik garis dimuat.</div>
        </main>
    </div>

    <footer>
                    &copy; 2026 TugasKu
            </footer>

        <script src="/js/util.js"></script>
    <script src="/js/chart.min.js"></script>
    <script>new Grafik('.grafik-batang').init();</script>
    <script>new Grafik('.grafik-garis').init();</script>
</body>
</html>

Urutan di kedua stack mengikuti aturan yang jelas. @push berperilaku antrean — yang dikirim lebih dulu keluar lebih dulu: statistik.css diikuti grafik.css di head, lalu urutan script di body. @prepend('scripts') menempatkan util.js di paling depan antrean meskipun ditulis di halaman — perpindahan inilah fungsinya, misalnya untuk polyfill yang harus dieksekusi sebelum library lain. @pushOnce menjaga grafik.css dan chart.min.js masing-masing tampil satu kali padahal partial di-include dua kali, sementara @push biasa menghasilkan dua baris inisialisasi berbeda — satu untuk grafik batang, satu untuk grafik garis.

Duplikasi yang Dicegah @pushOnce #

Perilaku berbeda kedua directive itu kita buktikan dengan mengganti @pushOnce('styles') menjadi @push('styles') pada partial. Head berubah menjadi:

text
    <title>Statistik</title>
        <link rel="stylesheet" href="/css/statistik.css">
    <link rel="stylesheet" href="/css/grafik.css">
    <link rel="stylesheet" href="/css/grafik.css">
</head>

Stylesheet grafik dimuat ganda karena setiap include mengirim salinannya sendiri. Browser menoleransi duplikasi CSS, tetapi library JavaScript yang dieksekusi dua kali bisa memicu error registrasi ganda — alasan kuat memakai @pushOnce untuk semua aset bersama.

@once di dalam @push #

Sebelum @pushOnce tersedia, dedup dilakukan dengan directive @once. Kita uji kedua posisi penulisannya pada partial yang di-include dua kali — @once di dalam @push, dan @once yang membalut @push:

blade
@push('scripts')
    @once
        <script src="/js/sekali-dalam.js"></script>
    @endonce
@endpush

Keduanya menghasilkan tepat satu baris output — pola @once bekerja di kedua posisi. Perbedaannya hanya keringkasan: @pushOnce menuntaskan hal yang sama dalam satu pasangan directive tanpa nesting.

Stack juga ramah terhadap component — pengiriman @push tidak harus berasal dari halaman anak. Sebuah component yang dipakai dua kali dalam satu halaman dapat mengirim asetnya sendiri lewat @pushOnce, dan aset tersebut tetap mendarat di titik @stack pada layout. Kita verifikasi dengan component kecil berisi @pushOnce('scripts') yang dirender dua kali: script-nya tampil tepat satu kali di posisi @stack('scripts') sebelum </body>, persis seperti aset yang dikirim dari partial.

Aset kini terkumpul rapi, dan perangkat Blade kita lengkap: layout mewarisi kerangka, component menyediakan bagian kecil, slot mengantar konten, stack menata aset. Chapter penutup section ini merangkai semuanya menjadi strategi UI reusable yang utuh.