TL;DR
This issue aims to describe how if you setup docker on a fullstack project, you may loose some developer experience like in-editor linting / formating + git hooks and propose a solution.
Without docker
Here is an example of how you would make an advanced setup of eslint/prettier (with husky for precommit hooks) on a regular frontend project without docker topheman/my-react-app-starter@9c0fa1b :
The husky/precommit hooks part will be addressed on an other issue.
With docker
First install prettier, eslint and a few eslint plugins because we want some advanced rules:
docker-compose run --rm front npm install --save-dev --save-exact prettier
docker-compose run --rm front npm install --save-dev cross-env eslint-config-airbnb eslint-config-prettier eslint-plugin-cypress eslint-plugin-prettier
Note: We need to docker-compose run --rm front
to run the npm install
command inside the docker container, which is a Linux environment, because we are making the call from our host machine which could be a MacOS or a Windows (which means that some native node_modules
might differ and will need to be compiled on the right platform to run inside the docker container AND to save the proper versions on the package-lock.json
).
Then we'll have to create a few files:
front/.eslintignore
:
/build/**
/coverage/**
/docs/**
/tmp/**
/src/libs/**
front/.eslintrc
:
{
"extends": ["react-app", "airbnb", "prettier"],
"plugins": ["prettier", "cypress"],
"rules": {
"prettier/prettier": "error",
"no-console": "off",
"react/jsx-filename-extension": "off",
"react/forbid-prop-types": [2, { "forbid": ["any"] }],
"react/no-did-mount-set-state": "off",
"import/prefer-default-export": "off",
"prefer-template": "off",
"no-underscore-dangle": ["error", { "allowAfterThis": true }],
"global-require": "off",
"import/no-extraneous-dependencies": [
"error",
{
"devDependencies": true,
"optionalDependencies": false,
"peerDependencies": false
}
]
},
"globals": {
"cy": true
},
"env": {
"mocha": true,
"cypress/globals": true
}
}
front/.prettierignore
:
.git
package-lock.json
package.json
.eslintignore
.gitignore
.prettierignore
.gitignore
*.fixtures.json
src/libs/**
front/.prettierrc
:
Add the following scripts to the front/package.json
:
"lint": "npx eslint .",
"pretty": "npx prettier --write '**/*.{js,jsx,json,css,scss}'",
That way, we will be able to run eslint and prettier from inside the docker container like this:
docker-compose run --rm front npm run lint
docker-compose run --rm front npm run pretty
For example, the lint
task will be run from inside the docker container (NOT from the host):
- on CircleCI
- on precommit hooks
Developer Experience
But this is not enough.
- I want to have my lint errors highlighted in my IDE/editor
- I want prettier to format my code when I save a file
- I don't want to use any global modules (can't make any assumption about the computer of the developer, only that he/she may have docker, npm and node)
The things described above:
- need to happen on the host machine - NOT on the docker container
- for the moment, no
node_modules
are installed on the host, they are installed on the container (see docker-compose.override.yml where the front-deps
modules is declared)
- they are tied with IDE/editor implementation specific plugin. For example, the VS Code ESLint extension will use the version of
eslint
of your working directory (and needed eslint plugins), same for prettier
Solution
This means that we also need to install the node_modules
on the host and not alter package-lock.json
file while installing.
- How to run
npm install
based on package-lock.json
, but ensure that it won't be updated in any way ?
- On the other hand, we can't fully base the
npm install
on package-lock.json
, because host platform and container platform may differ (if your on a Mac for example, you will have to install some optional modules like fsevents
)
Further notes about Cypress and Husky
This is the same kind of problem for cypress and husky:
- cypress:
- needs to be ran inside the container in command line mode (as it will be ran on CI)
- should also be ran on the host (to access the GUI to debug tests)
- husky (not exaclty the same):
- needs to be ran from the host (when a git commit is made on the host)
- also, should be installed at the very root of the project, to install commit hooks inside
.git
at the root