Denys Vuika's Blog

Denys Vuika

Preact Project with TypeScript and Parcel

May 11, 2019

In this article, I am going to walk you through the process of configuring a new web application project that is powered by Preact library, and backed by TypeScript and Parcel bundler. The article is part of a series of posts on Preact and React development.

Introduction

This article aims to help you with a quick Preact project setup. I am going to guide you through the following steps:

  • creating a project scaffold
  • integrating with TypeScript
  • building and running a simple Preact application
  • creating scripts to run and build for production
  • styling support
  • application routing

Also, at the bottom of the article, you are going to get a link to the GitHub repository with the final result.

Creating a Project Scaffold

Let’s start with creating a new project folder called preact-getting-started or any other name of your choice.

mkdir preact-getting-started
cd preact-getting-started

In this article, I am going to use an ultra-fast Yarn package manager. I strongly recommend taking a look if you are using NPM.

You can set up a new project by running the following command:

yarn init --yes

As a result, you should get a package.json file with minimal information about the project. You need this file to store metadata and third party library dependencies.

Configuring Git

If you intend to use Git with your project, run the following command to initialize a new Git repository in the current folder:

git init

Next, create a .gitignore file in the project root folder with the following content:

node_modules
dist
.cache

That instructs Git not to commit specific folders to the source code repository.

Integrating with TypeScript

To configure the TypeScript support, you first need to install the “typescript” library:

yarn add typescript -D

After that, create a tsconfig.json file in the project root with the content from the listing below:

{
  "compilerOptions": {
    "outDir": "./dist",
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "es6",
    "moduleResolution": "node",
    "target": "es6",
    "jsx": "react",
    "jsxFactory": "h"
  },
  "include": ["./src/**/*"]
}

That is the minimal TypeScript configuration to enable integration with Preact. Let’s now see what it takes to create and run a simple application.

Building and Running a Simple Preact Application

For the next step, we need to install a Preact and Parcel bundler libraries.

The Parcel is a blazingly fast, zero-configuration web application bundler that allows you to focus on building your application, rather than spending time on configuring the bundling and packaging process itself. Make sure you check the Documentation section to see details on all fantastic features.

yarn add parcel-bundler -D
yarn add preact

Now, create an src folder and put the following index.html file inside:

<html>
  <body>
    <div id="root"></div>
    <script src="./index.tsx"></script>
  </body>
</html>

As you can see from the snippet above, we have an application placeholder div element called root, and an import of the index.tsx file you are going to create next:

import { h, render } from 'preact';

const App = () => <h1>Hello from Preact and Typescript!</h1>;

render(<App />, document.getElementById('root'));

For the sake of simplicity, we show a “heading” element with a dummy string.

Creating Scripts to Run and Build for Production

Typically, you are going to use the Parcel CLI commands for two main scenarios: running the application locally during the development process, and building the release artifacts, also known as “production build.”

You can automate the process by providing the scripts section within the package.json file:

{
  "scripts": {
    "start": "parcel src/index.html",
    "build": "parcel build src/index.html"
  }
}

To run the application locally with a lightweight web server, run the following command:

npm start

You should see the following output, note the URL address you can use to browse the application:

Server running at http://localhost:1234
✨  Built in 1.68s.

Navigate to http://localhost:1234, and application looks similar to the following picture:

preact application
Running Preact Application

That is pretty much all you need to start developing. The application is running in the “watch” mode by default. That means every time you make changes to the code, the browser page refreshes and you see the updated application in action.

Styling Support

The Parcel bundler makes styling your applications super easy. For example, you can import an SCSS file, and the Parcel takes care about installing and using the sass module behind the scenes. Let’s see that in action now.

Create a src/styles.scss file with the following content:

$primary-color: white;
$secondary-color: blue;

body {
  color: $primary-color;
  background-color: $secondary-color;
}

For demonstration purposes, we create a couple of SASS variables and change the style of the body element. All you need to do now is to import the style into your application, for instance index.tsx file:

import { h, render } from 'preact';
import './styles.scss';

const App = () => <h1>Hello from Preact and Typescript!</h1>;

render(<App />, document.getElementById('root'));

Launch your application or switch to a running one, and note the application now looks different:

application styles
Application with custom styles

That is Parcel support for styling in action! As you can see, the integration process happens under the hood, and you focus on the styles and themes, rather than sass module setup and configuration.

Application Routing

Another vital feature of modern single-page web applications is “routing.” Let’s see what it takes to enable your Preact project with necessary routing capabilities. I am going to use preact-router library for that purpose.

yarn add preact-router

Switch to the index.tsx file and create a few simple components to simulate different pages of the application.

const Home = () => <h2>Home Page</h2>;
const Page1 = () => <h2>Page 1</h2>;
const Page2 = () => <h2>Page 2</h2>;
const Error = () => <h3>Error</h3>;

Now, you can import the Router component, and define the pages like in the next listing:

import { Router } from 'preact-router';

const App = () => (
  <div>
    <h1>Hello from Preact and Typescript!</h1>

    <Router>
      <Home path="/" />
      <Page1 path="page1" />
      <Page2 path="page2" />
      <Error default />
    </Router>
  </div>
);

With the code above, you should see the Home component on the main screen every time you visit http://localhost:1234/. The Page1 component is accessible via /page1, and all missing paths, like for instance /missing, should end up showing the Error component content.

Let’s quickly craft a Header component to see navigation in action.

const Header = () => (
  <header>
    <nav>
      <a href="/">Home</a>
      <a href="/page1">Page 1</a>
      <a href="/page2">Page 2</a>
      <a href="/missing">Missing</a>
    </nav>
  </header>
);

Next, add some styling for the links to take into account the theming settings we made earlier:

header {
  nav {
    a {
      color: $primary-color;
      margin-right: 5px;
    }
  }
}

Finally, let’s put the Header component to the top of the page outside the Router element. In that case, you can use the Header links on every application page.

const App = () => (
  <div>
    <Header />
    <h1>Hello from Preact and Typescript!</h1>

    <Router>
      <Home path="/" />
      <Page1 path="page1" />
      <Page2 path="page2" />
      <Error default />
    </Router>
  </div>
);

Run the application and click various header links. Notice how content changes depending on the route.

application routes
Application routes

At this point, your application template is ready, and you can save it for future reuse or keep extending it further.

Summary

As you can see, getting started with Preact and TypeScript is trivial, and the Parcel bundler makes the whole process effortless and pleasant.

You can find the final example of the project on GitHub by following this link: preact-getting-started.