├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .jest └── setup.ts ├── .prettierignore ├── .prettierrc ├── .storybook ├── main.js └── preview.js ├── .vscode └── settings.json ├── README.md ├── generators ├── plopfile.js └── templates │ ├── Component.tsx.hbs │ ├── stories.tsx.hbs │ ├── styles.ts.hbs │ └── test.tsx.hbs ├── jest.config.js ├── next-env.d.ts ├── next.config.js ├── package.json ├── public ├── img │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── hero-illustration.svg │ ├── icon-192.png │ ├── icon-512.png │ ├── logo-gh.svg │ └── logo.svg └── manifest.json ├── src ├── components │ └── Container.tsx ├── pages │ ├── _app.tsx │ ├── _document.tsx │ ├── after-fill.tsx │ ├── after-responsive.tsx │ ├── after.tsx │ ├── before.tsx │ ├── external.tsx │ ├── fixed.tsx │ ├── index.tsx │ ├── low-quality.tsx │ ├── priority.tsx │ ├── styled-image.tsx │ └── unsized.tsx └── styles │ └── global.ts ├── tsconfig.json └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel", "@babel/preset-typescript"], 3 | "plugins": [ 4 | [ 5 | "babel-plugin-styled-components", 6 | { 7 | "ssr": true, 8 | "displayName": true 9 | } 10 | ] 11 | ], 12 | "env": { 13 | "test": { 14 | "plugins": [ 15 | [ 16 | "babel-plugin-styled-components", 17 | { 18 | "ssr": false, 19 | "displayName": false 20 | } 21 | ] 22 | ] 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = spaces 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | !.storybook 2 | !.jest 3 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2020": true, 5 | "jest": true, 6 | "node": true 7 | }, 8 | "settings": { 9 | "react": { 10 | "version": "detect" 11 | } 12 | }, 13 | "extends": [ 14 | "eslint:recommended", 15 | "plugin:react/recommended", 16 | "plugin:@typescript-eslint/eslint-recommended", 17 | "plugin:@typescript-eslint/recommended", 18 | "plugin:prettier/recommended" 19 | ], 20 | "parser": "@typescript-eslint/parser", 21 | "parserOptions": { 22 | "ecmaFeatures": { 23 | "jsx": true 24 | }, 25 | "ecmaVersion": 11, 26 | "sourceType": "module" 27 | }, 28 | "plugins": ["react", "react-hooks", "@typescript-eslint"], 29 | "rules": { 30 | "react-hooks/rules-of-hooks": "error", 31 | "react-hooks/exhaustive-deps": "warn", 32 | "react/prop-types": "off", 33 | "react/react-in-jsx-scope": "off", 34 | "@typescript-eslint/explicit-module-boundary-types": "off" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: [pull_request] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout Repository 9 | uses: actions/checkout@v2 10 | 11 | - name: Setup Node 12 | uses: actions/setup-node@v1 13 | with: 14 | node-version: 14.x 15 | 16 | - name: Install dependencies 17 | run: yarn install 18 | 19 | - name: Linting 20 | run: yarn lint 21 | 22 | - name: Test 23 | run: yarn test 24 | 25 | - name: Build 26 | run: yarn build 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | 21 | # debug 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | # local env files 27 | .env.local 28 | .env.development.local 29 | .env.test.local 30 | .env.production.local 31 | 32 | # sw stuff 33 | public/sw.js 34 | public/workbox-*.js 35 | 36 | # storybook 37 | storybook-static 38 | -------------------------------------------------------------------------------- /.jest/setup.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom' 2 | import 'jest-styled-components' 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | !.storybook 2 | !.jest 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "semi": false, 4 | "singleQuote": true 5 | } 6 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../src/components/**/stories.tsx'], 3 | addons: ['@storybook/addon-essentials'], 4 | webpackFinal: (config) => { 5 | config.resolve.modules.push(`${process.cwd()}/src`) 6 | return config 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | import GlobalStyles from '../src/styles/global' 2 | 3 | export const decorators = [ 4 | (Story) => ( 5 | <> 6 | 7 | 8 | > 9 | ) 10 | ] 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.formatOnSave": false, 3 | "editor.codeActionsOnSave": { 4 | "source.fixAll.eslint": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |  3 | 4 | This is a [Next.js](https://nextjs.org/) boilerplate to be used in a course called [React Avançado](https://reactavancado.com.br/). 5 |  6 | ## What is inside? 7 | 8 | This project uses lot of stuff as: 9 | 10 | - [TypeScript](https://www.typescriptlang.org/) 11 | - [NextJS](https://nextjs.org/) 12 | - [Styled Components](https://styled-components.com/) 13 | - [Jest](https://jestjs.io/) 14 | - [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) 15 | - [Storybook](https://storybook.js.org/) 16 | - [Eslint](https://eslint.org/) 17 | - [Prettier](https://prettier.io/) 18 | - [Husky](https://github.com/typicode/husky) 19 | 20 | ## Getting Started 21 | 22 | First, run the development server: 23 | 24 | ```bash 25 | npm run dev 26 | # or 27 | yarn dev 28 | ``` 29 | 30 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 31 | 32 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. 33 | 34 | ## Commands 35 | 36 | - `dev`: runs your application on `localhost:3000` 37 | - `build`: creates the production build version 38 | - `start`: starts a simple server with the build production code 39 | - `lint`: runs the linter in all components and pages 40 | - `test`: runs jest to test all components and pages 41 | - `test:watch`: runs jest in watch mode 42 | - `storybook`: runs storybook on `localhost:6006` 43 | - `build-storybook`: create the build version of storybook 44 | 45 | ## Learn More 46 | 47 | To learn more about Next.js, take a look at the following resources: 48 | 49 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 50 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 51 | 52 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 53 | 54 | ## Deploy on Vercel 55 | 56 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 57 | 58 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 59 | -------------------------------------------------------------------------------- /generators/plopfile.js: -------------------------------------------------------------------------------- 1 | module.exports = (plop) => { 2 | plop.setGenerator('component', { 3 | description: 'Create a component', 4 | prompts: [ 5 | { 6 | type: 'input', 7 | name: 'name', 8 | message: 'What is your component name?' 9 | } 10 | ], 11 | actions: [ 12 | { 13 | type: 'add', 14 | path: '../src/components/{{pascalCase name}}/index.tsx', 15 | templateFile: 'templates/Component.tsx.hbs' 16 | }, 17 | { 18 | type: 'add', 19 | path: '../src/components/{{pascalCase name}}/styles.ts', 20 | templateFile: 'templates/styles.ts.hbs' 21 | }, 22 | { 23 | type: 'add', 24 | path: '../src/components/{{pascalCase name}}/stories.tsx', 25 | templateFile: 'templates/stories.tsx.hbs' 26 | }, 27 | { 28 | type: 'add', 29 | path: '../src/components/{{pascalCase name}}/test.tsx', 30 | templateFile: 'templates/test.tsx.hbs' 31 | } 32 | ] 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /generators/templates/Component.tsx.hbs: -------------------------------------------------------------------------------- 1 | import * as S from './styles' 2 | 3 | const {{pascalCase name}} = () => ( 4 | 5 | {{pascalCase name}} 6 | 7 | ) 8 | 9 | export default {{pascalCase name}} 10 | -------------------------------------------------------------------------------- /generators/templates/stories.tsx.hbs: -------------------------------------------------------------------------------- 1 | import { Story, Meta } from '@storybook/react/types-6-0' 2 | import {{pascalCase name}} from '.' 3 | 4 | export default { 5 | title: '{{pascalCase name}}', 6 | component: {{pascalCase name}} 7 | } as Meta 8 | 9 | export const Default: Story = () => <{{pascalCase name}} /> 10 | -------------------------------------------------------------------------------- /generators/templates/styles.ts.hbs: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const Wrapper = styled.main`` 4 | -------------------------------------------------------------------------------- /generators/templates/test.tsx.hbs: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react' 2 | 3 | import {{pascalCase name}} from '.' 4 | 5 | describe('<{{pascalCase name}} />', () => { 6 | it('should render the heading', () => { 7 | const { container } = render(<{{pascalCase name}} />) 8 | 9 | expect(screen.getByRole('heading', { name: /{{pascalCase name}}/i })).toBeInTheDocument() 10 | 11 | expect(container.firstChild).toMatchSnapshot() 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testEnvironment: 'jsdom', 3 | testPathIgnorePatterns: ['/node_modules/', '/.next/'], 4 | collectCoverage: true, 5 | collectCoverageFrom: ['src/**/*.ts(x)?', '!src/**/stories.tsx'], 6 | setupFilesAfterEnv: ['/.jest/setup.ts'], 7 | modulePaths: ['/src/'], 8 | moduleNameMapper: { 9 | '^styled-components': 10 | '/node_modules/styled-components/dist/styled-components.browser.cjs.js' 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | images: { 3 | deviceSizes: [320, 640, 768, 1024, 1600], 4 | domains: ['source.unsplash.com'] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-avancado-boilerplate", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "eslint src --max-warnings=0", 10 | "test": "jest", 11 | "test:watch": "yarn test --watch", 12 | "generate": "yarn plop --plopfile generators/plopfile.js", 13 | "storybook": "start-storybook -s ./public -p 6006", 14 | "build-storybook": "build-storybook -s ./public" 15 | }, 16 | "husky": { 17 | "hooks": { 18 | "pre-commit": "lint-staged" 19 | } 20 | }, 21 | "lint-staged": { 22 | "src/**/*": [ 23 | "yarn lint --fix", 24 | "yarn test --findRelatedTests --bail" 25 | ] 26 | }, 27 | "dependencies": { 28 | "next": "10.0.1", 29 | "next-pwa": "^3.1.5", 30 | "react": "17.0.1", 31 | "react-dom": "17.0.1", 32 | "styled-components": "5.2.0" 33 | }, 34 | "devDependencies": { 35 | "@babel/core": "^7.12.3", 36 | "@babel/preset-typescript": "^7.12.1", 37 | "@storybook/addon-essentials": "6.0.27", 38 | "@storybook/react": "6.0.27", 39 | "@testing-library/jest-dom": "^5.11.5", 40 | "@testing-library/react": "^11.1.0", 41 | "@types/jest": "^26.0.15", 42 | "@types/node": "^14.14.5", 43 | "@types/react": "^16.9.53", 44 | "@types/styled-components": "^5.1.4", 45 | "@typescript-eslint/eslint-plugin": "^4.6.0", 46 | "@typescript-eslint/parser": "^4.6.0", 47 | "babel-loader": "^8.1.0", 48 | "babel-plugin-styled-components": "^1.11.1", 49 | "eslint": "^7.12.1", 50 | "eslint-config-prettier": "^6.14.0", 51 | "eslint-plugin-prettier": "^3.1.4", 52 | "eslint-plugin-react": "^7.21.5", 53 | "eslint-plugin-react-hooks": "^4.2.0", 54 | "husky": "^4.3.0", 55 | "jest": "^26.6.1", 56 | "jest-styled-components": "^7.0.3", 57 | "lint-staged": "^10.5.0", 58 | "plop": "^2.7.4", 59 | "prettier": "^2.1.2", 60 | "typescript": "^4.0.5" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /public/img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/1.jpg -------------------------------------------------------------------------------- /public/img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/2.jpg -------------------------------------------------------------------------------- /public/img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/3.jpg -------------------------------------------------------------------------------- /public/img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/4.jpg -------------------------------------------------------------------------------- /public/img/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/5.jpg -------------------------------------------------------------------------------- /public/img/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/6.jpg -------------------------------------------------------------------------------- /public/img/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/7.jpg -------------------------------------------------------------------------------- /public/img/hero-illustration.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/img/icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/icon-192.png -------------------------------------------------------------------------------- /public/img/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/willianjusten/nextjs10-image/c5eb4ed74b59a9271c6d30ac158abf0f671efe0a/public/img/icon-512.png -------------------------------------------------------------------------------- /public/img/logo-gh.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "React Avançado - Boilerplate", 3 | "short_name": "React Avançado", 4 | "icons": [ 5 | { 6 | "src": "/img/icon-192.png", 7 | "type": "image/png", 8 | "sizes": "192x192" 9 | }, 10 | { 11 | "src": "/img/icon-512.png", 12 | "type": "image/png", 13 | "sizes": "512x512" 14 | } 15 | ], 16 | "background_color": "#06092B", 17 | "description": "Boilerplate utilizando Typescript, React, NextJS e Styled Components!", 18 | "display": "fullscreen", 19 | "start_url": "/", 20 | "theme_color": "#06092B" 21 | } 22 | -------------------------------------------------------------------------------- /src/components/Container.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const Container = styled.main` 4 | display: grid; 5 | grid-gap: 3rem; 6 | justify-content: center; 7 | grid-template-columns: 1fr; 8 | 9 | > div { 10 | margin: auto; 11 | } 12 | 13 | a { 14 | text-align: center; 15 | display: block; 16 | margin-top: 2rem; 17 | } 18 | 19 | img { 20 | max-width: 1600px; 21 | margin: 3rem auto; 22 | display: block; 23 | } 24 | ` 25 | -------------------------------------------------------------------------------- /src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import { AppProps } from 'next/app' 2 | import Head from 'next/head' 3 | 4 | import GlobalStyles from 'styles/global' 5 | 6 | function App({ Component, pageProps }: AppProps) { 7 | return ( 8 | <> 9 | 10 | NextJS 10 - Image Component 11 | 12 | 13 | 14 | 18 | 19 | 20 | 21 | > 22 | ) 23 | } 24 | 25 | export default App 26 | -------------------------------------------------------------------------------- /src/pages/_document.tsx: -------------------------------------------------------------------------------- 1 | import Document, { 2 | Html, 3 | Head, 4 | Main, 5 | NextScript, 6 | DocumentContext 7 | } from 'next/document' 8 | import { ServerStyleSheet } from 'styled-components' 9 | 10 | export default class MyDocument extends Document { 11 | static async getInitialProps(ctx: DocumentContext) { 12 | const sheet = new ServerStyleSheet() 13 | const originalRenderPage = ctx.renderPage 14 | 15 | try { 16 | ctx.renderPage = () => 17 | originalRenderPage({ 18 | enhanceApp: (App) => (props) => 19 | sheet.collectStyles() 20 | }) 21 | 22 | const initialProps = await Document.getInitialProps(ctx) 23 | return { 24 | ...initialProps, 25 | styles: ( 26 | <> 27 | {initialProps.styles} 28 | {sheet.getStyleElement()} 29 | > 30 | ) 31 | } 32 | } finally { 33 | sheet.seal() 34 | } 35 | } 36 | 37 | render() { 38 | return ( 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | ) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/pages/after-fill.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | import styled, { css } from 'styled-components' 4 | 5 | import { Container } from 'components/Container' 6 | 7 | type ObjectFitProps = { 8 | objectFit: 'cover' | 'contain' | 'none' 9 | } 10 | 11 | const ImageWrapper = styled.div` 12 | ${({ objectFit }) => css` 13 | position: relative; 14 | width: 300px; 15 | height: 500px; 16 | 17 | img { 18 | object-fit: ${objectFit}; 19 | } 20 | `} 21 | ` 22 | 23 | export default function AfterFill() { 24 | return ( 25 | 26 | 27 | Back 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ) 43 | } 44 | -------------------------------------------------------------------------------- /src/pages/after-responsive.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | 4 | import { Container } from 'components/Container' 5 | 6 | export default function AfterResponsive() { 7 | return ( 8 | 9 | 10 | Back 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /src/pages/after.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | 4 | import { Container } from 'components/Container' 5 | 6 | export default function After() { 7 | return ( 8 | 9 | 10 | Back 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /src/pages/before.tsx: -------------------------------------------------------------------------------- 1 | import { Container } from 'components/Container' 2 | import Link from 'next/link' 3 | 4 | export default function Before() { 5 | return ( 6 | 7 | 8 | Back 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/pages/external.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | import { Container } from 'components/Container' 4 | 5 | export default function External() { 6 | return ( 7 | 8 | 9 | Back 10 | 11 | 17 | 23 | 29 | 35 | 41 | 47 | 53 | 54 | ) 55 | } 56 | -------------------------------------------------------------------------------- /src/pages/fixed.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | 4 | import { Container } from 'components/Container' 5 | 6 | export default function Fixed() { 7 | return ( 8 | 9 | 10 | Back 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import styled from 'styled-components' 3 | 4 | const HomeContainer = styled.main` 5 | display: grid; 6 | align-items: center; 7 | justify-content: center; 8 | height: 100vh; 9 | padding: 20px; 10 | 11 | h1 { 12 | margin-bottom: 10px; 13 | } 14 | 15 | ul { 16 | list-style: none; 17 | padding-top: 30px; 18 | } 19 | 20 | li { 21 | padding: 10px 0; 22 | } 23 | ` 24 | 25 | export default function Home() { 26 | return ( 27 | 28 | 29 | NextJS 10 - Image Optimization 30 | 31 | You can{' '} 32 | 33 | watch this video to explanations (pt-br) 34 | {' '} 35 | and{' '} 36 | 37 | code here. 38 | 39 | 40 | Or click the links bellow to see the differences: 41 | 42 | 43 | 44 | 45 | 46 | Before 47 | 48 | 49 | 50 | 51 | 52 | After - unsized images (Deprecated) 53 | 54 | 55 | 56 | 57 | 58 | After - fixed images (Non responsiveness) 59 | 60 | 61 | 62 | 63 | 64 | After - defined sizes (intrinsic mode) 65 | 66 | 67 | 68 | 69 | 70 | After - not defined sizes (fill mode) 71 | 72 | 73 | 74 | 75 | 76 | After - defined sizes (responsive mode) 77 | 78 | 79 | 80 | 81 | 82 | After - styled images 83 | 84 | 85 | 86 | 87 | 88 | Low quality 89 | 90 | 91 | 92 | 93 | 94 | Without lazy loading - priority 95 | 96 | 97 | 98 | 99 | 100 | External images 101 | 102 | 103 | 104 | 105 | 106 | 107 | ) 108 | } 109 | -------------------------------------------------------------------------------- /src/pages/low-quality.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | 4 | import { Container } from 'components/Container' 5 | 6 | export default function LowQuality() { 7 | return ( 8 | <> 9 | 10 | 11 | Back 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | > 22 | ) 23 | } 24 | -------------------------------------------------------------------------------- /src/pages/priority.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | import { Container } from 'components/Container' 4 | 5 | export default function Priority() { 6 | return ( 7 | 8 | 9 | Back 10 | 11 | 12 | 13 | 14 | {/* just a huge block of space */} 15 | 16 | 17 | 18 | 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /src/pages/styled-image.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | import styled from 'styled-components' 4 | 5 | import { Container } from 'components/Container' 6 | 7 | const ImageWrapper = styled.div` 8 | height: 320px; 9 | width: 320px; 10 | margin: auto; 11 | position: relative; 12 | 13 | img { 14 | border-radius: 50%; 15 | } 16 | ` 17 | 18 | export default function Styled() { 19 | return ( 20 | 21 | 22 | Back 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /src/pages/unsized.tsx: -------------------------------------------------------------------------------- 1 | import Link from 'next/link' 2 | import Image from 'next/image' 3 | 4 | import { Container } from 'components/Container' 5 | 6 | export default function Unsized() { 7 | return ( 8 | 9 | 10 | Back 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /src/styles/global.ts: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components' 2 | 3 | const GlobalStyles = createGlobalStyle` 4 | * { 5 | margin: 0; 6 | padding: 0; 7 | box-sizing: border-box; 8 | } 9 | 10 | html { 11 | font-size: 62.5%; 12 | } 13 | 14 | body { 15 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; 16 | font-size: 1.6rem; 17 | } 18 | ` 19 | 20 | export default GlobalStyles 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "src", 4 | "target": "es5", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "strict": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "noEmit": true, 11 | "esModuleInterop": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "jsx": "preserve" 17 | }, 18 | "exclude": ["node_modules"], 19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"] 20 | } 21 | --------------------------------------------------------------------------------
31 | You can{' '} 32 | 33 | watch this video to explanations (pt-br) 34 | {' '} 35 | and{' '} 36 | 37 | code here. 38 | 39 |
Or click the links bellow to see the differences: