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>:
<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:
{{-- 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:
@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'])
@endsectionHasil Render: Urutan Head dan Body #
Route::view('/statistik', 'statistik') dan satu request GET menghasilkan:
=== 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> — 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>
© 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:
<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:
@push('scripts')
@once
<script src="/js/sekali-dalam.js"></script>
@endonce
@endpushKeduanya 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.