topheman / docker-experiments

Discover docker with a simple use case in development, production (local kubernetes) and CI
97 stars 11 forks source link

Setup eslint/prettier on docker + host #1

Open topheman opened 6 years ago

topheman commented 6 years ago

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 https://github.com/topheman/my-react-app-starter/commit/9c0fa1b881decde46c11957b1e5cab3aeccc7d1c :

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):

Developer Experience

But this is not enough.

The things described above:

Solution

This means that we also need to install the node_modules on the host and not alter package-lock.json file while installing.

Further notes about Cypress and Husky

This is the same kind of problem for cypress and husky:

topheman commented 6 years ago

A solution (from this twitter thread) might be to:

topheman commented 5 years ago

The following resource may be useful as an intermediary step : https://nickjanetakis.com/blog/docker-tip-75-how-to-avoid-node-modules-in-your-volume-mounts

pierreyves-lebrun commented 5 years ago

I stumbled upon the same problem, which ends up being quite frustrating as all the workarounds I’ve seen so far are somewhat hacky.

Edit: actually there is one elegant solution to it: https://code.visualstudio.com/docs/remote/containers

topheman commented 5 years ago

I've been told about this solution. You're right @pierreyves-lebrun , this might be the first one true elegant way to solve that problem in a long time. cc @warpdesign