Next.js: рдХрд╛рдиреВрдиреА рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдВрдХ рдореЗрдВ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдмрдВрдбрд▓ рдирд╣реАрдВ рдорд┐рд▓рд╛ рдФрд░ рд╣рд╛рд░реНрдб рд░реАрдлреНрд░реЗрд╢ (рдПрд╕рдПрд╕рдЖрд░) рдкрд░ 404 рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 20 рд╕рд┐рддре░ 2018  ┬╖  119рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: vercel/next.js

рдХрд╛рдиреВрдиреА рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдВрдХ рдореЗрдВ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдмрдВрдбрд▓ рдирд╣реАрдВ рдорд┐рд▓рд╛ рдФрд░ рд╣рд╛рд░реНрдб рд░реАрдлреНрд░реЗрд╢ (рдПрд╕рдПрд╕рдЖрд░) рдкрд░ 404 рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ

рдмрдЧ рд░рд┐рдкреЛрд░реНрдЯ

рдмрдЧ рдХрд╛ рд╡рд░реНрдгрди рдХрд░реЗрдВ

рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рд╢реАрд░реНрд╖рдХ рдХреЛ рдФрд░ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рд╕рднреА рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдореБрджреНрджреЛрдВ рдХреЛ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ 6-рдХреИрдирд░реА (рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛтАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рдирд╣реАрдВ рд╣реИ) рдпрд╛ рдмреЗрд╣рддрд░ рд╕реЗрд╡рд╛ (рдЬреЛ рд╢рд╛рдпрдж рдЙрддреНрдкрд╛рджрди рд╕реНрдерд┐рд░ рдирд┐рд░реНрдпрд╛рдд рдореЗрдВ рд╣реА рд╕рдЪ рд╣реИ) рдореЗрдВ рддрдп рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдореИрдВ рдЕрдкрдиреЗ рдореМрдЬреВрджрд╛ рдмреНрд▓реЙрдЧ рдХреЛ next.js рдкрд░ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд┐рдпрд╛ рдерд╛ред рдореЗрд░рд╛ рдЕрдЧрд▓рд╛.js рд╕рдВрдЪрд╛рд▓рд┐рдд рдмреНрд▓реЙрдЧ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж рдирд╡реАрдирддрдо serve рдЗрд╕рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рджреЗрд╡ рдПрдирд╡реА рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдФрд░ рдЙрддреНрдкрд╛рджреЛрдВ рдореЗрдВ 301 Moved Permanently рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ; рдпрд╛ рджреЗрд╡ рдореЗрдВ рдЯреВрдЯреЗ рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рд╕рдорд░реНрдерди рдХреЗ рд╕рд╛рде рд░рд╣рддреЗ рд╣реИрдВред

рдкреНрд░рдЬрдирди рдХрд░рдирд╛

рдпрд╣рд╛рдВ рдиреНрдпреВрдирддрдо рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдорд╛рдорд▓рд╛ рд╣реИ (рд░реЗрдкреЛ рд░реЗрдкреЛ рдХрд╛ рд▓рд┐рдВрдХ рд╕реНрдирд┐рдкреЗрдЯ рдХреЗ рдиреАрдЪреЗ рд╣реИ):

// pages/index.js
import Link from "next/link";

export default () => (
  <Link href="/about/">
    <a>About</a>
  </Link>
);

// pages/index.js
export default () => "about";

рдиреНрдпреВрдирддрдо рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд░реЗрдкреЛ https://github.com/iamstarkov/next.js-trailing-slash-bug-demo

  1. рдХреНрд▓реЛрди рд░реЗрдкреЛ git clone https://github.com/iamstarkov/next.js-trailing-slash-bug-demo
  2. рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрджрд▓реЗрдВ cd next.js-trailing-slash-bug-demo
  3. yarn
  4. рджреЗрд╡ рдЪрд▓рд╛рдПрдБ: yarn dev
  5. рдУрдкрди http://рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ : 3000/
  6. devtools' рдиреЗрдЯрд╡рд░реНрдХ рдЯреИрдм рдЦреЛрд▓реЗрдВ
  7. рдирд┐рд░реАрдХреНрд╖рдг http://localhost:3000/_next/static/development/pages/about.js 200ed . рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ
  8. рдирд┐рд░реАрдХреНрд╖рдг http://localhost:3000/_next/on-demand-entries-ping?page=/about/ 200ed . рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ
  9. http://localhost:3000/about/ 404ed рд╣реЛрдиреЗ рдХрд╛ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░реЗрдВ
  10. http://localhost:3000/about/ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рдЧрд╛рддрд╛рд░ рдкреНрд░рдпрд╛рд╕реЛрдВ рдХрд╛ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░реЗрдВ
  11. рдЯрд░реНрдорд┐рдирд▓ рдореЗрдВ рдирд┐рд░реАрдХреНрд╖рдг рдХрд░реЗрдВ Client pings, but there's no entry for page: /about/
  12. рдкреГрд╖реНрда рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВ
  13. 404 рдкреГрд╖реНрда рджреЗрдЦреЗрдВред
  14. рдпреВрдЖрд░рдПрд▓ рдореЗрдВ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рд╣рдЯрд╛ рджреЗрдВ рдпрд╛ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ http://localhost : 3000/about
  15. рдкреНрд░реЗрдХреНрд╖рдг рдкреГрд╖реНрда 200ed . рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ
  16. рддреНрд░реБрдЯрд┐ рджреГрдврд╝рддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪрд░рдг 5-15 рдПрдХ рдмрд╛рд░ рджреЛрд╣рд░рд╛рдПрдВред

рдЕрдкреЗрдХреНрд╖рд┐рддреН рд╡реНрдпрд╡рд╣рд╛рд░

  1. /about/ рдХреЛ 404 not found рд░реВрдк рдореЗрдВ рд╣рд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП
  2. /about/ рдХреЛ 200 ok рд░реВрдк рдореЗрдВ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП
  3. рд╕рд░реНрд╡рд░ рдХреЛ Client pings, but there's no entry for page: /about/ рдкреНрд░рд┐рдВрдЯ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
  4. /about рдФрд░ /about/ рдХреЛ рдПрдХ рд╣реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП

рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ

рдПрди/рдП

рд╡реНрдпрд╡рд╕реНрдерд╛ рдЬрд╛рдирдХрд╛рд░реА

  • рдУрдПрд╕: macOS рд╣рд╛рдИ рд╕рд┐рдПрд░рд╛ 10.13.6 (17G65)
  • рдмреНрд░рд╛рдЙрдЬрд╝рд░ (рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛, рд▓реЗрдХрд┐рди рдХреНрд░реЛрдо 69.0.3497.100 рдФрд░ рд╕рдлрд╛рд░реА рд╕рдВрд╕реНрдХрд░рдг 12.0 (13606.2.11) рдореЗрдВ рдкреБрди: рдкреЗрд╢ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ) (рд╕рдлрд╛рд░реА 11 рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рдерд╛)
  • Next.js рдХрд╛ рд╕рдВрд╕реНрдХрд░рдг: 7.0.0 (5.x рдФрд░ 6.x рдкрд░ рд░рд┐рдкреНрд░реЛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)

рдЕрддрд┐рд░рд┐рдХреНрдд рд╕рдВрджрд░реНрдн

рдпрд╣рд╛рдВ рд╕рдорд╕реНрдпрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреЛрдИ рдЕрдиреНрдп рд╕рдВрджрд░реНрдн рдЬреЛрдбрд╝реЗрдВред

рдЕрдЧрд░ рдЖрдк рдЗрд╕ рдХреЛрдб рдХреЛ https://github.com/zeit/next.js/blob/459c1c13d054b37442126889077b7056269eeb35/server/on-demand-entry-handler.js#L242 -L249 рдореЗрдВ рдмрджрд▓рддреЗ рд╣реИрдВ

рдпрд╛ node_modules/next/dist/server/on-demand-entry-handler.js рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ

          const { query } = parse(req.url, true)
          const page = normalizePage(query.page)
