DEV Community

Kenneth Mark
Kenneth Mark

Posted on • Edited on

Deploying your Adonis v5 applications on Heroku

Pre-requisites

Introduction

Once you have created your account and installed the Heroku CLI, log into your Heroku account with

heroku login
Enter fullscreen mode Exit fullscreen mode

After logging into your Heroku account, create an application in Heroku and add the Heroku git remote origin url since Heroku will be using git to deploy your application.

heroku git:remote -a {APPLICATION-NAME}
Enter fullscreen mode Exit fullscreen mode

If you have enabled automatic deploys with Github then you can skip this step.

Configure Package.json

To ensure your application runs smoothly on Heroku we need to tell Heroku or any other hosting provider to use the right version of Node to effectively run our application. Our application is written in typescript and some features it uses aren’t available in older versions of Node. The version of Node best suited our typescript application is v12.18.3 which is the current stable version as of today.

"engines": {
    "node": "12.18.3"
}
Enter fullscreen mode Exit fullscreen mode

Copy and paste this in your package.json file

Scripts

Adonis.js comes default with scripts for running our application in development but not in production. The scripts below show does the job. Please replace the scripts in your package.json with the one below.

 "scripts": {
    "build": "node ace build --prod",
    "start": "node ace serve --watch",
    "start:prod": "node ./build/server.js"
  }
Enter fullscreen mode Exit fullscreen mode

Procfile

The Profile tells Heroku how to run our application. Firstly create a file named Procfile in the root of your profile and paste the script below inside.

release: ENV_SILENT=true node ace migration:run --force && node ace db:seed 
web: npm run start:prod
Enter fullscreen mode Exit fullscreen mode

There are 2 main commands here. The release and web command/phase.
The release commands run right after the application has been built or in this case transpiled to raw JavaScript and the web command runs the application on the server. In the release command we tell our application to silent the Env errors because Adonis expects a .env file to run the application smoothly and then we run our migrations and do some seeding in case we have some. The seeding part is optional
In the web command we just run the npm run start:prod we wrote earlier in our package.json file. With this command, Heroku runs the production JavaScript version of our application.

Database connection

Your application will more than likely use a database to store data. Adonis.js provides us with different database providers to perform CRUD operations with. Your database could be hosted with any provider of your choice but Heroku allows us to append DB service to our deployment.

SQLite

You should not be using SQLite in production but if you are only running small app that nobody but yourself uses then you can choose to use SQLite. If you choose to run SQLite in production, there is nothing you have to do but run migrations.

MySQL

First and foremost, please ensure you have installed the MySQL node driver in your project, using npm i mysql to do it.
Heroku provides us with different a MySQL addon/service we can use in conjunction with our application. To use it, go the resources tab in your heroku dashboard and start typing MySQL in the add-on input. You would see a select dropdown with a ClearDB MySQL option.

Please select it and proceed. This provisions a MySQL database that you can use with your application. To use the database in your application, go the settings tabs in your Heroku dashboard and click the Reveal Config Vars button and copy the CLEARDB_DATABASE_URL value.

Now in your local .env file create a new entry called CLEARDB_DATABASE_URL and paste the copied value.

Usage

Firstly, install url-parse with npm install URL-parse. This package allows us to parse the database url we copied from the Heroku dashboard into a JavaScript object we will later use. Once installed, find the config/database.ts file and paste the code below in your imports.

import Url from url-parse
const CLEARDB_DATABASE_URL = new Url(Env.get(CLEARDB_DATABASE_URL))
Enter fullscreen mode Exit fullscreen mode

Once you have pasted the code above, replace the MySQL object with the one below

    mysql: {
      client: 'mysql',
      connection: {
        host: CLEARDB_DATABASE_URL.host as string,
        port: Number(''),
        user: CLEARDB_DATABASE_URL.username as string,
        password: CLEARDB_DATABASE_URL.password as string,
        database: CLEARDB_DATABASE_URL.pathname.substr(1) as string
      },
      healthCheck: false,
    },
Enter fullscreen mode Exit fullscreen mode

Configure for production

To make use of our new MySQL database in our application, we can dynamically set the default connection based on the environment we are running our application in. Ensure you import the Application module using import Application from '@ioc:Adonis/Core/Application' before you copy the code below.

connection: Application.inDev ? sqlite : mysql 
Enter fullscreen mode Exit fullscreen mode

Once pasted, the application will use SQlite in development and MySQL in production. You can configure this to your liking.

Postgres

Just like with MySQL, please ensure you have installed the Postgres node driver in your project before you proceed., You can do so by using npm i pg to do it.

Configuring database access for Postgres is very similar to the doing the same for MySQL so please first read it diligently before you read the Postgres section. To use Postgress, go to the resources tab in the Heroku dashboard and select a Heroku Postgres. Go the settings tab and copy the DATABASE_URL and paste it in your .env file. Append ?ssl=no-verify to the DATABASE_URL in both .env file and in your settings tab under Reveal Config Vars. This ensures you do not run into any SSL issues. Only remove it if you know what you are doing.
Lastly, to configure Postgres for production replace your connection string with the code below

connection: Application.inDev ? sqlite : pgs 
Enter fullscreen mode Exit fullscreen mode

Dynamicity

Since will be running on application in both the development and production environments it important to make sure values being used in the application are dynamic. They can be hard-coded and check with if statements but that will introduce a lot of repetitive boilerplate code and you will disregarding the DRY principles of programming. To solve this problem, Adonis.js has an Application module that contains properties with information about your application and one of the properties on the Application class is inDev. You can for example use it to set a default database connection as seen above or set a default email address for to send emails in development.

const email = Application.inDev ? 'test@test.com' : 'johndoe@company.com'

Mail.send((message) => {
  message
    .from(email)
    .to('test@adonisjs.com')
    .subject('Welcome Onboard!')
    .htmlView('emails/welcome', { name: 'John Doe' })
})

Enter fullscreen mode Exit fullscreen mode

Deploy

Once the you completed everything above. You can now joyfully deploy your application to heroku.

git add . 
git commit -m "initial commit"
git push -u origin master
git push heroku master
Enter fullscreen mode Exit fullscreen mode

Once deployed, the application will show you a link to the application if deployed correctly. Click on the link and voila, you should see your application running just fine.

Conclusion

Deploying Adonis on Heroku is quite similar to deploying to deploying other node applications. You can use the steps in this tutorial and apply it to other Adonis.js applications you build.

Top comments (2)

Collapse
 
dramoslace profile image
Deiby Dayans R

Hi,
thanks for the article.

Do you know how to use migration:fresh command on heroku?

I'm actually watching just these commands:

migration:rollback
migration:run
migration:status

Collapse
 
crud_engr profile image
Ayinla Abeeb

Great article. I am new to sqlite. How do you run the migration in heroku.