Complete GatsbyJS Setup with TypeScript, SASS, and Jest

How-to guide on setting up Gatsby project with type-checking and unit testing enhancements.

Paul Pan
ACM at UCSD
5 min readOct 31, 2019

--

Unit testing, type checking, and style enhancements with these languages and frameworks help enormously with development workflow.

Having developed web apps with React for the past few months using TypeScript as the primary language, I have been spoiled by the strict type checks that are unavailable in JavaScript. Due to the nature of TypeScript, I have saved numerous hours of debugging potential type violations. Fortunately, TypeScript is incredibly easy to set up using React’s create-react-app CLI as you only need to pass in the “ — typescript” flag. Furthermore, a unit testing framework, Jest, is included by default in all React project created using the command mentioned earlier. SASS, a language with extra features that is compiled down to standard CSS, can also be used by simply installing the node-sass module.

Unfortunately, all these aforementioned useful features from standard React take much more effort to set up on Gatsby, a static site generator based on React. I have struggled a lot myself, and I believe many people do as well. Because of this, I have created a guide to ease the set-up process for others.

Create Gatsby App

In order to develop with Gatsby, there is a command line tool that can set up a template project for us. Follow this guide until the part where you start using the Gatsby CLI.

Then, type this command to create the template project:

gatsby new project_name

Replace project_name with the name of the project of your choice.

In the bash terminal, type:

cd project_name

Again replacing project_name with the name of your actual project.

Once you are in the project directory, you want to generate the static files to be hosted on a local server. Enter this command to do so:

gatsby develop

Converting Source Code from JavaScript to TypeScript

Image from (https://www.robertcooper.me/get-started-with-typescript-in-2019)

This process is the most complicated out of the three, as you need to install many new packages and modify project structure in order to get TypeScript to compile properly and to lint well in your favorite code editor.

First, you need to install the packages gatsby-plugin-typescript into dependencies and typescript into devDependencies.

npm install -s gatsby-plugin-typescript
npm install -D typescript

Once you have the two installed, it’s time to add the dependency to your gatsby-config.js in your project root directory.

Find the plugins key in the modules.export object and insert the following entry into the array.

plugins: [`gatsby-plugin-typescript`]

Now that the plugin is utilized by Gatsby, we need to create a tsconfig.json file in the project directory telling the React runtime where to check for typings.

Insert the following:

{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"allowJs": true,
"declaration": false,
"importHelpers": true,
"jsx": "react",
"lib": ["dom", "es2015", "es2017"],
"module": "commonjs",
"noEmitHelpers": false,
"noImplicitAny": true,
"noResolve": false,
"noUnusedLocals": true,
"noUnusedParameters": false,
"preserveConstEnums": true,
"removeComments": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "esnext"
},
"include": ["./src/**/*", "./__tests__/**/*"]
}

Then, create an .eslint file in the project directory containing the following:

{
"extends": ["@pacote/eslint-config", "@pacote/eslint-config-react", "@pacote/eslint-config-jest"]
}

ESLint helps with linting code style and correctness both via your text editor and via the command line.

Install the three packages listed in the .eslint file into the devDependencies of package.json by running the following command:

npm install -D @pacote/eslint-config @pacote/eslint-config-react @pacote/eslint-config-jest

Install remaining peer dependencies into devDependencies when you receive warnings while installing.

After installation, convert all JavaScript files in the src directory, and add typing as necessary.

SASS Plugin for Gatsby

Installing the SASS plugin allows for compilation of .sass and .scss files into .css, which can be interpreted by the browser.

Run the following command to install the SASS compiler and plugin for Gatsby:

npm install -s node-sass gatsby-plugin-sass

Add the following into the plugin array in the gatsby-config.js file:

plugins: [`gatsby-plugin-sass`]

Convert any .css file to .scss and you are good to go.

Wrap up with Jest for Unit Testing

Setting up Jest for unit testing requires the installation of several packages first.

npm install -D jest babel-jest react-test-renderer babel-preset-gatsby identity-obj-proxy ts-jest

Create a jest.config.js file with the following content telling Jest how to configure the unit testing.

module.exports = {
transform: {
"^.+\\.tsx?$": "ts-jest",
"^.+\\.jsx?$": "<rootDir>/jest-preprocess.js",
},
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.([tj]sx?)$",
moduleNameMapper: {
".+\\.(css|styl|less|sass|scss)$": "identity-obj-proxy",
".+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
"<rootDir>/__mocks__/file-mock.js",
},
moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
testPathIgnorePatterns: ["node_modules", ".cache", "public"],
transformIgnorePatterns: ["node_modules/(?!(gatsby)/)"],
globals: {
__PATH_PREFIX__: "",
},
testURL: "http://localhost",
setupFiles: ["<rootDir>/loadershim.js"],
}

The transform key for .jsx and .js files needs a JavaScript file to tell Jest how to transform it during testing. Add the jest-preprocess.js file in the project directory with the following:

const babelOptions = {
presets: ["babel-preset-gatsby"],
}
module.exports = require("babel-jest").createTransformer(babelOptions

Let’s add another file called loadershim.js with the following content, which is required by Jest during setup:

global.___loader = {
enqueue: jest.fn(),
}

Next, create a __mocks__ folder in the project directory containing the two files, file-mock.js and gatsby.js.

file-mock.js:

module.exports = "test-file-stub"

gatsby.js:

const React = require("react")
const gatsby = jest.requireActual("gatsby")
module.exports = {
...gatsby,
graphql: jest.fn(),
Link: jest.fn().mockImplementation(
// these props are invalid for an `a` tag
({
activeClassName,
activeStyle,
getProps,
innerRef,
partiallyActive,
ref,
replace,
to,
...rest
}) =>
React.createElement("a", {
...rest,
href: to,
})
),
StaticQuery: jest.fn(),
useStaticQuery: jest.fn(),
}

Now, we can write tests for our React components. Create a __tests__ directory with header.tsx. This is the sample component test file that we are going to test the header for.

header.tsx:

import React from "react"
import renderer from "react-test-renderer"
import Header from "../src/components/header"describe("Header", () => {
it("renders correctly", () => {
const tree = renderer
.create(<Header siteTitle="Default Starter" />)
.toJSON()
expect(tree).toMatchSnapshot()
})
})

Install typing packages into devDependencies of package.json as necessary if your text editor complains about typings not being installed.

Summary

Unlike projects created with the create-react-app CLI, Gatsby starter variants of React projects demand much more challenging setups in order to get the commonly used frameworks and libraries working. However, once you have a project set up, the extra features of Gatsby really pays off in the long term.

References

Set up your development environment with Gatsby

Using SASS in Gatsby

Unit testing in Gatsby

--

--

Paul Pan
ACM at UCSD

Third-year Computer Science student at UC San Diego. Full-stack web developer using the MERN stack. Currently focusing on Machine Learning acoustics.