Uploading a Laravel and React Project to Heroku

Uploading a Laravel and React Project to Heroku

I've been gone for a while, but I'm back!

During my 'break' I gave Inertia with Laravel another chance and ended up liking it. I'm still not a fan of how Laravel devs still have to go to multiple places for docs, but it's what we have so far until the Laravel team or someone brave puts everything in one place. When I was getting reacquainted, I needed to upload my project to production. I'm a frequent user of Heroku because of their free plan, but getting PHP and Node to work together took a bit of work. Here's how I did it.

Pre-requisites:

  • Make a Heroku account. It's totally free.
  • Download and install the Heroku CLI.
    • Carefully follow the instructions and ensure that you have your login credentials set. You don't have to create a repository yet.
    • You must have git installed. If you don't, do it.
  • Make a new Laravel project in your projects folder by running $ laravel new laravel-inertia-project in your terminal.

First Steps: In this tutorial, we'll be using Laravel Breeze, which is the simplest way to implement a Vue or React frontend in our Laravel project.

  • Install Laravel Breeze by running $ composer require laravel/breeze --dev. Then we'll install Breeze and its Inertia stack by running these two commands:
$ php artisan breeze:install --inertia
$ npm install
  • Once that's done, we'll need to set up React. Laravel Breeze and Inertia will automatically install Vue, so we'll need to do a bit of work here.

    • Run:

      $ npm install react react-dom
      $ npm install @inertiajs/inertia @inertiajs/inertia-react
      
    • Go to resources/js/app.js and make some changes so that we can build our own frontend instead of using Vue.

import {InertiaApp} from@inertiajs/inertia-react’
import React from ‘react’
import {render} from ‘react-dom’

const app = document.getElementById(‘app’)

render (
    <InertiaApp
        initialPage={JSON.parse(app.dataset.page)}
        resolveComponent={name => import(`./Pages/${name}`).then(
  module => module.default
        )}
    />,
    app
)
  • To ensure that Babel can understand the little JSX code that we’ll be writing, we’ll need to install a Babel preset by running $ npm install --save-dev @babel/preset-react. We can then use this preset by creating a .babelrc file in the root with this code:
{
    "presets": ["@babel/preset-react"]
}
  • We'll need to go to resources/js and delete the Pages and Components folders you see there, and just replace it with a Pages folder with a file called HelloWorld.js in it.
  • In HelloWorld.js, we'll make a simple Hello World app:
import React from 'react'

const HelloWorld = () => (
   <p>Hello world!</p>
)

export default HelloWorld
  • Next, go to routes/web.php, and delete the routes that you see there. Then, we'll use Inertia to render our Hello World page without sending any data.
Route::get('/', function(){
    return Inertia::render('HelloWorld', []);
}
  • Finally, go to webpack.mix.js and ensure that you see mix.js('resources/js/app.js', 'public/js'. If you see .vue() attached to mix, delete it or you'll get errors. Now compile your assets by running $ npm run dev.

The Work Begins:

  • Run $ git init to set git up in your project. Then add your files to git by running $ git add ..
  • Create a new Heroku app by running $ heroku create.
  • Before we commit and push, we need to create a Procfile. This file will tell Heroku what commands to run when the application starts up. For PHP, the file will only have one line: web: vendor/bin/heroku-php-apache2 public/. Create Procfile in your root folder and copy-paste the line in the file, or run $ echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile in your terminal. NOTE: It's best to create the file first before writing to it. You'll see less errors this way.

The Work Continues:

  • Before we can push our work up to Heroku, we'll need to create two buildpacks. Buildpacks are scripts that make the right environment to run a programming language. Because we have React and Inertia, we'll need a buildpack for Node as well as PHP.
    • For PHP, run $ heroku buildpacks:set heroku/php.
    • For Node, run $ heroku buildpacks:add --index 1 heroku/nodejs.
    • NOTE: The --index 1 basically states that this buildpack will run first. The buildpack for the primary language must always be run last.
  • We'll need to ensure Heroku does not ignore our devDependencies in package.json, which it does by default. Run $ heroku config:set NPM_CONFIG_PRODUCTION=false.

The Work Ends:

  • Now we can commit and push our project up to Heroku:
$ git commit -m "First commit to Heroku"
$ git push heroku main
  • NOTE: If for some reason the heroku remote wasn't added, run $ heroku git:remote -a {APP_NAME}. Go to your Heroku dashboard to see the name if you lost it.

  • For Laravel to work, we'll need an APP_KEY. One is already set locally, but we need one for Heroku. Run $ heroku config:set APP_KEY={key}.

  • Run $ heroku open to open and run the app. It should open to https://{APP_NAME}.netlify.app and you should see "Hello World" on your screen.

Conclusion:

  • If you need to debug, Heroku provides logs for your app. Run $ heroku config:set LOG_CHANNEL=errorlog so your stack trace errors are logged there.
  • I love Heroku because it's one of the best ways to host PHP apps for free.
  • If you're on the free plan of Heroku, your app will 'sleep' at different intervals. If you don't like this behavior, especially as you're building out your app, you can just subscribe to their 'Hobby' plan which costs a dollar less than a Disney Plus subscription.