Skip to content

Instantly share code, notes, and snippets.

@pixelmattersdev
Last active November 30, 2023 03:23
Show Gist options
  • Save pixelmattersdev/e31c8283b57e99106cf6b4f6dd80de50 to your computer and use it in GitHub Desktop.
Save pixelmattersdev/e31c8283b57e99106cf6b4f6dd80de50 to your computer and use it in GitHub Desktop.
How to set up a Front-End project with Vite, React, and TypeScript
npm init vite@latest demo-project -- --template react-ts
.
├── index.html
├── package.json
├── src
│   ├── App.css
│   ├── App.tsx
│   ├── favicon.svg
│   ├── index.css
│   ├── logo.svg
│   ├── main.tsx
│   └── vite-env.d.ts
├── tsconfig.json
└── vite.config.ts
{
"name": "demo-project",
"version": "0.0.0",
"engines":{
"node": ">=16.13.0",
"npm": ">=8.1.0"
},
// ...
}
npm install eslint --save-dev
npx eslint --init
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JSON
The config that you've selected requires the following dependencies:
eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
✔ Would you like to install them now with npm? · Yes
Installing eslint-plugin-react@latest, @typescript-eslint/eslint-plugin@latest, @typescript-eslint/parser@latest
Successfully created .eslintrc.json file
npm install eslint-plugin-react-hooks --save-dev
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended", // This line was added
"plugin:react/jsx-runtime",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2021,
"sourceType": "module"
},
"plugins": ["react", "@typescript-eslint"],
"rules": {},
"settings": {
"react": {
"version": "detect"
}
}
}
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking" // This line was added
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2021,
"sourceType": "module",
"project": "./tsconfig.json" // This line was added
},
"plugins": ["react", "@typescript-eslint"],
"rules": {},
"settings": {
"react": {
"version": "detect"
}
}
}
{
"name": "demo-project",
"version": "0.0.0",
// ...
"scripts":{
// ...
"lint:scripts": "eslint --ext .ts,.tsx src"
},
// ...
}
npm install stylelint stylelint-config-standard stylelint-config-recess-order --save-dev
{
"extends": ["stylelint-config-standard", "stylelint-config-recess-order"]
}
{
"name": "demo-project",
"version": "0.0.0",
// ...
"scripts":{
// ...
"lint:styles": "stylelint \"src/**/*.css\""
},
// ...
}
{
"editor.codeActionsOnSave": {
"source.fixAll": true
}
}
npm install prettier eslint-config-prettier eslint-plugin-prettier stylelint-config-prettier --save-dev
{
"semi": false,
"singleQuote": true
}
{
"extends": [
"stylelint-config-standard",
"stylelint-config-recess-order",
"stylelint-config-prettier" // this config was added
]
}
npx sb init --builder storybook-builder-vite
import { ComponentStory, ComponentMeta } from '@storybook/react'
import App from './App'
export default {
title: 'Components/App',
component: App,
} as ComponentMeta<typeof App>
const Template: ComponentStory<typeof App> = (args) => <App {...args} />
export const Default = Template.bind({})
import '../src/index.css' // this line was added
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
npm install jest --save-dev
{
"name": "demo-project",
"version": "0.0.0",
// ...
"scripts":{
// ...
"test": "jest"
},
// ...
}
npm test
> demo-project@0.0.0 test
> jest
No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In /Users/username/code/demo-project
16 files checked.
testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 0 matches
testPathIgnorePatterns: /node_modules/ - 16 matches
testRegex: - 0 matches
Pattern: - 0 matches
test('demo', () => {
expect(true).toBe(true)
})
npm test
> demo-project@0.0.0 test
> jest
PASS src/demo.test.js
✓ demo (2 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.581 s, estimated 1 s
Ran all test suites.
npm install eslint-plugin-jest --save-dev
{
"env": {
"browser": true,
"es2021": true,
"jest": true // This line was added
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:react/jsx-runtime",
"plugin:prettier/recommended",
"plugin:jest/recommended", // This line was added
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2021,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": ["react", "@typescript-eslint", "jest"], // This line was updated with "jest"
"rules": {
"prettier/prettier": "error"
},
"settings": {
"react": {
"version": "detect"
}
}
}
npm install ts-jest @types/jest --save-dev
module.exports = {
preset: 'ts-jest',
}
npm test
> demo-project@0.0.0 test
> jest
PASS src/demo.test.ts
✓ demo (2 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.477 s, estimated 1 s
Ran all test suites.
npm install @testing-library/react @testing-library/jest-dom --save-dev
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jest-environment-jsdom', // this line was added
}
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { App } from './App'
it('renders hello message', () => {
render(<App />)
expect(screen.getByText('Hello Vite + React!')).toBeInTheDocument()
})
npm test
> demo-project@0.0.0 test
> jest
PASS src/demo.test.ts
FAIL src/App.test.tsx
● Test suite failed to run
Jest encountered an unexpected token
SyntaxError: Unexpected token '<'
1 | import { useState } from 'react'
> 2 | import logo from './logo.svg'
| ^
3 | import './App.css'
4 |
5 | export const App: React.FC = () => {
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
at Object.<anonymous> (src/App.tsx:2:1)
Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 7.411 s
Ran all test suites.
module.exports = {
preset: 'ts-jest',
moduleNameMapper: {
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
},
testEnvironment: 'jest-environment-jsdom',
}
npm install identity-obj-proxy --save-dev
module.exports = 'test-file-stub'
npm test
> demo-project@0.0.0 test
> jest
PASS src/demo.test.ts
PASS src/App.test.tsx
Test Suites: 2 passed, 2 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 5.124 s, estimated 7 s
Ran all test suites.
npm install cypress --save-dev
{
"name": "demo-project",
"version": "0.0.0",
// ...
"scripts":{
// ...
"cypress:open": "cypress open"
},
// ...
}
npm install eslint-plugin-cypress @testing-library/cypress --save-dev
{
"extends": ["plugin:cypress/recommended"]
}
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress", "@testing-library/cypress"]
},
"include": ["**/*.ts"]
}
{
// ...
"plugins": ["react", "@typescript-eslint"],
"ignorePatterns": ["cypress/**/*"], // this line was added
"rules": {
"prettier/prettier": "error"
},
// ...
"overrides": [
{
"files": ["src/**/*.test.ts", "src/**/*.test.tsx"], // this line was updated
"env": {
"jest": true
},
"extends": ["plugin:jest/recommended"],
"plugins": ["jest"]
}
]
}
module.exports = {
preset: 'ts-jest',
testMatch: ['**/src/**/?(*.)+(spec|test).[jt]s?(x)'], // this line was added
// ...
}
cypress
├── .eslintrc.json
├── fixtures
├── integration
├── plugins
│   └── index.ts
├── support
│   ├── commands.ts
│   └── index.ts
└── tsconfig.json
import '@testing-library/cypress/add-commands'
describe('App', () => {
it('increments the counter', () => {
cy.visit('http://localhost:3000/')
cy.findByRole('button', { name: /count is:/i }).click()
cy.findByRole('button', { name: /count is:/i }).should(
'contain',
'count is: 1'
)
})
})
{
"baseUrl": "http://localhost:3000" // this line was added
}
describe('App', () => {
it('increments the counter', () => {
cy.visit('/') // this line was updated
cy.findByRole('button', { name: /count is:/i }).click()
cy.findByRole('button', { name: /count is:/i }).should(
'contain',
'count is: 1'
)
})
})
npm install --save-dev chromatic
name: "Chromatic"
on: push
jobs:
chromatic-deployment:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Install dependencies
run: npm install
- name: Publish to Chromatic
uses: chromaui/action@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
name: "Main"
on: pull_request
jobs:
lint-and-test:
name: Run linters and then tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version-file: ".nvmrc"
cache: "npm"
- name: Install dependencies
run: npm install
- name: Run ESLint
run: npm run lint:scripts
- name: Run Stylelint
run: npm run lint:styles
- name: Run Tests
run: npm test
env:
CI: true
- name: Run Cypress
uses: cypress-io/github-action@v2
with:
build: npm run build
start: npm run serve -- --port=3000
wait-on: http://localhost:3000
browser: chrome
headless: true
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version-file: ".nvmrc"
cache: "npm"
- name: Install dependencies
run: npm install
- name: Run ESLint
run: npm run lint:scripts
- name: Run Stylelint
run: npm run lint:styles
- name: Run Tests
run: npm test
env:
CI: true
- name: Run Cypress
uses: cypress-io/github-action@v2
with:
build: npm run build
start: npm run serve -- --port=3000
wait-on: http://localhost:3000
browser: chrome
headless: true
npm install --save-dev @commitlint/config-conventional @commitlint/cli
{
"extends": ["@commitlint/config-conventional"]
}
npm install husky --save-dev
npx husky install
npm set-script prepare "husky install"
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'
git add .
git commit -m "bad commit message"
⧗ input: bad commit message
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ found 2 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
husky - commit-msg hook exited with code 1 (error)
git commit -m "feat: setup semantic commit messages"
[feat/semantic-releases b9d74c1] feat: setup semantic commit messages
4 files changed, 1832 insertions(+), 23 deletions(-)
create mode 100644 .commitlintrc.json
create mode 100755 .husky/commit-msg
npm install --save-dev semantic-release
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/github"
]
}
name: "Release"
on:
push:
branches:
- main
jobs:
semantic-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version-file: ".nvmrc"
cache: "npm"
- name: Install dependencies
run: npm install
- name: Release a new version
run: npx semantic-release
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment