yarn create next-app -e <endereço do repo do boilerplate>
informar o nome do seu projeto quando solicitado no terminal
renomear o projeto no package.json
yarn create next-app
nome do projeto: client
// startar servidor em modo desenvolvimento
yarn dev
// build de produção
yarn build
// starta o servidor em modo produção com o build feito
yarn start
add o arquivo tsconfig.json na pasta raíz client.
instalar dependencias:
yarn add --dev typescript @types/react @types/node
startar o servidor novamente para que o next atualize o arquivo tsconfig.json:
yarn dev
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true, // modificar para true
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve"
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx"
],
"exclude": [
"node_modules"
]
}
criar pasta src
mover a pasta pages e a pasta styles para dentro da pasta src
renomear o arquivo index.js para index.tsx
criar arquivo .editorconfig na pasta raíz (client) e add as rules:
# editorconfig.org
root = true
[*]
indent_style = spaces
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
npx eslint --init
opções:
✔ How would you like to use ESLint? · To check syntax and find problems ✔ What type of modules does your project use? · JavaScript modules (import/export) ✔ Which framework does your project use? · react ✔ Does your project use TypeScript? · Yes ✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JSON ✔ Would you like to install them now with npm? · No / Yes
se optar por instalar as dependências manualmente:
yarn add --dev eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest eslint@latest
add plugin para react hooks
yarn add eslint-plugin-react-hooks --dev
add config no arquivo eslintrc.json:
{
// ...
"settings": {
"react": {
"version": "detect"
}
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
],
"plugins": [
// ...
"react-hooks"
],
"rules": {
// ...
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react/prop-types": "off", // para evitar conflitos com o typescript
"explicit-module-boundary-types": "off", // pq já estamos utilizando o ts
"react/react-in-jsx-scope": "off" // pq estamos trabalhando com o next, não precisamos importar
}
}
instalar o plugin no vscode (para que os erros sejam apontados automaticamente no ediitor)
https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint, ou rodar no terminal
eslint src --fix
src: nome da pasta que quer verificar
—fix: opcional, caso queira corrigir alguns problemas automaticamente
caso queria, pode cadastrar o comando no package.json.
https://prettier.io/docs/en/configuration.html
yarn add --dev prettier eslint-config-prettier eslint-plugin-prettier
criar arquivo .prettierrc e add suas config, por exemplo:
{
"trailingComma": "none",
"semi": false,
"singleQuote": true
}
no arquivo .eslintrc add config do prettier:
{
// ...
"extends": [
"plugin:prettier/recommended",
],
// ...
"rules": {
"@typescript-eslint/explicit-module-boundary-types": "off",
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
}
}
você também pode criar um arquivo de config do VSCode do projeto:
.vscode/settings.json
{
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
*formatOnSave deve ficar como false
yarn add --dev husky lint-staged
package.json:
{
"scripts": {
// ...
"lint": "eslint src --max-warnings=0"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*": ["yarn lint --fix"]
},
}
yarn add --dev jest @babel/preset-typescript @types/jest
yarn add --dev babel-jest @babel/core @babel/preset-env
add jest no arquivo .eslintrc
{
"env": {
// ...
"jest": true,
"node": true
},
}
criar arquivo jest.config.js:
module.exports = {
testEnvironment: 'jsdom',
testPathIgnorePatterns: ['/node_modules/', '/.next/'],
collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts(x)'],
setupFilesAfterEnv: ['<rootDir>/.jest/setup.ts']
}
- testEnvironment: front jsdom, simula browser
- collectCoverageFrom: arquivos dentro da pasta src que tenham extensão .ts ou .tsx
criar pasta e arquivo .jest/setup.ts
// configurar depois
criar arquivo .babelrc
{
"presets": ["next/babel", "@babel/preset-typescript"]
}"test": "jest",
"test:watch": "yarn test --watch",
package.json:
{
"scripts": {
"test": "jest",
"test:watch": "yarn test --watch",
},
// ...
}
yarn add --dev @testing-library/react @testing-library/jest-dom
add import no arquivo .jest/setup.ts
import '@testing-library/jest-dom'
package.json
{
// ...
"lint-staged": {
"src/**/*": [
"yarn test --findRelatedTests --bail"
]
},
// ...
}
*—bail: para o teste quando falhar/ --findRelatedTests só quebrar quando algum teste quebrar
yarn add styled-components
yarn add --dev @types/styled-components babel-plugin-styled-components
add plugins config ao arquivo .babelrc
{
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true
}
]
],
"presets": ["next/babel", "@babel/preset-typescript"]
}
por estarmos trabalhando com next, temos que configurar e sobreescrever o arquivo Documents original, para isso criamos um arquivo _document.tsx dentro da pasta pages:
import Document, {
Html,
Head,
Main,
NextScript,
DocumentContext
} from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />)
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
}
} finally {
sheet.seal()
}
}
render() {
return (
<Html lang="pt-BR">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
yarn add --dev jest-styled-components
add import no arquivo .jest/setup.ts
**import 'jest-styled-components';**
tsconfig.json
{
"compilerOptions": {
"baseUrl": "src"
// ...
}
}
arquivo principal: src/pages/_app.tsx
import { AppProps } from 'next/app';
import Head from 'next/head';
import GlobalStyles from 'styles/global';
function App({ Component, pageProps }: AppProps) {
return (
<>
<Head>
<title>React Avançado - Boilerplate</title>
<link rel="shortcut icon" href="/img/icon-512.png" />
<link rel="apple-touch-icon" href="/img/icon-512.png" />
<meta
name="description"
content="A simple project starter to work with TypeScript, React, NextJS and Styled Components"
/>
</Head>
<GlobalStyles />
<Component {...pageProps} />
</>
);
}
export default App;
stilo principal: src/styles/global.ts
import { createGlobalStyle } from 'styled-components';
const GlobalStyles = createGlobalStyle`
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
html, body, #__next {
height: 100%;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif
}
`;
export default GlobalStyles;
npx -p @storybook/cli sb init --type react
yarn add --dev @storybook/addon-knobs
yarn add @types/node
para rodar:
yarn storybook
*ver config:
- https://github.com/layshidani/react-avancado-boilerplate/commit/35c03ea0ea80e28df5c6c50f912dbd1754715eaf
- https://github.com/layshidani/react-avancado-boilerplate/commit/2ac64b32a60b999f4136d343e795b8b63e24d83f
yarn add next-pwa
config:
rodar pela 1ª vez:
NODE_ENV=production yarn build
depois, rodar o projeto yarn run start
no chrome dev tools > lighthouse
yarn add -D plop
ver config: https://github.com/layshidani/react-avancado-boilerplate/commit/364088d4923028bb94006058ad64bf7b649855de
para usar:
yarn generator <nome-do-componente>