Skip to Content
Made with 🖤 by @1chooo
Wiki

Wiki

Here, we will discuss the problems and solutions that we have encountered in the development process.

Support for TypeScript 5.x in Create React App

In the https://github.com/1chooo/1chooo.com/pull/76, when I tried to upgrade the react-scripts to 5.x, I got the following error:

npm error code ERESOLVE npm error ERESOLVE could not resolve npm error npm error While resolving: react-scripts@5.0.1 npm error Found: typescript@5.5.4 npm error node_modules/typescript npm error typescript@"^5.5.4" from the root project npm error peer typescript@">= 2.7" from fork-ts-checker-webpack-plugin@6.5.3 npm error node_modules/fork-ts-checker-webpack-plugin npm error fork-ts-checker-webpack-plugin@"^6.5.0" from react-dev-utils@12.0.1 npm error node_modules/react-dev-utils npm error react-dev-utils@"^12.0.1" from react-scripts@5.0.1 npm error node_modules/react-scripts npm error react-scripts@"5.0.1" from the root project npm error 1 more (tsutils) npm error npm error Could not resolve dependency: npm error peerOptional typescript@"^3.2.1 || ^4" from react-scripts@5.0.1 npm error node_modules/react-scripts npm error react-scripts@"5.0.1" from the root project

Add the following to the package.json to solve the problem: 1

+ "overrides": { + "typescript": "^5.5.4" + },

[!IMPORTANT] The version of overrides must be the same as the version of TypeScript in dependencies.

Migrate from Create React App to NextJS

"scripts": { "dev": "next dev", "build": "next build", "start": "next start" },
$ npm uninstall react-scripts $ npm uninstall react-router-dom $ npm install next

Dangerously Set innerHTML

https://dev.to/shareef/rendering-markdown-made-easy-with-react-markdown-in-reactjs-and-nextjs-web-apps-259d