+         console.log('query.page', query.page);
+         console.log('page', page);
+         console.log('Object.keys(entries)', Object.keys(entries));
          const entryInfo = entries[page]

          // If there's no entry.
          // Then it seems like an weird issue.
          if (!entryInfo) {
            const message = `Client pings, but there's no entry for page: ${page}`

рдФрд░ next dev рдкреБрдирд░рд╛рд░рдВрдн рдХрд░реЗрдВ рдФрд░ http://localhost : 3000/ рдЦреЛрд▓реЗрдВ рдФрд░ рдлрд┐рд░ рд▓рд┐рдВрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ:

  • /about
    query.page /about page /about Object.keys(entries) [ '/', '/about' ]
  • /about/ :
    query.page /about/ page /about/ Object.keys(entries) [ '/', '/about' ] Client pings, but there's no entry for page: /about/

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдорд╕реНрдпрд╛ (рдЗрд╕рдХрд╛ рдХрдо рд╕реЗ рдХрдо рд╣рд┐рд╕реНрд╕рд╛) рдСрдирдбреЗрдореИрдВрдбрдПрдВрдЯреНрд░реАрд╣реИрдВрдбрд▓рд░ рдХреЗ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдореЗрдВ рдкреГрд╖реНрда рдЦреЛрдЬрдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрдерддрд╛ рд╣реИ рдпрджрд┐ рдкреГрд╖реНрда рдореЗрдВ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рд╣реИред

рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдореЗрд░реА 2 рдШрдВрдЯреЗ рдХреА рдЬрд╛рдВрдЪ рдФрд░ рддреИрдпрд╛рд░реА рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░ рд╕рдХрддреА рд╣реИред

story 8 feature request

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рд╣рдо рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рдЙрддрд╛рд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВтАФрдПрдХ-рдПрдХ рджрд┐рди!

рд╕рднреА 119 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рд╕рдмрд╕реЗ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдФрд░ рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рдореБрджреНрджреЗ #1189 рдФрд░ #3876 . рд╣реИрдВ

рдЗрд╕рдХреЗ рдЕрдВрдд рдореЗрдВ рд╣рд▓ рд╣реЛрдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ! @timneutkens рдЕрдЧрд▓реЗ 7 рдХреЗ рд▓рд┐рдП рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдХреНрдпрд╛ рд╣реИ?

@NathanielHill рдореИрдВ рдЗрд╕реЗ next@7 рдкрд░ рдкреБрди: рдкреЗрд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ

рдореИрдВ рдиреЗрдХреНрд╕реНрдЯрдЬ 7 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рджреЗрд╡ рдФрд░ рдареЗрд╕ рджреЛрдиреЛрдВ рдкрд░ рдореЗрд░реЗ рд▓рд┐рдП 404 рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░ рд░рд╣рд╛ рд╣реИ:

  • рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдкреГрд╖реНрда рд▓реЛрдб рдкрд░
  • рдкреГрд╖реНрда рдкрд░ рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВ

рдФрд░ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ:

  • рдПрдХ рдмрд╛рд╣рд░реА рд▓рд┐рдВрдХ
  • рдПрдХ рдЖрдВрддрд░рд┐рдХ рд▓рд┐рдВрдХ
  • рдпреВрдЖрд░рдПрд▓ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЪрд┐рдкрдХрд╛рдпрд╛ рдЧрдпрд╛

рдмрд╕ рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреЛ рд╣рдЯрд╛рдиреЗ рд╕реЗ рд╕рдорд╕реНрдпрд╛ рдареАрдХ рд╣реЛ рдЬрд╛рддреА рд╣реИред

рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдЕрдХреНрд╕рд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░, рд╕рд░реНрд╡рд░ рдФрд░/рдпрд╛ рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рдЬреЛрдбрд╝реЗ рдЬрд╛рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд▓рд┐рдВрдХ рдЪрд┐рдкрдХрд╛рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЬрдм рдореИрдВ рдЖрдВрддрд░рд┐рдХ рд▓рд┐рдВрдХ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ, рддреЛ рдпрд╣ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдирд╛ рдХрдард┐рди рд╣реИ рдХрд┐ рдмрд╛рд╣рд░реА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд┐рд╕ рд▓рд┐рдВрдХ рдкрд░ рдЖ рд░рд╣реЗ рд╣реИрдВ

рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рд╕рдВрд╕реНрдХрд░рдг 7 рдореЗрдВ рднреА рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВред рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИ, рд▓реЗрдХрд┐рди, рдореИрдВ рдПрдХ Next.js рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛ рджреВрд╕рд░реЗ рдирд╛рдУ рдкрд░рд┐рдирд┐рдпреЛрдЬрди рдХреЗ рд╕рдмрдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдЕрд▓рд┐рдпрд╛рд╕рд┐рдВрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рддреЛ рд╣рдорд╛рд░рд╛ рдЖрдзрд╛рд░ рдпреВрдЖрд░рдПрд▓ primer.style рдФрд░ рд╣рдо рдЕрдкрдиреЗ primer-components.now.sh Next.js рдРрдк рдХреЛ primer.style/components рдЙрдкрдирд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЙрддреНрдкрд╛рджрди рдкрд░, primer.style/components рдХрд╛ рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдкреГрд╖реНрда рдареАрдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди primer.style/components/ 404 рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИред

рдореБрдЭреЗ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рд╕рд╛ рдЦреЛрдЬрдирд╛ рдкрдбрд╝рд╛ред рдореИрдВ Netlify рдкрд░ рд╕реНрдерд┐рд░ рдкрд░рд┐рдирд┐рдпреЛрдЬрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛

рдореБрдЭреЗ рднреА рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╣реЛ рд░рд╣реА рд╣реИ рдФрд░ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд╖реНрдЯрдкреНрд░рдж рд╣реИ, рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдЬрд▓реНрдж рд╣реА рдареАрдХ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред

рдпрджрд┐ рдЖрдк рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдмрд╕ рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред <Link href='/about' as='/about/'><a>about</a></Link> рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рд╢реБрдХреНрд░рд╡рд╛рд░/рдЕрдЧрд▓реЗ рдорд╛рд░реНрдЧреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдпрд╣ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рддреЛ рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдХрд╛рдВрдЯрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдЖрдк trailingSlash рдХреЛ рдкреНрд░реЛрдк рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЙрдореНрдореАрдж рд╣реИ рдпреЗ рдорджрдж рдХрд░реЗрдЧрд╛

рдпрджрд┐ рдЖрдк рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдмрд╕ рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред <Link href='/about' as='/about/'><a>about</a></Link> рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рд╢реБрдХреНрд░рд╡рд╛рд░/рдЕрдЧрд▓реЗ рдорд╛рд░реНрдЧреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рддреЛ рдпрд╣ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рддреЛ рдореЗрд░реЗ рдкрд╛рд╕ рдПрдХ рдХрд╛рдВрдЯрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдЖрдк trailingSlash рдХреЛ рдкреНрд░реЛрдк рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЙрдореНрдореАрдж рд╣реИ рдпреЗ рдорджрдж рдХрд░реЗрдЧрд╛

@aluminick рдореБрдЭреЗ рдХреНрд╖рдорд╛ рдХрд░реЗрдВ, рдореИрдВрдиреЗ рдЕрднреА рдпрд╣ рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИ рдФрд░ рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдореБрдЭреЗ рдЕрднреА рднреА рдЯреНрд░реЗрд▓рд┐рдВрдЧ-рд╕реНрд▓реЗрд╢ рдкреЗрдЬ (рдирд╡реАрдирддрдо рд░рд┐рд▓реАрдЬ) рдорд┐рд▓рддрд╛ рд╣реИ, рдЬреЛ рд░реАрдлреНрд░реЗрд╢ (рд╡рд░реНрддрдорд╛рди рд╡реНрдпрд╡рд╣рд╛рд░) рдХреЗ рдмрд╛рдж рдирд╣реАрдВ рдорд┐рд▓рддрд╛ рд╣реИред

рди рддреЛ #6664 рдФрд░ рди рд╣реА #6752 рдЗрдирд╕реЗ рдорджрдж рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ experimental.exportTrailingSlash рдорджрдж рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ next export , рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐

@Janpot рджреНрд╡рд╛рд░рд╛ рдПрдХ рдЖрд╢рд╛рдЬрдирдХ рдкреБрд▓ рдЕрдиреБрд░реЛрдз #6421 рдерд╛ рдЬреЛ рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдХрд┐рд╕реА рднреА рдЖрдо рд╕рд╣рдорддрд┐ рддрдХ рдирд╣реАрдВ рдкрд╣реБрдВрдЪрд╛ рдерд╛

@iamstarkov рдЗрд╕ рдореБрджреНрджреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдХреНрдпрд╛ рд╣реИ? server.js рд╣реБрдХ рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдХреЛрдИ рд╕рдорд╛рдзрд╛рди?

@dryleaf рд╕реНрдерд┐рддрд┐: рдпрд╣ рдЕрднреА рднреА рдЦреБрд▓рд╛ рд╣реИ

рдПрдХ рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛... рдПрдХрд╛рдзрд┐рдХ рдлрд╝реЙрд░рд╡рд░реНрдб рд╕реНрд▓реИрд╢ рдЬреЛрдбрд╝реЗ рдЬрд╛рдиреЗ рдкрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░реЗрдВред рдЙрджрд╛рд╣рд░рдг: https://github.com/zeit/next.js///////////issues/5214

GitHub url рдЕрдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИрдВ

@iamstarkov рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЖрдкрдХрд╛ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИред рд▓реЗрдХрд┐рди рдореЗрд░реА рдореВрд▓ рдкреЛрд╕реНрдЯ рдХреЛ рджреЛрдмрд╛рд░рд╛ рдкрдврд╝рдиреЗ рдХреЗ рдмрд╛рдж, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдФрд░ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рд╕рдХрддрд╛ рдерд╛ред

рдЬрдм рдХреЛрдИ рдРрдк Next.js рдХреЗ рд╕рд╛рде рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ url рдХреЛ (рдЕрдзрд┐рдорд╛рдирддрдГ) рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рдХрд╛ рдПрдХ рд╕рд░рд▓ рдкреНрд░рджрд░реНрд╢рди рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП GitHub url рдХрд╛ рдорддрд▓рдм рд╣реИред рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдпрджрд┐ рдХреЛрдИ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реНрд▓реИрд╢ рдЬреЛрдбрд╝рддрд╛ рд╣реИ, рддреЛ рдпреВрдЖрд░рдПрд▓ рдХреЛ рдЕрднреА рднреА рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдиреЗрдХреНрд╕реНрдЯрдЬ 9 рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдЕрдкрдбреЗрдЯ?

рдореИрдВ рдиреЗрдХреНрд╕реНрдЯ рдореЗрдВ рдирдпрд╛ рд╣реВрдВ рд▓реЗрдХрд┐рди рдЖрдк рд▓реЛрдЧ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдЙрдкрд╛рдп рдЕрдкрдирд╛ рд░рд╣реЗ рд╣реИрдВ?

@iamstarkov рдЗрд╕ рдореБрджреНрджреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдХреНрдпрд╛ рд╣реИ?

рдореИрдВ рд╣реИрд░рд╛рди рд╣реВрдВ рдХрд┐ рдХрд░реАрдм рдПрдХ рд╕рд╛рд▓ рд╕реЗ рдЗрд╕ рдорд╕рд▓реЗ рдХрд╛ рдХреЛрдИ рд╣рд▓ рдирд╣реАрдВ рдирд┐рдХрд▓рд╛!
рдХреНрдпрд╛ Next.js рдЯреАрдо рдХреЛ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рдЕрдиреНрдп рдХрд╛рд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ?

рдкреАрдЫреЗ рдХреЗ рд╕реНрд▓реИрд╢ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ URL рдХреЛ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╡реЗрдм рдкрд░ рдХрд┐рд╕реА рднреА рд╕рд╛рдЗрдЯ рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВред

рдЕрдЧрд░ рдпрд╣ Next.js рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдЗрд╕реЗ рдЕрднреА рдореЗрдВ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рджреЗрдВред
рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрд▓рдЭрди рдореЗрдВ рд╣реВрдВ рдХрд┐ Zeit рдЯреАрдо рд╡рд░реНрд╖реЛрдВ рд╕реЗ рдРрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдореБрджреНрджреЛрдВ рдХреА рдЙрдкреЗрдХреНрд╖рд╛ рдХрд░рддреА рд╣реИред

@exentrich рдпрд╣

now.json :

"routes": [
    {
      "src": "/(.*)/",
      "status": 301,
      "headers": { "Location": "/$1" }
    },
    ...
]

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореБрдЭреЗ рдпрд╣ рднреА рд╕рдордЭ рдореЗрдВ рдирд╣реАрдВ рдЖрддрд╛ рдХрд┐ рдЗрд╕реЗ рдиреЗрдХреНрд╕реНрдЯ.рдЬреЗрдПрд╕ рджреНрд╡рд╛рд░рд╛ рд╣реА рдХреНрдпреЛрдВ рдирд╣реАрдВ рд╕рдВрднрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЯреАрдо рдиреЗ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдХреНрдпреЛрдВ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд░ рджрд┐рдпрд╛ рд╣реИред

рдпрд╣, public/ (рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ) рдХреЗ рд╕рд╛рде рдореБрдЦреНрдп рдореБрджреНрджреЗ рд╣реИрдВ рдЬреЛ рдореБрдЭреЗ рд╕реАрдЖрд░рдП рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрддреЗ рджрд┐рдЦрд╛рдИ рджреЗ рд░рд╣реЗ рд╣реИрдВред

@rauchg

@ рдирдерд╛рдирд┐рдПрд▓рд╣рд┐рд▓ рдзрдиреНрдпрд╡рд╛рдж!
рдореИрдВрдиреЗ рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рд▓реЗрдХрд┐рди рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ рд╣рдЯрд╛ рджрд┐рдП рдЧрдП рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП /some/?query=1 /some рдмрд┐рдирд╛ рдХрд┐рд╕реА рдкреНрд░рд╢реНрди рдХреЗ

рд╣рд╛рдБ, рдпрд╣ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХреА рддрд░рд╣ рд▓рдЧрддрд╛ рд╣реИ @exentrich

рдореИрдВрдиреЗ рдЙрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рдЕрдиреБрдорд╛рди рдирд╣реАрдВ рд▓рдЧрд╛рдпрд╛ рд╣реЛрдЧрд╛ рдЬреИрд╕рд╛ рдХрд┐ рдореБрдЭреЗ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдПрдХ рдирд┐рд╣рд┐рдд ^ рдФрд░ $ рд░реЗрдЧреЗрдХреНрд╕ рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рд▓рдкреЗрдЯрд╛ рдЧрдпрд╛ рд╣реИ (рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдЖрдкрдХрд╛ рдЙрджрд╛рд╣рд░рдг рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рдПрдЧрд╛)ред рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реЛ: man_shrugging: рд╢реБрднрдХрд╛рдордирд╛рдПрдВ

рдПрдХ рдХрд╕реНрдЯрдо рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рдФрд░ avinoamr/рдХрдиреЗрдХреНрдЯ-рд╕реНрд▓реИрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИ рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рд╣реА рд╕рдорд╕реНрдпрд╛ рдореЗрдВ рдЪрд▓ рд░рд╣рд╛ рд╣реИ

рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдмрдбрд╝рд╛ рдореБрджреНрджрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ / рдорд╛рд░реНрдЧ рддреНрд░реБрдЯрд┐ рдкреГрд╖реНрда рдлреЗрдВрдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рд╕реЗ рдПрд╕рдИрдУ рдХреЛ рдиреБрдХрд╕рд╛рди рд╣реЛрддрд╛ рд╣реИ (рдЬреЛ рдХрд┐ рдЕрдЧрд▓рд╛ рдХреЗ рдкреНрд░рд╛рдердорд┐рдХ рдбреНрд░реЙ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ)ред

301 рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдФрд░ рдХрд╕реНрдЯрдо рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рд╕рднреА рдареАрдХ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╣реИрдХ рд╣реЛрдиреЗ рд▓рдЧрддреЗ рд╣реИрдВред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдореЗрд░реЗ рдкрд╛рд╕ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдХрд╕реНрдЯрдо рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рдХреЗ рдиреЗрдХреНрд╕реНрдЯ рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдПрдХ рдкреВрд░реНрдг рдХрд╛рдордХрд╛рдЬреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди

рдкреБрдирд╢реНрдЪ: рдореБрдЭреЗ рдиреЗрдХреНрд╕реНрдЯ тЭдя╕П . рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдмрд┐рд▓реНрдХреБрд▓ рдкрд╕рдВрдж рд╣реИ

рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдмрдбрд╝рд╛ рдореБрджреНрджрд╛ рд╣реИ, рдЦрд╛рд╕рдХрд░ рдХреНрдпреЛрдВрдХрд┐ / рдорд╛рд░реНрдЧ рддреНрд░реБрдЯрд┐ рдкреГрд╖реНрда рдлреЗрдВрдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рд╕реЗ рдПрд╕рдИрдУ рдХреЛ рдиреБрдХрд╕рд╛рди рд╣реЛрддрд╛ рд╣реИ

рдпрд╣ рдЖрдкрдХреЗ SEO рдХреЛ рдиреБрдХрд╕рд╛рди рдирд╣реАрдВ рдкрд╣реБрдВрдЪрд╛рддрд╛ рд╣реИред Google рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреЛ рдПрдХ рднрд┐рдиреНрди рдкреГрд╖реНрда рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирддрд╛ рд╣реИред 404 рд╣реЛрдиреЗ рд╕реЗ рдЖрдкрдХреА рд╕рд╛рдЗрдЯ рдХреЗ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдЧреИрд░-рдореМрдЬреВрджрд╛ рдкреГрд╖реНрда рдХреА рддреБрд▓рдирд╛ рдореЗрдВ SEO рдкрд░ рдХреЛрдИ рдкреНрд░рднрд╛рд╡ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрдм рддрдХ рдЖрдк рдЗрд╕реЗ рдХрд┐рд╕реА рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рд╕реЗ рд▓рд┐рдВрдХ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддрдм рддрдХ Google рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╕реНрдерд╛рди рдкрд░ рдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред рдпрд╣ рдореБрджреНрджрд╛, рдЬрдмрдХрд┐ рдЕрднреА рднреА рдПрдХ рд╡реИрдз рдореБрджреНрджрд╛ рд╣реИ, рдЖрдк рд╕рднреА рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХрдо рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред

@ рдирд┐рдХ-рдЬреЙрди @NathanielHill @dkrish @exentrich

301 рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЖрдкрдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдПрдХ рдХрд╕реНрдЯрдо server.js рд╕рд╛рде рдореЗрд░рд╛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реВрдВред

301 рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рднреА SEO рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХреЛ рд╕реНрд▓реИрд╢ рдФрд░ рдиреЙрди-рд╕реНрд▓реИрд╢ рд░реВрдЯ рдХреЗ рд▓рд┐рдП рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХрдВрдЯреЗрдВрдЯ рдкреЗрдирд▓реНрдЯреА рдирд╣реАрдВ рдорд┐рд▓реЗрдЧреАред

рдореБрдЭреЗ тЭдя╕П Next.js рдкрд╕рдВрдж рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЗрд╕ рдХрд╛рдо рдХреЗ рдмрд┐рдирд╛ рдЗрд╕реЗ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реЛрдЯ рджреЗрддрд╛ рд╣реВрдВред

// server.js

const { createServer } = require('http');
const { parse } = require("url");
const next = require("next");

const dev = process.env.NODE_ENV !== 'production'
const port = parseInt(process.env.PORT, 10) || 3000;
const app = next({ dev, quiet: false });
const handle = app.getRequestHandler();

(async () => {
    await app.prepare();
    const server = createServer();

    server.on('request', async (req, res) => {

        const parsedUrl = parse(req.url, true);
        const { pathname, query } = parsedUrl;

        if (pathname.length > 1 && pathname.slice(-1) === "/") {
            console.log('server.js - redirect on "/"...', pathname, query);
            const queryString = await Object.keys(query).map(key => key + '=' + query[key]).join('&');
            res.writeHead(301, { Location: pathname.slice(0, -1) + (queryString ? '?'+ queryString : '') });
            res.end();
        }

        handle(req, res, parsedUrl);

    });

    await server.listen(port);
    console.log(`ЁЯЪА Ready on http://localhost:${port}`);

})();

@ рдЬрдирдкреЛрдЯ

рдпрд╣ рдЖрдкрдХреЗ SEO рдХреЛ рдиреБрдХрд╕рд╛рди рдирд╣реАрдВ рдкрд╣реБрдВрдЪрд╛рддрд╛ рд╣реИред Google рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреЛ рдПрдХ рднрд┐рдиреНрди рдкреГрд╖реНрда рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирддрд╛ рд╣реИред 404 рд╣реЛрдиреЗ рд╕реЗ рдЖрдкрдХреА рд╕рд╛рдЗрдЯ рдХреЗ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдЧреИрд░-рдореМрдЬреВрджрд╛ рдкреГрд╖реНрда рдХреА рддреБрд▓рдирд╛ рдореЗрдВ SEO рдкрд░ рдХреЛрдИ рдкреНрд░рднрд╛рд╡ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рд╣реИред

рдореИрдВ рдЖрдкрдХреА рдмрд╛рдд рд▓реЗрддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдПрд╕рдИрдУ рдХреЛ рд╕рд╣рдЬ рд░реВрдк рд╕реЗ рдЪреЛрдЯ рдирд╣реАрдВ рдкрд╣реБрдВрдЪрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдкрд░ рд╣рд░ рдмрд╛рд░ URL рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреЛ рд╕рд╣реА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рджрдмрд╛рд╡ рдбрд╛рд▓рддрд╛ рд╣реИ, рдЬреЛ рдорд╛рдирд╡реАрдп рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдЕрдзреАрди рд╣реИред рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдЬреЛ рдиреЗрдХреНрд╕реНрдЯ рдореЗрдВ рдирдпрд╛ рд╣реИ, рдЙрд╕реЗ рдЬрд░реВрд░реА рдирд╣реАрдВ рдкрддрд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд (рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рджрд┐рдЦрдиреЗ рд╡рд╛рд▓рд╛) рдпреВрдЖрд░рдПрд▓ 404 рдкреЗрдЬ рдкрд░ рд▓реЗ рдЬрд╛рдПрдЧрд╛ред <Link href='/people/'>

рдПрдХ рдкрд░рд┐рдкрдХреНрд╡ рдврд╛рдВрдЪрд╛ рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рдРрд╕реА рдорд╛рдирд╡реАрдп рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдЕрдзреАрди рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрдм рддрдХ рдЖрдк рдЗрд╕реЗ рдХрд┐рд╕реА рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рд╕реЗ рд▓рд┐рдВрдХ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддрдм рддрдХ Google рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╕реНрдерд╛рди рдкрд░ рдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред

рдлрд┐рд░ рд╕реЗ - рд╡рд╣рд╛рдБ рдЕрдХрд╕реНрдорд╛рдд _ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рд▓реЛрдЧреЛрдВ рдХреЗ рдореБрджреНрджреЗ рдореМрдЬреВрдж www.mysite.com/people/_ _ рдХреЗ рдмрдЬрд╛рдп www.mysite.com/people_ (- рдпрд╣рд╛рдВ рддрдХ рдХрд┐ рд╕рдмрд╕реЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЬреЛ рджреЛрдиреЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдХреБрд▓ рд╡реИрд╕рд╛ рд╣реА рд╣реЛрдиреЗ рд▓рдЧрддреЗ рд╣реИрдВ)ред

рдпреЗ рджреЛрдиреЛрдВ рдкрд░рд┐рджреГрд╢реНрдп _can_ SEO рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рдЕрдм, SEO рдкреНрд░рднрд╛рд╡ рдкрд░ рд╡рд┐рдЪрд╛рд░ рди рдХрд░рддреЗ рд╣реБрдП, URL рдХрд╛ рдЕрд░реНрдердкреВрд░реНрдг рдЕрд░реНрде рднреА рд╣реИ - _does_ _ www.mysite.com/people / _ рдХрд┐рд╕ рдУрд░ рдЗрд╢рд╛рд░рд╛ рдХрд░рддрд╛ рд╣реИ? рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдХреА рдУрд░ рдЗрд╢рд╛рд░рд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдЕрдЧрд▓рд╛ pages > people > index.js рдореЗрдВ рдЬреЛ рдХреБрдЫ рднреА рд╣реИ рдЙрд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП (рдЬреИрд╕рд╛ рдХрд┐ _www.mysite.com/people_ рдХреЗ рд▓рд┐рдП pages > people.js рдХреЗ рд╡рд┐рдкрд░реАрдд) рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдпрд╣ рдХреБрдЫ рднреА рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдПрдХ рдмрд╣реБрдд рд╣реА рд╣реИ рд░реВрдЯрд┐рдВрдЧ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдореЗрдВ рдЙрдЪреНрдЪ рд╕реНрддрд░реАрдп рджреЛрд╖ред

рдкреНрд░рдореБрдЦ рд░реВрдЯрд┐рдВрдЧ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХреБрдЫ рдкреНрд░рд╛рд╡рдзрд╛рди рд╣реИрдВ - рдЬреИрд╕реЗ рд░рд┐рдПрдХреНрдЯ рд░рд╛рдЙрдЯрд░ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ isExact

рдЬрдмрдХрд┐ рдореИрдВ рд╕рдордЭрддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдк рдХрд╣рд╛рдВ рд╕реЗ рдЖ рд░рд╣реЗ рд╣реИрдВ, рдореБрдЭреЗ рдЕрднреА рднреА рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдЬреНрд╡рд▓рдВрдд рдореБрджреНрджрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЖрдЧреЗ рдмрдврд╝рд╛рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ

next export . рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рднреА рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдкрд░рд┐рд╣рд╛рд░реНрдп рд╣реИ

рд▓реЛрдЧреЛрдВ рдХреЗ рдЧрд▓рддреА рд╕реЗ рд▓рд┐рдВрдХ рд╣реЛрдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдореМрдЬреВрдж рд╣реИ...

рдореМрдЬреВрдж рд╣реИ рдЧрд▓рддреА рд╕реЗ рдХрд┐рд╕реА рднреА рдЧреИрд░ рдореМрдЬреВрджрд╛ рдпреВрдЖрд░рдПрд▓ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рд▓реЛрдЧреЛрдВ рдХрд╛ рдореБрджреНрджрд╛ рдХреНрдпреЛрдВ рдХрд░реЗрдВрдЧреЗ /some/path/ рд╣реЛ рдХрдо рдЧреИрд░ рдореМрдЬреВрджрд╛ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ /some/path/dhgfiuwo ?

рдпреВрдЖрд░рдПрд▓ рдХрд╛ рдЕрд░реНрдердкреВрд░реНрдг рдЕрд░реНрде рднреА рд╣реИ

рдпрд╣ рдЕрддреНрдпрдзрд┐рдХ рд╡реНрдпрдХреНрддрд┐рдкрд░рдХ рд╣реИ, рдЬрд╣рд╛рдБ рддрдХ рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ рд╡рд╣рд╛рдБ рдХреЛрдИ рдХрд▓реНрдкрдирд╛ рдирд╣реАрдВ рд╣реИ рдЬреЛ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреА рд╣реИ рдХрд┐ рд╢рдмреНрджрд╛рд░реНрде рдЕрдВрддрд░ рдХреНрдпрд╛ рд╣реИред рдпреВрдЖрд░рдПрд▓ рд╕реНрдкреЗрдХ рдХреЗ рдореБрддрд╛рдмрд┐рдХ, рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдХреЗ рд╕рд╛рде рдФрд░ рдмрд┐рдирд╛ рдЕрд▓рдЧ рдпреВрдЖрд░рдПрд▓ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдВ рдХрдо рд╕реЗ рдХрдо 7 рдЕрд▓рдЧ-рдЕрд▓рдЧ рдорд╛рдиреНрдп рд╡реНрдпрд╡рд╣рд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪ рд╕рдХрддрд╛ рд╣реВрдВ:

  • рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде рдФрд░ рдЙрд╕рдХреЗ рдмрд┐рдирд╛
  • 404 рдХреЗ рд╕рд╛рде, рдмрд┐рдирд╛ рд╕рдВрдХрд▓реНрдк рдХреЗ
  • рд╕рдВрдХрд▓реНрдк рдХреЗ рд╕рд╛рде, рдмрд┐рдирд╛ 404
  • рдмрд┐рдирд╛ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХреЗ рд╕рд╛рде
  • рдХреЗ рд╕рд╛рде рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд┐рдП рдмрд┐рдирд╛
  • рд╡рд┐рд╣рд┐рдд рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рд╕рд╛рде рдФрд░ рдмрд┐рдирд╛ рд╕рдорд╛рди рд╕рд╛рдордЧреНрд░реА рд╣реИ with
  • рд╡рд┐рд╣рд┐рдд рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рдФрд░ рдмрд┐рдирд╛ рд╕рдорд╛рди рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде рдФрд░ рдмрд┐рдирд╛

рдЗрд╕реЗ /pages/some-page.js рдФрд░ /pages/some-page/index.js (рдпрд╛ рджреЛрдиреЛрдВ) рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХреЗ рд╕рд╛рде рдЬреЛрдбрд╝реЗрдВред

рдХреНрдпрд╛ next.js рдЙрди рд╕рднреА рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП? рдХреНрдпрд╛ рдЗрд╕реЗ рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡реНрдпрд╡рд╣рд╛рд░ рдЪреБрдирдирд╛ рдЪрд╛рд╣рд┐рдП?

рдореИрдВ рдЗрд╕рдХреЗ рдЦрд┐рд▓рд╛рдл рдирд╣реАрдВ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЗрд╕реЗ рдкрд╣рд▓реЗ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЬрд┐рддрдирд╛ рд▓рдЧрддрд╛ рд╣реИ рдЙрд╕рд╕реЗ рдХрд╣реАрдВ рдЕрдзрд┐рдХ рдмрд╛рд░реАрдХрд┐рдпрд╛рдВ рд╣реИрдВред

рдХрд┐рд╕реА рднреА рдЧреИрд░-рдореМрдЬреВрджрд╛ рдпреВрдЖрд░рдПрд▓ рд╕реЗ рдЧрд▓рддреА рд╕реЗ рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдВрдХ рд╣реЛрдиреЗ рдХрд╛ рдореБрджреНрджрд╛ рдореМрдЬреВрдж рд╣реИ, рдХреНрдпреЛрдВ/рдХреБрдЫ/рдкрде//рдХреБрдЫ/рдкрде/dhgfiuwo рд╕реЗ рдХрдо рдЧреИрд░-рдореМрдЬреВрдж рд╣реЛрдЧрд╛?

рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП /some/path/dhgfiuwo - рд▓реЛрдЧ рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ dhgfiuwo рдорд╛рд░реНрдЧ рдЧрд╛рдпрдм рд╣реЛ рд╕рдХрддрд╛ рд╣реИред (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ dhgfiuwo рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдирд╣реАрдВ рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ рдФрд░ users/dhgfiuwo рдЧрд▓рдд рд╣реИред рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ рдПрдХ рдЕрдкреЗрдХреНрд╖рд┐рдд рдШрдЯрдирд╛ рд╣реИред)
/some/path/ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ - рд▓реЛрдЧ рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдкрде /some/path рдЬреИрд╕рд╛ рд╣реА рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрдиреНрдп рд╕рд╛рдЗрдЯреЛрдВ рдкрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рдореЗрдВ рдПрдХ рд╡рд┐рдлрд▓рддрд╛ would/some/path/ рдХрдо рдЧреИрд░ рдореМрдЬреВрджрд╛ рд╣реИ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ /some/path/dhgfiuwo ред

рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рджреВрд╕рд░реЛрдВ рдиреЗ рдЕрдкрдиреЗ рд╕рдорд╛рдзрд╛рди рдкреЛрд╕реНрдЯ рдХрд┐рдП рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЕрдкрдирд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ: https://github.com/DevSpeak/next-trailingslash

рдбрд╛рдпрдиреЗрдорд┐рдХ рд░реВрдЯреЗрдб рдкреЗрдЬреЛрдВ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕реБрдзрд╛рд░ рдФрд░ рд╕рдорд░реНрдерди рдЬрдм ?= рдХреА рдмрд╛рдд рдЖрддреА рд╣реИ рддреЛ рдЖрдИрдПрдордУ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдпрд╣ рдХреЗрд╡рд▓ рд╡рд┐рдЪрд╛рд░ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИред

рдПрдХ рддреНрд╡рд░рд┐рдд рд╕рдорд╛рдзрд╛рди рдХреЗ рд▓рд┐рдП, рдЖрдк рдбрд┐рдлрд╝реЙрд▓реНрдЯ _error рдкреГрд╖реНрда рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ (рдЬреИрд╕рд╛ рдХрд┐ @DevSpeak рдХреЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╣реИ)ред

@DevSpeak , рдореИрдВ рдЖрдкрдХреЗ рд░реЗрдкреЛ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдмрджрд▓рд╛рд╡реЛрдВ рдХреА рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реВрдВ:

рдпрд╣рд╛рдБ рдореИрдВ рдПрдХ рдЯрд╛рдЗрдкрдкреНрд░рддрд┐ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ (рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рддреНрд░реБрдЯрд┐ рдкреГрд╖реНрда рдХреЗ рдЖрдзрд╛рд░ рдкрд░):

/pages/_error.tsx (рдпрд╛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рд╣рдЯрд╛ рджреЗрдВ рдФрд░ рдЗрд╕реЗ /pages/_error.jsx рдирд╛рдо рджреЗрдВ):

import React from 'react';
import Head from 'next/head';
import { NextPageContext } from 'next';

const statusCodes: { [code: number]: string } = {
  400: 'Bad Request',
  404: 'This page could not be found',
  405: 'Method Not Allowed',
  500: 'Internal Server Error'
};

export type ErrorProps = {
  statusCode: number;
  title?: string;
};

/**
 * `Error` component used for handling errors.
 */
export default class Error<P = {}> extends React.Component<P & ErrorProps> {
  static displayName = 'ErrorPage';

  static getInitialProps({
    req,
    res,
    err
  }: NextPageContext): Promise<ErrorProps> | ErrorProps {
    const statusCode =
      res && res.statusCode ? res.statusCode : err ? err.statusCode! : 404;
    if (typeof window === 'undefined') {
      /**
       * Workaround for: https://github.com/zeit/next.js/issues/8913#issuecomment-537632531
       * Test vectors:
       * `/test/test/` -> `/test/test`
       * `/test/////test////` -> `/test/test`
       * `/test//test//?a=1&b=2` -> `/test?a=1&b=2`
       * `/test///#test` -> `/test#test`
       */
      const correctPath = (invalidPath: string) =>
        invalidPath
          .replace(/\/+$/, '')
          .replace(/\/+#/, '#')
          .replace(/\/+\?/, '?')
          .replace(/\/+/g, '/');
      if (req && res && req.url && correctPath(req.url) !== req.url) {
        res.writeHead(302, {
          Location: correctPath(req.url)
        });
        res.end();
      }
      const reqInfo = req
        ? `; Url: ${req.url}; IP: ${req.headers['x-forwarded-for'] ||
            (req.connection && req.connection.remoteAddress)};`
        : '';
      console.log(`Error rendered: ${statusCode}${reqInfo}`);
    }
    return { statusCode };
  }

  render() {
    const { statusCode } = this.props;
    const title =
      this.props.title ||
      statusCodes[statusCode] ||
      'An unexpected error has occurred';

    return (
      <div style={styles.error}>
        <Head>
          <title>
            {statusCode}: {title}
          </title>
        </Head>
        <div>
          <style dangerouslySetInnerHTML={{ __html: 'body { margin: 0 }' }} />
          {statusCode ? <h1 style={styles.h1}>{statusCode}</h1> : null}
          <div style={styles.desc}>
            <h2 style={styles.h2}>{title}.</h2>
          </div>
        </div>
      </div>
    );
  }
}

const styles: { [k: string]: React.CSSProperties } = {
  error: {
    color: '#000',
    background: '#fff',
    fontFamily:
      '-apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Fira Sans", Avenir, "Helvetica Neue", "Lucida Grande", sans-serif',
    height: '100vh',
    textAlign: 'center',
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center'
  },

  desc: {
    display: 'inline-block',
    textAlign: 'left',
    lineHeight: '49px',
    height: '49px',
    verticalAlign: 'middle'
  },

  h1: {
    display: 'inline-block',
    borderRight: '1px solid rgba(0, 0, 0,.3)',
    margin: 0,
    marginRight: '20px',
    padding: '10px 23px 10px 0',
    fontSize: '24px',
    fontWeight: 500,
    verticalAlign: 'top'
  },

  h2: {
    fontSize: '14px',
    fontWeight: 'normal',
    lineHeight: 'inherit',
    margin: 0,
    padding: 0
  }
};

рдзреНрдпрд╛рди рджреЗрдВ, рдЬрдм рдкреГрд╖реНрда рд╣рд┐рдЯ рд╣реЛрддрд╛ рд╣реИ рддреЛ рдпрд╣ рдПрдХ рддреНрд░реБрдЯрд┐ рднреА рд▓реЙрдЧ рдХрд░рддрд╛ рд╣реИ, рддрд╛рдХрд┐ рдЖрдк рдХрд┐рд╕реА рднреА рд▓рд┐рдВрдХ/рдЕрдиреНрдп рдореБрджреНрджреЛрдВ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рд▓реЙрдЧ рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХреЗрдВред

@DevSpeak @bitjson рдЖрдкрдХреЗ рд╕реБрдЭрд╛рд╡реЛрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдпрд╣ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИ рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдмрд╣реБрдд рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╣рд▓ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕ рдмрд╛рдд рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реБрдП рдХрд┐ _error.jsx рдореВрд▓ рд░реВрдк рд╕реЗ _errors_ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ рдФрд░ рдШрд░ рд░реВрдЯрд┐рдВрдЧ рддрд░реНрдХ рдирд╣реАрдВ рд╣реИ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ рдпрд╣ рд╕рдм рдХреЛрдб рд╣реИрдХреА рдФрд░ рдХрд╛рдлреА рдШреЛрд╖рдгрд╛рддреНрдордХ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛрдб рдмреЗрд╕ рдореЗрдВ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рдирд╛ рдПрдХ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП - рдпрд╣ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рдЖрдирд╛ рдЪрд╛рд╣рд┐рдПред = рдореЗрд░реА рд░рд╛рдп рд╣реИ рдХрд┐ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рд░реВрдЯрд┐рдВрдЧ рд▓реЙрдЬрд┐рдХ рдХреЗ рд╕рд╛рде рдмрдирд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рд░рд┐рдПрдХреНрдЯ рд░рд╛рдЙрдЯрд░ рдХреА рддрд░рд╣ рдСрдкреНрдЯ рдЖрдЙрдЯ рдХрд░рдиреЗ рдХреЗ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рдеред

@ рдирдерд╛рдирд┐рдПрд▓рд╣рд┐рд▓

рдпрд╣ рдЕрдЧрд▓реЗ рдирд┐рд░реНрдпрд╛рдд рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рднреА рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдкрд░рд┐рд╣рд╛рд░реНрдп рд╣реИ

рд░реБрдХреЛ - рдореБрдЭреЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдкрдврд╝рдиреЗ рд╕реЗ рд╕рдордЭ рдореЗрдВ рдЖрдпрд╛ рдХрд┐ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреЛрдб рд╣реИ:

рдкреГрд╖реНрдареЛрдВ рдХреЛ html рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрдпрд╛рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЕрд░реНрдерд╛рдд /about /about.html рдмрди рдЬрд╛рдПрдЧрд╛ред

рдкреГрд╖реНрдареЛрдВ рдХреЛ index.html рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдиреЗрдХреНрд╕реНрдЯ.js рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЕрд░реНрдерд╛рдд /about рдмрди рдЬрд╛рддрд╛ рд╣реИ /about/index.html рдФрд░ /about/ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд░реВрдЯ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реЛрддрд╛ рд╣реИред Next.js 9 рд╕реЗ рдкрд╣рд▓реЗ рдпрд╣ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡реНрдпрд╡рд╣рд╛рд░ рдерд╛ред рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд next.config.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

// next.config.js
module.exports = {
  exportTrailingSlash: true,
}

рднрд▓реЗ рд╣реА рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ next export рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдерд┐рд░ HTML рдирд┐рд░реНрдпрд╛рдд рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВ рд╣реИ, рдореИрдВ рдЗрд╕ рддрд░реНрдХ рд╕реЗ рд╕рд╣рдордд рдирд╣реАрдВ рд╣реВрдВ рдХрд┐ рд╕рд┐рд░реНрдл рдЗрд╕рд▓рд┐рдП рдХрд┐ рдЕрдЧрд▓рд╛ рдЗрд╕ (рдЕрджреНрднреБрдд) рд╕реБрд╡рд┐рдзрд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЕрдиреНрдп рдореЛрдб рдХреЛ рднреБрдЧрддрдирд╛ рдкрдбрд╝рддрд╛ рд╣реИ (рдореИрдВ рдирд╣реАрдВ рдЙрдкрдпреЛрдЧ рдХреЗ рдЖрдБрдХрдбрд╝реЛрдВ рдХреЛ рдЬрд╛рдирддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдзрд┐рдХ рд▓реЛрдЧ рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рдХреЗ рд╡рд┐рдкрд░реАрдд рдирд┐рдпрдорд┐рдд рд░реВрдк рд╕реЗ рд╕рд░реНрд╡рд░ рдореЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ) рдЦрд╛рд╕рдХрд░ рдЬрдм рдпрд╣ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ

FYI рдХрд░реЗрдВ: рдПрдХ RFC рд╣реИ рдЬреЛ рдЖрдкрдХреА рд░реБрдЪрд┐ рд▓реЗ рд╕рдХрддреА рд╣реИ https://github.com/zeit/next.js/issues/9081

// next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: "/:path*/",
        destination: "/:path",
        statusCode: 301
      }
    ];
  }
};

