4.

【Laravel】個別のページ(Bladeテンプレート)にcssやjsを反映させる方法

編集
この記事の要点
  • Laravel Blade で特定ページにだけ CSS / JS を読み込む方法
  • レイアウトに @stack / @section プレースホルダを定義
  • 個別 view から @push / @section で追加
  • 一般的に @stack('styles') / @stack('scripts')<head></body> 前に配置
  • 優先度の高い順 (e.g. Bootstrap → カスタム) で出力されるよう書く

 

方法 1: @stack / @push(推奨)

同じプレースホルダに複数箇所から追加できる「stack」を使う方法。

レイアウト側

<!-- resources/views/layouts/app.blade.php -->
<!DOCTYPE html>
<html>
<head>
    <title>@yield('title')</title>

    <!-- 共通 CSS -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">

    <!-- ページ固有 CSS の挿入箇所 -->
    @stack('styles')
</head>
<body>
    @yield('content')

    <!-- 共通 JS -->
    <script src="{{ asset('js/app.js') }}"></script>

    <!-- ページ固有 JS の挿入箇所 -->
    @stack('scripts')
</body>
</html>

個別ページ側

<!-- resources/views/users/index.blade.php -->
@extends('layouts.app')

@section('title', 'ユーザー一覧')

@push('styles')
    <link href="{{ asset('css/users.css') }}" rel="stylesheet">
    <style>
        .user-card { padding: 1em; }
    </style>
@endpush

@section('content')
    <h1>ユーザー一覧</h1>
    <div class="user-list">
        @foreach ($users as $user)
            <div class="user-card">{{ $user->name }}</div>
        @endforeach
    </div>
@endsection

@push('scripts')
    <script src="{{ asset('js/users.js') }}"></script>
    <script>
        document.querySelectorAll(".user-card").forEach(card => {
            card.addEventListener("click", () => console.log("clicked"));
        });
    </script>
@endpush

方法 2: @section / @yield

1 箇所からの挿入のみ (上書き) で十分なケース。

<!-- layouts/app.blade.php -->
<head>
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
    @yield('styles')
</head>
<body>
    @yield('content')
    <script src="{{ asset('js/app.js') }}"></script>
    @yield('scripts')
</body>

<!-- users/index.blade.php -->
@extends('layouts.app')

@section('styles')
    <link href="{{ asset('css/users.css') }}" rel="stylesheet">
@endsection

@section('content')
    ...
@endsection

@section('scripts')
    <script src="{{ asset('js/users.js') }}"></script>
@endsection

@push vs @section の使い分け

項目@stack / @push@yield / @section
挿入箇所複数 view から追加可能1 つの section を 1 つの view が定義
順序追加順(先 → 後)1 つだけ
用途レイアウト + コンポーネント両方から script 追加ページ固有の単一 CSS / JS
パーシャル / コンポーネント内から使える○ @push× (@yield は section 1 つに限定)

@once で重複防止

パーシャル (含めるパーツ) を複数回 include しても、CSS / JS は 1 回だけ読み込みたい:

<!-- partials/datepicker.blade.php -->
@once
    @push('styles')
        <link href="{{ asset('css/datepicker.css') }}" rel="stylesheet">
    @endpush
    @push('scripts')
        <script src="{{ asset('js/datepicker.js') }}"></script>
    @endpush
@endonce

<input type="text" class="datepicker">

<!-- 利用側 (datepicker を 3 回 include しても CSS/JS は 1 回だけ) -->
@include('partials.datepicker')
@include('partials.datepicker')
@include('partials.datepicker')

@prepend (先頭に追加)

後から追加するけど stack の先頭に置きたい(jQuery より先に Polyfill 等):

@prepend('scripts')
    <script src="https://polyfill.io/v3/polyfill.min.js"></script>
@endprepend

Vite との統合

Laravel 10+ はデフォルトで Vite を使う:

<!-- レイアウト -->
<head>
    @vite(['resources/css/app.css', 'resources/js/app.js'])
    @stack('styles')
</head>
<body>
    @yield('content')
    @stack('scripts')
</body>

<!-- 個別ページ -->
@push('styles')
    @vite(['resources/css/users.css'])
@endpush

@push('scripts')
    @vite(['resources/js/users.js'])
@endpush

# Vite が hot reload + バンドル + cache busting を自動化

条件付き読み込み

@push('scripts')
    @if (auth()->check())
        <script src="{{ asset('js/authenticated-user.js') }}"></script>
    @endif

    @env('production')
        <script src="{{ asset('js/analytics.js') }}"></script>
    @endenv

    @if (config('app.feature.chat'))
        <script src="{{ asset('js/chat.js') }}"></script>
    @endif
@endpush

パフォーマンスの考慮

  • defer / async: <script src="..." defer> でレンダーブロック回避
  • preload: <link rel="preload" href="..." as="script"> で先読み
  • Critical CSS: 重要な CSS はインラインで <style>
  • Vite で自動最適化: コード分割・遅延読み込みが自動
@push('scripts')
    <script src="{{ asset('js/users.js') }}" defer></script>
@endpush

@push('styles')
    <link rel="preload" href="{{ asset('fonts/Noto.woff2') }}" as="font" type="font/woff2" crossorigin>
@endpush

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 親ビューと子ビュー(@section, @yield, @extends, @parent, @include)
  2. 条件分岐(@if)
  3. 繰り返し(@for, @foreach, @forelse, @while)
  4. 個別のページにcssやjsを反映させる方法