skip to content

In Laravel, what does Blade compile a .blade.php template into, where is the result stored, and when is it recompiled?

level: juniorimportance: should knowfreq 36%

answer

  1. plain PHP, no runtime template parser
  2. storage/framework/views, VIEW_COMPILED_PATH
  3. file named by a hash of the path
  4. recompile when source is not older
  5. view.check_cache_timestamps defaults to true

basics

~20 s

Blade compiles each template into a plain PHP file stored in storage/framework/views (config key view.compiled, env VIEW_COMPILED_PATH). On render Laravel reuses it unless it is missing or the source file's modification time is not older than the compiled file's.

solid answer

~50 s

Blade is a compiler, not an interpreter: the first time a view renders, the `BladeCompiler` turns the `.blade.php` source into ordinary PHP, so `{{ $name }}` becomes an `echo e($name)` statement and `@extends` becomes a footer line that renders the layout, and writes it to `storage/framework/views`. That location is the `view.compiled` config key, overridable with `VIEW_COMPILED_PATH`; each file is named by an `xxh128` hash of the template's path and ends with a `/**PATH ... ENDPATH**/` comment so errors map back to the source. On later renders Laravel includes the compiled file directly and recompiles only when it is missing or the source's modification time is not older than the compiled file's. The timestamp check can be switched off with `view.check_cache_timestamps`, which defaults to `true`. Because the output is plain PHP, rendering adds almost no overhead, and `__DIR__` inside a view points at the compiled file.

code

html · 6 lines
html
<!-- resources/views/courses/show.blade.php -->
@extends('layouts.app')

@section('content')
    <h1>{{ $course->name }}</h1>
@endsection

go deeper

for a junior

Recall that Blade compiles templates into plain PHP files cached in storage/framework/views, and that editing a template recompiles it automatically on the next render.

for a middle

Explain the expiry check: compiled file missing, or source modification time not older than the compiled file. Name view.compiled, VIEW_COMPILED_PATH and view.check_cache_timestamps.

for a senior

Use the model when debugging: read a hash-named file in a stack trace through its PATH comment, spot DIR misuse, and know what turning the timestamp check off trades away.

for a principal

Weigh the filesystem assumptions: a writable compiled-views directory per server or container, and whether read-only images need views compiled at build time.

## Blade is a compiler Some template engines parse the template on every render. **Blade** does not. The first time a view is rendered, Laravel's `BladeCompiler` translates the `.blade.php` source into an ordinary PHP file, and every later render simply executes that file. The Blade docs describe templates as "compiled into plain PHP code and cached until they are modified", which is why Blade adds essentially no runtime overhead. What the translation produces: - `{{ $course->name }}` becomes `<?php echo e($course->name); ?>`. - `@section('content')` becomes a call that starts output buffering on the view factory, and `@endsection` a call that stops it and stores the content. - `@extends('layouts.app')` produces no output where it is written; it becomes a **footer** line, appended at the end of the compiled file, that makes and renders the layout with the child's variables. - Component tags such as `<x-layout>` are rewritten into calls that start, capture and render the component. - The compiler appends a `/**PATH <source path> ENDPATH**/` comment, which Laravel uses to point error pages at the original template rather than at the compiled file. ## Where compiled views live | Setting | Default | |---|---| | config key `view.compiled` | `storage/framework/views` (via `realpath(storage_path('framework/views'))`) | | env override | `VIEW_COMPILED_PATH` | | config key `view.cache` | `true`; `false` recompiles on every render | | config key `view.check_cache_timestamps` | `true`; `false` skips the freshness check | The `view` config file is not part of the Laravel 13 skeleton; the framework's defaults apply until you publish it, and keys such as `view.cache` and `view.check_cache_timestamps` are read with the defaults above even when the file is absent. Each compiled file is named with an `xxh128` hash of the template's path, so the directory holds opaque names like `3f9a...c2.php`. The directory must be writable by the PHP process. ## When a view is recompiled On each render, the compiler engine asks whether the view has **expired**: 1. If caching is disabled (`view.cache` is `false`), it has always expired. 2. If no compiled file exists at the hashed path, it has expired. 3. If timestamp checks are disabled, it has not expired. 4. Otherwise it has expired when the source file's modification time is **greater than or equal to** the compiled file's. When a view has expired, it is compiled again before it is executed. The compiler also compares a hash of the new output with the existing compiled file and leaves the file untouched when the output is identical, only bumping its timestamp so the next check sees it as fresh. This is why editing a template in development shows up on the next request without any command: saving the file advances its modification time. ## Reading a compiled view Opening a compiled file is the quickest way to understand a Blade directive. The layout directives, for example, turn out to be thin calls on the view factory, the object exposed to compiled templates as `$__env`: - `@section` and `@endsection` become `$__env->startSection(...)` and `$__env->stopSection()`; - `@yield('content')` becomes an echo of `$__env->yieldContent('content')`; - `@push` and `@stack` become `startPush` and an echo of `yieldPushContent`. Seeing that `@extends` compiles to a line at the very end of the file explains, without any documentation, why a child view's sections exist before its layout runs. ## Consequences worth knowing - **`__DIR__` and `__FILE__`** inside a Blade view refer to the compiled file under `storage/framework/views`, not to `resources/views`. The docs warn against using them in views. - **PHP's OPcache** caches compiled PHP files like any other script, so a compiled view is served as cached bytecode once it is warm. - **Inline templates** rendered with `Blade::render($string, $data)` are also written to the compiled-views directory; pass `deleteCachedView: true` to remove the temporary file afterwards. - A stack trace that mentions a hash-named file in `storage/framework/views` is a compiled Blade view; the `PATH` comment at its end names the source template. Precompiling every view during a deployment, and clearing the directory, are Artisan concerns covered with the other production cache commands.

  • Why does using __DIR__ inside a Blade view point somewhere unexpected?
    At render time Laravel executes the compiled PHP file in `storage/framework/views`, not the `.blade.php` source in `resources/views`. `__DIR__` and `__FILE__` are resolved by PHP for the file actually running, so they name the compiled-views directory and the hash-named file. Build paths with helpers such as `resource_path()` instead.
  • What happens to Blade rendering if view.check_cache_timestamps is set to false?
    Laravel stops comparing the source's modification time with the compiled file's. A view is compiled once, when no compiled file exists, and after that edits to the template are ignored until the compiled files are removed or regenerated. It saves a filesystem stat per view render, which only makes sense where templates never change between deploys.

saying these in an interview costs you the question

  • Blade parses the template text on every request
  • Compiled views are stored in resources/views next to the templates
  • A compiled view is rebuilt only when you run an Artisan command
  • __DIR__ inside a Blade view points at resources/views
  • Blade keeps compiled templates in memory rather than on disk