@Janpot рдЗрд╕реЗ рдкреНрдпрд╛рд░ рдХрд░реЗрдВ - рдпрд╣ рд╣рдореЗрдВ рдЖрдзреЗ рд░рд╛рд╕реНрддреЗ рдореЗрдВ рд▓рд╛рдПрдЧрд╛ рдпрд╛рдиреА рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдмрдирд╛рдиреЗ рдХреЗ рдмрд┐рдирд╛ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕рдорд░реНрдерди рд╣реЛрдЧрд╛ред рдпрд╣ рдЕрднреА рднреА рдЕрдирд┐рд╡рд╛рд░реНрдп рд╣реЛрдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдЬреЛрдбрд╝реЗ рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рдорд╛рд░реНрдЧ рдХреЗ рд▓рд┐рдП, рдЙрдиреНрд╣реЗрдВ next.config.js рдореЗрдВ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рд╕реЗрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ - рдпрд╛ рд╢рд╛рдпрдж рд╣рдо рд╕рднреА рдорд╛рдорд▓реЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд░реЗрдЧреЗрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ @bitjson рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:

          .replace(/\/+$/, '')
          .replace(/\/+#/, '#')
          .replace(/\/+\?/, '?')
          .replace(/\/+/g, '/')

рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрджрд┐ рдХреЛрд░ рдЯреАрдо рдЗрд╕ рдЖрд░рдПрдлрд╕реА рдХреЛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджреЗ рд░рд╣реА рд╣реИ, рддреЛ рдореИрдВ рдЕрддреНрдпрдзрд┐рдХ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рд╣рдо рдПрдХ рдХрджрдо рдЖрдЧреЗ рдмрдврд╝реЗрдВ рдФрд░ рдЗрд╕реЗ _config_ рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рдХрд░реЗрдВ рддрд╛рдХрд┐ рдХреЛрдИ рднреА рдЗрд╕ рддрд░рд╣ рд╕реЗ

// next.config.js
module.exports = {
  ignoreStrictRoutes: false, // default value: true
};

рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рдХрджрдо рд╣реИ - рдЕрдЪреНрдЫрд╛ рд╕рд╛рдорд╛рди @Timer !! рдореИрдВ

@ рдирд┐рдХ-рдЬреЙрди рдЬрд┐рд╕ рдкрде рдХреЛ рдореИрдВрдиреЗ "/:path*/" рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рд╣реИ, рдЙрд╕реЗ рд╕рднреА рдХреЛ рдкрдХрдбрд╝рдирд╛ рдЪрд╛рд╣рд┐рдП ( :path рдПрдХ рдЦрдВрдб рдХреЛ рдкрдХрдбрд╝рддрд╛ рд╣реИ, * рдЗрд╕реЗ 0 рд╕реЗ n рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдкрдХрдбрд╝рддрд╛ рд╣реИред)

@ рдЬрдирдкреЛрдЯ рдЖрд╣ рдореЗрд░рд╛ рдмреБрд░рд╛ тАНтЩВ рдореИрдВ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд░рд╣рд╛ рд╣реВрдВ рдХрд┐ рд╣рдореЗрдВ рдЙрд╕ рд░реЗрдЧреЗрдХреНрд╕ рдореЗрдВ рдХрд┐рд╕реА рднреА рдкрд┐рдЫрд▓реА рдХреНрд╡реЗрд░реА рдкреИрд░рд╛ рдкрд░ рднреА рд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рдЕрднреА рднреА рджреВрд╕рд░реЗ рднрд╛рдЧ рдХреЗ рд╕рд╛рде рдЦрдбрд╝рд╛ рд╣реВрдВ:

рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрджрд┐ рдХреЛрд░ рдЯреАрдо рдЗрд╕ рдЖрд░рдПрдлрд╕реА рдХреЛ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рджреЗ рд░рд╣реА рд╣реИ, рддреЛ рдореИрдВ рдЕрддреНрдпрдзрд┐рдХ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реВрдВ рдХрд┐ рд╣рдо рдПрдХ рдХрджрдо рдЖрдЧреЗ рдмрдврд╝реЗрдВ рдФрд░ рдЗрд╕реЗ рдПрдХ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдмрдирд╛рдПрдВ рдЬрд┐рд╕рд╕реЗ рдХреЛрдИ рднреА рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓ рд╕рдХреЗ

// next.config.js
module.exports = {
  ignoreStrictRoutes: false, // default value: true
};

рдпрджрд┐ рдЖрдк рдПрдХ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рд╕рдЦреНрдд рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рддреЛ рдЖрдк рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдХрд╕реНрдЯрдо рд░реВрдЯ рд╣реИрдВрдбрд▓рд░ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

app.render(req, res, urlWithoutTrailingSlash, query);

рдЗрд╕ рддрд░рд╣ рд╣рдо /path рдФрд░ /path/ рджреЛрдиреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдФрд░ рдПрдХ рд╣реА рдкреГрд╖реНрда рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВред

Oauth рдлрд╝реЗрдбрд░реЗрд╢рди рдкреНрд░рджрд╛рддрд╛рдУрдВ рдХреЛ рдЕрдХреНрд╕рд░ рдЕрдиреБрдЧрд╛рдореА рдлрд╝реЙрд░рд╡рд░реНрдб рд╕реНрд▓реИрд╢ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдмрд╣реБрдд рдЬрдЯрд┐рд▓ рдмрдирд╛ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдореЗрдВ рддрдХрдиреАрдХреА рдЪреБрдиреМрддреА рдХреНрдпрд╛ рд╣реИ? рдпрд╛ рдпрд╣ рдЕрдЧрд▓реЗ рд╕реЗ рдПрдХ рдбрд┐рдЬрд╛рдЗрди рдирд┐рд░реНрдгрдп рд╣реИ?

рдореИрдВрдиреЗ рдЗрд╕ рдзрд╛рдЧреЗ рдореЗрдВ рдЕрдм рддрдХ рдЗрд╕рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдЕрдм рдХреЗ рд╕рд╛рде рддреИрдирд╛рддреА рдХреЗ рдмрд╛рдж рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдЕрдиреБрднрд╡ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдореИрдВ рдХреЗрд╡рд▓ now dev рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╕рдордп рдЗрд╕реЗ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдЕрдиреБрднрд╡ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

const removeTrailingSlashes = (req, res, expressNext) => {
  if (req.path.substr(-1) === '/' && req.path.length > 1) {
    const query = req.url.slice(req.path.length);
    res.redirect(301, req.path.slice(0, -1) + query);
  } else {
    expressNext();
  }
};

рдЗрд╕реЗ рд╕реНрдЯреИрдХ рдУрд╡рд░рдлреНрд▓реЛ рд╕реЗ рдорд┐рд▓рд╛ рдФрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ред рдпрд╣ рд╕рдорд╛рдзрд╛рди рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

@ рдЧрдгреЗрд╢ рдХрдерд╛рд░ рдореИрдВ рдирд╣реАрдВ рджреЗрдЦрддрд╛ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдпрджрд┐ рдЖрдк рдиреЗрдХреНрд╕реНрдЯ.рдЬреЗрдПрд╕ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдо рдЗрд╕ рдкрд░ рд╕рд╣рдордд рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдпрд╣ рд╡рд┐рдиреНрдпрд╛рд╕ рдпреЛрдЧреНрдп рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╣рдореЗрд╢рд╛ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ, рд╕рд╛рдкреЗрдХреНрд╖ рдпреВрдЖрд░рдПрд▓ рддрд░реНрдХ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реЛрддрд╛ рд╣реИ рдЬрдм рд╕рднреА рдкреГрд╖реНрда рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддреЗ рд╣реИрдВред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИ рдХрд┐ /about/index.tsx /about рдмрдЬрд╛рдп /about/ , рд▓реЗрдХрд┐рди рдЕрдм рдпрд╣ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ рдХрд┐ рдЕрдЧрд▓рд╛ рд╕реНрд▓реИрд╢ рдХреЗ рдмрд┐рдирд╛ рдЙрдореНрдореАрдж рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рд╕рднреА рдкреГрд╖реНрда рд╕реНрд▓реИрд╢ рдореЗрдВ рд╕рдорд╛рдкреНрдд рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдкреГрд╖реНрдареЛрдВ рдХреЛ рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдЙрдкрдкреГрд╖реНрдареЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рдЬреЛ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдкреГрд╖реНрдареЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рддрд░реАрдХрд╛ рд╣реИред

/about/index.tsx рдлрд╝рд╛рдЗрд▓ рдХреЗ рдЕрдВрджрд░ рд╕рд╛рдкреЗрдХреНрд╖ рд▓рд┐рдВрдХ рдмрдирд╛рдирд╛ рдЕрдм рдмреЛрдЭрд┐рд▓ рд╣реИред рдпрджрд┐ рдЖрдк ./mysubpage/ рд▓рд┐рдВрдХ рдмрдирд╛рддреЗ рд╣реИрдВ рддреЛ рдпрд╣ рд╕рд╛рдЗрдЯ рдХреЗ рд░реВрдЯ рдХреА рдУрд░ рдЗрд╢рд╛рд░рд╛ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдЙрдкрдкреГрд╖реНрдареЛрдВ рдХреЛ рдЧреИрд░-рдирд╛рдо рдмрджрд▓рдиреЗ рдпреЛрдЧреНрдп рдмрдирд╛рддрд╛ рд╣реИред рдореИрдВ рдПрдХ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдирд╣реАрдВ рдмрдирд╛ рд╕рдХрддрд╛ /about/ рдкреГрд╖реНрдареЛрдВ рд╕реЗ рднрд░рд╛ рд╣реИ рдХрд┐ рдореИрдВ рд╕рд┐рд░реНрдл рдирд╛рдо рдмрджрд▓ рд╕рдХрддрд╛ рд╣реВрдБ, рдХреНрдпреЛрдВрдХрд┐ рдореБрдЭреЗ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рд╕рд╛рдкреЗрдХреНрд╖ рд▓рд┐рдВрдХ рдХреЛ рднреА рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

рд╕рд╛рде рд╣реА wget -r рд╕рд╛рдЗрдЯ рд╣рдореЗрд╢рд╛ рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреЗ рд╕рд╛рде, index.html рдлрд╝рд╛рдЗрд▓реЛрдВ рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рд╕рдордЭрджрд╛рд░ рдкрд░рд┐рдгрд╛рдо рдЙрддреНрдкрдиреНрди рдХрд░рддреА рд╣реИред

рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рд╕реЗрдЯрд┐рдВрдЧ рдХреЛ рдмрджрд▓рдирд╛ рдмрдбрд╝реЗ рдкреИрдорд╛рдиреЗ рдкрд░ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рддреЛрдбрд╝ рд░рд╣рд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕рднреА рд╕рд╛рдЗрдЯреЗрдВ рдЧреИрд░-рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреА рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореИрдВ рд╕рдВрд╕реНрдХрд░рдг 9 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ рдФрд░ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдЕрднреА рднреА рд╣рд▓ рдирд╣реАрдВ рд╣реБрдИ рд╣реИ

рдореИрдВ рдЕрдкрдиреЗ next.config.js рдкрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреА рддрд░рд╣ рдХреБрдЫ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдерд╛:

exportPathMap: async function() {
  const paths = {
    '/': { page: '/' },
    '/authors/index.html': { page: '/authors' },
  };

  return paths;
},

/authors рдкрд╣реБрдВрдЪрдиреЗ рд╕реЗ 302 location рд╕реЗ /authors/ ред рдореИрдВ http-serve рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рд╕рд░реНрд╡рд░-рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИ рдпрд╛ рдирд╣реАрдВред

рдЬрдм рдореБрдЭреЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рддреЛ рдореИрдВ рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХреЗ рд╕рд╛рде рдЖрдпрд╛

рдореЗрд░реЗ _error.js рдкреГрд╖реНрда рдореЗрдВ

Error.getInitialProps = ({ res, err, asPath }) => {
    const statusCode = res ? res.statusCode : err ? err.statusCode : 404;

    const checkForTrailingSlashes = () => {
        if (asPath.match(/\/$/)) { // check if the path ends with trailing slash
            const withoutTrailingSlash = asPath.substr(0, asPath.length - 1);
            if (res) {
                res.writeHead(302, {
                    Location: withoutTrailingSlash
                })
                res.end()
            } else {
                Router.push(withoutTrailingSlash)
            }
        }
    }

    if (statusCode && statusCode === 404) {
        checkForTrailingSlashes();
    } else {
        // 
    }
    return { statusCode };
}

рдХреНрдпрд╛ рдпрд╣ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рджреВрд░ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реИ?

рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕рд╛ рд╣реИ?

рдкреЗрдЬ/_app.jsx

``` 'рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛' рд╕реЗ рдЖрдпрд╛рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛;
'рдЕрдЧрд▓рд╛/рдРрдк' рд╕реЗ рдРрдк рдЖрдпрд╛рдд рдХрд░реЗрдВ;

рдирд┐рд░реНрдпрд╛рдд рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡рд░реНрдЧ MyApp рдРрдк рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддрд╛ рд╣реИ {
рдкреНрд░рд╕реНрддреБрдд рдХрд░рдирд╛() {
const {рдШрдЯрдХ, рдкреЗрдЬрдкреНрд░реЙрдкреНрд╕, рд░рд╛рдЙрдЯрд░: {asPath}} = this.props;

// Next.js currently does not allow trailing slash in a route.
// This is a client side redirect in case trailing slash occurs.
if (asPath.length > 1 && asPath.endsWith('/')) {
  const urlWithoutEndingSlash = asPath.replace(/\/*$/gim, '');

  if (typeof window !== 'undefined') {
    window.location.replace(urlWithoutEndingSlash);
  }
  return null;
}

return <Component {...pageProps} />;

}
}
```

@cnblackxp рд╕реБрдЭрд╛рд╡ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдЗрд╕рд╕реЗ рдореБрдЭреЗ рдорджрдж рдорд┐рд▓реАред рдЧреИрд░-рдкрд┐рдЫрд▓рд╛ 404 рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡реНрдпрд╡рд╣рд╛рд░ рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕реЗ рдХреИрд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рд╣реИ (рдпрд╛рдиреА рдореИрдВ рдбрд┐рдлрд╝реЙрд▓реНрдЯ Error рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдлрд┐рд░ рд╕реЗ рдирд┐рд░реНрдпрд╛рдд рдХрд░ рд░рд╣рд╛ рд╣реВрдВ):

import Error from "next/error";
import Router from "next/router";

export default Error;

Error.getInitialProps = ({ res, err, asPath }) => {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404;

  if (statusCode && statusCode === 404) {
    if (asPath.match(/\/$/)) {
      const withoutTrailingSlash = asPath.substr(0, asPath.length - 1);
      if (res) {
        res.writeHead(302, {
          Location: withoutTrailingSlash
        });
        res.end();
      } else {
        Router.push(withoutTrailingSlash);
      }
    }
  }

  return { statusCode };
};

рд╣рд╛рдБ, рд╡рд╣ @cansin рддрдм рддрдХ

@AlexSapoznikov рдХреЗ рд╕рдорд╛рдзрд╛рди рдореЗрдВ рдЫреЛрдЯрд╛ рд╕реБрдзрд╛рд░:

  render() {
    const { Component, pageProps, router: { asPath } } = this.props;

    // Next.js currently does not allow trailing slash in a route.
    // This is a client side redirect in case trailing slash occurs.
    if (pageProps.statusCode === 404 && asPath.length > 1 && asPath.endsWith('/')) {

рдпрд╣рд╛рдВ рдХреЗрд╡рд▓ рдЕрдВрддрд░ рдпрд╣ рдЬрд╛рдВрдЪ рд░рд╣рд╛ рд╣реИ рдХрд┐ рд╕реНрдерд┐рддрд┐ рдХреЛрдб 404 рд╣реИред рдореБрдЭреЗ рдЧрддрд┐рд╢реАрд▓ рдорд╛рд░реНрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдорд╕реНрдпрд╛рдПрдВ рдЖрдИрдВ, рдЬрд╣рд╛рдВ рд╡реЗ рд╣рдореЗрд╢рд╛ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХреЗ рдХрд╛рд░рдг рд╕рд░реНрд╡рд░ рдкрд░ рдкреНрд░рддрд┐рдкрд╛рджрди рдХрд░ рд░рд╣реЗ рдереЗред рдпрджрд┐ рдЖрдк рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рд░реВрдЯрд┐рдВрдЧ рдХреЛ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рд▓рд┐рдВрдХ href рдкреНрд░реЛрдк рдореЗрдВ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рдирд╣реАрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рдЖрдкрдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред

рддреНрд░реБрдЯрд┐ рдШрдЯрдХ рдореЗрдВ рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдореЗрдВ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░реЗрдЧрд╛ рдЬреЛ рдореБрдЭреЗ рдкрд░реЗрд╢рд╛рди рдХрд░рддрд╛ рд╣реИред рдореЗрд░реЗ рдкрд┐рдЫрд▓реЗ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдореЗрдВ рдХреБрдЫ рд╕реБрдзрд╛рд░:

рдХреНрдпрд╛ рд╕реБрдзрд╛рд░ рд╣реБрдЖ рд╣реИ рдХрд┐ рдЕрдм рдпрд╣ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдореЗрдВ рдиреЗрдХреНрд╕реНрдЯ/рд░рд╛рдЙрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдпреВрдЖрд░рдПрд▓ рд░рд┐рдкреНрд▓реЗрд╕рдореЗрдВрдЯ рдмрд┐рдирд╛ рд░реАрд▓реЛрдб рдХреЗ рд╣реЛрддрд╛ рд╣реИред

рдкреЗрдЬ/_app.jsx

import App from 'next/app';
import Router from 'next/router';

export default class MyApp extends App {
  render() {
    const { Component, pageProps, router: { asPath, route } } = this.props;

    // Next.js currently does not allow trailing slash in a route.
    // This is a client side redirect in case trailing slash occurs.
    if (pageProps.statusCode === 404 && asPath.length > 1 && asPath.endsWith('/')) {
      const routeWithoutEndingSlash = route.replace(/\/*$/gim, '');
      const asPathWithoutEndingSlash = asPath.replace(/\/*$/gim, '');

      if (typeof window !== 'undefined') {
        Router.replace(routeWithoutEndingSlash, asPathWithoutEndingSlash);
      }
      return null;
    }

    return <Component {...pageProps} />;
  }
}

404 рдлрд┐рдХреНрд╕ рдХреЗ рд▓рд┐рдП @mbrowne рдХреЛ рднреА рдзрдиреНрдпрд╡рд╛рдж :)

@cansin рдХрд╛ рд╕рдорд╛рдзрд╛рди рд▓рд┐рдпрд╛ рдФрд░ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рдЬреЛрдбрд╝рд╛

MyError.getInitialProps = async ({ res, err, asPath }) => {
  // Capture 404 of pages with traling slash and redirect them
  const statusCode = res 
    ? res.statusCode
    : (err ? err.statusCode : 404);

  if (statusCode && statusCode === 404) {
    const [path, query = ''] = asPath.split('?');                                                                                                                                                                                             
    if (path.match(/\/$/)) {
      const withoutTrailingSlash = path.substr(0, path.length - 1); 
      if (res) {
        res.writeHead(302, {
          Location: `${withoutTrailingSlash}${query ? `?${query}` : ''}`,
        }); 
        res.end();
      } else {
        Router.push(`${withoutTrailingSlash}${query ? `?${query}` : ''}`);
      }   
    }   
  }

@pinpointcoder рдХреНрдпрд╛ рдЖрдк рдПрдХ рдпреВрдЖрд░рдПрд▓ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдФрд░ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╣реЛрддреЗ рд╣реИрдВ? рдХреНрдпрд╛ рдЖрдк /blog/?123 рддрд░реНрдЬ рдкрд░ рд╕реЛрдЪ рд░рд╣реЗ рд╣реИрдВ?

рдКрдкрд░ рджрд┐рдП рдЧрдП рдЖрдкрдХреЗ рдХреБрдЫ рдХрд╛рдордХрд╛рдЬ рдХреЗ рд▓рд┐рдП рд╕рднреА рдХреЛ рдзрдиреНрдпрд╡рд╛рджред рдЙрдиреНрд╣реЛрдВрдиреЗ рдХрд╛рдо рдХрд┐рдпрд╛!

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдХреНрдпрд╛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдиреЗрдХреНрд╕реНрдЯ рдХреА рдЯреАрдо рд╕реЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рддрд░реАрдХрд╛ рд╣реИ? рдпрд╣ рдореБрджреНрджрд╛ рдпрд╣рд╛рдВ рд╕рд╛рд▓реЛрдВ рд╕реЗ рд╣реИред

рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкреГрд╖реНрда рдЕрдЧрд▓реЗ рдирд┐рд░реНрдпрд╛рдд рдореЗрдВ рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреЗ рд╕рд╛рде рдкреНрд░рд╕реНрддреБрдд рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ

@pinpointcoder рдХреНрдпрд╛ рдЖрдк рдПрдХ рдпреВрдЖрд░рдПрд▓ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдФрд░ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд╣реЛрддреЗ рд╣реИрдВ? рдХреНрдпрд╛ рдЖрдк /blog/?123 рддрд░реНрдЬ рдкрд░ рд╕реЛрдЪ рд░рд╣реЗ рд╣реИрдВ?

@coodoo рдЙрд╕реЗ рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рд╣рд╛рдБ, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ рдРрд╕рд╛ рдмрд╣реБрдд рд╣реЛрддрд╛ рд╣реИред рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдПрдХ WordPress рд╕рд╛рдЗрдЯ рдХреЛ Next.js рдкрд░ рдХреНрд░рдорд┐рдХ рд░реВрдк рд╕реЗ рдорд╛рдЗрдЧреНрд░реЗрдЯ рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╣реВрдВ, рдФрд░ рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ, рдореВрд▓ "рдбреЗрд╡рд▓рдкрд░реНрд╕" рдиреЗ рдкреНрд░рддреНрдпреЗрдХ URL рдкрд░ рдПрдХ рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреЛ рдмрд╛рдзреНрдп рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдиреБрдЧрд╛рдореА рджреЛрдиреЛрдВ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЕрдиреБрд░реЛрдз рд╣реИрдВ рд╕реНрд▓реИрд╢ рдФрд░ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ред

рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рдХрдИ рдмреНрд▓реЙрдЧ рдкреЛрд╕реНрдЯ рдорд╛рдЗрдЧреНрд░реЗрдЯ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдХреИрдирдирд┐рдХрд▓ рдпреВрдЖрд░рдПрд▓ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдПрдХ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рд╢рд╛рдорд┐рд▓ рд╣реИ, рдпрд╣ рдЕрднреА рдореЗрд░реЗ рдЧрдзреЗ рдореЗрдВ рдПрдХ рдмрдбрд╝рд╛ рджрд░реНрдж рд╣реИред

рдореИрдВрдиреЗ рдЗрд╕реЗ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдФрд░ рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдпрд╣ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ, рдФрд░ рдЖрдк рдЕрднреА рднреА next.js рдХреА рдлрд╝рд╛рдЗрд▓-рдЖрдзрд╛рд░рд┐рдд рд░реВрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рддрд░рд╣ рдЖрдк рдЙрд╕ URL рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ next.js рджреЗрдЦрддрд╛ рд╣реИ рдФрд░ рдЕрд╕рд▓реА URL рдХреЗ рдЕрдВрдд рдореЗрдВ рдЕрднреА рднреА рдПрдХ рд╕реНрд▓реИрд╢ рд╣реИ:

const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const conf = require('./next.config.js')

const PORT = process.env.PORT || 5000

const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev, conf })
const handle = app.getRequestHandler()

app.prepare().then(() => {
    createServer((req, res) => {
        // If there is a slash at the end of the URL, remove it before sending it to the handle() function.
        // This is a workaround for https://github.com/zeit/next.js/issues/5214
        const url =
            req.url !== '/' && req.url.endsWith('/')
                ? req.url.slice(0, -1)
                : req.url
        // Be sure to pass `true` as the second argument to `url.parse`.
        // This tells it to parse the query portion of the URL.
        const parsedUrl = parse(url, true)

        handle(req, res, parsedUrl)
    }).listen(PORT, err => {
        if (err) throw err
        console.log(`> Ready on http://localhost:${PORT}`)
    })
})

рджреЗрдЦреЗрдВ https://nextjs.org/docs/advanced-features/custom-server

@mbrowne рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░рдгреЛрдВ рдХрд╛ рдПрдХ рд╕рдореВрд╣ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЦреНрдп рдмрд╛рдд рдЬрд┐рд╕рдиреЗ рдореБрдЭреЗ рдЕрдм рддрдХ рдПрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХрд╛ рд╣реИ, рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ рдЖрдк рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╕реНрдЯреЗрдЯрд┐рдХ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдЦреЛ рджреЗрддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╕реНрдереИрддрд┐рдХ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ?

рд╣рдореЗрдВ рдЗрд╕ рд╕рдордп рдЕрдкрдиреЗ рдРрдк рдХреЗ рд▓рд┐рдП рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╕реНрдереИрддрд┐рдХ рдЕрдиреБрдХреВрд▓рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕ рдкрд░ рдзреНрдпрд╛рди рдирд╣реАрдВ рджрд┐рдпрд╛ред

рдореИрдВ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЬрдм рдЖрдк рд╕рдВрд╢реЛрдзрд┐рдд (рдмрд┐рдирд╛ рдкреНрд░рдореБрдЦ рд╕реНрд▓реИрд╢ рдХреЗ) url рдХреЛ handle , рддреЛ SSR рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рд╕реЗ рдЕрд▓рдЧ url рджреЗрдЦрддрд╛ рд╣реИред
рдореИрдВ рдЙрди рдЦрд░рд╛рдм рд╣реИрдХреНрд╕ рдХреЗ рдмрд┐рдирд╛ рдкреНрд░рдореБрдЦ рд╕реНрд▓реИрд╢ рдХреЗ рд╕рд╛рде рдпреВрдЖрд░рдПрд▓ рд╕реЗ рдореЗрд▓ рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП next рд░рд╛рдЙрдЯрд░ рдкрд╕рдВрдж рдХрд░реВрдВрдЧрд╛ред

2020 рдФрд░ рдпрд╣ рдмрдЧ рдЕрднреА рднреА рд╣реЛрддрд╛ рд╣реИред рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп

рдпрд╣ рдПрдХ рдЦрд░рд╛рдм рдмрдЧ рд╣реИ рдЬрд┐рд╕реЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдареАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред /products рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди /products/ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде

<Link href="/products">
  <a>Products</a>
</Link>

рдореБрдЭреЗ рд╕рдордЭ рдЖ рдЧрдпрд╛

index.js:1 Warning: Prop `href` did not match. Server: "/products" Client: "/products/"

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдЧрд░ рдореИрдВ рд▓рд┐рдВрдХ рдХреЛ /products/ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ, рд▓рд┐рдВрдХ рдкрд░ рдЬрд╛рддрд╛ рд╣реВрдВ, рдФрд░ рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди рдкреГрд╖реНрда рдХреЛ рд░реАрдлреНрд░реЗрд╢ рдХрд░рддрд╛ рд╣реВрдВ, рддреЛ рдореБрдЭреЗ 404 рдорд┐рд▓рддрд╛ рд╣реИред рдпрд╣ рдХрд╛рдлреА рджрд░реНрджрдирд╛рдХ рд╡рд┐рдХрд╛рд╕ рдЕрдиреБрднрд╡ рд╣реИред

рдпрд╣ рдореБрджреНрджрд╛ рдкрд╣рд▓реА рдмрд╛рд░ 1.5 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рд░рд┐рдкреЛрд░реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛; рдХреНрдпрд╛ рд╣рдо рдХреГрдкрдпрд╛ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╕реБрдзрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдпрд╣ рдЕрднреА рднреА 9.3.4 рдореЗрдВ рдореМрдЬреВрдж рд╣реИред

рдореИрдВрдиреЗ рдПрд╕рдИрдУ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рд╕рд╛рдордЧреНрд░реА рджрд┐рдЦрд╛рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЧреИрд░-рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдпреВрдЖрд░рдПрд▓ рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рди рдХрд┐рдпрд╛ред

app.prepare().then(() => {
  createServer((req, res) => {
    if (req.url !== '/' && req.url.endsWith('/')) {
      res.writeHead(301, { Location: req.url.slice(0, -1) })
      res.end()
    }
    handle(req, res, parse(req.url, true))
  }).listen(PORT, err => {
    if (err) throw err
    console.log(`> Ready on http://localhost:${PORT}`)
  })
})

SEO рдХреЗ рд▓рд┐рдП, rel="canonical" рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдЗрд╕ 404 рд╕рдорд╕реНрдпрд╛ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдпрд╣ рдПрдХ рдЦрд░рд╛рдм рдмрдЧ рд╣реИ рдЬрд┐рд╕реЗ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдареАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред /products рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди /products/ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде

<Link href="/products">
  <a>Products</a>
</Link>

рдореБрдЭреЗ рд╕рдордЭ рдЖ рдЧрдпрд╛

index.js:1 Warning: Prop `href` did not match. Server: "/products" Client: "/products/"

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЕрдЧрд░ рдореИрдВ рд▓рд┐рдВрдХ рдХреЛ /products/ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реВрдВ, рд▓рд┐рдВрдХ рдкрд░ рдЬрд╛рддрд╛ рд╣реВрдВ, рдФрд░ рд╡рд┐рдХрд╛рд╕ рдХреЗ рджреМрд░рд╛рди рдкреГрд╖реНрда рдХреЛ рд░реАрдлреНрд░реЗрд╢ рдХрд░рддрд╛ рд╣реВрдВ, рддреЛ рдореБрдЭреЗ 404 рдорд┐рд▓рддрд╛ рд╣реИред рдпрд╣ рдХрд╛рдлреА рджрд░реНрджрдирд╛рдХ рд╡рд┐рдХрд╛рд╕ рдЕрдиреБрднрд╡ рд╣реИред

рдпрд╣ рдореБрджреНрджрд╛ рдкрд╣рд▓реА рдмрд╛рд░ 1.5 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рд░рд┐рдкреЛрд░реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛; рдХреНрдпрд╛ рд╣рдо рдХреГрдкрдпрд╛ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╕реБрдзрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рдпрд╣ рдЕрднреА рднреА 9.3.4 рдореЗрдВ рдореМрдЬреВрдж рд╣реИред

рдореБрдЭреЗ рднреА рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдпрд╣ рдореБрджреНрджрд╛ рдорд┐рд▓ рд░рд╣рд╛ рд╣реИред

рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдЗрд╕реЗ рдХреИрд╕реЗ рдареАрдХ рдХрд┐рдпрд╛, https://medium.com/@thisisayush/handling -404-trailing-slash-error-in-nextjs-f8844545afe3

рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдореИрдВрдиреЗ рдЗрд╕реЗ рдХреИрд╕реЗ рдареАрдХ рдХрд┐рдпрд╛, https://medium.com/@thisisayush/handling -404-trailing-slash-error-in-nextjs-f8844545afe3

рдзрдиреНрдпрд╡рд╛рдж, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред

@timneutkens рдХрд┐рд╕реА рднреА рдореМрдХреЗ рдкрд░ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд╛рд╕ рдХрд╛рд░реНрдпрдХреНрд░рдо рдореЗрдВ рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ?

рдЗрд╕рд╕реЗ рднреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рд╕рдорд╛рдзрд╛рди рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рдПрдХ рдХреЛ рд╣рдЯрд╛рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рд╕реНрд▓реИрд╢ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╕реЗрдЯ рдХреА рдЧрдИ рд╕рд╛рдЗрдЯреЛрдВ рдХрд╛ рд░рдЦрд░рдЦрд╛рд╡ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдврд╛рдВрдЪреЗ рдХреЛ рдЗрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЛ рдордирдорд╛рдиреЗ рдврдВрдЧ рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

@AlexSapoznikov рдХреЗ рд╕рдорд╛рдзрд╛рди рдиреЗ рд╣рдорд╛рд░реЗ рд▓рд┐рдП Netlify (рдЬреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдЬреЛрдбрд╝рддрд╛ рд╣реИ) рдХреЗ рд╕рд╛рде рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ред рдпрд╣рд╛рдВ рдПрдХ рдЙрдиреНрдирдд рд╕рдВрд╕реНрдХрд░рдг рд╣реИ рдЬреЛ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореНрд╕ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рддрд╛ рд╣реИ:

import App from "next/app";

export default class MyApp extends App {
  render() {
    const { Component, pageProps, router, router: { asPath } } = this.props;

    // Next.js currently does not allow trailing slash in a route, but Netlify appends trailing slashes. This is a
    // client side redirect in case trailing slash occurs. See https://github.com/zeit/next.js/issues/5214 for details
    if (asPath && asPath.length > 1) {
      const [path, query = ""] = asPath.split("?");
      if (path.endsWith("/")) {
        const asPathWithoutTrailingSlash = path.replace(/\/*$/gim, "") + (query ? `?${query}` : "");
        if (typeof window !== "undefined") {
          router.replace(asPathWithoutTrailingSlash, undefined, { shallow: true });
          return null;
        }
      }
    }

    return <Component {...pageProps} />;
  }
}

рдореИрдВ рдХреНрд╖рдорд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдПрдХ рдЕрдЧрд▓рд╛ рдЬреЗрдПрд╕ рдиреМрд╕рд┐рдЦрд┐рдпрд╛ рд╣реВрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдЕрдиреНрдп рдПрд╕рдбреАрдХреЗ рдФрд░ рдкреНрд▓реЗрдЯрдлреЙрд░реНрдо рдкрд░ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд╡рд┐рдХрд╛рд╕ рдХрд╛ рдЕрдиреБрднрд╡ рд╣реИред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ "рдмрдЧ" рдиреЗ рдореБрдЭреЗ рд╕рдмрд╕реЗ рдЬреНрдпрд╛рджрд╛ рд╣реИрд░рд╛рди рдХрд┐рдпрд╛ред рдореЗрд░реЗ рд▓рд┐рдП, рдЗрд╕рдиреЗ "рдХрдо рд╕реЗ рдХрдо рд╡рд┐рд╕реНрдордп рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд" рдХрд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд┐рдпрд╛ред рдореБрдЭреЗ рдмрд╕ рдЙрдореНрдореАрдж рдереА рдХрд┐ рдореЗрд░рд╛ /about/ рдФрд░ /about рд╡рд╣реА рдХрд╛рдо рдХрд░реЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдореИрдВрдиреЗ рдЕрдкрдиреЗ /pages/about/ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ index.tsx рд░рдЦрд╛ рд╣реИред

рдореИрдВрдиреЗ рдкрд╣рд▓реА рдмрд╛рд░ 1990 рдХреЗ рджрд╢рдХ рдХреЗ рдЕрдВрдд рдореЗрдВ рдЕрдкрдиреЗ рд╕рд░реНрд╡рд░ рдкрд░ HTML FTP'd рдХреЗ рд╕рд╛рде рд╡реЗрдм рд╕рд╛рдЗрдЯ рдмрдирд╛рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛, рдФрд░ рдмрд╛рдж рдореЗрдВ PHP рдФрд░ Apache, рдФрд░ рдЕрдВрддрддрдГ рдЬрд╛рд╡рд╛ рд╕рд░реНрд╡рд░ рдкрд░ рдЪрд▓рд╛ рдЧрдпрд╛ред рдЕрдм рдореИрдВ рдореЛрдмрд╛рдЗрд▓ рдРрдкреНрд╕ рдореЗрдВ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рд╣реВрдВред рдпрд╣ рдореЗрд░реЗ рд▓рд┐рдП рдЕрдЬреАрдм рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдореБрдЭреЗ рдЗрд╕реЗ рдЕрдкрдиреЗ рджреЗрд╡ рд╕рд░реНрд╡рд░ рдкрд░ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдкреЗрдЬ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред

рдореИрдВ рдПрдХ рд╕реНрдерд┐рд░ рдирд┐рд░реНрдпрд╛рдд рдХрд░рдиреЗ рдХреА рдпреЛрдЬрдирд╛ рдмрдирд╛ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдпрд╣ рдЙрддреНрдкрд╛рджрди рдореЗрдВ рджрд┐рдЦрд╛рдИ рдирд╣реАрдВ рджреЗрдЧрд╛, рднрд▓реЗ рд╣реА рдореИрдВ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рди рд▓рд┐рдЦреВрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рджреЗрд╡ рдФрд░ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЛ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдкрд░реЗрд╢рд╛рди рдХрд░рддрд╛ рд╣реИред

рдХреНрдпрд╛ рд╣рдо рдПрдХ "рдЕрдЧрд▓рд╛ рджреЗрд╡" рдзреНрд╡рдЬ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЗрд╕реЗ рдареАрдХ рдХрд░рддрд╛ рд╣реИ рдЗрд╕рд▓рд┐рдП рд╣рдо рдЖрд▓рд╕реА рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдХреЗрд╡рд▓ рджреЗрд╡/рдбреАрдмрдЧ рд╕рдордп рдХреЗ рд▓рд┐рдП рдЕрддрд┐рд░рд┐рдХреНрдд рд░реВрдЯрд┐рдВрдЧ рддрд░реНрдХ рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ?

рдзрдиреНрдпрд╡рд╛рдж!

рдкреАрдПрд╕: рд╣рд╛рдВ, рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ /about рдФрд░ /about/ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рдпреВрдЖрд░рдПрд▓ рд╣реИрдВред рдЬрдм рдореИрдВрдиреЗ рдЕрдкрдиреЗ /pages/about/ рдлрд╝реЛрд▓реНрдбрд░ рдХреЗ рдЕрдВрджрд░ рдПрдХ index.tsx рдлрд╝рд╛рдЗрд▓ рдбрд╛рд▓реА, рддреЛ рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рднреНрд░рдорд┐рдд рд╣реЛ рдЧрдпрд╛, рдФрд░ рдкрд╛рдпрд╛ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ /about рдкрде рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди /about/ рд╕рд╛рде рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ /about/ ред рдЕрдЧрд░ рдпрд╣ рджреВрд╕рд░реА рддрд░рдл рд╣реЛрддрд╛ рддреЛ рдореБрдЭреЗ рдХрдо рдЖрд╢реНрдЪрд░реНрдп рд╣реЛрддрд╛ред

pps: рдЬрдм рдореЗрд░реЗ рдкрд╛рд╕ <Link></Link> рдШрдЯрдХ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ /about/ рдЗрд╢рд╛рд░рд╛ рдХрд░рддрд╛ рд╣реИ рддреЛ рдпрд╣ рдЕрддрд┐рд░рд┐рдХреНрдд рднреНрд░рдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдерд╛ рдФрд░ рдпрд╣ рдЕрдкреЗрдХреНрд╖рд╛ рдХреЗ рдЕрдиреБрд░реВрдк рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдлрд┐рд░ рдЬрдм рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдкрд░ рд░реАрдлреНрд░реЗрд╢ рдХрд┐рдпрд╛, рддреЛ рдпрд╣ рддреБрд░рдВрдд 404 рд╣реЛ рдЧрдпрд╛, рднрд▓реЗ рд╣реА рдпреВрдЖрд░рдПрд▓ рдирд╣реАрдВ рдмрджрд▓рд╛ред рдпрд╣ рдмрд╣реБрдд рдЖрд╢реНрдЪрд░реНрдп рдХреА рдмрд╛рдд рдереАред :-рдбреА

рд▓реЗрдХрд┐рди рдпрд╣ рдЦрд░рд╛рдм рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рд░реБрдХреЛ! рд╣рдо рдПрдХ рдХрд╕реНрдЯрдо рдЬреЛрдбрд╝рд╛ checkForTrailingSlash рдЕрдВрджрд░ рд╕рдорд╛рд░реЛрд╣ _error.js рдХрд┐ рд╕реНрд▓реИрд╢ рдФрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдкрдЯреНрдЯреА рд╣реЛрдЧреАред рдпрд╣ рдХреБрдЫ рд╕рдордп рддрдХ рдареАрдХ рд░рд╣рд╛ рдЬрдм рддрдХ рдХрд┐ рд╣рдордиреЗ (рдЖрдЦрд┐рд░рдХрд╛рд░) рдПрдХ рдХрд╕реНрдЯрдо 404 рдкреЗрдЬ рдЬреЛрдбрд╝рд╛ рдФрд░ рдкрд╛рдпрд╛ рдХрд┐ рдХрд╕реНрдЯрдо 404 рдкреЗрдЬ рдХреЗ рд╕рд╛рде, Next.js рдкреВрд░реА рддрд░рд╣ рд╕реЗ Error рдмрд╛рдпрдкрд╛рд╕ рдХрд░ рджреЗрддрд╛ рд╣реИ ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ Error.getInitialProps рдЕрдВрджрд░ рдЖрдкрдХрд╛ рдХреЛрдИ рднреА рдХрд╕реНрдЯрдо рддрд░реНрдХ рдЕрдм рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ - рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдХреЗ рд▓рд┐рдП рдЪреЗрдХ рд╕рд╣рд┐рддред

рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдореИрдВ _app.js рд╕рдорд╛рдзрд╛рди рджреВрд╕рд░реЛрдВ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реВрдВрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рдХрд╕реНрдЯрдо рд╕рд░реНрд╡рд░ рдЕрднреА рддрдХ рдПрдХ рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИред

@AlexSapoznikov рдХреЗ рд╕рдорд╛рдзрд╛рди рдиреЗ рд╣рдорд╛рд░реЗ рд▓рд┐рдП Netlify (рдЬреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдЬреЛрдбрд╝рддрд╛ рд╣реИ) рдХреЗ рд╕рд╛рде рдЕрдЪреНрдЫрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ред рдпрд╣рд╛рдВ рдПрдХ рдЙрдиреНрдирдд рд╕рдВрд╕реНрдХрд░рдг рд╣реИ рдЬреЛ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореНрд╕ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рддрд╛ рд╣реИ:

import App from "next/app";

export default class MyApp extends App {
  render() {
    const { Component, pageProps, router, router: { asPath } } = this.props;

    // Next.js currently does not allow trailing slash in a route, but Netlify appends trailing slashes. This is a
    // client side redirect in case trailing slash occurs. See https://github.com/zeit/next.js/issues/5214 for details
    if (asPath && asPath.length > 1) {
      const [path, query = ""] = asPath.split("?");
      if (path.endsWith("/")) {
        const asPathWithoutTrailingSlash = path.replace(/\/*$/gim, "") + (query ? `?${query}` : "");
        if (typeof window !== "undefined") {
          router.replace(asPathWithoutTrailingSlash, undefined, { shallow: true });
          return null;
        }
      }
    }

    return <Component {...pageProps} />;
  }
}

рдЖрдкрдХреЗ рдХреЛрдб рдирдореВрдиреЗ рдореЗрдВ рдПрдХ рдЧрдВрднреАрд░ рддреНрд░реБрдЯрд┐ рд╣реИ: рдПрдХ рдХреНрд╡реЗрд░реА рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде рдЕрдиреБрдХреНрд░рдордгрд┐рдХрд╛ рдорд╛рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдПрдХ рддреНрд░реБрдЯрд┐ рджреЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдХреЗрд╡рд▓ рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ Next.js рдХреЛ asPath рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред

рдпрд╣ рдЗрд╕реЗ рдареАрдХ рдХрд░рддрд╛ рд╣реИ:

  if (asPath && asPath.length > 1) {
    const [path, query = ''] = asPath.split('?');
    if (path.endsWith('/') && path.length > 1) {
      const asPathWithoutTrailingSlash =
        path.replace(/\/*$/gim, '') + (query ? `?${query}` : '');
      if (typeof window !== 'undefined') {
        router.replace(asPathWithoutTrailingSlash, undefined, {
          shallow: true,
        });
        return null;
      }
    }
  }

SSR рдХреЗ рд╕рд╛рде рдпрд╣ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ @pjaws рдФрд░ @AlexSapoznikov рд╕рдорд╛рдзрд╛рди рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬреЛрдбрд╝рдирд╛ рдкрдбрд╝рд╛:

  static async getInitialProps({ Component, ctx, router }) {
    /* Fixes the trailing-slash-404 bug for server-side rendering. */
    const { asPath } = router;
    if (asPath && asPath.length > 1) {
      const [path, query = ""] = asPath.split("?");
      if (path.endsWith("/") && path.length > 1) {
        const asPathWithoutTrailingSlash =
          path.replace(/\/*$/gim, "") + (query ? `?${query}` : "");
        if (ctx.res) {
          ctx.res.writeHead(301, {
            Location: asPathWithoutTrailingSlash,
          });
          ctx.res.end();
        }
      }
    }
    return {
      pageProps: Component.getInitialProps
        ? await Component.getInitialProps(ctx)
        : {},
    };
  }

рд╕рдВрднрд╡рддрдГ рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рддрд░рд╣ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдПрдХ рдРрд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рдП рдЬреЛ SSR рдФрд░ CSR рджреЛрдиреЛрдВ рдХреЗ рджреМрд░рд╛рди рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рджреЛрдиреЛрдВ рд╕реНрдерд╛рдиреЛрдВ ( getInitialProps рдФрд░ render ) рдореЗрдВ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред

рджреНрд╡рд╛рд░рд╛

рдпрд╣ рдареАрдХ рд╣реЛ рдЬрд╛рдПрдЧрд╛ рд▓реЗрдХрд┐рди рд╢реАрд░реНрд╖рдХ рдЧрд▓рдд рд╣реИред рд╣рдореНрдо
image

@AlexSapoznikov @pjaws

рдЖрдкрдХрд╛ рд╕рдорд╛рдзрд╛рди рд╣рдореЗрдВ рдЕрдирдВрдд рд▓реВрдк рдореЗрдВ рдбрд╛рд▓рддрд╛ рд╣реИ:

  if (asPath && asPath.length > 1) {
    const [path, query = ''] = asPath.split('?');
    if (path.endsWith('/') && path.length > 1) {
      const asPathWithoutTrailingSlash =
        path.replace(/\/*$/gim, '') + (query ? `?${query}` : '');
      if (typeof window !== 'undefined') {
        router.replace(asPathWithoutTrailingSlash, undefined, {
          shallow: true,
        });
        return null;
      }
    }
  }

рд╕рдВрджрд░реНрдн

рд╣рдорд╛рд░реЗ рдирд┐рдпрдВрддреНрд░рдг рд╕реЗ рдкрд░реЗ рдХрд╛рд░рдгреЛрдВ рдХреЗ рдХрд╛рд░рдг, рд╣рдо рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП exportTrailingSlash рдореЗрдВ рд╡рд┐рдХрд▓реНрдк next.config.js ред

рд╣рдо рджреВрд╕рд░реЗ рдкреЗрдЬ рдХрд╛ рд▓рд┐рдВрдХ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рд╣рдо рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рд▓рд┐рдВрдХ /somepage?param=whatever ред

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдЧрд▓рд╛ рд▓рд┐рдВрдХ рдЗрд╕реЗ /somepage/?param=whatever рдФрд░ рд╣рдореЗрдВ рдкреЗрдЬ рдирд╣реАрдВ рдорд┐рд▓рд╛ред

рдКрдкрд░ рджрд┐рдП рдЧрдП рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкреИрд░рд╛рдо рд╕рдорд╕реНрдпрд╛ рд╣рд▓ рд╣реЛ рдЬрд╛рддреА рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ /somepage/ рдЬреИрд╕реЗ рдкрд░рд┐рдирд┐рдпреЛрдЬрд┐рдд рдкреГрд╖реНрда рдкрд░ рдЬрд╛рдиреЗ рдкрд░ рдпрд╣ рдПрдХ рдЕрдирдВрдд рд▓реВрдк рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддрд╛ рд╣реИред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ @ronyeh рдиреЗ рдпрд╣рд╛рдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдЕрдЪреНрдЫрд╛ рдореБрджреНрджрд╛ рдмрдирд╛рдпрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рд╕рдорд╛рдзрд╛рди рдЪрд╛рд╣рддрд╛ рд╣реВрдВ :(

SSR рдХреЗ рд╕рд╛рде рдпрд╣ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ @pjaws рдФрд░ @AlexSapoznikov рд╕рдорд╛рдзрд╛рди рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬреЛрдбрд╝рдирд╛ рдкрдбрд╝рд╛:

  static async getInitialProps({ Component, ctx, router }) {
    /* Fixes the trailing-slash-404 bug for server-side rendering. */
    const { asPath } = router;
    if (asPath && asPath.length > 1) {
      const [path, query = ""] = asPath.split("?");
      if (path.endsWith("/") && path.length > 1) {
        const asPathWithoutTrailingSlash =
          path.replace(/\/*$/gim, "") + (query ? `?${query}` : "");
        if (ctx.res) {
          ctx.res.writeHead(301, {
            Location: asPathWithoutTrailingSlash,
          });
          ctx.res.end();
        }
      }
    }
    return {
      pageProps: Component.getInitialProps
        ? await Component.getInitialProps(ctx)
        : {},
    };
  }

рд╕рдВрднрд╡рддрдГ рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рддрд░рд╣ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдПрдХ рдРрд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рдП рдЬреЛ SSR рдФрд░ CSR рджреЛрдиреЛрдВ рдХреЗ рджреМрд░рд╛рди рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рджреЛрдиреЛрдВ рд╕реНрдерд╛рдиреЛрдВ ( getInitialProps рдФрд░ render ) рдореЗрдВ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред

рдЗрд╕рдиреЗ getServerSideProps рд╡рд╛рд▓реЗ рдкреГрд╖реНрдареЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдЕрдм рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рд╡рд╛рд▓реЗ url 404 рдХреЗ рдмрд┐рдирд╛ рдПрдХ рд╣реА рдкреГрд╖реНрда рдкрд░ рд▓реМрдЯ рд░рд╣реЗ рд╣реИрдВред
рд▓реЗрдХрд┐рди рдПрдХ рдЧрдбрд╝рдмрдбрд╝ рд╣реИ, рдореЗрд░реЗ рдкрд╛рд╕ рдХреБрдЫ рдкреГрд╖реНрда рд╣реИрдВ рдЬреЛ рдЧрддрд┐рд╢реАрд▓ рдорд╛рд░реНрдЧреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕реНрдЯреЗрдЯрд┐рдХрдкрд╛рде рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдореИрдВ рдЙрди рдкрд░ getServerSideProps рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рдФрд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЬрдм рдЗрди рдЧрддрд┐рд╢реАрд▓ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдХреЗ рд╕рд╛рде рдмреНрд░рд╛рдЙрдЬрд╝ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╡реЗ рдкрд╣рд▓реЗ 404 рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рд╡реЗ рдкреГрд╖реНрда рдкрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рддреЗ рд╣реИрдВ .

рдореИрдВ рдПрдХ /api/test рдлрд╝реЛрд▓реНрдбрд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реВрдБ

  • рдкреЗрдЬ/рдПрдкреАрдЖрдИ/test.tsx
  • рдкреЗрдЬ/рдПрдкреАрдЖрдИ/рдЯреЗрд╕реНрдЯ/[рдЖрдИрдбреА] .tsx

рдпрд╣ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ

  • рдкреНрд░рд╛рдкреНрдд / рдПрдкреАрдЖрдИ / рдкрд░реАрдХреНрд╖рдг
  • рдкреНрд░рд╛рдкреНрдд / рдПрдкреАрдЖрдИ / рдкрд░реАрдХреНрд╖рдг / 123
  • рдкреНрд░рд╛рдкреНрдд / рдПрдкреАрдЖрдИ / рдкрд░реАрдХреНрд╖рдг / 123 /

рдФрд░ рдореБрдЭреЗ рдЕрднреА рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛

  • рдкреНрд░рд╛рдкреНрдд / рдПрдкреАрдЖрдИ / рдкрд░реАрдХреНрд╖рдг /

рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджрд╛ рд╣реИ
рдкреА/рдбреА рдПрдХреНрд╕рдкреЛрд░реНрдЯрдЯреНрд░реЗрд▓рд┐рдВрдЧрд╕реНрд▓реИрд╢ = рд╕рдЪ рдЗрд╕реЗ рд╣рд▓ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ

рдпрд╣ рдПрдХ рдмрд╣реБрдд рдкреБрд░рд╛рдирд╛ рдореБрджреНрджрд╛ рд╣реИ, рдХреНрдпрд╛ рдХреЛрдИ рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдЗрд╕реЗ рдЗрддрдиреЗ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рд╕рдВрдмреЛрдзрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛?

рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЕрдм рдХреНрдпрд╛ рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред

рдореЗрд░реА рд╕рдордЭ рдпрд╣ рд╣реИ рдХрд┐ рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИрдВ:

| | рдПрдХреНрд╕рдкреЛрд░реНрдЯрдЯреНрд░реЗрд▓рд┐рдВрдЧрд╕реНрд▓реИрд╢: рдЕрд╕рддреНрдп | рдПрдХреНрд╕рдкреЛрд░реНрдЯрдЯреНрд░реЗрд▓рд┐рдВрдЧрд╕реНрд▓реИрд╢: рд╕рдЪ |
|---------------------------|-------------------------- -----|--------------------------|
| url / | . рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП | рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП |
| url /| . рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП | рдХрд╛рдо рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП |

рдпрд╣ рдЕрдкреЗрдХреНрд╖рд╛ рдХреЗ рдЕрдиреБрд░реВрдк рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрд╣рд╛рдВ:

  • рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рд╣рдо exportTrailingSlash: false
  • рдкрд░рд┐рдирд┐рдпреЛрдЬрди (рдЙрддреНрдкрд╛рджрди рдмрд┐рд▓реНрдб) рдХреЗ рд▓рд┐рдП рд╣рдо exportTrailingSlash: true рдФрд░ рдПрдХ nginx url/ рдХреЛ url/index.html рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддрд╛ рд╣реИ

рдореИрдВ @ andrescabana86 рдореЗрдВ рдЬреЛ рджреЗрдЦ рд╕рдХрддрд╛ рд╣реВрдВ GET /api/test/123/ рдЬрдмрдХрд┐ GET /api/test/ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

@Izhaki рдореИрдВрдиреЗ рджреЛрдиреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рдареЗрд╕ рдкрд░ рддреИрдирд╛рддреА ... рдФрд░ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ

  • рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ / рдПрдкреАрдЖрдИ / рдкрд░реАрдХреНрд╖рдг /

рдФрд░ рдореИрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдБ exportTrailingSlash: true

рдпрджрд┐ рдЖрдк рдЪрд╛рд╣реЗрдВ рддреЛ рдореИрдВ рдПрдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд░реЗрдкреЛ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ, рд╢рд╛рдпрдж рдореИрдВ рдмреАрдЪ рдореЗрдВ рдХреБрдЫ рднреВрд▓ рдЧрдпрд╛ред

рдЖрдкрдХреЗ рдЬрд╡рд╛рдмреЛрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж

@ andrescabana86 рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдПрдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд░реЗрдкреЛ рдпрд╣рд╛рдВ рдХрд┐рддрдиреА рдорджрдж рдХрд░реЗрдЧрд╛ - рдпрд╣ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рддреИрдирд╛рдд рд╕рд░реНрд╡рд░ рдкрд░ рдХреБрдЫ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рд╣рдо рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдЗрд╕ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ package.json рдЕрдкрдиреЗ рдкреНрд░реЛрдбрдХреНрд╢рди рдмрд┐рд▓реНрдб ( exportTrailingSlash: true ) рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░ рд░рд╣реЗ рд╣реИрдВ:

"serve:out": "docker run --rm -v $(pwd)/out:/static -p 5000:80 flashspys/nginx-static"

рдХреГрдкрдпрд╛ рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдЖрдкрдХреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ http://localhost:5000/api/test/ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

(рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ $(pwd) рдореИрдХ/рд▓рд┐рдирдХреНрд╕ рдкрд░ рд╣реИ - рдЗрд╕реЗ рд╡рд┐рдВрдбреЛрдЬрд╝ рдХреЗ рд▓рд┐рдП рджреЗрдЦреЗрдВ)

@Izhaki рд╕рдорд╕реНрдпрд╛ рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереА рдХрд┐ (рдЬреИрд╕рд╛ рдХрд┐ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд░рд┐рдкреЛрд░реНрдЯ рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ) "рдХрд╛рдиреВрдиреА рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдВрдХ рдореЗрдВ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдиреЗрд╡рд┐рдЧреЗрд╢рди рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рд╣рд╛рд░реНрдб рд░реАрдлреНрд░реЗрд╢ (рдПрд╕рдПрд╕рдЖрд░) рдкрд░ рдмрдВрдбрд▓ рдФрд░ 404 рдирд╣реАрдВ рдорд┐рд▓рд╛"ред рдЗрд╕рд▓рд┐рдП рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рд░реВрдЯ рдкрд░рд┐рд╡рд░реНрддрди, рдмрдирд╛рдо рд╣рд╛рд░реНрдб рд░рд┐рдлреНрд░реЗрд╢ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рдмреАрдЪ рдПрдХ рдмреЗрдореЗрд▓ рдерд╛ред рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╕рдорд╕реНрдпрд╛ Next.js рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рд╕рд╛рде рдмрдиреА рд░рд╣рддреА рд╣реИред рдПрдХ рдмрд╛рд░ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдореИрдВ рдпрд╣рд╛рдВ рд╡рд╛рдкрд╕ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВред

рдмрд╕ 9.4.1 рдФрд░ exportTrailingSlash: true рд╕рд╛рде рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ред

рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрдиреЗ рдкрд░ http://localhost:6500/admin/ рдЬрд╛рдХрд░ 404 рд▓реМрдЯрд╛рддрд╛ рд╣реИред

рд▓реЗрдХрд┐рди рдЬрдм рдЖрдк рдирд┐рд░реНрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВ рддреЛ рд╡рд╣реА рд░рд╛рд╕реНрддрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ exportTrailingSlash рд╕рдВрдХреЗрдд рджреЗрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреЗрд╡рд▓ _exports_ рдХреЗ рд▓рд┐рдП рд╣реИред

рд╣рдо рдХреНрдпрд╛ рдХрд░рддреЗ рд╣реИрдВ рдЙрдкрдпреЛрдЧ рд╣реИ:

exportTrailingSlash: process.env.NODE_ENV === 'production'

рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЬрдм рд╣рдо рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ рддреЛ рдЪреАрдЬреЗрдВ рдЗрд░рд╛рджреЗ рд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИрдВред рдФрд░ рддреИрдирд╛рдд рд╣реЛрдиреЗ рдкрд░ (рдирд┐рд░реНрдпрд╛рдд рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рдареАрдХ рд╕реЗ рдХрд╛рдо рдХрд░реЗрдВред

рдХреНрдпрд╛ рдпрд╣ рдЗрд╕рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдФрд░ рд╡реНрдпрд╡рд╣рд╛рд░реНрдп рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реИ?

рдЕрдЧрд░ рдХреЛрдИ рдпреВрдЖрд░рдПрд▓ рд╡рд┐рдХрд╛рд╕ рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдЙрддреНрдкрд╛рджрди рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рдХреНрдпрд╛ рдЖрдкрдХреЛ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдпрд╣ рдХрдо рд╕реЗ рдХрдо рдЖрд╢реНрдЪрд░реНрдп рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рдЦрд┐рд▓рд╛рдл рд╣реИ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдЕрднреА рднреА рдПрдХ рдмрдЧ рдорд╛рдирд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

^ рдЙрд╕ рдиреЗ рдХрд╣рд╛, рдореБрдЭреЗ рдкреВрд░рд╛ рдпрдХреАрди рд╣реИ рдХрд┐ рдкрд╣рд▓реЗ рдЙрддреНрдкрд╛рджрди рдкрд░ рдПрдХ рдкреГрд╖реНрда рд░реАрдлреНрд░реЗрд╢ рдмрдирд╛рдо рд░рд╛рдЙрдЯрд░.рдкреБрд╢ рдШрдЯрдирд╛ рдХреЗ рдмреАрдЪ рдПрдХ рд╡рд┐рд░реЛрдзрд╛рднрд╛рд╕реА рд╡реНрдпрд╡рд╣рд╛рд░ рдерд╛ред рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдХреНрдпрд╛ рдЕрдм рднреА рдРрд╕рд╛ рд╣реИред

@andrescabana86 @Izhaki exportTrailingSlash рдЕрд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рд╡рд╣ рд╡рд┐рдХрд▓реНрдк Next.js рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд╕реНрдерд┐рд░ рдирд┐рд░реНрдпрд╛рдд рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИред рдЬрдм рд╕рд╣реА рд╣реЛрддрд╛ рд╣реИ, example/index.html рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдЬрдм рдпрд╣ рдЧрд▓рдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ example.html рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИред рдореЗрд░реА рд╕рдордЭ рдпрд╣ рд╣реИ рдХрд┐ exportTrailingSlash рдХрд╛ рд╡рд┐рдХрд╛рд╕ рдореЛрдб рд╕реЗ рдХреЛрдИ рд▓реЗрдирд╛-рджреЗрдирд╛ рдирд╣реАрдВ рд╣реИред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рднреНрд░рдо рдХрд╛ рдПрдХ рд╕реНрд░реЛрдд рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рдЖрдкрдХреЗ рдкрд╛рд╕ exportTrailingSlash next.js рд╣реЛрддрд╛ рд╣реИ рддреЛ рд▓рд┐рдВрдХ рдореЗрдВ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдпрд╣ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рднреА рд╣реЛрддрд╛ рд╣реИ рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдРрд╕рд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП? рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рднреА рддрд░рд╣, рдпрд╣ рдХреЗрд╡рд▓ example/index.html рдмрдирд╛рдо example.html - рдЖрдкрдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдЕрдЧрд░ рдХреЛрдИ рдпреВрдЖрд░рдПрд▓ рд╡рд┐рдХрд╛рд╕ рдкрд░ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рд▓реЗрдХрд┐рди рдЙрддреНрдкрд╛рджрди рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рдХреНрдпрд╛ рдЖрдкрдХреЛ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдпрд╣ рдХрдо рд╕реЗ рдХрдо рдЖрд╢реНрдЪрд░реНрдп рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХреЗ рдЦрд┐рд▓рд╛рдл рд╣реИ? рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдЕрднреА рднреА рдПрдХ рдмрдЧ рдорд╛рдирд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдореИрдВ рдЧрд▓рдд рд╣реЛ рд╕рдХрддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди ExportTrailingSlash рд╡рд┐рдХрд▓реНрдк nginx рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рдерд╛ рдЬреЛ /something.html рдкрд░реЛрд╕рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдирд╣реАрдВ рдХрд┐рдП рдЧрдП рд╣реИрдВ рдЬрдм url /something ред

рд╕реНрдерд╛рдиреАрдп рджреЗрд╡ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЕрдЧрд▓реЗ рд╕рд░реНрд╡рд░ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИред рддреЛ рдХреНрдпрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рдХреНрдпрд╛ рдирд╣реАрдВ рдпрд╣ рдЗрд╕ рдмрд╛рдд рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЗ рдРрдк рдореЗрдВ рдХреНрдпрд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЖрдк рдПрдХ рдорд╛рдорд▓рд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЬрдм exportTrailingSlash рд╕рддреНрдп рд╣реИ, рддреЛ рдЕрдЧрд▓реЗ рд╕рд░реНрд╡рд░ рдХреЛ рдЯреНрд░реЗрд▓рд┐рдВрдЧ рд╕реНрд▓реИрд╢ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдорд╛рд░реНрдЧреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ export рдХреЛ exportTrailingSlash рдХреБрдЫ рд╣рдж рддрдХ рдЕрдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдмрдирд╛ рджреЗрдЧрд╛)ред

FWIW рдЗрд╕ рдкрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИ #13333

рдореИрдВ рдмрд╣реБрдд рдЕрдиреБрднрд╡реА рдХреЛрдбрд░ рдирд╣реАрдВ рд╣реВрдВ, рдореБрдЦреНрдп рд░реВрдк рд╕реЗ рдмрд╣реБ-рдкреГрд╖реНрда рд╡рд╛рд▓реА рд▓реИрдВрдбрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП Next.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВред рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдореИрдВ рд▓рдЧрднрдЧ рд╣рд░ рд╕рдордп рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рдорд╛рдзрд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, рдЗрд╕рдХреЗ рдкреНрд░рднрд╛рд╡ рд╕реЗ рдЕрдирдЬрд╛рдиред рдпрд╣рд╛рдБ рдЗрд╕рдХрд╛ рдЫреАрди рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ:

// In your server.js
server.get('/:id', (req, res) => {
  const actualPage = `/${req.params.id}`
  app.render(req, res, actualPage)
})

рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреЛрдб рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдореИрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реНрдерд┐рд░ рдпреВрдЖрд░рдПрд▓ рдЙрдкрд╕рд░реНрдЧреЛрдВ рдЖрджрд┐ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рд▓реЗрдХрд┐рди рдпрд╣ рдЫреАрди рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╕рдВрд╕реНрдХрд░рдг exportTrailingSlash рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рд╕рдорд╕реНрдпрд╛ рдХреЗ рд▓рд┐рдП рдареАрдХ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред рд╕реЗрдЯрд┐рдВрдЧ рдФрд░ рдЙрд╕рдХрд╛ рдкреНрд░рднрд╛рд╡ Link s рдкрд░ред рдЬреИрд╕реЗ рдпреВрдЖрд░рдПрд▓ /about рдФрд░ /about/ рдареАрдХ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред

рд╡рд░реНрддрдорд╛рди рд░реВрдк рдореЗрдВ рдпрд╣ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ Next.js рдХреА рдореВрд▓ рд░реВрдЯрд┐рдВрдЧ рдХреА рдирдХрд▓ рдХрд░рддрд╛ рд╣реИред рдирдХрд╛рд░рд╛рддреНрдордХ рдкрдХреНрд╖: рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрд╕реНрдЯрдо server.js рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдФрд░ рдЖрдкрдХреЛ рдЗрд╕реЗ "рдЧрд╣рд░реЗ" URL (рдЕрддрд┐рд░рд┐рдХреНрдд "рд╕рдмрдлрд╝реЛрд▓реНрдбрд░реНрд╕" рдХреЗ рд╕рд╛рде) рдХреЗ рд▓рд┐рдП рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕рдорд░реНрдерди рджреЗрдирд╛ рд╣реЛрдЧрд╛, рдЬреИрд╕реЗ /company/about/ ред рд▓реЗрдХрд┐рди рдпрд╣ рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рд╕рд░рд▓ рд╕рдорд╛рдзрд╛рди рдкреНрд░рддреАрдд рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдкрдиреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдХрд╕реНрдЯрдо server.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

SSR рдХреЗ рд╕рд╛рде рдпрд╣ рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ @pjaws рдФрд░ @AlexSapoznikov рд╕рдорд╛рдзрд╛рди рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬреЛрдбрд╝рдирд╛ рдкрдбрд╝рд╛:

  static async getInitialProps({ Component, ctx, router }) {
    /* Fixes the trailing-slash-404 bug for server-side rendering. */
    const { asPath } = router;
    if (asPath && asPath.length > 1) {
      const [path, query = ""] = asPath.split("?");
      if (path.endsWith("/") && path.length > 1) {
        const asPathWithoutTrailingSlash =
          path.replace(/\/*$/gim, "") + (query ? `?${query}` : "");
        if (ctx.res) {
          ctx.res.writeHead(301, {
            Location: asPathWithoutTrailingSlash,
          });
          ctx.res.end();
        }
      }
    }
    return {
      pageProps: Component.getInitialProps
        ? await Component.getInitialProps(ctx)
        : {},
    };
  }

рд╕рдВрднрд╡рддрдГ рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╡рд┐рдЪрд╛рд░ рд╣реИ рдХрд┐ рдХрд┐рд╕реА рддрд░рд╣ рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рдПрдХ рдРрд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рдП рдЬреЛ SSR рдФрд░ CSR рджреЛрдиреЛрдВ рдХреЗ рджреМрд░рд╛рди рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рджреЛрдиреЛрдВ рд╕реНрдерд╛рдиреЛрдВ ( getInitialProps рдФрд░ render ) рдореЗрдВ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред

рдЗрд╕рдиреЗ getServerSideProps рд╡рд╛рд▓реЗ рдкреГрд╖реНрдареЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдЕрдм рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рд╡рд╛рд▓реЗ url 404 рдХреЗ рдмрд┐рдирд╛ рдПрдХ рд╣реА рдкреГрд╖реНрда рдкрд░ рд▓реМрдЯ рд░рд╣реЗ рд╣реИрдВред
рд▓реЗрдХрд┐рди рдПрдХ рдЧрдбрд╝рдмрдбрд╝ рд╣реИ, рдореЗрд░реЗ рдкрд╛рд╕ рдХреБрдЫ рдкреГрд╖реНрда рд╣реИрдВ рдЬреЛ рдЧрддрд┐рд╢реАрд▓ рдорд╛рд░реНрдЧреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕реНрдЯреЗрдЯрд┐рдХрдкрд╛рде рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рдореИрдВ рдЙрди рдкрд░ getServerSideProps рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рдФрд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЬрдм рдЗрди рдЧрддрд┐рд╢реАрд▓ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рдХреЗ рд╕рд╛рде рдмреНрд░рд╛рдЙрдЬрд╝ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╡реЗ рдкрд╣рд▓реЗ 404 рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ рдФрд░ рдлрд┐рд░ рд╡реЗ рдкреГрд╖реНрда рдкрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рддреЗ рд╣реИрдВ .

@gauravkrp рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдЕрддреНрдпрдВрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЬреЛрдбрд╝ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ @AlexSapoznikov рд╕рдорд╛рдзрд╛рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрднреА рднреА Google рдХреЛ рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП 404 рд▓реМрдЯрд╛рдПрдЧрд╛ (рдЪреВрдВрдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рд╣реЛрддрд╛ рд╣реИ)ред рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ SEO рдПрдХ рдкреНрд░рдореБрдЦ рдХрд╛рд░рдг рд╣реИ рдХрд┐ рд╣рдо рдореЗрдВ рд╕реЗ рдмрд╣реБрдд рд╕реЗ рд▓реЛрдЧ рдкрд╣рд▓реЗ рд╕реНрдерд╛рди рдкрд░ Next.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВред

рдореБрдЭреЗ рдпрд╣ рднреА рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ getInitialProps рдореЗрдВ рдбрд╛рд▓рдиреЗ рд╕реЗ рдмрд╕ рдЪрд╛рд░реЛрдВ рдУрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдореБрдЦреНрдп рд╕рдорд╛рд░реЛрд╣ рдХреЗ рдЕрдВрджрд░ рдХрд╛ рдЯреБрдХрдбрд╝рд╛ рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░ рдЕрдирд╛рд╡рд╢реНрдпрдХ рд╣реИред рдпрд╣рд╛рдВ рдкреНрд░рдореБрдЦ рдЪреЗрддрд╛рд╡рдиреА рдпрд╣ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕реЗ рд╣реЛрдиреЗ рд╕реЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╕реНрдЯреЗрдЯрд┐рдХ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝реЗрд╢рди рдЦреЛ рд░рд╣реЗ рд╣реИрдВ - рд╢рд╛рдпрдж 404 рдХреЗ рд╕рдореВрд╣ рд╕реЗ рдмреЗрд╣рддрд░ред

рдХреБрдЫ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП...

рдореЗрд░рд╛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ Express + Next.js ред
express 4.17.1
next 9.4.5-canary.7

рдЬрдм рд╡рд┐рдХрд╛рд╕

рдЧрддрд┐рд╢реАрд▓ рд░рдирдЯрд╛рдЗрдо

// next.config.js
module.exports = {
  exportTrailingSlash: false,
};

// app.js
const Next = require('next').default;
const NextApp = Next({ dev });
const NextHandler = NextApp.getRequestHandler();
NextApp.prepare();
app.get('*', (req, res) => NextHandler(req, res));

рдЬрдм рдЙрддреНрдкрд╛рджрди

рд╕реНрдерд┐рд░ рдирд┐рд░реНрдпрд╛рдд
next build рдФрд░ next export -o dist/ рдЪрд▓рд╛рдПрдБ

// next.config.js
module.exports = {
  exportTrailingSlash: true,
};

// app.js
app.use('/_next', express.static('dist/_next', { etag: true, index: false, maxAge: '365d', redirect: false, dotfiles: 'ignore' }));
app.use('/fonts', express.static('dist/fonts', { etag: true, index: false, maxAge: '365d', redirect: false, dotfiles: 'ignore' }));
app.use('/img', express.static('dist/img', { etag: true, index: false, maxAge: '365d', redirect: false, dotfiles: 'ignore' }));
app.use(express.static('./dist', { index: ['index.html'] }));
app.use((req, res) => {
  res.Redirect('/404'); // <- Express will auto handle both /404 or /404/
});

рдирд┐рд╖реНрдХрд░реНрд╖ рдХреЗ рддреМрд░ рдкрд░

рдХреНрд▓рд╛рдЗрдВрдЯ рдРрдк рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдХреЗ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рддреЗ рд╕рдордп рдореБрдЭреЗ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ,
static route рдкрд░ рднреА рд╣рд╛рд░реНрдб рд░рд┐рдлреНрд░реЗрд╢ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред

рд▓реЗрдХрд┐рди dynamic route рдкрд░ рд╣рд╛рд░реНрдб рд░реАрдлреНрд░реЗрд╢ рд╣реЛрдиреЗ рдкрд░ рдпрд╣ 404 рд╣реЛ рдЬрд╛рдПрдЧрд╛,
рдЬреИрд╕реЗ /album/[id].jsx рдпрд╛ /album/123 ,
рдЗрд╕рд▓рд┐рдП рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрддреНрд╕реБрдХ рд╣реВрдВред

рдЬреИрд╕реЗ
/album/123 рдкрд░ 404 рд╣рд┐рдЯ рдХрд░рдиреЗ рдкрд░,
рд╕рд░реНрд╡рд░ рдХреЛ html рд╕рд╛рдордЧреНрд░реА рдкреНрд░рджрд╛рди рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП,
рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдмрд┐рдирд╛ рдХрд┐рд╕реА рд╕рдорд╕реНрдпрд╛ рдХреЗ рдкреЗрдЬ рд▓реЛрдб рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдЧрд╛,
рдЬрдм Next.js рдмреВрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ next/router рдЗрд╕реЗ рд╕реНрд╡рддрдГ рд╕рдВрднрд╛рд▓ рд▓реЗрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдХреНрдпрд╛ рдЙрддреНрдкрд╛рджрди рдкрд░ рдЗрд╕ рдореБрджреНрджреЗ рдХрд╛ рдХреЛрдИ рдЕрд╕реНрдерд╛рдпреА рд╕рдорд╛рдзрд╛рди рд╣реИ?

рд╣рдо рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рдЙрддрд╛рд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВтАФрдПрдХ-рдПрдХ рджрд┐рди!

рдХреНрдпрд╛ рдЙрддреНрдкрд╛рджрди рдкрд░ рдЗрд╕ рдореБрджреНрджреЗ рдХрд╛ рдХреЛрдИ рдЕрд╕реНрдерд╛рдпреА рд╕рдорд╛рдзрд╛рди рд╣реИ?

рдЗрд╕ рд╕реВрддреНрд░ рдореЗрдВ рдХрдИ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВ рд╡рд░реНрддрдорд╛рди рдореЗрдВ @gauravkrp рджреНрд╡рд╛рд░рд╛ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдкреЛрд╕реНрдЯ рдХреА

рдЖрдк рдпрд╣рд╛рдВ рдкреАрдЖрд░ рдХрд╛ рдЯреНрд░реИрдХ рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВ: #13333

рдЗрд╕реЗ рдЕрдм next@^9.4.5-canary.17 рдореЗрдВ рд╣рд▓ рдХрд░ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ!

рдлреАрдЪрд░ рдХреЛ рдХреИрдирд░реА рд╕реЗ рдорд╛рд╕реНрдЯрд░ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдореЗрдВ рдХрд┐рддрдирд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ?

рдЗрд╕реЗ рдЕрдм next@^9.4.5-canary.17 рдореЗрдВ рд╣рд▓ рдХрд░ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ!

рдФрд░ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреИрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ? рдмрд╕ рдкрд┐рдЫрд▓рд╛ рд╕реНрд▓реИрд╢ рд╣рдЯрд╛ рд░рд╣рд╛ рд╣реИ? рдпрджрд┐ рдореИрдВ " www.site.com/help/ " рддрдХ www.site.com/help ", рдХреНрдпрд╛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╡рд┐рдХрд▓реНрдк рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрд╣рд╛рдБ рд╣рдо рдЕрдВрддрд┐рдо рд╕реНрд▓реИрд╢ рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдЪреБрдирддреЗ рд╣реИрдВ? " www.site.com/help/ " рдпрд╛ " www.site.com/help " рддрдХ рдкрд╣реБрдВрдЪрдирд╛ рдЫреЛрдбрд╝ рджреЗрдЧрд╛ рдпрд╛ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░реЗрдЧрд╛ рдпрд╛ рдЕрдВрдд рдореЗрдВ "/" рдЬреЛрдбрд╝ рджреЗрдЧрд╛: " www.site.com/help/ "

@Valnexus #13333 рджреЗрдЦреЗрдВ, рдЗрд╕рдореЗрдВ рдПрдХ рдкреНрд░рдпреЛрдЧрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рд╢рд╛рдорд┐рд▓ рд╣реИ:

module.exports = {
  experimental: {
    trailingSlash: true
  }
}

рдлреАрдЪрд░ рдХреЛ рдХреИрдирд░реА рд╕реЗ рдорд╛рд╕реНрдЯрд░ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдореЗрдВ рдХрд┐рддрдирд╛ рд╕рдордп рд▓рдЧрддрд╛ рд╣реИ?

рдЬрдм рдпрд╣ рддреИрдпрд╛рд░ рд╣реЛ рдЬрд╛рдПред рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдореЗрдВ рдЕрднреА рднреА рдХрд┐рдирд╛рд░реЗ рдХреЗ рдорд╛рдорд▓реЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд░рд╣рд╛ рд╣реИред рдПрдХ рдмрд╛рд░ рдЙрдиреНрд╣реЗрдВ рдареАрдХ рдХрд░ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рддреЛ рдпрд╣ рд╕реНрдерд┐рд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

@timneutkens @Janpot

рдореИрдВрдиреЗ рдирд╡реАрдирддрдо рдЕрдЧрд▓реА рдХреИрдирд░реА (9.4.5-рдХреИрдирд░реА.27) рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рд▓реЗрдХрд┐рди рдЬрдм рдореИрдВ test рдкреЗрдЬ рдмрдирд╛рддрд╛ рд╣реВрдВ рдФрд░ рдореИрдВ www.example/test/ рддрдХ рдкрд╣реБрдВрдЪрддрд╛ рд╣реВрдВ рддреЛ рдпрд╣ www.example/test рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рджреЛрдиреЛрдВ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╡рд╣рд╛рд░ рд╕рдорд╛рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЬрдм www.example/test/ рддрдХ рдкрд╣реБрдВрдЪреЗрдВ рддреЛ рдЗрд╕реЗ www.example/test/ рдкрд░ рд░рд╣рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЬрдм www.example/test рддрдХ рдкрд╣реБрдВрдЪ рд╣реЛ рддреЛ рдЗрд╕реЗ www.example/test рдкрд░ рд░рд╣рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдореИрдВ рдЗрд╕реЗ Nuxt.js рдкрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░рддрд╛ рд╣реВрдВ, рдпрд╣ рд╡рд╣реА рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдореИрдВ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдХрд░рддрд╛ рд╣реВрдВред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рджреЛрдиреЛрдВ рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╡рд╣рд╛рд░ рд╕рдорд╛рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдЦреЛрдЬ рдЗрдВрдЬрди рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╕рд╛рдордЧреНрд░реА рдирд╣реАрдВ рджреЗрдЦрддреЗ рд╣реИрдВред рдЖрдкрдХрд╛ рд╕рдЯреАрдХ рдЙрдкрдпреЛрдЧ-рдорд╛рдорд▓рд╛ рдХреНрдпрд╛ рд╣реИ?

рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдпрд╣ рдПрдХ рдмрдВрдж рдореБрджреНрджрд╛ рдХреНрдпреЛрдВ рд╣реИ рдЕрдЧрд░ рдЗрд╕реЗ рдЕрднреА рддрдХ рдПрдХ рд╕реНрдерд┐рд░ рд░рд┐рд▓реАрдЬ рдореЗрдВ рд╡рд┐рд▓рдп рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЕрдЧрд░ рдореИрдВ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕рдордЭ рдЧрдпрд╛ рддреЛ рдпрд╣ рдЕрднреА рдХреЗ рд▓рд┐рдП рдХреИрдирд░реА рд░рд┐рд▓реАрдЬ рдореЗрдВ рд╣реА рддрдп рд╣реИ, рд╣реИ рдирд╛?

рдЬрдм рдЙрдирдХрд╛ рд╕рдВрдмрджреНрдз рдкреБрд▓ рдЕрдиреБрд░реЛрдз рднреВрдорд┐ рдкрд░ рдЖрддрд╛ рд╣реИ, рддреЛ рд╕рдорд╕реНрдпрд╛рдПрдБ рдмрдВрдж рд╣реЛ рдЬрд╛рддреА рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╡реЗ рдХреИрдирд░реА рдкрд░ рддрддреНрдХрд╛рд▓ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реИрдВред рдпрджрд┐ рдЖрдкрдХреЛ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдХреГрдкрдпрд╛ рдХреИрдирд░реА рдЪреИрдирд▓ рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдХрд░реЗрдВред

рдмрдврд╝рд┐рдпрд╛ рд╣реИред рдзрдиреНрдпрд╡рд╛рдж, @ рдЯрд╛рдЗрдорд░!

@Janpot рдореИрдВрдиреЗ рджреЗрдЦрд╛ рдХрд┐ https://github.com/issues/ рдФрд░ https://github.com/issues рдмрд┐рдирд╛ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХреЗ рд╕рдорд╛рди рд╡реНрдпрд╡рд╣рд╛рд░ рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВред

https://twitter.com/explore/ рдФрд░ https://twitter.com/explore , рдпрд╣ рднреАред

рдЕрдЧрд░ рдЗрд╕реЗ рд╕рд░реНрдЪ рдЗрдВрдЬрди рдореЗрдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рд╣реИ, рддреЛ рдЬреАрдердм рдФрд░ рдЯреНрд╡рд┐рдЯрд░ рдиреЗ рдЗрд╕реЗ рдареАрдХ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛?
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕реА рднреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реИред

рдХреЛрдИ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрдкрдпреЛрдЧ-рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИ, рдпрд╣ рд╕рд┐рд░реНрдл рдореЗрд░реА рд░рд╛рдп рд╣реИ рдХрд┐ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЕрдЧрд░ рдЗрд╕реЗ рд╕рд░реНрдЪ рдЗрдВрдЬрди рдореЗрдВ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рд╣реИ, рддреЛ рдЬреАрдердм рдФрд░ рдЯреНрд╡рд┐рдЯрд░ рдиреЗ рдЗрд╕реЗ рдареАрдХ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛?

@armspkt рдпрд╣ рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдЯреНрд╡рд┐рдЯрд░ <link rel="canonical"> рд╡рд┐рд╢реЗрд╖рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЦреЛрдЬ рдмреЙрдЯ рдХреЛ рдпрд╣ рдмрддрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЙрдиреНрд╣реЗрдВ рдХреМрди рд╕рд╛ рдкреГрд╖реНрда рдХреНрд░реЙрд▓ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЕрдиреНрдп рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЛ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рддреЛ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдЖрдкрдХреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ SEO рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╡реНрдпрд╡рд╣рд╛рд░реНрдп рддрд░реАрдХрд╛ рд╣реИред рдЖрдк рдпрд╣рд╛рдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред

@ziserman рдЕрдЧрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЗрд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рдХрдИ рддрд░реАрдХреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдиреБрднрд╡ рдХреЗ рд▓рд┐рдП рдЙрд╕реА рдпреВрдЖрд░рдПрд▓ рдХреЛ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд┐рдП рдмрд┐рдирд╛ рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдПред

@Janpot https://github.com/nuxt-community/nuxt-i18n/issues/422

Nuxtjs рдХреЗ рдкрд╛рд╕ рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ (рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд, рд╕рддреНрдп, рдЕрд╕рддреНрдп)

рдХреНрдпрд╛ рдиреЗрдХреНрд╕реНрдЯрдЬ рдХреЗ рдкрд╛рд╕ рднреА рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд░рд▓ рд╡рд┐рдХрд▓реНрдк рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП?

рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд╛ рдХрд╛рд░рдг рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдЦреЛрдЬ рдЗрдВрдЬрди рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд╕рд╛рдордЧреНрд░реА рдирд╣реАрдВ рджреЗрдЦрддреЗ рд╣реИрдВред рдЖрдкрдХрд╛ рд╕рдЯреАрдХ рдЙрдкрдпреЛрдЧ-рдорд╛рдорд▓рд╛ рдХреНрдпрд╛ рд╣реИ?

@Janpot рд╣рдорд╛рд░реЗ рдПрдкреАрдЖрдИ рдореЗрдВ рдХрдИ рдЬрдЧрд╣реЛрдВ рдкрд░ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рд╣реИрдВред рдирд╡реАрдирддрдо рд░рд┐рд▓реАрдЬрд╝ рдмреИрдХрдПрдВрдб рдкрд░ 404 рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрдврд╝рд╛рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдкрд┐рдЫрд▓реА рд╕реНрд▓реИрд╢ рд╡рд╛рд▓реЗ рдпреВрдЖрд░рдПрд▓ (/ рдПрдкреАрдЖрдИ/рдЯреЗрд╕реНрдЯ/ ->/рдПрдкреАрдЖрдИ/рдЯреЗрд╕реНрдЯ) рдореЗрд▓ рдирд╣реАрдВ рдЦрд╛рддреЗ рд╣реИрдВ

рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдХрд┐ рдпрд╣ рд╕рднреА рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛ рдпрд╛ рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдпрд╣ рд╕рдорд╛рдзрд╛рди рдорд┐рд▓ рдЧрдпрд╛ рд╣реИ рдЬреЛ рдореЗрд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдЗрд╕реЗ _app.js рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдбрд╛рд▓реЗрдВред

static async getInitialProps(ctx) {
    const appProps = await App.getInitialProps(ctx);

    // Remove trailing slash
    const path = ctx.router.asPath,
            res = ctx.ctx.res;

    if (path.length > 1 && /\/$/.test(path)) {
        res.writeHead(301, {Location: path.slice(0, -1)})
        res.end();
    }

    return {...appProps};
}

@mlbonniec рдореИрдВрдиреЗ рдЖрдкрдХреА рдЯрд┐рдкреНрдкрдгреА рдХреЛ рдЫреЛрдЯрд╛ рдХрд░ рджрд┐рдпрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ Next.js рдРрдк рдореЗрдВ рдЧрдВрднреАрд░ рдкреНрд░рджрд░реНрд╢рди рдкреНрд░рддрд┐рдЧрдорди рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред

рдирд╡реАрдирддрдо next@canary рд╕рдВрд╕реНрдХрд░рдг рдЗрд╕ рдмрдЧ рдХреЛ рдареАрдХ рдХрд░рддрд╛ рд╣реИ, рдХреГрдкрдпрд╛ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЕрдкрдЧреНрд░реЗрдб рдХрд░реЗрдВ!

@mlbonniec рдореИрдВрдиреЗ рдЖрдкрдХреА рдЯрд┐рдкреНрдкрдгреА рдХреЛ рдЫреЛрдЯрд╛ рдХрд░ рджрд┐рдпрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ Next.js рдРрдк рдореЗрдВ рдЧрдВрднреАрд░ рдкреНрд░рджрд░реНрд╢рди рдкреНрд░рддрд┐рдЧрдорди рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред

рдирд╡реАрдирддрдо next@canary рд╕рдВрд╕реНрдХрд░рдг рдЗрд╕ рдмрдЧ рдХреЛ рдареАрдХ рдХрд░рддрд╛ рд╣реИ, рдХреГрдкрдпрд╛ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЕрдкрдЧреНрд░реЗрдб рдХрд░реЗрдВ!

рдХреЛрдИ рджрд┐рдХреНрдХрдд рдирд╣реАрдВ рд╣реИ!
рд╣рд╛рд▓рд╛рдБрдХрд┐, рдореИрдВрдиреЗ рдкрд╣рд▓реЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдерд╛, рдФрд░ рдЗрд╕рд╕реЗ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рд╣реБрдЖред
npm update

рдЕрдЧрд░ рдирд╡реАрдирддрдо рдиреЗрдХреНрд╕реНрдЯ.рдЬреЗрдПрд╕ рдХреИрдирд░реА рдЖрдкрдХреЗ рд▓рд┐рдП рдмрдЧ рдХреЛ рдареАрдХ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдХреГрдкрдпрд╛ рдПрдХ рдирдпрд╛ рдореБрджреНрджрд╛ рдЦреЛрд▓реЗрдВ рддрд╛рдХрд┐ рд╣рдо рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓ рд╕рдХреЗрдВред ЁЯЩП

рддреНрд╡рд░рд┐рдд рдкреНрд░рд╢реНрди, next export рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЗрд╕ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рдХреИрд╕реЗ рд╕рдВрднрд╛рд▓реЗрдВрдЧреЗ? рдЕрдиреБрдЧрд╛рдореА рд╕реНрд▓реИрд╢ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд┐рд▓реНрдХреБрд▓ рдирдпрд╛ рдкреГрд╖реНрда рдмрдирд╛рдХрд░? рдореБрдЭреЗ рдирд╣реАрдВ рд▓рдЧрддрд╛ рдХрд┐ рдПрдХ рдирд┐рд░реНрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдРрдк HTTP рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ (рдпрд╛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддрд╛ рд╣реИ) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рдЬреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ next export рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЙрдирдХреЗ рд╕рднреА <Link /> рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдкрд░ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗ, рд▓реЗрдХрд┐рди рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдореИрдиреНрдпреБрдЕрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рд▓рдХреНрд╖реНрдп рдпрд╛ next start рд╕рд╛рде рдкрд░рд┐рдирд┐рдпреЛрдЬрд┐рдд рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЗрди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВрдЧреЗред

@Timer рдПрдХ рдмрд╛рд░ рдЬрдм рдпрд╣ рдкреВрд░реНрдг рд░рд┐рд▓реАрдЬрд╝ рддрдХ рдкрд╣реБрдБрдЪ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХреНрдпрд╛ рд╣рдореЗрдВ рдЕрднреА рднреА рдкреНрд░рдпреЛрдЧрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА?

@Timer рдПрдХ рдмрд╛рд░ рдЬрдм рдпрд╣ рдкреВрд░реНрдг рд░рд┐рд▓реАрдЬрд╝ рддрдХ рдкрд╣реБрдБрдЪ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХреНрдпрд╛ рд╣рдореЗрдВ рдЕрднреА рднреА рдкреНрд░рдпреЛрдЧрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА?

рдирд╣реАрдВ, рдЬреИрд╕рд╛ рд╣реИ рд╡реИрд╕рд╛ рд╣реА рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛ред

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ trailingSlash рд╡рд┐рдХрд▓реНрдк next export рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛? /page/ рдХреЛ /page (рдпрд╛ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд) рдореЗрдВ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реИ, рдХрд╣реЗрдВ, рдЬреАрдердм рдкреЗрдЬ?

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ trailingSlash рд╡рд┐рдХрд▓реНрдк next export рд▓рд┐рдП рдХрд╛рдо рдирд╣реАрдВ рдХрд░реЗрдЧрд╛? /page/ рдХреЛ /page (рдпрд╛ рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд) рдореЗрдВ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рдХреНрдпрд╛ рд╣реИ, рдХрд╣реЗрдВ, рдЬреАрдердм рдкреЗрдЬ?

рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛтАЛтАЛрдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдЬреАрдердм рдкреЗрдЬ рдореЗрдВ рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдлреАрдЪрд░ рдирд╣реАрдВ рд╣реИред рдпрд╣ vercel.com рдкрд░ рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рд╣реЙрдмреА рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рднреА рдореБрдлрд╝реНрдд рд╣реИ (рдЬреИрд╕реЗ рдЬреАрдердм рдкреЗрдЬ рд╣реИ)ред

рдЬреЛ рдкреНрд░реЛрдЬреЗрдХреНрдЯ next export рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЙрдирдХреЗ рд╕рднреА <Link /> рдХреНрд▓рд╛рдЗрдВрдЯ-рд╕рд╛рдЗрдб рдкрд░ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдП рдЬрд╛рдПрдВрдЧреЗ, рд▓реЗрдХрд┐рди рд╕рд░реНрд╡рд░-рд╕рд╛рдЗрдб рд░реАрдбрд╛рдпрд░реЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдореИрдиреНрдпреБрдЕрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред рд╕рд░реНрд╡рд░ рд░рд╣рд┐рдд рд▓рдХреНрд╖реНрдп рдпрд╛ next start рд╕рд╛рде рдкрд░рд┐рдирд┐рдпреЛрдЬрд┐рдд рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЗрди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВрдЧреЗред

рд╣рд╛рдп @ рдЯрд╛рдЗрдорд░ рдХреНрдпрд╛ рдЖрдк рдФрд░ рд╕рдордЭрд╛ рд╕рдХрддреЗ рд╣реИрдВ? рдореИрдВ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдХреИрд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ? рддреЛ рдпрд╣рд╛рдБ рдореЗрд░реА рд╕реНрдерд┐рддрд┐ рд╣реИред рдореИрдВ рдЕрдкрдиреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ next-i18next рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВред рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ next build && next export рд╕рд╛рде рдкрд░рд┐рдирд┐рдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╕рднреА рдЖрдВрддрд░рд┐рдХ рд▓рд┐рдВрдХ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рдЬрдм рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ URL рджрд░реНрдЬ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЙрдирдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ 404 рддреНрд░реБрдЯрд┐ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рдпрд╣рд╛рдВ рд╕реЗ рдореИрдВрдиреЗ trailingSlash:true рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдФрд░ рдЗрд╕рд▓рд┐рдП рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рджрд░реНрдЬ рдХрд░реЗрдВ /pricing рдЕрдм рдХрд╛рдо рдХрд░реЗрдЧрд╛ рд▓реЗрдХрд┐рди /zh/pricing 404 рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

knipferrc picture knipferrc  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

olifante picture olifante  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

kenji4569 picture kenji4569  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

flybayer picture flybayer  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

renatorib picture renatorib  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