-
Execute following commands
npm install --save-dev eslint-config-prettier eslint-plugin-prettier eslint-plugin-md prettier
-
Add following scripts to your
package.json
"lint:js": "eslint src/**/*.js", "lint": "eslint . --cache --max-warnings=0", "lint:fix": "eslint --fix .",
-
Add
.eslintrc
{ "env": { "node": true, "es6": true }, "parserOptions": { "ecmaVersion": 2018 }, "extends": [ "eslint:recommended", "plugin:prettier/recommended", "plugin:md/prettier" ], "plugins": ["prettier"], "rules": { "prettier/prettier": "error" } }
-
Add
.eslintignore
dist/ node_modules/
-
Add
.prettierrc
{ "printWidth": 80, "useTabs": false, "tabWidth": 2, "singleQuote": true, "trailingComma": "es5", "semi": true, "bracketSpacing": true, "bracketSameLine": false, "arrowParens": "always", "proseWrap": "preserve", "endOfLine": "auto" }
-
Validate that Linting is working:
npm run lint
-
Install
husky
:npx husky -init && npm install
-
Change
.husky/pre-commit
to:#!/bin/sh . "$(dirname "$0")/_/husky.sh" npm run lint:fix
-
rm .husky/_/.gitignore
-
To omit
devDependencies
from being installed use:npm install --production
-
How to update dependencies
npm install npm update # remove the packages specified as devDependencies from the `node_modules` folder npm prune --production # commit the update git add . && git commit -m "Update dependencies" # add devDependencies back again npm install git status # if new node_modules/foo folders show up, add them to .gitignore file
-
-
Save HansKre/0dc7419dd6be7a00ef8f2826ee3c550d to your computer and use it in GitHub Desktop.
Note: This plugin does not provide any config-options.
https://www.npmjs.com/package/prettier-plugin-organize-imports
yarn add -W root -D prettier-plugin-organize-imports
yarn prettier:format
With options how imports should be sorted
https://www.npmjs.com/package/@trivago/prettier-plugin-sort-imports
https://www.typescriptlang.org/tsconfig#Type_Checking_6248
The strict flag enables a wide range of type checking behavior that results in stronger guarantees of program correctness. Turning this on is equivalent to enabling all of the strict mode family options, which are outlined below. You can then turn off individual strict mode family checks as needed.
// tsconfig.compilerOptions
"noUnusedParameters": true,
"noUnusedLocals": true,
"allowUnreachableCode": false,
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"strict": true,
To enable TypeScript-rules, typed-linting must be enabled in parserOptions
first.
See this for the strict rules.
If your project enables typed linting, we suggest enabling the recommended-type-checked
Ï and stylistic-type-checked
configurations to start.
If a majority of developers working on your project are comfortable with TypeScript and typescript-eslint, consider replacing recommended-type-checked
with strict-type-checked
.
- strict-type-checked Contains all of recommended, recommended-type-checked, and strict, along with additional strict rules that require type information. Rules newly added in this configuration are similarly useful (and opinionated) to those in strict.
//.eslintrc.cjs
/* eslint-env node */
module.exports = {
extends: [
'eslint:recommended',
// 'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-type-checked',
// 'plugin:@typescript-eslint/strict-type-checked',
// 'plugin:@typescript-eslint/stylistic',
'plugin:@typescript-eslint/stylistic-type-checked',
// further rules ...
'plugin:react/recommended',
'plugin:prettier/recommended',
'plugin:storybook/recommended',
],
plugins: ['@typescript-eslint'],
parser: '@typescript-eslint/parser',
parserOptions: {
// https://stackoverflow.com/questions/58510287/parseroptions-project-has-been-set-for-typescript-eslint-parser
// to always use tsconfig.jsons nearest to source files
project: true,
tsconfigRootDir: __dirname, // "."
},
root: true,
};
npm i -D lint-staged
"lint-staged": {
"*.{scss,html,json,md}": "prettier --write --config ./.prettierrc",
"*.scss": "stylelint --fix",
"*.{js,tsx,ts}": "eslint --fix --no-ignore --max-warnings=0",
// do not use the below!! because it checks the staged
// files, but not whether changed file breaks another file
"**/*.ts": "tsc-files --noEmit"
},
// lint-staged.config.js
const { ESLint } = require('eslint');
const removeIgnoredFiles = async (files) => {
const eslint = new ESLint();
// ignore files which are in .eslintignore
const ignoredFiles = await Promise.all(
files.map((file) => eslint.isPathIgnored(file))
);
const filteredFiles = files.filter((_, i) => !ignoredFiles[i]);
return filteredFiles.join(' ');
};
module.exports = {
'*.{js,ts, tsx}': async (files) => {
const filesToLint = await removeIgnoredFiles(files);
return [`eslint --max-warnings=0 ${filesToLint}`];
},
'*.{css,html,json,md}': 'prettier --write --config ./.prettierrc.js',
};
// .eslintignore
node_modules
**/*.js
generated
npx --no-install lint-staged
module.exports = {
semi: true,
tabWidth: 2,
printWidth: 100,
singleQuote: true,
trailingComma: 'es5',
bracketSameLine: false,
arrowParens: 'always',
importOrderSeparation: true,
plugins: [require.resolve('@trivago/prettier-plugin-sort-imports')],
importOrder: [
'^@dlb-library/(.*)$',
'^src/app/apollo/(.*)$',
'^src/app/components/(.*)$',
'^src/app/constants/(.*)$',
'^src/app/generated/(.*)$',
'^src/app/pages/(.*)$',
'^src/app/types',
'^src/app/utils',
'^[./]',
],
};
"rules": {
"react/react-in-jsx-scope": "off",
"comma-dangle": "off",
"@typescript-eslint/comma-dangle": "off"
},
import alias from '@rollup/plugin-alias'; | |
import url from '@rollup/plugin-url'; | |
import { exec } from 'child_process'; | |
import { glob } from 'glob'; | |
import { fileURLToPath } from 'node:url'; | |
import { extname, relative, resolve } from 'path'; | |
import { defineConfig, normalizePath } from 'vite'; | |
import dts from 'vite-plugin-dts'; | |
import { libInjectCss } from 'vite-plugin-lib-inject-css'; | |
import { viteStaticCopy } from 'vite-plugin-static-copy'; | |
/** | |
* The @rollup/plugin-alias plugin is used to resolve the aliases in js-files only. To achieve the same for .d.ts-files, we need to run the tsc-alias command after the build is done: | |
* https://github.com/ezolenko/rollup-plugin-typescript2/issues/201 | |
*/ | |
const tscAlias = () => { | |
return { | |
name: 'tsAlias', | |
writeBundle: () => { | |
void new Promise((resolve, reject) => { | |
exec('tsc-alias', function callback(error, stdout, stderr) { | |
if (stderr || error) { | |
reject(stderr || error); | |
} else { | |
resolve(stdout); | |
} | |
}); | |
}); | |
}, | |
}; | |
}; | |
const projectRootDir = resolve(__dirname); | |
export default defineConfig({ | |
plugins: [ | |
url(), | |
dts({ | |
include: ['src'], | |
}), | |
libInjectCss(), | |
alias({ | |
entries: [ | |
{ | |
find: 'assets', | |
replacement: resolve(projectRootDir, 'src/assets'), | |
}, | |
{ | |
find: 'components', | |
replacement: resolve(projectRootDir, 'src/components'), | |
}, | |
{ | |
find: 'containers', | |
replacement: resolve(projectRootDir, 'src/containers'), | |
}, | |
{ | |
find: 'store', | |
replacement: resolve(projectRootDir, 'src/store'), | |
}, | |
{ | |
find: 'scss', | |
replacement: resolve(projectRootDir, 'src/scss'), | |
}, | |
{ | |
find: 'typings', | |
replacement: resolve(projectRootDir, 'src/typings'), | |
}, | |
{ | |
find: 'utils', | |
replacement: resolve(projectRootDir, 'src/utils'), | |
}, | |
], | |
}), | |
viteStaticCopy({ | |
targets: [ | |
{ | |
src: normalizePath(resolve(projectRootDir, 'src/scss', '_vars.scss')), | |
dest: './scss', | |
}, | |
{ | |
src: normalizePath( | |
resolve(projectRootDir, 'src/config', 'devProxy.cjs') | |
), | |
dest: './config', | |
}, | |
{ | |
src: normalizePath( | |
resolve(projectRootDir, 'src/config', 'webpack.config.cjs') | |
), | |
dest: './config', | |
}, | |
], | |
}), | |
tscAlias(), | |
], | |
build: { | |
lib: { | |
entry: resolve(__dirname, 'index.ts'), | |
name: '@foo/shared-frontend', | |
formats: ['es'], | |
}, | |
rollupOptions: { | |
external: [ | |
'react/jsx-runtime', | |
'lodash', | |
'moment', | |
'react', | |
'react-dom', | |
'react-final-form', | |
'storeon', | |
'storeon/react', | |
], | |
input: Object.fromEntries( | |
glob.sync('src/**/*.{ts,tsx}').map((file) => [ | |
// The name of the entry point | |
// src/nested/foo.ts becomes nested/foo | |
relative('src', file.slice(0, file.length - extname(file).length)), | |
// The absolute path to the entry file | |
// src/nested/foo.ts becomes /project/src/nested/foo.ts | |
fileURLToPath(new URL(file, import.meta.url)), | |
]) | |
), | |
output: { | |
assetFileNames: 'styles/[name][extname]', | |
entryFileNames: '[name].js', | |
}, | |
}, | |
}, | |
}); |
module.exports = {
...
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
loader: "ts-loader",
options: {
// Ignore TypeScript errors when compiling
// this helps start a project even with errors
transpileOnly: true,
},
},
// let's webpack ignore certrain file-patterns
{
test: /\.map$/,
loader: "ignore-loader",
},
]
}
}