JavaScript
    JavaScript - Overview
    ESlint
    D3.js
    mongodb
    Socket.io
    File Upload
    Web Crawling

Next.js

Updated: 2022-03-26

Next.js + MDX

const withMDX = require('@next/mdx')({
  extension: /\.(md|mdx)$/,
});

module.exports = withMDX({
  // Pick up MDX files in the /pages/ directory
  pageExtensions: ['js', 'jsx', 'md', 'mdx'],
});

Google Analytics

Add this to any of the <Head>:

import Head from 'next/head';
import Script from 'next/script';

<Head>
  <Script async src="https://www.googletagmanager.com/gtag/js?id=XXXXXXXX" />
  <Script
    dangerouslySetInnerHTML={{
      __html: `
        window.dataLayer = window.dataLayer || [];
        function gtag(){dataLayer.push(arguments);}
        gtag('js', new Date());

        gtag('config', 'XXXXXXXX');
      `,
    }}
  />
</Head>;

Sitemap

Use nextjs-sitemap package.

Image

Local image: no need to specify width and height since they are available at the build time.

import localImage from '/path/to/image.jpg';
import Image from 'next/image';

<Image src={localImage} />;

Remote image: need to specify width and height.

<Image src="http://example.com/image.png" width={400} height={500} />

How to use Node.js API vs Web API

Server-side only: Node.js API

To use path, fs, put them inside getStaticProps(), which is called at the build time on the server-side but not on the client-side:

import { promises as fs } from 'fs';
import path from 'path';

export async function getStaticProps(context) {
  const filepath = path.join(process.cwd(), 'path/to/file');
  const content = (await fs.readFile(filepath)).toString();
  return {
    props: {
      content: await Promise.all(content),
    },
  };
}

Client-side only: Web API

To use window or other Web APIs, use the useEffect hook, which only executes client-side:

import { useEffect } from 'react';

useEffect(() => {
  // You now have access to `window`
}, []);

Get Window Height

As mentioned above, window is available inside useEffect():

const [mapHeight, setMapHeight] = useState(0);

useEffect(() => {
  setMapHeight(window.innerHeight - 100);
}, []);

Deployment

If your site is static, you can use next build && next export to export the static HTML.

Otherwise Next.js has a built-in server. You can check Next.js's package.json, it depends on express.

Trouble Shooting

The default Firebase app already exists.

Solution: check if (!firebase.apps.length):

import firebase from 'firebase-admin';
import { initializeApp, cert } from 'firebase-admin/app';

if (!firebase.apps.length) {
  initializeApp({
    credential: cert(serviceAccount),
  });
}

Undefined router

The result of const router = useRouter(); may be undefined at the first rendering.

Solution: check router.isReady in useEffect:

const router = useRouter();
useEffect(() => {
  if (!router.isReady) return;
  // ...
}, [router.isReady]);