diff options
| author | Armand Philippot <git@armandphilippot.com> | 2023-12-16 17:31:12 +0100 |
|---|---|---|
| committer | Armand Philippot <git@armandphilippot.com> | 2023-12-16 19:43:40 +0100 |
| commit | bb2f79e09dd4776d611e4751ede1cbb43340fba0 (patch) | |
| tree | c519128975c5e18c3657858eab2935a230a3228d | |
| parent | bc9a120b56494d5502de9619b79594653b8fd6e6 (diff) | |
fix(build): handle Next.js errors and warnings during build
* extract Blog component from BlogPage (paginated) and extract Article
component from ArticlePage to avoid `Cannot read properties` errors due
to fallback route
* fix sitemap build (cjs not supported)
* fix eslint warnings (react/jsx-no-literals)
* update `start` script since I'm using standalone output
* update `postbuild` script since we need to copy public and static
files to standalone directory (Next.js does not handle it itself
because we should use a CDN...)
| -rw-r--r-- | .env.example | 4 | ||||
| -rw-r--r-- | package.json | 5 | ||||
| -rw-r--r-- | src/components/molecules/modals/tooltip/tooltip.tsx | 2 | ||||
| -rw-r--r-- | src/components/organisms/forms/search-form/search-form.tsx | 6 | ||||
| -rw-r--r-- | src/components/organisms/nav/main-nav/main-nav.tsx | 13 | ||||
| -rw-r--r-- | src/pages/_app.tsx | 1 | ||||
| -rw-r--r-- | src/pages/article/[slug].tsx | 19 | ||||
| -rw-r--r-- | src/pages/blog/page/[number].tsx | 44 | ||||
| -rw-r--r-- | yarn.lock | 33 |
9 files changed, 97 insertions, 30 deletions
diff --git a/.env.example b/.env.example index 12ac09a..5f0c62f 100644 --- a/.env.example +++ b/.env.example @@ -35,6 +35,10 @@ NEXT_PUBLIC_ACKEE_FILENAME="tracker.js" NEXT_PUBLIC_ACKEE_SITE_ID="your-id-string" NEXT_PUBLIC_GITHUB_TOKEN="your-token" +# Use this if you get an error like "Error: 'sharp' is required to be installed +# in standalone mode for the image optimization to function correctly." +#NEXT_SHARP_PATH="node_modules/sharp" + # Use this only in development mode. It prevents "unable to verify the first # certificate" error when using a local domain with mkcert certificate for # backend. diff --git a/package.json b/package.json index b90b656..f1ba943 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,8 @@ "dev": "next dev", "prebuild": "yarn run i18n:compile", "build": "next build", - "postbuild": "next-sitemap", - "start": "next start", + "postbuild": "next-sitemap --config next-sitemap.config.cjs && shx cp -r public .next/standalone && shx cp -r .next/static .next/standalone/.next/static", + "start": "node .next/standalone/server.js", "lint": "next lint && yarn run lint:spelling", "lint:spelling": "cspell \"**\" --no-progress", "deploy": "sh ./bin/deploy.sh", @@ -123,6 +123,7 @@ "postcss": "^8.4.32", "prettier": "^3.1.1", "sass": "^1.69.5", + "shx": "^0.3.4", "storybook": "^7.6.5", "storybook-dark-mode": "^3.0.3", "stylelint": "^16.0.2", diff --git a/src/components/molecules/modals/tooltip/tooltip.tsx b/src/components/molecules/modals/tooltip/tooltip.tsx index 525900d..87e9ac8 100644 --- a/src/components/molecules/modals/tooltip/tooltip.tsx +++ b/src/components/molecules/modals/tooltip/tooltip.tsx @@ -83,7 +83,9 @@ export const Tooltip: FC<TooltipProps> = ({ {heading} </Heading> } + // eslint-disable-next-line react/jsx-no-literals icon={<Icon aria-hidden shape="help" size="sm" />} + // eslint-disable-next-line react/jsx-no-literals kind="secondary" ref={modalRef} > diff --git a/src/components/organisms/forms/search-form/search-form.tsx b/src/components/organisms/forms/search-form/search-form.tsx index a803d8c..eb4f51d 100644 --- a/src/components/organisms/forms/search-form/search-form.tsx +++ b/src/components/organisms/forms/search-form/search-form.tsx @@ -124,7 +124,11 @@ const SearchFormWithRef: ForwardRefRenderFunction< </Button> </Form> {messages?.error && submitStatus === 'FAILED' ? ( - <Notice className={styles.notice} kind="error"> + <Notice + className={styles.notice} + // eslint-disable-next-line react/jsx-no-literals + kind="error" + > {messages.error} </Notice> ) : null} diff --git a/src/components/organisms/nav/main-nav/main-nav.tsx b/src/components/organisms/nav/main-nav/main-nav.tsx index 5a19399..57d8d6e 100644 --- a/src/components/organisms/nav/main-nav/main-nav.tsx +++ b/src/components/organisms/nav/main-nav/main-nav.tsx @@ -28,10 +28,19 @@ const MainNavWithRef: ForwardRefRenderFunction<HTMLElement, MainNavProps> = ( return ( <Nav {...props} className={wrapperClass} ref={ref}> - <NavList isInline spacing="2xs"> + <NavList + isInline + // eslint-disable-next-line react/jsx-no-literals + spacing="2xs" + > {items.map(({ id, ...link }) => ( <NavItem key={id}> - <NavLink {...link} isStack variant="main" /> + <NavLink + {...link} + isStack + // eslint-disable-next-line react/jsx-no-literals + variant="main" + /> </NavItem> ))} </NavList> diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 525335f..42b3de4 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -22,6 +22,7 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => { domainId={CONFIG.ackee.siteId} server={CONFIG.ackee.url} storageKey={STORAGE_KEY.ACKEE} + // eslint-disable-next-line react/jsx-no-literals tracking="full" > <MotionProvider diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index e18de75..ecff692 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -3,7 +3,7 @@ import type { ParsedUrlQuery } from 'querystring'; import type { GetStaticPaths, GetStaticProps } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; -import { useCallback } from 'react'; +import { type FC, useCallback } from 'react'; import { useIntl } from 'react-intl'; import { getLayout, @@ -60,12 +60,8 @@ type ArticlePageProps = { translation: Messages; }; -/** - * Article page. - */ -const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({ data }) => { +const Article: FC<Pick<ArticlePageProps, 'data'>> = ({ data }) => { const intl = useIntl(); - const { isFallback } = useRouter(); const { article, isLoading } = useArticle(data.post.slug, data.post); const { comments, isLoading: areCommentsLoading } = useComments({ fallback: data.comments, @@ -137,7 +133,7 @@ const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({ data }) => { [] ); - if (isFallback || isLoading) return <LoadingPage />; + if (isLoading) return <LoadingPage />; const { content, id, intro, meta, slug, title } = article; const { @@ -276,6 +272,15 @@ const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({ data }) => { ); }; +/** + * Article page. + */ +const ArticlePage: NextPageWithLayout<ArticlePageProps> = ({ data }) => { + const { isFallback } = useRouter(); + + return isFallback ? <LoadingPage /> : <Article data={data} />; +}; + ArticlePage.getLayout = (page) => getLayout(page); type PostParams = { diff --git a/src/pages/blog/page/[number].tsx b/src/pages/blog/page/[number].tsx index fa1123d..e524a64 100644 --- a/src/pages/blog/page/[number].tsx +++ b/src/pages/blog/page/[number].tsx @@ -3,7 +3,7 @@ import type { ParsedUrlQuery } from 'querystring'; import type { GetStaticPaths, GetStaticProps } from 'next'; import Head from 'next/head'; import { useRouter } from 'next/router'; -import { useCallback } from 'react'; +import { type FC, useCallback } from 'react'; import { useIntl } from 'react-intl'; import { getLayout, @@ -78,23 +78,12 @@ type BlogPageProps = { translation: Messages; }; -/** - * Blog index page. - */ -const BlogPage: NextPageWithLayout<BlogPageProps> = ({ +const Blog: FC<Pick<BlogPageProps, 'data' | 'lastCursor' | 'pageNumber'>> = ({ data, lastCursor, pageNumber, }) => { - useRedirection({ - isReplacing: true, - to: ROUTES.BLOG, - whenPathMatches: (path) => - path === `${ROUTES.BLOG}${PAGINATED_ROUTE_PREFIX}/1`, - }); - const intl = useIntl(); - const { isFallback } = useRouter(); const { articles, error, @@ -256,8 +245,6 @@ const BlogPage: NextPageWithLayout<BlogPageProps> = ({ [intl] ); - if (isFallback) return <LoadingPage />; - const pageUrl = `${CONFIG.url}${ROUTES.BLOG}`; return ( @@ -359,6 +346,30 @@ const BlogPage: NextPageWithLayout<BlogPageProps> = ({ ); }; +/** + * Blog index page. + */ +const BlogPage: NextPageWithLayout<BlogPageProps> = ({ + data, + lastCursor, + pageNumber, +}) => { + useRedirection({ + isReplacing: true, + to: ROUTES.BLOG, + whenPathMatches: (path) => + path === `${ROUTES.BLOG}${PAGINATED_ROUTE_PREFIX}/1`, + }); + + const { isFallback } = useRouter(); + + return isFallback ? ( + <LoadingPage /> + ) : ( + <Blog data={data} lastCursor={lastCursor} pageNumber={pageNumber} /> + ); +}; + BlogPage.getLayout = (page) => getLayout(page); type BlogPageParams = { @@ -414,7 +425,8 @@ export const getStaticPaths: GetStaticPaths = async () => { { length: totalPages }, (_, index) => index + 1 ); - const paths = pagesArray.map((number) => { + // We remove /blog/page/1 since it is redirected to /blog + const paths = pagesArray.slice(1).map((number) => { return { params: { number: `${number}` } }; }); @@ -8747,7 +8747,7 @@ glob@^10.0.0: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" -glob@^7.1.3, glob@^7.1.4: +glob@^7.0.0, glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -9441,6 +9441,11 @@ internal-slot@^1.0.4, internal-slot@^1.0.5: hasown "^2.0.0" side-channel "^1.0.4" +interpret@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== + intl-messageformat@10.5.8: version "10.5.8" resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.5.8.tgz#7184da425f360a53a5483a6194e16d666b011fc0" @@ -12992,6 +12997,13 @@ recast@^0.23.1, recast@^0.23.3: source-map "~0.6.1" tslib "^2.0.1" +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== + dependencies: + resolve "^1.1.6" + redent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" @@ -13240,7 +13252,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -13578,6 +13590,23 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shelljs@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +shx@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.4.tgz#74289230b4b663979167f94e1935901406e40f02" + integrity sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g== + dependencies: + minimist "^1.2.3" + shelljs "^0.8.5" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" |
