React Locally
Create my own react starter kit
Few words
I thought it might be a good idea to write a few words about why I went to the trouble of creating my own starter kit.
With every new project, I used to copy what I did on the previous project, remove everything except the boilerplate, add a few tools and refactor the code a bit. Rinse and repeat.
So, I created my first react starter kit react-locally
to avoid going through this painful procedure every time I started a project, with the goal of
getting me up and running faster with all the tools and libraries I needed.
Why I create my own?
As you may know, Facebook created their own starter kit called create-react-app
, developed
by the React community, and maintained by Facebook. It includes all the basics needed to get
started, which is why it’s so popular and used by a lot of developers.
So, why didn’t I just use that?
The serious answer is that, I don’t know JavaScript,
and there is so many dependencies
and devDependency
in that project.
Looking inside it feels like I’m dead.
That’s why I threw myself into a painful procedure of creating my own react starter kit.
Another answer is that, as a poor and low cost web developer, I eat CSS. But when it comes to JavaScript books or projects, 80% of it goes over my head. I set a basic rule— if I don’t know what this framework or plugin is for, I won’t use it.
So I have to know, or learn first.
The funny thing is, when it comes to learning new things, my brain acts like a sloth, so I go slow.
What’s in it?
I need a few features to ensure my development workflow is fast, structured, and efficient. So I choose:
- 🔥
vite
as build tool. Its hot reloading and page refreshing in blessing fast. - 👀
react
as the view. - 👮
typescript
as catch types errors early in editor. - 🧹
eslint
,eslint-airbnb-config
andprettier
- combines performing code formatting. Stop worrying about code style consistency. - 🖌️
dart-sass
support - I extend it with CSS Modules. - 🔀
react-router-dom
v6 as the router. - 🪖
react-helmet-async
provides control of the page title/meta/styles/scripts from within my components. SEO friendly. - 🧪
vitest
as the test framework.
All in all there are 24 dependencies in the react-locally
starter pack…
I try my best to keep them up to date.
Why I keep it open source?
For me. Simple.
Imagine you’re in a huge library, trying to find a book. Sometimes, you forget where you put it! That’s me with my code. So, I keep it open source, like leaving a map for myself.
And, I believe there is someone who might have similar needs as mine. Feel free to check it out, folk. Contribute if you think something’s missing.
And if you just want to get started, the quickest way, if you already have git and node, is this:
git clone -b main git@github.com:zafree/react-locally.git your-project
cd your-project
yarn install
yarn dev
Or if you’re curious about how I crafted it, then keep scrolling. '
Start writing the process
At last, it’s time to learn something new. My brain is already starting to act like a sloth. So I will go slow. If you’re following, follow me slowly.
Before starting, I break down the entire process into simple, easy-to-follow steps:
- setup
Vite + React + TypeScript
- level it up with
eslint
,eslint-airbnb-config
, and - get pretty with
prettier
- add
dart-sass
+ CSS Module - testing with
Vitest
- integrate
react-router-dom
Step 1
Setup Vite + React + TypeScript
.
- 🔥
vite
hot reloading and page refreshing in blessing fast. - 👀
react
one library covers two worlds— web and native. - 👮
typescript
catch types errors early in editor.
It is so easy to install React + Typescript using Vite. Open terminal and type:
yarn create vite
Now go to project dir and run:
yarn install
Step 2
yarn add eslint -D
eslint-plugin-react@latest
@typescript-eslint/eslint-plugin@latest
@typescript-eslint/parser@latest
npx eslint --init
I already have eslint
in my project, so just need to level it up with eslint-airbnb-config
.
- 🚩
eslint
check syntax and find problems. - 📖
eslint-airbnb-config
to follow some rules.
Let’s install eslint-airbnb-config
:
npx install-peerdeps --dev eslint-config-airbnb
eslint-config-airbnb@19.0.4
eslint@^8.2.0
eslint-plugin-import@^2.25.3
eslint-plugin-jsx-a11y@^6.5.1
eslint-plugin-react@^7.28.0
eslint-plugin-react-hooks@^4.3.0 --dev
After it installed, it’s time to update hooks
inside .eslintrc
config file:
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
- 'eslint:recommended',
+ 'airbnb',
+ 'airbnb/hooks',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
Now I need these rules also support TypeScript. For that I need to install
eslint-config-airbnb-typescript
:
yarn add eslint-config-airbnb-typescript -D
...and update hook:
extends: [
'airbnb',
+ 'airbnb-typescript',
'airbnb/hooks',
...
]
Now I have rules for my .tsx
files as well.
Now, I need to tell ESLint where to find my TypeScript config.
Set
parserOptions.project
to the path of tsconfig.json
.
+ parserOptions: {
+ project: './tsconfig.json'
+ },
Now, I can add my custom rules also, like:
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
+ 'react/react-in-jsx-scope': 0,
},
Lastly, update tsconfig.json
:
"include": [
"src",
+ "vite.config.ts",
+ ".eslintrc.cjs",
]
the developer window. Done. From now airbnb’s default rules are applied all over my code.
Step 3
So at this point, ESLint is configured, which handles code style and things like missing semicolons or using single quotes vs double quotes.
For handling code formatting, I’m going to install prettier
:
yarn add -D prettier eslint-config-prettier eslint-plugin-prettier
- 💄
prettier
handle code formatting. - 🚧
eslint-config-prettier
will turns off all rules that might conflict withprettier
. - 🤡
eslint-plugin-prettier
runsprettier
as aneslint
rules.
Configuration File
I’m going to create
.prettierrc.cjs
(as like .eslintrc.cjs
) file that exports an object using module.exports
.
const config = {
trailingComma: "es5",
tabWidth: 2,
semi: false,
singleQuote: true,
};
module.exports = config;
Integrating with Linters
After reading the doc,
I found that eslint-plugin-prettier
is generally not recommended,
but it can be useful in certain circumstances, which aligns with my needs.
Open .eslintrc
config file and add prettier
to the plugins section:
plugins: [
'react-refresh',
+ 'prettier',
],
Also, add
plugin:prettier/recommended
as the last item in the extends array in .eslintrc
config file. This allows eslint-config-prettier
to override other configs.
extends: [
'airbnb',
'airbnb-typescript',
'airbnb/hooks',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
+ 'plugin:prettier/recommended',
]
Step 4
I love CSS, and Dart Sass is my go-to for every project.
Vite or React does not provide built-in support for .scss
, .sass
, .less
, .styl
or stylus
files.
To use sass
, first I have to install it:
yarn add sass -D
- 🖌️
dart-sass
CSS with superpowers.
Now I just need to use CSS modules combined with sass
by prepending .module
to
the file extension, for example Header.module.sass
.
Just need a few adjustments
on render classNames. I prefer localsConvention: 'camelCase'
and shorter generateScopedName
.
To do that, open vite.config.ts
file and add a css
section as follows:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
+ css: {
+ modules: {
+ localsConvention: 'camelCase',
+ generateScopedName: '[local]__[hash:base64:4]',
+ },
+ },
})
Now there’s no need to worry about class names mismatching.
If you're curious why I use CSS Modules, check out this article by Glen Madden. It has the answer you need.
Step 5
If I have no plans to write any unit tests in my project, I skip this step.
Write unit testing for every component is definitely a best practice. So I do my best to write some, even though I’m not good at it. But integrating a testing library is definitely a good add-ons.
Let’s setup vitest
:
yarn add vitest -D
- 🧪
vitest
super fast testing framework.
There is an example list for different
setups provided by Vitest. The one I am going to be utilizing here is react-testing-lib
this.
You can also check out React Testing Library.
To get started, I am going to install:
yarn add -D jsdom @testing-library/react @testing-library/jest-dom
- 🍃
jsdom
manipulate the virtual DOM, tests without launching a real browser. - 🪶
@testing-library/react
light-weight solution for testing React components. - 🎭
@testing-library/jest-dom
provides custom DOM element matchers for Jest.
Now from the example,
open their config
file and update my vite.config.ts
accordingly:
+ /* eslint-disable import/no-extraneous-dependencies */
+ /// <reference types="vitest" />
+ /// <reference types="vite/client" />
import react from '@vitejs/plugin-react'
import { defineConfig } from 'vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
+ test: {
+ globals: true,
+ environment: 'jsdom',
+ setupFiles: ['./src/setupTests.ts'],
+ css: true,
+ },
})
At this point, along with setting globals: true
, they are instructed that we need to go into
tsconfig.json
file and update compilerOptions
:
{
"compilerOptions": {
...
"jsx": "react-jsx",
+ "types": ["vitest/globals"],
...
},
...
}
Now it’s ready to write any unit testing.
Step 6
This is the last step.
I ask myself, does my website or application have multiple pages or routes?
If yes, I use react-route-dom
.
Once my website loads, it’s allowing me to navigate between pages without any browser refreshing. It's like magic, delivering a smooth user experience while navigation.
Install it as a dependency:
yarn add react-router-dom
- 🔀
react-router-dom
navigate between pages without any browser refreshing.
After that, I followed the tutorial, spending an hour to set up everything I needed. I have to do just two things.
1st, wrap AppLayout
component with BrowserRouter
in my App.tsx
file:
import { BrowserRouter } from 'react-router-dom'
import AppLayout from './components/app-layout/AppLayout'
function App() {
return (
<BrowserRouter>
<AppLayout />
</BrowserRouter>
)
}
export default App
2nd, set up NavLink
and Routes
in AppLayout
component:
import { NavLink, Route, Routes } from 'react-router-dom'
import Home from '../../pages/home/Home'
import Contact from '../../pages/contact/Contact'
function AppLayout() {
return (
<>
<nav>
<NavLink to="/">Home</NavLink>
<NavLink to="/contact">Contact</NavLink>
</nav>
<Routes>
<Route index element={<Home />} />
<Route path="contact" element={<Contact />} />
</Routes>
</>
)
}
export default AppLayout
All done! This setup will enable navigation between my pages without browser refreshing.
Zafree, available for hire
Hire meRead more
Fluid typography
Target render font-size: calc(vw + em)
- CSS
PMI Bangladesh
A meetup landing page proposal
- Design
- Proposal
Pilpil.js
A tiny JavaScript library for Progressive Image Loading.
- JavaScript
PayPal Fun
How I Welcome PayPal in Bangladesh.
- CSS
- JavaScript
CSS Zen Garden
A friendly CSS design challenge by recruiter before hiring me.
- Design
BUBT Professional Meetup
It’s the “Meetup” we all BUBTians wanted to attend.
- Community
- Design
- Development
Lets guess!
Which one is image and which one build with CSS?
- CSS
Sticky-kit problem
There is a problem in sticky-kit with bootstrap. I fixed it.
- JavaScript