A quick start guide to creating an app with Preact, TypeScript and Ruby on Rails

25 March 2020
·
preact
·

After following this guide, you will have created a "Hello world" application that uses Preact, TypeScript and Ruby on Rails. We'll also be installing ESLint!

Installing prerequisites - ruby and sqlite3

Make sure you have installed rbenv and Ruby:

brew install rbenv

ruby --version

# if your version of Ruby is old:
rbenv install 2.7.0
rbenv rehash
rbenv global 2.7.0

You'll most likely have sqlite3 already installed (check using sqlite3 --version) but if you don't you can download it from the SQLite download page.

Installing Ruby on Rails

Then install Ruby on Rails:

gem update --system
gem install bundler
RBENV_VERSION=2.7.0 rbenv exec gem install rails --version 6.0.2.1

Once installed, open a new terminal window and double-check that it was successfully installed:

rails --version

Create your Ruby on Rails app with React

Since there isn't Preact boilerplate code available, I found it much easier to get started with React and then switch it out for Preact afterwards.

rails new <APP_NAME> --webpack=react

Add TypeScript and ESLint

bundle exec rails webpacker:install:typescript
yarn add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-preact @types/webpack-env
yarn add babel-plugin-transform-react-jsx

Make sure to update all of your JavaScript files to end with .ts and .tsx!

If your code is rendering a Preact component you'll want it to end in .tsx. If it's just a util file with some functions in it, then you only need .ts (but you can still just use .tsx and it will work fine).

Add the following line in tsconfig.json:

"compilerOptions": {
    "jsxFactory": "h",
    //...
}

Then add a lint script to your package.json:

"scripts": {
    "lint": "eslint app/javascript/**/*.ts[x]"
}

Also make sure to create a .eslintrc.js file in your root folder and add the following:

module.exports = {
    root: true,
    parser: '@typescript-eslint/parser',
    plugins: [
        '@typescript-eslint',
    ],
    extends: [
        'eslint:recommended',
        'plugin:@typescript-eslint/eslint-recommended',
        'plugin:@typescript-eslint/recommended',
        'preact'
    ],
};

Install Preact

yarn add preact

And add the the following to the plugin section of your babel.config.js file:

plugins: [
    ["transform-react-jsx", { "pragma": "h" }],
]

Now that you've got Preact, you can also delete react and react-dom from your dependencies in your package.json file.

Create your first controller

Create your first controller. I've named mine hello:

rails generate controller hello

This will create a file for you called app/controllers/hello_controller.rb. Add the following code to it:

class HelloController < ApplicationController
    def home
    end    
end

Then add this new controller you've created to config/routes.rb:

Rails.application.routes.draw do
    root to: 'hello#home'
end

Switch out any React references for Preact

When we first created this app, a app/javascript/packs/hello_react.tsx file will have been created for us. Rename this to hello_preact.tsx, and switch out its contents for a Preact component:

import { render, h } from 'preact';

const Hello = () => (
    <div>Hello world!</div>
)

document.addEventListener('DOMContentLoaded', () => {
    render(<Hello />, document.body);
});

And finally, we need to add our new Preact component to app/views/hello/home.html.erb

<%= javascript_pack_tag 'hello_preact' %>

<h1>Hello world!</h1>

Starting things up

Finally, we can run these two commands to start up our Preact + Rails app:

rails s --binding=127.0.0.1
./bin/webpack-dev-server

And voila! 🎉 You should now have a "Hello world" app that uses Preact and Ruby on Rails.


I struggled to find good documentation online to help me get started with this stack, so I hope this guide has helped you if you were facing the same difficulties.

Happy coding!

References

Getting Started with Rails

Rails: Install Rails 5.2.3 with rbenv

typescript-eslint

🦉 Subscribe to my monthly newsletter for updates on my latest posts and projects.