Next.js + TypeScript にて 外部 JS を読み込んで扱う

Next.js にて外部 JS を読み込んで使用するまでのメモ。

環境

  • Next.js v15
  • React v19
  • TypeScript v5
  • App Router

Script - Next.js

Next.js にて外部ファイルを扱う場合、
Script - Next.js という便利なコンポーネントが用意されているので、
それを使う。

また、十分に機能を使うには Client Component で使用する。

サンプルコード

下記ライプラリで試してみる。

構成

/src
  ├ /app
  │   └ page.tsx
  ├ /features
  │   └ /sample
  │       └ index.tsx
  └ /types
      └ global.d.ts

/src/app/page.tsx

import Sample from "@/features/sample"

export default function Page() {
	return <Sample />
}

/src/types/global.d.ts

declare class Chart {
	constructor(target: HTMLElement, option: object)
}

type DayJS = {
	format: () => string
}

declare function dayjs(): DayJS

/src/features/sample/index.tsx

サンプルコードをほぼコピペ

"use client"

import { useState as UseState } from "react"
import Script from "next/script"
// declare class Chart {
// 	constructor(target: HTMLElement, option: object)
// }

function ChartJS(): React.ReactNode {
	function onLoad() {
		console.log("onLoad")
	}

	function onReady() {
		console.log("onReady")
		const ctx = document.getElementById("chart")
		if (!ctx) {
			console.error(`not found <canvas id="chart"></canvas>`)
			return
		}
		new Chart(ctx, {
			type: "bar",
			data: {
				labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
				datasets: [
					{
						label: "# of Votes",
						data: [12, 19, 3, 5, 2, 3],
						borderWidth: 1,
					},
				],
			},
			options: {
				scales: {
					y: {
						beginAtZero: true,
					},
				},
			},
		})
	}

	function onError(e: Error) {
		console.log("onError")
		console.error(e)
	}

	return (
		<>
			<Script
				src="https://cdn.jsdelivr.net/npm/chart.js"
				strategy="afterInteractive"
				onLoad={onLoad}
				onReady={onReady}
				onError={onError}
			/>
			<div>
				<canvas id="chart"></canvas>
			</div>
		</>
	)
}
// declare function dayjs(): {
// 	format: () => string
// }

function DayJS(): React.ReactNode {
	const [value, setValue] = UseState("")

	function onLoad() {
		console.log("onLoad")
	}

	function onReady() {
		console.log("onReady")
		setValue(dayjs().format())
	}

	function onError(e: Error) {
		console.log("onError")
		console.error(e)
	}

	return (
		<>
			<Script
				src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"
				strategy="afterInteractive"
				onLoad={onLoad}
				onReady={onReady}
				onError={onError}
			/>
			<div>{value}</div>
		</>
	)
}
export default function Sample(): React.ReactNode {
	return (
		<>
			<ChartJS />
			<DayJS />
		</>
	)
}

ビルドエラーメモ

Type error: Cannot find name 'Xxxx'.

Next.js + TypeScript でビルドする時に、
外部 JS の型定義をしていないとエラーが起きる。

'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.

関数として扱うものを new で宣言して扱うとエラーが出る。

const v = new foo() // NG
const v = foo() // OK