- NextJs v10.0.5
- react v17.0.1
- Typescript v4.1.3
- @emotion/react v11.1.4
- setup node env
nvm use || npm install
- remove unwanted files in
public/
,src/
- add
.env
and other .env files - preview dev progress on
http://localhost:3000/
npm run dev
- read Setup for notes
- install nvm in the os
-
nvm install node git init
- add
.gitignore
-
node -v > .nvmrc
-
npm init -y
-
npm i -S next react react-dom
- add a script to your package.json like this:
{ "scripts": { "dev": "next dev", "build": "next build", "start": "next start" } }
-
npm i -D typescript @types/react @types/node
- create
tsconfig.json
{ "compilerOptions": { "target": "esnext", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "allowSyntheticDefaultImports": true, "alwaysStrict": true, "skipLibCheck": true, "strict": false, "forceConsistentCasingInFileNames": true, "noEmit": true, "noFallthroughCasesInSwitch": true, "noUnusedLocals": true, "noUnusedParameters": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "baseUrl": "./src" }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules", "next.config.js"] }
- create
src/pages
folder (orpages
) - create
pages.tsx
undersrc/pages/
(i.e.src/pages/index.tsx
for/
route)
-
npm i -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react eslint-import-resolver-typescript npm i -D eslint-config-airbnb eslint-plugin-jsx-a11y eslint-plugin-import eslint-plugin-react-hooks npm i -D prettier eslint-config-prettier eslint-plugin-prettier
- create
.eslintrc.js
module.exports = { env: { browser: true, node: true, es2020: true, jest: true, }, parser: '@typescript-eslint/parser', // Specifies the ESLint parser parserOptions: { ecmaVersion: 2020, sourceType: 'module', ecmaFeatures: { jsx: true, }, }, plugins: ['@typescript-eslint', 'react', 'react-hooks', 'prettier'], extends: [ 'airbnb', 'plugin:@typescript-eslint/recommended', 'plugin:react/recommended', 'plugin:import/errors', 'plugin:import/warnings', 'plugin:import/typescript', 'prettier', 'prettier/@typescript-eslint', 'prettier/react', 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. ], rules: { '@typescript-eslint/no-unused-vars': [ 'error', { vars: 'all', args: 'after-used', ignoreRestSiblings: false, }, ], '@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/explicit-function-return-type': 0, '@typescript-eslint/no-namespace': 0, '@typescript-eslint/explicit-module-boundary-types': 0, 'import/extensions': [ 1, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }, ], 'import/no-extraneous-dependencies': [ 'error', { devDependencies: true, }, ], 'react/jsx-filename-extension': [ 1, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }, ], 'react/react-in-jsx-scope': 0, 'react/jsx-first-prop-new-line': 0, 'react/prop-types': 0, 'react/jsx-props-no-spreading': [2, { custom: 'ignore' }], 'jsx-a11y/anchor-is-valid': [ 'error', { components: ['Link'], specialLink: ['hrefLeft', 'hrefRight'], aspects: ['invalidHref', 'preferButton'], }, ], 'prettier/prettier': 2, 'react-hooks/rules-of-hooks': 2, 'react-hooks/exhaustive-deps': 2, 'no-bitwise': 2, }, settings: { 'import/resolver': { node: { extensions: ['.js', '.jsx', '.ts', '.tsx'], }, typescript: {}, }, react: { version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use }, }, };
- create
.prettierrc.js
module.exports = { semi: true, trailingComma: 'es5', singleQuote: true, printWidth: 80, tabWidth: 2, };
-
npm i -D jest babel-jest @types/jest @next/env
-
add scripts in
package.json
"scripts": { "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage" },
-
create
jest.config.js
module.exports = { moduleFileExtensions: ['ts', 'tsx', 'js'], testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|js?|tsx?|ts?)$', globals: { NODE_ENV: 'test', }, snapshotSerializers: ['enzyme-to-json/serializer'], transform: { '^.+\\.(j|t)sx?$': 'babel-jest', }, coveragePathIgnorePatterns: [ '/node_modules/', 'jest.setup.js', '<rootDir>/configs/', 'jest.config.js', '.json', '.snap', ], setupFiles: ['<rootDir>/jest/jest.setup.js'], coverageReporters: ['json', 'lcov', 'text', 'text-summary'], moduleNameMapper: { '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/__mocks__/mocks.js', '\\.(css|less|scss)$': '<rootDir>/__mocks__/mocks.js', }, moduleDirectories: ['node_modules', 'src'], };
-
create
babel.config.js
module.exports = { presets: ['next/babel'], };
-
create
jest/jest.setup.js
import { join } from 'path'; import { loadEnvConfig } from '@next/env'; // to load '.env' files in test loadEnvConfig(join(__dirname, '../'));
-
change
env
in.eslintrc.js
env: { browser: true, node: true, jest: true },
-
npm i -S @emotion/core npm i -D @emotion/babel-plugin @emotion/eslint-plugin @emotion/jest
-
change
babel.config.js
module.exports = { presets: [ [ 'next/babel', { 'preset-react': { runtime: 'automatic', importSource: '@emotion/react', }, }, ], ], plugins: ['@emotion/babel-plugin'], };
-
add rules and plugins to
.eslintrc.js
module.exports = { // ... rules: { // ... '@emotion/no-vanilla': 'error', '@emotion/import-from-emotion': 'error', '@emotion/styled-import': 'error', }, // ... plugins: [ '@emotion', // ... ], // ... };
-
add
jest/jest.setupAfterEnv.js
import { matchers } from '@emotion/jest'; expect.extend(matchers);
-
add serializers and setup files to
jest/jest.config.js
// ... snapshotSerializers: ['@emotion/jest/serializer'], // ... setupFilesAfterEnv: ['<rootDir>/jest.setupAfterEnv.js'], // ...
-
add to
tsconfig.json
{ "compilerOptions": { "jsxImportSource": "@emotion/react" } }
(deploy to /docs intead of using gh-pages branch; replace {folder} with the project name in github repo)
- add
.env.production
NEXT_PUBLIC_LINK_PREFIX=/{folder}
- create
LINK_PREFIX
innext.config.js
const LINK_PREFIX = process.env.NEXT_PUBLIC_LINK_PREFIX || ''; module.exports = () => ({ basePath: LINK_PREFIX, });
- change
scripts
inpackage.json
{ "scripts": { "export": "NODE_ENV=production npm run build && next export -o docs && touch docs/.nojekyll" } }
-
npm i -S react-redux @reduxjs/toolkit next-redux-wrapper npm i -D @types/react-redux @types/webpack-env
- create custom
rootReducer
,makeStore
,wrapper
similar to ones in filessrc/features/redux/reducers.tsx
andsrc/features/redux/store.tsx
and apply them insrc/pages/_app.tsx