2.2 Frontend frameworks
2.2 Frontend frameworks
Een project dat aangemaakt wordt met pnpm create vite bevat een ontoereikende basisconfiguratie voor ESLint en nog niets voor Prettier.
Hieronder bespreken we hoe we deze kunnen toevoegen aan een bestaand project.
ESLint
De basisconfiguratie is relatief beperkt, de readme die in de vite + swc + react + ts template zit raad dan ook aan om enkele extra configuratie toe te voegen. Deze instructies leiden wel naar een goede configuratie, maar maken nog gebruik van het oude ESLint configuratie-formaat.
Aangezien de documentatie voor het nieuwe formaat ondertussen goed beschikbaar is en het oude formaat niet meer ondersteund zal worden in toekomstige versies van ESLint, maken we nu al gebruik van het nieuwe formaat en passen we de instructies in de readme aan naar de nieuwe configuratie (flatconfig).
Basisconfiguratie bouwen
Omdat we gebruik maken van TypeScript volgen we de instructies op de TypeScript Eslint website die hieronder vereenvoudigd weergegeven worden. We beginnen we met onderstaande libraries te installeren.
Vervolgens voegen we een basis configuratie toe aan het (nieuwe) bestand ./eslint.config.mjs.
Info
Op het moment van schrijven (2025-09-05) geeft onderstaande code een foutmelding op de gemarkeerde lijn.
De array in tsEslint.configs.recommendedTypeChecked bevat een array met verschillende configuratie objecten, dit is een geldig argument voor de tsEslint.config functie. Je kan dit verifiëren door een array rond alle andere objecten in de config te plaatsen. Door een mismatch in de types van de TS ESLint library wordt deze configuratie echter niet als geldig herkend, maar de code werkt wel.
Aangezien console.log, alert, confirm, prompt en debugger statements niet proper zijn in productie code, voegen we ook regels toe die dit verbieden.
// @ts-check
import eslint from '@eslint/js'
import tsEslint from 'typescript-eslint'
export default tsEslint.config(
eslint.configs.recommended,
{
rules: {
'no-alert': ['error'],
'no-debugger': ['error'],
'no-console': ['error', {allow: ['warn', 'error']}],
},
},
tsEslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
},
},
},
)Basisconfiguratie uitbreiden
Nu we een basisconfiguratie hebben kunnen we deze uitbreiden zoals beschreven in de readme. Als eerste stap moeten we enkele regels toevoegen aan de parserOptions property, de code die in de readme staat moet aangepast worden naar het nieuwe configuratie-formaat en resulteert in onderstaande code.
De eerste aanpassing geeft aan dat we de laatste versie van ECMAScript gebruiken, zo hebben we toegang tot de laatste features van JavaScript en geeft de linter hier geen foutmeldingen voor.
// @ts-check
import eslint from '@eslint/js'
import tsEslint from 'typescript-eslint'
export default tsEslint.config(
eslint.configs.recommended,
{
rules: {
'no-alert': ['error'],
'no-debugger': ['error'],
'no-console': ['error', {allow: ['warn', 'error']}],
},
},
tsEslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
ecmaVersion: 'latest',
projectService: true,
},
},
},
)De readme raadt vervolgens aan om de @typescript-eslint/recommended regels te vervangen door @typescript-eslint/recommended-type-checked of @typescript-eslint/strict-type-checked. Dit kunnen we overslaan aangezien we deze regels al toegevoegd hebben in de basisconfiguratie.
Daarna volgt een optionele instructie die de stylistic regels toevoegt. Zoals de naam doet vermoeden hebben deze regels invloed op de stijl van de code. De ESLint stylistic plugin bevat zeer veel regels en kan heel granulair geconfigureerd worden, we gebruiken dit pakket niet omwille van de complexiteit en gebruiken Prettier als dedicated formatter.
De laatste stap die beschreven wordt in de readme is het toevoegen van de eslint-plugin-react plugin. Deze plugin bevat regels die specifiek zijn voor React en JSX, we installeren deze plugin met het volgende commando:
Vervolgens kunnen we de documentatie in het eslint-plugin-react repository volgen om uiteindelijk tot volgende configuratie te komen.
We activeren ook enkele regels die een consistent gebruik van quotes afdwingen in JSX-elementen en een regel die vereist dat je import {type SomeInterface} from 'somewhere' gebruikt in plaats van import {SomeInterface} from 'somewhere' als SomeInterface enkel gebruikt wordt voor type annotaties.
// @ts-check
import eslint from '@eslint/js'
import tsEslint from 'typescript-eslint'
import reactPlugin from 'eslint-plugin-react'
import globals from 'globals'
export default tsEslint.config(
eslint.configs.recommended,
{
rules: {
'no-alert': ['error'],
'no-debugger': ['error'],
'no-console': ['error', {allow: ['warn', 'error']}],
},
},
tsEslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
ecmaVersion: 'latest',
projectService: true,
},
},
},
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
...reactPlugin.configs.flat.recommended,
// Required when using React 17+.
...reactPlugin.configs.flat['jsx-runtime'],
languageOptions: {
...reactPlugin.configs.flat.recommended.languageOptions,
globals: {
...globals.serviceworker,
...globals.browser,
},
},
rules: {
"jsx-quotes": ["error", "prefer-double"],
"react/jsx-curly-brace-presence": ["error", {
props: "never",
children: "never",
}],
"@typescript-eslint/consistent-type-imports": "error"
}
},
)Als laatste plugin voegen we eslint-plugin-react-hooks nog toe aan de configuratie.
Deze plugin, die onderhouden wordt door het React team bij Meta, geeft foutmeldingen als een hook (zie les 2) niet correct gebruikt wordt. We moeten deze plugin niet manueel installeren omdat deze al inbegrepen is in de vite + swc + react + ts template.
// @ts-check
import eslint from '@eslint/js'
import tsEslint from 'typescript-eslint'
import reactPlugin from 'eslint-plugin-react'
import reactPluginHooks from 'eslint-plugin-react-hooks'
import globals from 'globals'
export default tsEslint.config(
eslint.configs.recommended,
{
rules: {
'no-alert': ['error'],
'no-debugger': ['error'],
'no-console': ['error', {allow: ['warn', 'error']}],
},
},
tsEslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
ecmaVersion: 'latest',
projectService: true,
},
},
},
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
...reactPlugin.configs.flat.recommended,
// Required when using React 17+.
...reactPlugin.configs.flat['jsx-runtime'],
languageOptions: {
...reactPlugin.configs.flat.recommended.languageOptions,
globals: {
...globals.serviceworker,
...globals.browser,
},
},
rules: {
"jsx-quotes": ["error", "prefer-double"],
"react/jsx-curly-brace-presence": ["error", {
props: "never",
children: "never",
}],
"@typescript-eslint/consistent-type-imports": "error"
}
},
{
plugins: {
"react-hooks": reactPluginHooks,
},
rules: {
...reactPluginHooks.configs.recommended.rules,
},
},
)Vanaf les 3 maken we gebruik van Tailwind CSS en shadcn om de UI van onze applicatie te bouwen. Deze libraries maken gebruik van enkele configuratiebestanden die in plain JavaScript geschreven zijn, daarom kunnen deze niet toegevoegd worden aan tsconfig.ts en niet verwerkt worden door de TypeScript configuratie van ESLint. Ook de ESLint configuratie zelf voegen we toe aan de ignore array omwille van dezelfde redenen.
Het is mogelijk om in de ESLint configuratiefiles aparte secties voor TypeScript en JavaScript bestanden te maken, maar dan moeten we de configuratie die uit tsEslint.configs.recommendedTypeChecked komt samenvoegen met de configuratie voor de languageOptions. Aangezien de recommendedTypeChecked config overërft van 2 andere configs en naast linting regels ook configuratie bevat is dit een complexe opdracht die tot een veel langere eslint.config.mjs file zou leiden. Daarom kiezen we ervoor om de Tailwind en shadcn configuratiebestanden te negeren in de ESLint configuratie, zo krijgen we geen foutmeldingen voor deze bestanden, maar worden deze niet gelint.
// @ts-check
import eslint from '@eslint/js'
import tsEslint from 'typescript-eslint'
import reactPlugin from 'eslint-plugin-react'
import reactPluginHooks from 'eslint-plugin-react-hooks'
import globals from 'globals'
export default tsEslint.config(
eslint.configs.recommended,
{
rules: {
'no-alert': ['error'],
'no-debugger': ['error'],
'no-console': ['error', {allow: ['warn', 'error']}],
},
},
tsEslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
ecmaVersion: 'latest',
projectService: true,
},
},
},
{
files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'],
...reactPlugin.configs.flat.recommended,
// Required when using React 17+.
...reactPlugin.configs.flat['jsx-runtime'],
languageOptions: {
...reactPlugin.configs.flat.recommended.languageOptions,
globals: {
...globals.serviceworker,
...globals.browser,
},
},
rules: {
"jsx-quotes": ["error", "prefer-double"],
"react/jsx-curly-brace-presence": ["error", {
props: "never",
children: "never",
}],
"@typescript-eslint/consistent-type-imports": "error"
}
},
{
plugins: {
"react-hooks": reactPluginHooks,
},
rules: {
...reactPluginHooks.configs.recommended.rules,
},
},
{
ignores: [
"tailwind.config.js",
"postcss.config.js",
"eslint.config.mjs",
],
}
)Gebruik van ESLint
Het is vanzelfsprekend dat ESLint foutmeldingen geeft in je IDE (als alles correct geconfigureerd is zoals beschreven is de development environment sectie). Het is echter ook interessant om het volledige project te controleren op fouten en deze eventueel op te lossen. Hiervoor voegen we twee script toe aan het package.json bestand. Het eerste commando lint geeft enkel weer of er fouten zijn, het tweede commando lint-fix probeert de fouten automatisch op te lossen.
{
"name": "frontend_lecture1_example",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint ./src",
"lint-fix": "eslint ./src --fix",
"preview": "vite preview"
},
"dependencies": {
...
},
"devDependencies": {
...
}
}Deze nieuwe script kunnen uitgevoerd worden met volgende commando's:
Prettier
De installatie van Prettier is veel eenvoudiger dan die van ESLint. We beginnen met een installatie commando.
Vervolgens moeten we het configuratiebestand .prettierrc aanmaken en opvullen me de stijlregels die we willen gebruiken. Hieronder de regels die in deze cursussen gehandhaafd worden.
{
"arrowParens": "avoid",
"bracketSameLine": true,
"bracketSpacing": false,
"semi": false,
"singleQuote": true,
"jsxSingleQuote": false,
"quoteProps": "as-needed",
"trailingComma": "all",
"singleAttributePerLine": false,
"htmlWhitespaceSensitivity": "css",
"proseWrap": "preserve",
"insertPragma": false,
"printWidth": 120,
"requirePragma": false,
"tabWidth": 2,
"useTabs": false,
"embeddedLanguageFormatting": "auto",
"endOfLine": "auto"
}Tenslotte voegen we opnieuw een commando toe aan het package.json waarmee alle bestanden in de src folder geformatteerd kunnen worden.
{
"name": "frontend_lecture1_example",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint ./src",
"lint-fix": "eslint ./src --fix",
"format": "prettier --write ./src",
"preview": "vite preview"
},
"dependencies": {
...
},
"devDependencies": {
...
}
}Dit nieuwe commando kan uitgevoerd worden met onderstaand shell commando.