JavaScript

Knowledge Base

JavaScript > Tools

Prettier

Prettier ist ein Code-Formatting-Tool mit einem vergleichsweise starren Vorgaben und wenigen Einstellungen (siehe unten), wie Quellcode formattiert werden soll und sieht sich als Lösung für die vgl. endlosen Debatten in Teams bzgl. wie etwas formattiert werden muss:

Letztendlich hat jeder Entwickler für sich bestimmte Präferenzen und tatsächlich gibt es viele Überschneidungen (best practises) und gleichzeitig wieder extreme Abweichungen, die zu Unmut im Team führen. Die Zeit, die dafür verwendet wird, ist in der Regel verlorene Zeit und zumeist ist am Ende keiner richtig glücklich mit der Kompromiss-Lösung.

Prettier hat diese Entscheidungen (fast) alle abgenommen und - in der Tat - löst es damit das oben beschriebene Problem (eigene Erfahrung):

Sowohl bei meinen eigenen Projekten (bei denen nur ich verantwortlich für den Quellcode bin) als auch bei externen Projekten habe ich sehr viel Zeit mit Überlegung für die "beste" Variante des Quellcodes verbracht (und verloren) und der Quellcode wurde dadurch nicht besser - sondern maximal nur "vereinheitlicht" - aber letztendlich ist es aus meiner Sicht egal, wie der Quellcode aussieht - sofern er einheitlich irgendeinem Standard folgt.

Mittlerweile verwende ich 0% meiner Zeit in die Formatierung - weil ich bei allen Projekten Prettier verwende. Mit jedem Speichern wird die Formatierung angewendet und damit sehen alle Komponenten automatisch identisch aus. Der Vorteil ergibt sich auch, dass ich während der Programmierung keine Zeit "verschwende", einzelne Zeilen oder ähnliches zu formattieren (Speichern reicht).

Umgekehrt sehe ich mich auch weiterhin mühsam manuell formatieren, wenn Prettier nicht zur Verfügung steht (z. B. (Einrücken von Parametern beim Insert oder Einrücken von Joins bei Stored Procedures für den MS SQL Server ...).

---

Prettier ist ein Code-Formatierer und deckt nicht die komplette Funktionalität von ESLint ab. Deshalb verwende ich ESLint mit Prettier und überschreibe nur die Code Formatierungsregeln von ESLint mit den Vorgaben von Prettier.

Leider ist hier die Dokumentation von Prettier (https://prettier.io/docs/en/integrating-with-linters.html) vollkommen verwirrend - tatsächlich ist es sehr leicht und man muss nur folgendes tun:

1. Installation:

npm i -D prettier eslint-config-prettier eslint-plugin-prettier

2. eslintrc.js erweitern:

{
  "extends": ["plugin:prettier/recommended"]
}

 

<= dies tut folgendes (leider findet man diese Antwort aber hier: https://github.com/prettier/eslint-plugin-prettier#recommended-configuration und nicht wirklich klar bei Prettier selbst ...):

  • Enables eslint-plugin-prettier.
  • Sets the prettier/prettier rule to "error".
  • Extends the eslint-config-prettier configuration.

---

eslintrc.js sieht dann z. B. so aus:

module.exports = {
    // Defines globals which are used within the environment
    env: {
        browser: true,
        es6: true,
        node: true, // Allow node globals (e. g. in dev packaging files)
        jest: true, // Allow jest globals (in test files)
    },
 
    // Defines preset rules (which can be overwritten or extended in the rules section)
    extends: [
        "eslint:recommended",
        "plugin:react/recommended",
 
        // Overwrite pre-defined eslint code formatting rules with prettier rules (+ activates prettier-plugin / so no need to add it to the plugin section)
        "plugin:prettier/recommended",
    ],
 
    // Adds additional set of rules
    plugins: ["react", "react-hooks"],
 
    // Uses the parser which understands the same as the babel transpiler
    parser: "babel-eslint",
 
    parserOptions: {
        // ESLint expects valid <= JS 2018 code (not sure if this has an effect with babel-eslint parser)
        ecmaVersion: 2018,
 
        // Javascript code is separated into ECMAScript modules
        sourceType: "module",
 
        // ESLint expects additional features - here JSX code
        ecmaFeatures: {
            jsx: true,
        },
    },
 
    // No additional globals (exept those defined via env section)
    globals: {},
 
    // Additional settings for react plugin
    settings: {
        react: {
            //Automatically detect react version
            version: "detect",
        },
    },
 
    // Additional rules which will overwrite the preset rules of "extends" section
    rules: {
        // require destructuring from arrays and/or objects
        "prefer-destructuring": [
            2,
            {
                VariableDeclarator: {
                    array: true,    // default: true
                    object: true, // default: true
                },
                AssignmentExpression: {
                    array: false, // default: true
                    object: false, // default: true
                },
            },
        ],
        // warning for use of console
        "no-console": "warn",
 
        // error in case of == and != instead of === and !==
        eqeqeq: "error",
 
        // Curly for any block (even for single lines)
        curly: "error",
 
        // Error in case of hook rules not fulfilled
        "react-hooks/rules-of-hooks": "error",
        "react-hooks/exhaustive-deps": "warn",
 
        // Enforce curly brackets for props -> propname={"Hello"} instead of propname="Hello"
        "react/jsx-curly-brace-presence": ["error", { props: "always", children: "ignore" }],
    },
};