Camilo Martinez
Posted on May 9, 2022
Idiomas: [🇺🇸] English - [🇪🇸] Español
Vite es de lejos la mejor alternativa para crear proyectos de React hoy en día.
npm create vite@latest <project-name> -- --template <react-swc|react-swc-ts>
# npm 7+, extra double guion es requerido
cd <project-name>
npm install
npm run dev
Con estos comandos creamos un proyecto muy básico y limpio que sirve como punto de inicio, pero que va a necesitar algunas herramientas extras para automatizar tareas que pueden facilitar tu vida y la de tu equipo de desarrollo.
VSCode
Se recomienda hacer estas configuraciones en los ajustes del proyecto y no en los ajustes globales.
Empezaremos creando una carpeta .vscode
con un archivo settings.json
dentro.
# 📄 Archivo: /.vscode/settings.json
-----------------------------------
{
"explorer.fileNesting.patterns": {
"*.js": "$(capture).js.map, $(capture).*.js, $(capture)_*.js, $(capture)*.snap",
"*.jsx": "$(capture).js, $(capture).*.jsx, $(capture)_*.js, $(capture)_*.jsx, $(capture)*.snap",
"*.ts": "$(capture).js, $(capture).d.ts.map, $(capture).*.ts, $(capture)_*.js, $(capture)_*.ts, $(capture)*.snap",
"*.tsx": "$(capture).ts, $(capture).*.tsx, $(capture)_*.ts, $(capture)_*.tsx, $(capture)*.snap",
},
"emmet.excludeLanguages": [],
"emmet.includeLanguages": {
"markdown": "html",
"javascript": "javascriptreact",
"typescript": "typescriptreact"
},
"emmet.showSuggestionsAsSnippets": true,
"emmet.triggerExpansionOnTab": true,
"files.exclude": {
"**/*.js.map": {
"when": "$(basename)"
},
"**/node_modules": true,
},
"html.autoClosingTags": true,
"javascript.autoClosingTags": true,
"javascript.suggest.completeFunctionCalls": true,
"typescript.suggest.completeFunctionCalls": true,
"javascript.inlayHints.functionLikeReturnTypes.enabled": true,
"typescript.inlayHints.functionLikeReturnTypes.enabled": true,
"javascript.inlayHints.parameterNames.enabled": "all",
"typescript.inlayHints.parameterNames.enabled": "all",
"javascript.suggest.autoImports": true,
"search.exclude": {
"**/coverage": true,
"**/node_modules": true
},
"typescript.autoClosingTags": true,
"typescript.suggest.autoImports": true,
}
Existen muchas extensiones y configuraciones para VSCode por ahí. Si necesitas un toque extra, les recomiendo darle una mirada a VSCode - Essentials y VSCode - React Flavored.
Depuración
No hay necesidad de instalar una extension extra para hacer depuración de React desde VSCode.
# 📄 File: /.vscode/launch.json
-----------------------------------
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome", // o "msedge"
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
}
]
}
Desactive la apertura automática del navegador adicionando BROWSER=none
al archivo .env
en tu proyecto. También hay que cambiar el script dev
para que use el mismo puerto.
# 📄 Archivo: package.json
-----------------------------------
{
"scripts": {
- "dev": "vite",
+ "dev": "vite --port 3000",
}
}
Ejecute el comando npm run dev
e inicie el navegador desde el panel de Depuración. Ahora puedes adicionar puntos de interrupción (break points) directamente en VSCode.
Extensiones
Si quiere que VSCode muestre extensions recomendadas cuando abra el proyecto.
# 📄 File: /.vscode/extentions.json
-----------------------------------
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"stylelint.vscode-stylelint",
"ZixuanChen.vitest-explorer"
]
}
Linter
- Extensión ES Lint
# 📄 Archivo: /.vscode/settings.json
-----------------------------------
{
+ "editor.formatOnSave": true,
+ "javascript.format.enable": false,
+ "javascript.validate.enable": true,
+ "typescript.format.enable": false,
+ "typescript.validate.enable": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ }
}
Instale este paquete en la carpeta del proyecto:
npm install -D eslint
npm init @eslint/config
Pueden elegir la configuración que deseen, pero la que recomiendo es:
Use: To check syntax, find problems, and enforce code style
Type of modules: JavaScript modules (import/export)
Framework: React
Typescript: No #o Yes si tu proyecto lo usa
Run: Browser #y Node si usa Next.js
Style guide: Popular -> Standard #JS sin punto y coma ;
Format: JSON
Excepción de los punto y coma
Debido a que la guía de estilosstandard
no usa puno y como debes tener presente los siguiente. Si la línea de código siguiente comienza con alguno de los siguientes operadores[
,(
,+
,\
*,/
,-
,,
,.
, será reconocida como una expresión perteneciente a la línea anterior. Por lo tanto, vas a necesitar empezar la línea con;
si quieres que la reconozca como una nueva sentencia de código.
Al finalizar va preguntar si desea instalar uno paquetes extras. La respuesta debe ser: yes (si). Cuando finalice, actualice las configuraciones de las reglas así:
# 📄 Archivo: .eslintrc.json
-----------------------------------
{
"rules": {
+ "no-console": "warn",
+ "react/prop-types": "off",
+ "react/self-closing-comp": "warn",
+ "react/react-in-jsx-scope": "off"
},
+ "settings": {
+ "react": {
+ "version": "detect"
+ }
+ }
}
Si estas usando TypeScript
también debes adicionar esta configuración:
# 📄 Archivo: .eslintrc.json
-----------------------------------
{
"parserOptions": {
+ "project": ["tsconfig.json"],
+ "createDefaultProgram": true
},
"rules": {
"no-console": "warn",
"react/prop-types": "off",
"react/self-closing-comp": "warn",
+ "@typescript-eslint/consistent-type-definitions": ["error", "type"],
+ "@typescript-eslint/explicit-function-return-type": "off",
},
}
Cree un archivo .eslintignore
en la raíz del proyecto:
# 📄 Archivo: .eslintignore
-----------------------------------
build
coverage
dist
No es necesario adicionar los
node_modules
porque los ignora por defecto.
Si no quieres usar la extensión de ES Lint
, adicione los comandos list
(listar) y fix
(corregir) al final de la lista de scripts
:
# 📄 Archivo: package.json
-----------------------------------
{
"scripts": {
+ "lint": "eslint .",
+ "lint:fix": "eslint . --fix --ext .js,.jsx,.ts,.tsx"
}
}
Evitar error import React
Desde React 17, no es necesario usar
import React
cuando solo se usa JSX, pero si lo debemos hacer para usar Hooks o los otros métodos que provee React.
Para evitar que ES Lint
nos alerte sobre el import React
debemos adicionar el siguiente plugin a la configuración:
# 📄 Archivo: .eslintrc.json
-----------------------------------
{
"extends": [
"plugin:react/recommended",
"standard-with-typescript",
+ "plugin:react/jsx-runtime",
],
}
Lineas en Blanco
Si quiere preservar líneas en blanco después de las definiciones.
# 📄 Archivo: .eslintrc.json
-----------------------------------
{
"rules": {
+ "padding-line-between-statements": [
+ "error",
+ {
+ "blankLine": "always",
+ "prev": "*",
+ "next": "return"
+ },
+ {
+ "blankLine": "always",
+ "prev": [
+ "const",
+ "let",
+ "var"
+ ],
+ "next": "*"
+ },
+ {
+ "blankLine": "any",
+ "prev": [
+ "const",
+ "let",
+ "var"
+ ],
+ "next": [
+ "const",
+ "let",
+ "var"
+ ]
+ }
+ ]
},
}
Auto ordenar
Si no quieres lidiar manualmente con el ordenamiento de propiedades o imports, o que cada persona en el equipo lo haga de forma diferente, adiciona estas configuraciones.
# 📄 Archivo: .eslintrc.json
-----------------------------------
{
"rules": {
+ "import/order": [
+ "warn",
+ {
+ "pathGroups": [
+ {
+ "pattern": "~/**",
+ "group": "external",
+ "position": "after"
+ }
+ ],
+ "newlines-between": "always-and-inside-groups"
+ }
+ ],
+ "react/jsx-sort-props": [
+ "warn",
+ {
+ "callbacksLast": true,
+ "shorthandFirst": true,
+ "noSortAlphabetically": false,
+ "reservedFirst": true
+ }
+ ]
},
}
Formato
ES Lint
podría ser suficiente y Prettier es totalmente opcional, pero recomiendo usarlo porque tiene mejor rendimiento a la hora de hacer formateo queES Lint
. El problema es que a veces se "pelean" entre ellos, así que hay que saber configurarlos para que trabajen juntos.
Si también lo quieres usar estos son los pasos.
- Extensión Prettier - Code formatter
# 📄 Archivo: /.vscode/settings.json
-----------------------------------
{
- "editor.codeActionsOnSave": {
- "source.fixAll.eslint": true
- }
+ "eslint.probe": [
+ "javascript",
+ "javascriptreact",
+ "typescript",
+ "typescriptreact"
+ ],
+ "[javascript][typescript]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.formatOnSave": false,
// Corre primero Prettier y luego ESLint
+ "editor.codeActionsOnSave": [
+ "source.formatDocument",
+ "source.fixAll.eslint"
+ ],
+ }
}
Instalar Prettier:
npm install -D prettier
Y ESLint (JS) para prettier:
npm install -D eslint-config-prettier
O TSLint (TS) para prettier:
npm install -D tslint-config-prettier
Cree un archivo .prettierignore
en la raíz del proyecto:
# 📄 Archivo: .prettierignore
-----------------------------------
build
coverage
dist
package-lock.json
No es necesario adicionar los
node_modules
porque los ignora por defecto.
Cree un archivo .prettierrc.json
en la raíz del proyecto
# 📄 Archivo: .prettierrc.json
-----------------------------------
{
"semi": false,
"singleQuote": true
}
Adicione la siguiente configuración al final de extends
:
# 📄 Archivo: .eslintrc.json
---
{
"extends": [
"plugin:react/recommended",
"standard-with-typescript",
"plugin:react/jsx-runtime",
+ "prettier", //de ultimo
],
}
Si no quieres usar la extensión de Prettier
, adicione los comandos check
(chequear) y write
(escribir) al final de la lista de scripts
:
# 📄 Archivo: package.json
-----------------------------------
{
"scripts": {
+ "format": "prettier . --check",
+ "format:fix": "prettier . --write"
}
}
HTML Linter
npm install -D htmlhint
Si también desea que se haga revision del HTML con eslint
instale este plugin:
npm install -D eslint-plugin-html
Adicione html
a la lista de plugins
# 📄 Archivo: .eslintrc.json
-----------------------------------
{
"plugins": [
"react",
+ "html"
],
}
CSS Linter
- Extensión Stylelint
Instale y configure en el proyecto:
npm install -D stylelint stylelint-config-standard stylelint-config-idiomatic-order
Cree un archivo de configuración llamado .stylelintrc.json
en la raíz del proyecto.
# 📄 Archivo: .stylelintrc.json
-----------------------------------
{
"extends": [
"stylelint-config-standard",
"stylelint-config-idiomatic-order"
],
"rules": {
"declaration-colon-newline-after": "always-multi-line"
},
"ignoreFiles": [
"build/**",
"coverage/**",
"dist/**",
"**/*.js",
"**/*.jsx",
"**/*.ts",
"**/*.tsx"
]
}
Si planea usar styled components
también instale
npm install -D stylelint-config-styled-components
# 📄 File: .stylelintrc.json
-----------------------------------
{
"extends": [
"stylelint-config-standard",
"stylelint-config-idiomatic-order",
+ "stylelint-config-styled-components"
],
"ignoreFiles": [
"build/**",
"coverage/**",
"dist/**",
"**/*.js",
- "**/*.jsx",
"**/*.ts",
- "**/*.tsx"
]
}
Para prevenir que tanto VSCode como Stylelint reporten los mismos errores, debemos deshabilitar los que trae VSCode por defecto.
# 📄 Archivo: /.vscode/settings.json
-----------------------------------
{
+ "stylelint.enable": true,
+ "css.validate": false,
+ "less.validate": false,
+ "scss.validate": false,
+ "[css][scss]": {
+ "editor.defaultFormatter": "stylelint.vscode-stylelint",
+ "editor.codeActionsOnSave": [
+ "source.fixAll.stylelint"
+ ],
+ }
}
Stylelint tiene cerca de 170 regalas. Algunas veces te va a mostrar errores que literalmente te van a causar problemas a futuro.
Git Linter
Si el proyecto aún no tiene configurado un repositorio de git, primero debe correr el comando:
git init
Usa Husky por debajo y solo corre el linter contra los archivos en staged
. Con esto nos aseguramos que no se suban cambios sin ser revisados antes por los linters configurados.
Instale y configure en el proyecto:
npx mrm@3 lint-staged
Pruebas
Usaremos Vitest que es compatible con el API de Jest, así que no toca reaprender demasiado sobre la sintaxis.
npm install -D vitest
Con la configuración global
no vas a necesitar importar las dependencias en cada archivo, adicionando automáticamente soporte a Jest.
# 📄 Archivo: vitest.config.ts
-----------------------------------
- import { defineConfig } from 'vite'
+ import { defineConfig } from 'vitest/config'
export default defineConfig({
+ test: {
+ globals: true,
+ },
})
Si estas usando typescript, también adiciona esta configuración.
# 📄 Archivo: tsconfig.json
-----------------------------------
{
+ "compilerOptions": {
+ "types": ["vitest/globals"],
+ }
}
El siguiente paso no es requerido, pero si quieres sacar ventaja del IntelliSense es recomendado iniciar los archivos así:
# 📄 Archivos: *.test.js
-----------------------------------
import { it, expect, describe } from "vitest";
Actualiza los scripts para poder correr las pruebas desde la terminal:
# 📄 Archivo: package.json
-----------------------------------
{
"scripts": {
+ "test": "vitest --run --reporter verbose",
+ "test:w": "vitest",
+ "test:ui": "vitest --ui",
}
}
Instantáneas
Si desea que las instantáneas (snapshots) se generen al mismo nivel que los archivos de prueba en lugar de la carpeta __snapshots__
. Adicione esta propiedad.
# 📄 Archivo: vitest.config.ts
-----------------------------------
export default defineConfig({
test: {
globals: true,
+ resolveSnapshotPath: (testPath, snapExtension) => testPath + snapExtension,
},
})
Cobertura
Para los reportes de cobertura, necesitaremos instalar @vitest/coverage-v8
npm install -D @vitest/coverage-v8
Actualiza los scripts con estos otros dos comandos:
# 📄 Archivo: package.json
-----------------------------------
{
"scripts": {
+ "test:c": "vitest run --coverage",
+ "test:cw": "vitest watch --coverage"
}
}
Y adiciona la siguiente configuración de @vitest/coverage-v8
.
# 📄 Archivo: vitest.config.ts
-----------------------------------
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
+ reporters: ['verbose'],
+ coverage: {
+ all: true,
+ reporter: ['text', 'html', 'lcov'],
+ include: ['**/src/**/*.{js,jsx,ts,tsx}'],
+ exclude: [
+ '**/src/main.{js,jsx,ts,tsx}',
+ '**/*.types.{ts,tsx}',
+ '**/*.test.{js,jsx,ts,tsx}',
+ '**/src/vite-env*',
+ ],
+ statements: 0,
+ branches: 0,
+ functions: 0,
+ lines: 0,
+ },
},
})
RTL (React Testing Library)
Ejecute este comando para instalar RTL
.
npm install -D @testing-library/react @testing-library/dom @testing-library/user-event @testing-library/jest-dom
También se necesita instalar jsdom
(o happy-dom
)
npm install -D jsdom
Y adicionarlo como environment
# 📄 Archivo: vitest.config.ts
-----------------------------------
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
+ environment: 'jsdom',
},
})
Con el setupFiles
se pueden extender los matchers
de jest-dom
forma global sin la necesidad importarlas en cada archivo.
# 📄 Archivo: .vitest/setup.ts
-----------------------------------
+ /* Extend Matchers */
+ import '@testing-library/jest-dom'
# 📄 Archivo: vitest.config.ts
-----------------------------------
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
+ setupFiles: '.vitest/setup.ts',
},
})
Si elegiste user eslint
es buena idea adicionar estos linters de RTL con este comando:
npm install --D eslint-plugin-testing-library eslint-plugin-jest-dom
Y adicionar estas condiciones al archivo de configuración de eslint
.
# 📄 Archivo: .eslintrc.json
-----------------------------------
{
"extends": [
"plugin:react/recommended",
"standard-with-typescript",
"plugin:react/jsx-runtime",
"prettier",
+ "plugin:testing-library/react",
+ "plugin:jest-dom/recommended"
],
"plugins": [
"react",
"html",
+ "testing-library",
+ "jest-dom"
],
"rules": {
+ "testing-library/await-async-query": "error",
+ "testing-library/no-await-sync-query": "error",
+ "testing-library/no-debugging-utils": "warn",
+ "testing-library/no-dom-import": "off",
+ "jest-dom/prefer-checked": "error",
+ "jest-dom/prefer-enabled-disabled": "error",
+ "jest-dom/prefer-required": "error",
+ "jest-dom/prefer-to-have-attribute": "error"
},
}
Adicionar al setupFiles
la configuración para que los matchers globales no colisionen con los de jest-dom
.
# 📄 Archivo: .vitest/setup.ts
-----------------------------------
/* Extend Matchers */
import '@testing-library/jest-dom'
+ import '@testing-library/jest-dom/extend-expect'
Mock Service Worker
Si también vas a usar msw para probar los HTTP requests necesitas correr este comando.
npm install -D msw cross-fetch
Y adicionar esta configuración global.
# 📄 Archivo: .vitest/setup.ts
-----------------------------------
+ /* Mock Service Worker */
+ import { afterAll, afterEach, beforeAll } from 'vitest'
+ import { fetch } from 'cross-fetch'
+ import { server } from './mocks/server'
+ // Add `fetch` polyfill.
+ global.fetch = fetch
+ // Establish API mocking before all tests
+ beforeAll(() => server.listen({ onUnhandledRequest: `error` }))
+ // Reset any request handlers that we may add during the tests,
+ // so they don't affect other tests
+ afterEach(() => server.resetHandlers())
+ // Clean up after the tests are finished
+ afterAll(() => server. Close())
Depuración
Para una depuración visual de las pruebas.
- Extensión Vitest - Test Explorer Adapter
Depuración
Esta no es una extensión. Se trata de un paquete de npm
que se debe instalar en el proyecto y que ayuda en el proceso de depuración.
npm install -S click-to-react-component
Aun cuando click-to-react-component
es adicionado como dependencies
, al crear el build
de producción el paquete va a ser removido con la ayuda de tree-shaking.
Usando la tecla alt
(u option
en macOS) y con una combinación de identificadores y clicks sobre el componente en el navegador, nos vamos a poder transportar al código del componente en el editor.
Funciona con vite
agregando estas configuraciones al proyecto:
# 📄 Archivo: /src/main.jsx
-----------------------------------
import React from "react"
import ReactDOM from "react-dom/client"
+import { ClickToComponent } from "click-to-react-component"
import App from "./App"
import "./index.css"
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<App />
+ <ClickToComponent />
</React.StrictMode>
)
⚠ Desafortunadamente, no es compatible con WSL
Estilos
PostCSS
Actualmente prefiero usar PostCSS
que Sass
porque es muchísimo más rápido y sigue más de cerca el estándar de CSS (presente o futuro) y no necesita renombrar las extensiones de los archivos. Así que, en un futuro, inclusive podrías remover PostCSS
de tu proyecto y continuaría trabajando sin la necesidad de hacer una migración.
npm install -D postcss-cli postcss
Para mi estos son los plugins esenciales:
npm install -D @csstools/postcss-nesting-experimental autoprefixer
Instale
Autoprefixer
solamente si necesita darles soporte a navegadores antiguos. Hay muchos pluginsPostCSS
, traten de no instalar demasiados o algunos que hagan cosas demasiado raras que se alejen del estándar actual o propuesto de CSS.
Cree un archivo postcss.config.cjs
en la raíz del proyecto:
# 📄 Archivo: postcss.config.cjs
-----------------------------------
module.exports = {
"plugins": {
"@csstools/postcss-nesting-experimental": true,
"autoprefixer": true
}
}
El orden de los plugin es importante porque se requiere que el
nesting
corra antes delautoprefixer
Si también estas usando Stylelint. Agrega este paquete:
npm install --D postcss-syntax
Agrégalo como customSyntax
en el archivo .stylelintrc.json
# 📄 Archivo: .stylelintrc.json
-----------------------------------
{
"extends": [
"stylelint-config-standard"
],
+ "customSyntax": "postcss-syntax"
}
Sass
Si en vez de PostCSS quieres seguir usando Sass. Vite tiene soporte de SCSS
incorporado, pero necesita que se instale este paquete:
npm install -D sass
Tener cuidado de usar el paquete
sass
y nonode-sass
porque ya está obsoleto.
Si decidiste usar Stylelint. Reemplaza estos paquetes:
npm remove stylelint-config-standard
npm install --D stylelint-config-standard-scss
Reemplázalos como extends
en el archivo .stylelintrc.json
# 📄 Archivo: .stylelintrc.json
-----------------------------------
{
"extends": [
- "stylelint-config-standard",
+ "stylelint-config-standard-scss"
]
}
Luego renombra manualmente todos los archivos con extensión .css
a .scss
y actualiza src/App.js
para que importe src/App.scss
.
Despliegue
Si va a publicar el proyecto en GitHub pages sin usar un dominio personalizado se deben cambiar algunas rutas.
# 📄 Archivo: vite.config.js
-----------------------------------
export default defineConfig({
plugins: [react()],
+ base: "./",
+ build: {
+ outDir: './docs'
+ }
})
That’s All Folks!
Happy Coding 🖖
Fuentes:
Posted on May 9, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.