Etienne Marais in Laravel 15 minutes

VueJS Components with Blade

For a long time I have been looking for a way to separate my frontend development out of my backend code. I never got sold on the idea having JS/Sass inside of a resources folder. All this combined with my backend API is very overwhelming when first introduced to a big project. Working on a multi-team project this becomes noisy and dirty quite fast.

Preamble

I wanted to solve a couple of things that will be able to scale for teams of any size.

1. Separate tests for UI from backend or API tests.

Running UI and API tests together creates super long wait times between changes. Ideally you are willing to wait a couple of seconds for a test suite to run. When UI is included in that wait period this compounds into minutes very easily. This is bad for the obvious reasons that it wastes a lot of time. You can easily see a project cost twice as much than it’s budget for all this time wasted between test suite waits.

2. Concurrent development of UI and API.

There is obviously no magic bullet that fixes all your team’s problems of productivity and collaboration and shipping things that aren’t broken to your users. This is just one step into a direction that makes it easier for different teams to be productive together.

3. UI components are semantic and contained.

There is nothing wrong with using a framework like bootstrap or foundation to make things look and work great. When your product grows and you need an increased number of custom components for your business’ needs, extending this becomes pretty hard in a multi team environment.

Ideally you’d want these components to be as semantic as possible for a new hire to pick up quickly. Another goal is to have UI components that are atomic and re-usable across the whole app but also ad-hoc projects and external tools and systems.

Another goal in my mind was to have UI component dependencies structured in such a way that it is obvious what is happening on a page. This also simplifies passing data to your components.

This was the main focus of my quest.

4. Automate as much of the frontend build process as possible.

No one likes to manually compile and minify anything. I’d recon no one likes to pull in the latest UI components by hand and then running build scripts to be able to see something in their screen.

These goals are mainly to solve some pain points with setups of UI vs API development these days.


Frontend

With VueJS 2.0 coming out soon I dived into getting a setup in line with my goals. I am using Laravel 5.3 and the latest stable version of VueJS that comes out of the box.

composer create-project laravel/laravel project

First update your gulpfile.js to get rid of that annoying notification.

process.env.DISABLE_NOTIFIER = true;

const elixir = require('laravel-elixir');

require('laravel-elixir-vue');

elixir(mix => {
    mix.sass('app.sass')
        .webpack([
            'app.js'
        ]);
});

Then in your /resources/assets/js/app.js file you can add two demo components.

// Bootstrap base dependencies
require('./bootstrap');

Vue.component('home-page', require('./components/HomePage.vue'));
Vue.component('second-page', require('./components/SecondPage.vue'));

const app = new Vue({
    el: 'body'
});

See how I only have one new Vue() instance

This will load all your page components first as well as their child components and bind one Vue instance to your application. This is the connection between your backend and frontend.

Namespace Folder

Backend

The backend setup is just as easy. First off start by defining your routes in routes/web.php

<?php
Route::get('/home', 'HomeController@index');
Route::get('/second', 'HomeController@second');

No frontend routes are needed because the pages are server rendered.

Interjection

I have been trying for a long time to get into javascript routing and I must confess it’s something that I never had a nice feeling over. I know this might be irrational but my gut tells me that you need some sort of control over what content you send the user down the wire.

Maybe this is the problem with apps today on a slower internet connection. It still feels odd trusting Javascript with something as important as routing. Somehow it still feels like a teenager that you don’t trust enough with your car keys.

This is a good hybrid I think. Something that keeps the frontend developers happy about making components within a contained frontend build. It keeps your backend developers happy because they have full control over what gets rendered and what are cachable. It solves SEO problems and it decouples the API from the UI.

</interjection>

Blade Views

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="">

    <title></title>

    <!-- Styles -->
    <link href="/css/app.css" rel="stylesheet">

    <!-- Scripts -->
    <script>
        window.Laravel = <?php echo json_encode([
            'csrfToken' => csrf_token(),
        ]); ?>
    </script>
</head>
<body>

    @yield('content')

    <!-- Scripts -->
    <script src="/js/all.js"></script>
</body>
</html>

Remember to add the all.js file to your main layout. This links the frontend components into the backend.

Rendering the components become very trivial.

@extends('layouts.app')

@section('content')
<home-page></home-page>
<second-page></second-page>
@endsection

<home-page></home-page> is a VueJS component.


There is no silver/golden/magic bullet that solves team issues and good comunication is still the best way of solving technical problems. By separating concerns, you can run pretty smoothly without many problems.

Bower

The next steps would be to completely rip out the fronend components into a repository if it’s own that can be released into major/minor/patch versions of the current feature states.

Setup a Styleguide URL that can be accessed by anyone in the office for extra hands on testing and to pick up early problems. The master branch of the frontend build would always be releasable and stable.

When the backend gets deployed, the latest master would get pulled in and a gulp task would copy the /dist/*.js and /dist/*.css files into their respective places.

Ideally you’d want to automate as much of this process as possible. We setup a jenkins build task to run on a webhook from github when a pull request has been merged. This will automatically run the tests and compile the components into the production build.

Tests need to run before compilation and will fail the build if anything is broken. This means that the backend production build will always have a passing build go live.