We'll add some custom functionality to the composer package we created in part one to create a Laravel boilerplate with things set up just how we prefer.
We will cover how to configure the preset to remove compiled files from version control
and have it automatically set up a better default layout for Laravel
Our first order of business will be to remove compiled assets from version control :skull:. Storing minified files in our git repository should be avoided. Since we can automatically generate those files with our build process, they aren't true "source" files.
A convention many of the community presets adopt is storing the new versions of files within our package's
src/stubs
directory, so we'll follow that with our example too.
Create a file at src/stubs/new-gitignore
containing the following:
1/node_modules2/public/hot3/public/storage4/public/css5/public/js6/public/mix-manifest.json7/storage/*.key8/vendor9/.idea10/.vscode11/.vagrant12Homestead.json13Homestead.yaml14npm-debug.log15yarn-error.log16.env17.phpunit.result.cache
1/node_modules2/public/hot3/public/storage4/public/css5/public/js6/public/mix-manifest.json7/storage/*.key8/vendor9/.idea10/.vscode11/.vagrant12Homestead.json13Homestead.yaml14npm-debug.log15yarn-error.log16.env17.phpunit.result.cache
We just added the public/css
, public/js
, and public/mix-manifest.json
paths on top of Laravel's default.
Now tell our Preset
class to replace the default .gitignore
file.
Open up the src/Preset.php
file and update the install()
method with the following.
1public static function install()2{3 // Replace the default .gitignore with our own4 copy(__DIR__ . '/stubs/new-gitignore', base_path('.gitignore'));5}
1public static function install()2{3 // Replace the default .gitignore with our own4 copy(__DIR__ . '/stubs/new-gitignore', base_path('.gitignore'));5}
If we were to run php artisan preset austencam
we should see the changes get made to our main app's .gitignore
file, pretty slick!
Let's do something more interesting now, like replacing the default views with a simple "app" layout.
Add a new file at this location in our package: src/resources/views/layouts/app.blade.php
:
1<!DOCTYPE html>2<html lang="{{ app()->getLocale() }}">3 <head>4 <meta charset="utf-8" />5 <meta http-equiv="X-UA-Compatible" content="IE=edge" />6 <meta name="viewport" content="width=device-width, initial-scale=1" />7 <meta name="csrf-token" content="{{ csrf_token() }}" />8 <!--9 Note: I'm pulling Tailwind CSS from the CDN to shorten this tutorial10 but most apps will want to build it with their own config, see11 https://tailwindcss.com/docs/installation for more details.12 -->13 <link14 href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css"15 rel="stylesheet"16 />17 <title>{{ config('app.name', 'Laravel') }}</title>18 </head>19 <body class="font-sans text-green antialiased text-grey-dark">20 <div id="app">@yield('body')</div>21 </body>22</html>
1<!DOCTYPE html>2<html lang="{{ app()->getLocale() }}">3 <head>4 <meta charset="utf-8" />5 <meta http-equiv="X-UA-Compatible" content="IE=edge" />6 <meta name="viewport" content="width=device-width, initial-scale=1" />7 <meta name="csrf-token" content="{{ csrf_token() }}" />8 <!--9 Note: I'm pulling Tailwind CSS from the CDN to shorten this tutorial10 but most apps will want to build it with their own config, see11 https://tailwindcss.com/docs/installation for more details.12 -->13 <link14 href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css"15 rel="stylesheet"16 />17 <title>{{ config('app.name', 'Laravel') }}</title>18 </head>19 <body class="font-sans text-green antialiased text-grey-dark">20 <div id="app">@yield('body')</div>21 </body>22</html>
This is a simple layout our app's views can inherit from. The default welcome.blade.php
the framework comes with is meant to be ripped out in favor of your favorite frontend framework anyway, so let's make our new welcome view use the new layout.
Create a file at src/stubs/resources/views/welcome.blade.php
with this code:
1@extends('layouts.app') @section('body')2<div class="min-h-screen flex items-center justify-center">3 <h1 class="text-3xl">Build Something Great!</h1>4</div>5@endsection
1@extends('layouts.app') @section('body')2<div class="min-h-screen flex items-center justify-center">3 <h1 class="text-3xl">Build Something Great!</h1>4</div>5@endsection
The only thing left to do is tell our preset to copy these files over. Open up the src/Preset.php
file and add the following use
statement.
1use Illuminate\Filesystem\Filesystem;
1use Illuminate\Filesystem\Filesystem;
Now update the install()
method in our src/Preset.php
file to match this code:
1 public static function install()2 {3 // Replace the default .gitignore with our own4 copy(__DIR__ . '/stubs/new-gitignore', base_path('.gitignore'));56 // Delete the default view and copy our stub views into place7 tap(new Filesystem, function ($files) {8 $files->delete(resource_path('views/welcome.blade.php'));9 $files->copyDirectory(__DIR__.'/stubs/resources/views', resource_path('views'));10 });11 }12}
1 public static function install()2 {3 // Replace the default .gitignore with our own4 copy(__DIR__ . '/stubs/new-gitignore', base_path('.gitignore'));56 // Delete the default view and copy our stub views into place7 tap(new Filesystem, function ($files) {8 $files->delete(resource_path('views/welcome.blade.php'));9 $files->copyDirectory(__DIR__.'/stubs/resources/views', resource_path('views'));10 });11 }12}
So let's break down the code we added there (starting with tap
). Some of you may be thinking "whoa, what the heck is tap?". Tap is a helper function that allows us to easily string together groups of actions without needing to use a temporary variable. It's a matter of personal preference really... I think of it as "we're taking a filesystem object, and performing these actions with it", so using tap
makes a lot of sense in this context.
Here are a couple other ways we could've written these lines:
1// One way2$files = new Filesystem;3$files->delete(...);4$files->copyDirectory(...);56// Another way.. but not the same object :(7(new Filesystem)->delete(...);8(new Filesystem)->copyDirectory(...);
1// One way2$files = new Filesystem;3$files->delete(...);4$files->copyDirectory(...);56// Another way.. but not the same object :(7(new Filesystem)->delete(...);8(new Filesystem)->copyDirectory(...);
Anyway, run our php artisan preset austencam
command again. We should see our new views in the resources/views
folder of the main app. Feel free to open up your app in the browser and check it out too!
Now we've got an idea of how to build any Laravel preset / boilerplate we want. Taking this knowledge further, your preset might contain custom vue components, the CSS framework of your choice, or any number of other customizations!
We've covered how to create a composer package in part one, how to extend the php artisan preset
command with our own preset, and how to configure that preset to set up a new app just how we'd like it. Now we can easily require our package from any Laravel app and to set up the app like we want in seconds. This is a great way to create your own boilerplate so you can more rapidly iterate on your ideas. Looking forward to seeing what you folks come up with!
Although my real preset does a few more things, I kept it simple for the sake of focusing on the process in this article. Laravel's base Preset class also includes a few useful methods you'll want to check out if you're building your own preset.
Please, if you run into problems or have any questions, feel free to reach out to me on twitter. I'd love to help. Thanks!