I recently upgraded richsoni.com to Gatsby Version 2.0, A previous post, 'Upgrading richsoni.com To Gatsby 2', chronicles that experience.
The main driver behind this upgrade was alleviate issues I was having with adding Typescript to the project. As I mentioned in 'Upgrading richsoni.com To Gatsby 2', I had the following assumption:
'However, my interest was piqued this week, after a few murky attempts at installing gatsby-plugin-typescript. It turns out that Typescript is bundled by default in Gatsby V2, making gatsby-plugin-typescript unnecessary. This was enough reason for me to perform the update. However, to my disappointment, this was not the case.' ~ From 'Upgrading richsoni.com To Gatsby 2'
This assumption was false, despite the Gatsby Version 2.0 Release notes, mentioning Typescript support:
Babel 7 Babel helps ensure the JavaScript you write works across different browsers (including older versions of Internet Explorer).
The upgrade brings:
Improved build speed Experimental support for automatic polyfilling See also our docs for this feature Support for more syntax e.g. TypeScript and JSX Fragments ~ Gatsby Version 2.0 Release Notes
I ended up repeating many of the steps I attempted before Upgrading richsoni.com To Gatsby 2, and ran into many of the same errors😢
But, at last I finally got everything working the way I expected, and my site is ready for its Typescript conversion.
Since this was such an Odyssey, I decided to outline the changes required in my repository. Hopefully, any other brave souls jettisoned on this journey will heed this advice, and save themselves the pain and sorrow.
At the end of this post, I give my recommended steps, hopefully it will save you from the obstacles I faced.
😱 Step 1: Hey Gatsby, I'm A Typescript File Now!
Since I thought Gatsby Version 2.0 natively supported Typescript, my first thought was to a file, and confirm that Typescript was working properly.
⚖ Obstacle 1: There are right and wrong files to choose
The first file I tried to convert was src/pages/index.js
.
I abandoned this strategy because I realized converting this file was introducing a lot of change.
Instead, I searched for a file with the following attributes:
- Not React
- No Dependencies
- Short
The file I decided to use was src/util/data.js
, a set of basic data transform functions:
$ mv src/util/data.{js,tsx}
$ cat src/util/data.tsx
export const performancesWithSetlist = (performances) => {
return performances
.edges
.map((e) => e.node)
.filter((e) => e.frontmatter.setlist)
};
export const performancesBySong = (performances, songs) => {
return performancesWithSetlist(performances)
.reduce((songs, event) => {
(event.frontmatter.setlist || []).map((song) => {
if(!songs[song]) { songs[song] = [] }
songs[song].push(event.fields.date)
});
return songs;
}, {});
}
export const performancesWithSong = (performances, song) => {
return performances
.edges
.filter((event) => event.node.frontmatter.setlist)
.filter((event) => event.node.frontmatter.setlist.includes(song));
}
export const nodesByBasename = (collection) => {
return collection.edges.map((e) => e.node).reduce((nodesByBasename, node) => {
return {...nodesByBasename,
[node.fields.basename]: node,
};
}, {})
};
I chose this file because of its size, and lack of dependencies.
👍🏻 Obstacle 2: LGTM
Running gatsby-develop
, with my newly saved data.tsx
generated errors.
This was expected, since the code was not converted to Typescript.
However, I was faced with absolutely 0 Typescript errors.
After some digging around the internet, I found this comment in the
I saw this listed in the caveats
section of the README for gatsby-plugin-typescript:
This plugin uses babel-plugin-transform-typescript to transpile typescript. It does not do type checking. Also since the TypeScript compiler is not involved, the following applies:
...
✅ Step 2: Check Please!
Its not very useful to write typescript, and have zero errors shown.
I found this plugin: gatsby-plugin-typescript-checker. The README, for that plugin states:
gatsby-plugin-typescript adds TypeScript transpilation but not type checking. This plug adds fork-ts-checker-webpack-plugin to Gatsby to display type errors in the browser and the command line.
Sounds Great! So I followed the installation steps in the README:
Install Plugins
$ yarn add gatsby-plugin-typescript gatsby-plugin-typescript-checker
Update gatsby-config.js:
plugins: [
'gatsby-plugin-typescript',
'gatsby-plugin-typescript-checker',
😕 Obstacle 3: Typescript?
After installing gatsby-plugin-typescript-checker, I was faced with a new error:
error Plugin gatsby-plugin-typescript-checker returned an error
Error: Cannot find module 'typescript'
Add Typescript
This error was resolved by simply adding Typescript as a dependency:
$ yarn add typescript
But, gatsby-develop
was still confused:
error UNHANDLED REJECTION
Error: Cannot find "tsconfig.json" file. Please check webpack and Fork TsCheckerWebpackPlugin configuration.
Possible errors:
- wrong `context` directory in webpack configuration (if `tsconfig` is not set or is a relative path in fork plugi n configuration)
- wrong `tsconfig` path in fork plugin configuration (sh ould be a relative or absolute path)
Since I have no experience with creating a tsconfig.json
file, I copied one from gatsby-starter-typescript-plus:
{
"compilerOptions": {
"module": "commonjs",
"target": "esnext",
"jsx": "preserve",
"lib": ["dom", "es2015", "es2017"],
"strict": true,
"noEmit": true,
"isolatedModules": true,
"esModuleInterop": true,
"skipLibCheck": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": false,
"preserveConstEnums": true
},
"include": ["./src/**/*"]
}
🎉 Voilà
Now gastby-develop
was providing useful typescript errors:
27:71 Parameter 'node' implicitly has an 'any' type.
25 |
26 | export const nodesByBasename = (collection) => {
> 27 | return collection.edges.map((e) => e.node).reduce((nodesByBasename, node) => {
| ^
28 | return {...nodesByBasename,
29 | [node.fields.basename]: node,
30 | };
ℹ 「wdm」: Failed to compile.
✍️Step 3: Typescriptify
The most naive way to typscriptify this file is to simply add any
types to all the variables:
+ export const performancesWithSetlist = (performances: any) => {
+ .map((e: any) => e.node)
+ .filter((e: any) => e.frontmatter.setlist)
+ export const performancesBySong = (performances: any) => {
+ .reduce((memo: any, event: any) => {
+ (event.frontmatter.setlist || []).map((song: any) => {
+ export const performancesWithSong = (performances: any, song: any) => {
+ .filter((event: any) => event.node.frontmatter.setlist)
+ .filter((event: any) => event.node.frontmatter.setlist.includes(song))
+ export const nodesByBasename = (collection: any) => {
+ return collection.edges.map((e: any) => e.node).reduce((memo: any, node: any) => {
And, then Gatsby was happy!
My Recommendation
To add Typescript to a Gatsby Version 2.0 project, do the following:
Step 1: Install Dependencies
$ yarn add gatsby-plugin-typescript gatsby-plugin-typescript-checker typescript`
Step 2: Setup a tsconfig
Either run tsc --init
, or copy an existing tsconfig.json
from another project.
I took mine from gatsby-starter-typescript-plus:
{
"compilerOptions": {
"module": "commonjs",
"target": "esnext",
"jsx": "preserve",
"lib": ["dom", "es2015", "es2017"],
"strict": true,
"noEmit": true,
"isolatedModules": true,
"esModuleInterop": true,
"skipLibCheck": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"removeComments": false,
"preserveConstEnums": true
},
"include": ["./src/**/*"]
}
Step 3: Update Gatsby Config
plugins: [
'gatsby-plugin-typescript',
'gatsby-plugin-typescript-checker',
Caveats
I am pretty sure I will have to add several more packages as I typescriptify my codebase. When this happens I will post an update.