Implement css modules to styles
npm create vite@latest react-sass-modules-tailwind -- --template react-ts
npm run dev
for a dev server and navigate to http://localhost:3000/
. The application will automatically reload if you change any of the source files.
Commit Structure Guidelines:
feat: Subject
(Introduces a new feature)fix: Subject
(Resolves a bug or issue)styles: Subject
(Updates styles such as SCSS, CSS, Stylus, Less, etc.)docs: Subject
(Modifies documentation, including README and environment configurations)test: Subject
(Adds or updates unit tests or end-to-end tests)refactor: Subject
(Improves existing code without changing functionality)IMPORTANTβοΈ
Subject is sentence-case
Please follow these steps:
Install and Configure Husky (Git Hooks) Go to βͺ
npm i -D husky
.husky
folder in the root directory):"prepare": "husky install"
commit-msg
to run a regular expression validator (CommitLint) before each commit:npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
echo "npx --no -- commitlint --edit \${1}" > .husky/commit-msg
pre-commit
to run lint-staged (Prettier and ESLint) and tests before each commit:"test:staged": "git diff --cached --diff-filter=d --name-only -- '*.test.tsx' | xargs -I {} npm run test --include={} --browsers=ChromeHeadless --watch=false"
Explanation:git diff
Displays changes in files--cached
Shows only staged files--diff-filter=d
Ignores deleted files--name-only
Displays only file names'*.test.tsx'
Filters only files with .test.tsx extension|
Redirects output from the previous command to the nextxargs
Takes a list of elements and passes them as arguments to another command-I {}
Saves the list of elements in {}npm run test
Executes tests--include={}
Includes the saved list of elements for individual testing--browsers=ChromeHeadless
Runs tests in Chrome without the graphical interface--watch=false
Does not open the browser windownpx husky add .husky/pre-commit "npx lint-staged && git diff --cached --diff-filter=d --name-only -- '*.test.tsx' | xargs -I {} npm run test --include={} --browsers=ChromeHeadless --watch=false"
echo "npx lint-staged && git diff --cached --diff-filter=d --name-only -- '*.test.tsx' | xargs -I {} npm run test --include={} --browsers=ChromeHeadless --watch=false" > .husky/pre-commit
pre-push
to execute a specified command before each push:npx husky add .husky/pre-push "#HERE ANYTHING COMMAND"
echo "#HERE ANYTHING COMMAND" > .husky/pre-push
Install and Configure Prettier Go to βͺ
npm i -D prettier
"prettier": "prettier . --write"
.prettierrc.json
{
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": false,
"quoteProps": "preserve",
"jsxSingleQuote": false,
"trailingComma": "none",
"bracketSpacing": true,
"bracketSameLine": false,
"jsxBracketSameLine": false,
"arrowParens": "always",
"embeddedLanguageFormatting": "auto",
"singleAttributePerLine": true,
"overrides": [
{
"files": ["*.js", "*.ts", "*.tsx", "*.jsx", "*.css", "*.scss"],
"options": {
"semi": true
}
}
]
}
.editorconfig
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false
Install and Configure Lint (Linter), Lint-Staged (Staged Commits Linter), and Commit Lint (Conventional Commits) Go to ESLint βͺ Go to Lint Staged βͺ Go to Commit Lint βͺ
npm i -D lint-staged @commitlint/types @commitlint/cli @commitlint/config-conventional @typescript-eslint/eslint-plugin eslint-plugin-html @typescript-eslint/parser eslint eslint-plugin-react-hooks eslint-plugin-react-refresh eslint-plugin-react
Create file .eslintrc.json
{
"root": true,
"env": {
"browser": true,
"es2020": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"plugin:react/recommended",
"plugin:react/jsx-runtime" // This line indicates that we are utilizing React 17 or higher and require its new rules
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"ecmaFeatures": {
"jsx": true, // We enable JSX support
"tsx": true // We enable TSX support
}
},
"settings": {
"react": {
"version": "detect"
}
},
"plugins": [
"react-refresh",
"@typescript-eslint",
"react",
"html"
],
"rules": {
"react-hooks/rules-of-hooks": "error", // Rules of hooks
"react/react-in-jsx-scope": "off", // Rule for allows the use of a TSX or JSX component without the need to import React
"react/jsx-uses-react": "off",
"react/jsx-uses-vars": "error", // Rule for disallow use var
"react/hook-use-state": "error", // Rule to check whether unstructured value and setter variables in a useState() call are named symmetrically
"react/jsx-key": "error", // Rule for using Keys in Child Elements within Loops
"quotes": [ // Rule for using double quotes
"error",
"double",
{
"avoidEscape": true,
"allowTemplateLiterals": true
}
],
"@typescript-eslint/quotes": [
"error",
"double",
{
"avoidEscape": true,
"allowTemplateLiterals": true
}
],
"eqeqeq": [ // Rule for strict equality (=== or !==)
"error",
"smart"
],
"no-console": [ // Rule to avoid using console statements
"error"
],
"no-else-return": [ // Rule to disallow else as a return
"error",
{
"allowElseIf": true
}
],
"no-empty": [ // Rule to disallow empty blocks
"error",
{
"allowEmptyCatch": false
}
],
"no-extra-semi": [ // Rule to disallow extra semicolons
"error"
],
"@typescript-eslint/no-extra-semi": [
"error"
],
"semi": [ // Rule to ensure there is a semicolon at the end
"error",
"always",
{
"omitLastInOneLineBlock": true,
"omitLastInOneLineClassBody": true
}
],
"@typescript-eslint/semi": [
"error",
"always",
{
"omitLastInOneLineBlock": true,
"omitLastInOneLineClassBody": true
}
]
}
}
Create file .lintstagedrc
{
"**/*.{js,jsx,ts,tsx}": ["prettier --write", "eslint"]
}
Script (Executes the linter):
"lint": "eslint ."
Script (Fixes errors reported by the linter):
"lint:fix": "eslint --fix ."
Script (Executes the linter for files staged for commit):
"lint:staged": "npx lint-staged"
Create file commitlint.config.ts
```typescript
import type { UserConfig } from "@commitlint/types"
import { RuleConfigSeverity } from "@commitlint/types"
/**
-> Level 0: Disables the rule 1: Enables the rule like a warning 2: Enables the rule like a error -> Applicable "always": Enables the rule always "never": Disable the rule always -> Value string|boolean|number|array
"name-rule": [Level, Applicable, Value] */
const Configuration: UserConfig = { extends: ["@commitlint/config-conventional"], rules: { "type-empty": [ // It is responsible for validating the type RuleConfigSeverity.Error, "never" ], "type-enum": [ // It is responsible for managing types (e.g., feat, fix, bug, and others) RuleConfigSeverity.Error, "always", ["feat", "fix", "styles", "docs", "test", "refactor"] ], "type-case": [ // It is responsible for enforcing case conventions in the type RuleConfigSeverity.Error, "always", "lower-case" ], "scope-empty": [ // It is responsible for managing the scope (e.g., feat(frontend), fix(web), and others) RuleConfigSeverity.Error, "always" ], "subject-empty": [ // It is responsible for validating the subject RuleConfigSeverity.Error, "never" ], "subject-case": [ // It is responsible for enforcing case conventions in the subject RuleConfigSeverity.Error, "always", "sentence-case" ], "subject-min-length": [ // It is responsible for ensuring the subject meets the minimum length requirement RuleConfigSeverity.Error, "always", 10 ], "subject-max-length": [ // It is responsible for enforcing the maximum length limit of the subject RuleConfigSeverity.Error, "always", 50 ], "body-empty": [ // It is responsible for validating the body RuleConfigSeverity.Error, "always" ], "footer-empty": [ // It is responsible for validating the footer RuleConfigSeverity.Error, "always" ] } } module.exports = Configuration
### Testing π§ͺ
Jest to testing application
[Go to βͺ](https://jestjs.io/docs/getting-started)
```bash
npm install --save-dev jest @types/jest jest-transform-stub @testing-library/react @testing-library/jest-dom @babel/preset-env @babel/preset-react react-test-renderer ts-jest jest-environment-jsdom @types/jest @babel/preset-typescript babel-plugin-transform-import-meta @babel/plugin-transform-runtime babel-plugin-transform-vite-meta-env
Script (Executes all unit tests):
"test": "jest --coverage"
Script (Executes a single unit test):
"test:one": "jest --coverage --collectCoverageFrom='your-url-relative-component-here' --watch your-url-relative-component-here"
Create file jest.config.cjs
and paste this:
module.exports = {
preset: "ts-jest",
testEnvironment: "jsdom",
transform: {
"^.+\\.(js|jsx|ts|tsx)$": [
"ts-jest",
{
tsconfig: false,
useESM: true,
babelConfig: true,
plugins: ["babel-plugin-transform-vite-meta-env"],
}
],
}
};
Create file babel.config.cjs
and paste this:
module.exports = function (api) {
api.cache(true);
const presets = [
["@babel/preset-env", { targets: { node: "current" } }],
"@babel/preset-typescript",
"@babel/preset-react",
];
return {
presets,
plugins: [
"@babel/plugin-transform-runtime",
"babel-plugin-transform-import-meta",
"babel-plugin-transform-vite-meta-env",
],
};
};
Configuration to import files
Add in tsconfig.json
within compilerOptions
:
/* Alias */
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@components/*": ["src/components/*"],
"@otherFolder/*": ["src/otherFolder/*"]
}
Add in vite.config.ts
import path from "path";
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
"@components": path.resolve(__dirname, "./src/components"),
"@otherFolder": path.resolve(__dirname, "./src/otherFolder")
}
}
Add in jest.config.cjs
moduleNameMapper: {
"^@components/(.*)$": "<rootDir>/src/components/$1",
"^@otherFolder/(.*)$": "<rootDir>/src/otherFolder/$1"
}
Disable eslint line
// eslint-disable-next-line here-rule
To disable
@apply error scss
for Tailwind CSS in VSCode, add the following script to your .vscode > settings.json:"scss.lint.unknownAtRules": "ignore"
If Husky isn't working on MacOS, execute the command (within the root project):
chmod ug+x .husky/*
To view prettified console objects in testing, use the following syntax:
console.log(JSON.stringify(obj, undefined, 2));
Developed By:
Diego Villa
. - Website: https://www.cabuweb.com