mkdir new-project && yarn create next-app --typescript
touch tsconfig.json
yarn dev
The tsconfig.json file will be updated after in this document.
We'll add some scripts with tools we'll set up later :
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"test": "jest --watch",
"type-check": "tsc --pretty --noEmit",
"fresh-install": "rm -rf node_modules/ build/ && yarn",
"check-all": "yarn lint && yarn type-check && yarn test --watchAll=false"
},
yarn lint
for linting the projectyarn test
for Jest testyarn fresh-install
for remove temporary files and rebuild the projectyarn check-all
for runing lint, typescript check and tests sequentially
Add eslint and prettier plugins in VS Code.
Add a file .vscode/settings.json with the following :
{
"workbench.colorCustomizations": {
"statusBar.background": "#ff6d6d" // Change this color!
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.formatOnSave": false,
"files.exclude": {
"**/.history": true,
"**/.next": true,
"**/node_modules": true,
}
}
NB: we are planning to let ESLint to format everything. So, we can disable the formatOnSave from VS Code.
ESLint comes with Next.js. So we don't need to yarn install it.
Populate the .eslintrc.json with the following:
{
"extends": [
"eslint:recommended",
"next/core-web-vitals",
"plugin:prettier/recommended"
],
"rules": {
"prettier/prettier": [
"error",
{
"trailingComma": "all",
"semi": false,
"printWidth": 120
}
],
"no-console": "warn"
}
}
The default eslint config in Next (eslint-config-next
), comes with eslint-plugin-react, eslint-plugin-react-hooks, eslint-plugin-next already configured. So no need to configure react hooks or the like. It sets also parser, plugins and settings.
yarn add -D prettier eslint-plugin-prettier eslint-config-prettier
Note : eslint-config-prettier runs Prettier as an ESLint rule. eslint-config-prettier only disabled all ESLint formating rules to avoid conflicts with Prettier.
.eslintrc.js is now :
module.exports = {
extends: [
"eslint:recommended",
"next/core-web-vitals",
"plugin:prettier/recommended"
],
rules: {
"prettier/prettier": [
"error",
{
trailingComma: "all",
semi: false,
printWidth: 120,
},
],
"no-console": "error",
},
}
Note: as Prettier is run in conjonction with ESlint, I prefer to store Prettier configuration in the .eslintrc.js instead of another .prettierrc file.
Update tsconfig.json
:
{
"compilerOptions": {
// baseUrl make that all code is stored in src directory (with the exception of /public)
"baseUrl": "src",
// paths is useful if you want to use absolute imports
"paths": {
"@/*": [
"*"
],
},
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"incremental": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": [
"next-env.d.ts",
"src",
],
"exclude": [
"node_modules"
]
}
yarn add -D jest ts-jest @types/jest
jest.config.js
// eslint-disable-next-line @typescript-eslint/no-var-requires
const nextJest = require("next/jest")
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: "./",
})
// Add any custom config to be passed to Jest
const customJestConfig = {
// Add more setup options before each test is run
// setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ["node_modules", "<rootDir>/"],
testEnvironment: "jest-environment-jsdom",
moduleNameMapper: {
"^@/components/(.*)$": "<rootDir>/src/components/$1",
"^@/utils/(.*)$": "<rootDir>/src/utils/$1",
},
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
NB: add moduleNameMapper
for absolute imports.
Important: the parser is set to @typescript-eslint/parser to make ESLint able to understand TS files.
Some other eslint plugins are useful and will be condfigured in a second time :
- @typescript-eslint/eslint-plugin : add ESLint for ts files
- @typescript-eslint/parser : comes with the precedent one
- eslint-plugin-jest
- eslint-plugin-testing-library
- eslint-plugin-jest-dom
- @testing-library/jest-dom
- @testing-library/react
yarn add -D @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-plugin-jest @testing-library/jest-dom @testing-library/react eslint-plugin-testing-library eslint-plugin-jest-dom
The final .eslintrc.json :
{
// Parser to make ESLint able to parse TS files.
"parser": "@typescript-eslint/parser",
// Bunch of rules.
"plugins": ["@typescript-eslint", "jest", "jsx-a11y", "testing-library", "jest-dom"],
// Rules to be used.
"extends": [
"eslint:recommended",
"plugin:jsx-a11y/recommended",
"plugin:testing-library/react",
// Helper for testing-library.
"plugin:jest-dom/recommended",
"plugin:jest/recommended",
"plugin:@typescript-eslint/recommended",
// Need to be last or almost.
"next/core-web-vitals",
// Priority on prettier to be last and potentially override other rules.
"plugin:prettier/recommended"
],
// Customize rules.
"rules": {
"prettier/prettier": [
"error",
{
"trailingComma": "all",
"semi": false,
"printWidth": 120
}
],
"jsx-a11y/anchor-is-valid": "off",
"no-console": "warn"
}
}
If you want to publish the package :
- add a .npmignore file at the root project with empty content. This will be used to not take care of the .gitignore
- add a files property in package.json (like files: ["lib/**/*"]) to only use this files in the published npm
package.json
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib/**/*"
],
"scripts": {
"prepare": "yarn build",
"prepublishOnly": "yarn lint",
},