In HTML, <div> cannot be a descendant of <p>. This will cause a hydration error.
... <Markdown> <p> ^^^ <http://localhost:3000/_next/static/chunks/src_dd03ef._.js:150:225> <div>
+ const isImageNode = (node: any): node is Element => { + return node && node.type === 'element' && node.tagName === 'img'; + }; const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content }) => ( <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]} components={{ + p: ({ node, children }) => { + const hasImage = node && node.children && node.children.some(isImageNode); + if (hasImage) { + return <>{children}</>; + } + return <p>{children}</p>; + }, ... > {content} </ReactMarkdown> ); export default MarkdownRenderer;

React Wrap Balancer

React Wrap Balancer is a simple React Component that makes your titles more readable in different viewport sizes. It improves the wrapping to avoid situations like single word in the last line, makes the content more “balanced”: 1

Simple React Component That Makes Titles More Readable

Usage

We have to install the package first:

npm i react-wrap-balancer

Then we can use it in our project:

import Balancer from 'react-wrap-balancer' // ... function Title() { return ( <h1> <Balancer>My Awesome Title</Balancer> </h1> ) }

If we have multiple <Balancer> components used, we can wrap them with <Provider> to share the re-balance logic:

import { Provider } from 'react-wrap-balancer' // ... function App() { return ( <Provider> <MyApp/> </Provider> ) }

Next.js Image Fast Loading

SEO Tools

Open Graph Meta Tags

Loose Autocomplete

acceptString = (str: "foo" | "bar" | (string & {})) => { console.log(str); }; acceptString("baz");

https://www.threads.net/@jimmy.chiang/post/C_vl632ygU_/?xmt=AQGzwdnxgbmCCfAF8xCgI2zZiemQtJDR7omD6Mb26Ge3CA

https://www.youtube.com/live/8HoOxOd86M4?t=2778&si=P2mxsBXVq8UmrAX_

Robots.txt

/** * https://www.cloudflare.com/zh-tw/learning/bots/what-is-robots-txt/ * https://www.cloudflare.com/robots.txt * https://github.com/vercel/vercel/blob/3e4223684609dbdb7d9a2b286294fe07941bf0d4/examples/hydrogen-2/app/routes/%5Brobots.txt%5D.tsx# * https://github.com/vercel/vercel/blob/3e4223684609dbdb7d9a2b286294fe07941bf0d4/packages/cli/test/dev/integration-2.test.ts# * https://github.com/vercel/vercel/blob/3e4223684609dbdb7d9a2b286294fe07941bf0d4/examples/hydrogen/src/routes/robots.txt.server.ts * @returns */ const robotsTxtContent = ` # ________ # __,_, | | # [_|_/ | OK | # // |________| # _// __ / # (_|) |@@| # \\ \\__ \\--/ __ # \\o__|----| | __ # \\ }{ /\\ )_ / _\\ # /\\__\\/ \\__O (__ # (--/\\--) \\__/ # _)( )(_ # \`---''---\` User-agent: * Disallow: `;
/** * This API endpoint generates a robots.txt file. Use this to control * access to your resources from SEO crawlers. * Learn more: https://developers.google.com/search/docs/advanced/robots/create-robots-txt */ import type {HydrogenRequest} from '@shopify/hydrogen'; export async function api(request) { const url = new URL(request.url); return new Response(robotsTxtData({url: url.origin}), { headers: { 'content-type': 'text/plain', // Cache for 24 hours 'cache-control': `max-age=${60 * 60 * 24}`, }, }); } function robotsTxtData({url}: {url: string}) { const sitemapUrl = url ? `${url}/sitemap.xml` : undefined; return ` User-agent: * Disallow: /admin Disallow: /cart Disallow: /orders Disallow: /checkouts/ Disallow: /checkout Disallow: /carts Disallow: /account ${sitemapUrl ? `Sitemap: ${sitemapUrl}` : ''} # Google adsbot ignores robots.txt unless specifically named! User-agent: adsbot-google Disallow: /checkouts/ Disallow: /checkout Disallow: /carts Disallow: /orders User-agent: Pinterest Crawl-delay: 1 `.trim(); }

Font Optimization

refactor(font): add Roboto font and update layout to optimize with next/font (#556)

Before

src/app/global.css
.root { /* font-family */ - --ff-poppins: "Poppins", sans-serif; } - html { - font-family: var(--ff-poppins); - }
src/app/font.ts
import { Roboto } from "next/font/google"; export const roboto = Roboto({ weight: ['400', '700'], style: ['normal', 'italic'], subsets: ['latin'], display: 'swap', })
src/app/layout.tsx
import { roboto } from "./font"; const RootLayout = (props: RootLayoutProps) => { const { children } = props return ( - <html lang="en"> + <html lang="en" className={`${roboto.className}`}>

Dynamic Manifest

Next.js provides a convenient way to generate a web app manifest dynamically using its metadata API. This approach allows you to customize your manifest based on your application’s configuration or environment. This allows browsers to present the web app similarly to native applications, enabling features like installation on the home screen and full-screen display. 2

RSS Feed

Minimize main-thread work

How to minimize the “Minimize main-thread work” in nextjs? #19436

How to minimize main thread work in React Component https://aatifbandey.medium.com/reduce-main-thread-work-in-react-component-a90c9bc1d9b3

Web Vitals

https://github.com/luciancah/nextjs-ko/blob/7f67677d32f7247d0d468f1b3e1bceb43a6e03bd/pages/docs/app/building-your-application/optimizing/analytics.mdx#L17 https://github.com/axiomhq/next-axiom/tree/0ad6cf706dc154b17bd65e11d850a8c2b710db61/src/webVitals

Using setTimeout with Promise for Delayed Execution

When testing rendering effects or simulating delays in asynchronous operations, you can use setTimeout wrapped in a Promise. This approach ensures clean and readable code, especially in async/await contexts.

Code Example

To add a timeout in your tests or development workflows:

await new Promise(resolve => setTimeout(resolve, 3000));

Explanation

  1. setTimeout: Executes a function after a specified delay (in milliseconds).
  2. Promise: Allows setTimeout to work seamlessly with async/await.
  3. 3000: Represents the delay in milliseconds (3 seconds in this example).

When to Use

  • To simulate network latency or slow computations.
  • To test skeleton loaders or other rendering effects.
  • To delay execution for debugging or animations.

Usage in a Function

async function simulateLoadingEffect() { console.log('Loading...'); await new Promise(resolve => setTimeout(resolve, 3000)); console.log('Done!'); } simulateLoadingEffect();

Output

  1. Displays “Loading…”
  2. Waits for 3 seconds
  3. Displays “Done!“

application/ld+json

Example - Apple

<script type="application/ld+json"> { "@context": "http://schema.org", "@id": "https://www.apple.com/#organization", "@type": "Organization", "name": "Apple", "url": "https://www.apple.com/", "logo": "https://www.apple.com/ac/structured-data/images/knowledge_graph_logo.png?202110180743", "subOrganization": { "@type": "Organization", "name": "Apple Support", "url": "https://support.apple.com", "@id": "https://support.apple.com/#organization" }, "contactPoint": [ { "@type": "ContactPoint", "telephone": "+1-800-692-7753", "contactType": "sales", "areaServed": "US" }, { "@type": "ContactPoint", "telephone": "+1-800-275-2273", "contactType": "technical support", "areaServed": "US", "availableLanguage": ["EN", "ES"] }, { "@type": "ContactPoint", "telephone": "+1-800-275-2273", "contactType": "customer support", "areaServed": "US", "availableLanguage": ["EN", "ES"] } ], "sameAs": [ "http://www.wikidata.org/entity/Q312", "https://www.youtube.com/user/Apple", "https://www.linkedin.com/company/apple", "https://www.facebook.com/Apple", "https://www.twitter.com/Apple" ] } </script>

Example - honghong.me

https://github.com/tszhong0411/honghong.me/blob/main/apps/web/src/app/page.tsx

$ npm i schema-dts
const jsonLd: WithContext<WebSite> = { '@context': 'https://schema.org', '@type': 'WebSite', name: SITE_TITLE, description: SITE_DESCRIPTION, url: SITE_URL, author: { '@type': 'Person', name: SITE_NAME, url: SITE_URL, sameAs: [SITE_FACEBOOK_URL, SITE_INSTAGRAM_URL, SITE_X_URL, SITE_GITHUB_URL, SITE_YOUTUBE_URL] }, mainEntityOfPage: { '@type': 'WebPage', '@id': SITE_URL }, inLanguage: 'en-US', copyrightYear: new Date().getFullYear(), keywords: SITE_KEYWORDS, dateCreated: '2020-12-05', dateModified: new Date().toISOString() } <script type='application/ld+json' dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />

References

Debugging Tools

https://developers.facebook.com/tools/debug/

png to webp

https://cloudconvert.com/png-to-webp

⨯ ESLint: Failed to load plugin 'jest' declared in '.eslintrc.js': Cannot find module 'eslint-plugin-jest' Require stack: - /Users/hugolin/Developer/1chooo.com/apps/web/__placeholder__.js ✓ Linting and checking validity of types

https://stackoverflow.com/questions/71781215/typeerror-failed-to-load-plugin-jest-declared-in-eslintrc-class-extends-v

⚠ Found lockfile missing swc dependencies, patching... ⚠ Lockfile was successfully patched, please run "npm install" to ensure @next/swc dependencies are downloaded
⨯ You are using configuration and/or tools that are not yet supported by Next.js with Turbopack: - Unsupported Next.js configuration option(s) (next.config.js) To use Turbopack, remove the following configuration options: - experimental.forceSwcTransforms If you cannot make the changes above, but still want to try out Next.js with Turbopack, create the Next.js playground app by running the following commands: npx create-next-app --example with-turbopack with-turbopack-app cd with-turbopack-app npm run dev ⚠ Learn more about Next.js and Turbopack: https://nextjs.link/with-turbopack
⚠ Using edge runtime on a page currently disables static generation for that page

https://nextjs.org/docs/messages/swc-disabled

https://buildui.com/posts/global-progress-in-nextjs

https://convertio.co/

Footnotes

  1. (react-scripts) Support for TypeScript 5.x #13080 2

  2. Generate a Web App Manifest with Next.js

Last updated on