Preact project setup with formatting and linting
This article describes the basic project setup of the Gachou frontend in more detail.
This article describes the basic project setup of the Gachou frontend in more detail. Specifically, I will write about:
- Preact and TypeScript
- eslint and prettier
- lint-staged and husky
- GitLab CI/CD pipelines
Why TypeScript?
In the past, I have done frontend projects in JavaScript and in TypeScript, and I don’t want to miss the advantages of TypeScript anymore. It gives you a lot of IDE code-completion, verified documentation and static checks that save you a lot of time. In my view, this outweighs the disadvantage of having to write (sometimes complicated) types.
Why Preact?
I have chosen Pre act for a couple of reasons:
- I wanted to use something familiar, and I have used React and Vue.js a lot in the past years.
- In my experience, React works better with TypeScript than Vue.js, mostly
because
tsx
is supported by TypeScript out of the box, - I wanted to try something new, so I chose “Preact” instead of React. Preact aims to be a “Fast 3kB alternative to React”.
- It is not completely compatible, and the community is not as big as the React community, but my impression is that it has a solid set of tools, like router, pre-rendering, etc.
The first step to creating the gachou-web-ui
project was running preact-cli
npx preact-cli create typescript gachou-web-ui
Configuring eslint and Prettier
If you are developing serious code you should definitely use eslint. It helps you identify bugs, enforce best-practices, and format your code. If you haven’t heard of eslint before, watch Feross Aboukhadijeh’s talk about this topic or have a look at https://eslint.org.
You should at least configure the recommended set of
rules, but I also like to add other rules like
eqeqeq to prevent harmful use of ==
for comparing values. Also, you do not have to specify all rules from the
beginning of the project. You can add new rules to the configuration when the
need arises.
Even though eslint can also format your code, I think Prettier handles this purpose better for the following reasons:
- I want bugs highlighted in red in my IDE, but formatting should just happen without me noticing. That’s why I don’t want code-formatting rules in eslint.
- Prettier formats much more rigorously than eslint. You can add spaces and new-lines all over a file. When you run Prettier, you can be (pretty) sure that everything is back as it was before. This comes very handy, if you want to keep you git-history free of code-format changes.
If you want to use both tools, you have to disable eslint-rules for layout and formatting, because they might format the code differently than Prettier does. Luckily, there is eslint-config-prettier which disables those rules.
There is also an eslint-plugin-prettier which is used by default, in some framework, but I do not like to use.
It runs Prettier as an eslint-rule. With that plugin, my IDE highlights wrongly formatted code, which is very distracting.
.eslintrc
Preact-CLI adds eslint by default, but only with a very basic configuration in
package.json
. This is the configuration that I use, not in package.json
, but
in a dedicated config-file .eslintrc
:
const baseConfig = {
extends: ["prettier", "eslint:recommended"],
ignorePatterns: ["build/"],
parserOptions: {
sourceType: "module",
ecmaVersion: 2021,
},
rules: {
eqeqeq: ["error", "always", { null: "ignore" }],
},
};
const typescriptFiles = {
files: "**/*.+(ts|tsx)",
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json",
},
plugins: ["@typescript-eslint/eslint-plugin"],
extends: [
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
],
};
const configFilesBasedOnNodeJs = {
files: [
"./*.config.js",
"./.eslintrc.js",
"./.eslintrc.js",
"./.storybook/main.js",
],
parserOptions: {
sourceType: "script",
ecmaVersion: 2021,
},
env: {
node: true,
},
};
module.exports = {
...baseConfig,
overrides: [typescriptFiles, configFilesBasedOnNodeJs],
};
.prettierignore + .eslintignore
In gachou-web-ui
I just ignore the same files to Prettier and eslint,even
though there are some lines that are not required for eslint (like log-files).
It is easier to maintain two files with exactly the same contents.
node_modules
/build
/*.log
/.idea
/.yarn
/junit.xml
/coverage/
yarn.lock
yarn.error.log
!/.storybook
When to run eslint and prettier?
Firstly, use an IDE integration to use Prettier as formatter and eslint for inspections. There are plugins for most IDEs.
To make it easier for developers, you should add scripts to the package.json
{
"scripts": {
"lint": "eslint --cache '**/*.{js,jsx,ts,tsx}'",
"format": "prettier -w .",
"test:format": "prettier --check ."
}
}
To make sure that the main
-branch of your repo only contains correct and
well-formatted code, you should run the test:format
-script and lint
-script
in your CI-pipeline before merging. For gachou-web-ui
I use GitLab CI/CD and
Yarn 3 with the following .gitlab-ci.yml
:
test:static:
stage: test
image: node:16
cache:
paths:
- .yarn/cache
- .eslintcache
script:
- "corepack enable"
- "yarn config set enableGlobalCache false"
- "yarn"
- "yarn lint"
- "yarn test:format"
With this setup, you will probably see the CI-pipeline fail very often, because you forgot to run Prettier or eslint before pushing. To avoid this, you should also use lint-staged and husky to run both them before each commit, on the staged files. That way, you don’t have to think about formatting anymore. It will just happen. And if eslint finds any issues in your changed files, the commit will fail.
In the gachou-web-ui
I installed lint-staged like described in its
README-file.
npx mrm@2 lint-staged
The configuration for lint-staged is written to package.json
. I had to add
some more file-types to make sure all relevant files are checked and formatted.
{
"lint-staged": {
"*.{js,ts,jsx,tsx}": "eslint --cache --fix",
"*.{js,jsx,ts,tsx,css,md}": "prettier --write"
}
}
Conclusion
I hope this post has shown you the benefits of using eslint and Prettier along
with CI-pipelines and pre-commit hooks. I also hope that it helps you set up
your next web-frontend project. gachou-web-ui
will evolve further, but this
setup lays the groundwork for future changes.
There are still more aspects I would like to write about, and more posts may come. If you have any feedback, you can contact my via the public e-mail address in my GitHub Profile.