🙆‍♀️

Next.jsがESModuleフォーマットサポートしてない問題(ERR_REQUIRE_ESM)の回避策

2021/07/03に公開

Next.jsでd3使おうとしたら、ハマりました。
Next.jsがESModuleフォーマットをサポートしてないのが原因のようです。
https://github.com/vercel/next.js/issues/9607

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/hogehoge/node_modules/robust-predicates/index.js
require() of ES modules is not supported.

仕組みは全然分かってないですが、一旦これで解決できたので共有します。
https://github.com/d3/d3-format/issues/114#issuecomment-826338584

ちなみに、next-transpile-modulesを使う回避策もあって、自分も使っていたのですが、
d3で適用させようとしても、途中でエラーが出てしまったため、上のgithubのリンクの回避策をとりました。(withTMってのがそれでコメントアウトしてます)
https://zenn.dev/tomon9086/scraps/3a1d9d3eed4864#comment-4729aa5b084adc

next.config.js
// eslint-disable-next-line @typescript-eslint/no-var-requires
// const withTM = require('next-transpile-modules')(['react-children-utilities'])
/* eslint-disable @typescript-eslint/no-var-requires, no-undef */

const path = require('path')

function generateIncludes(modules) {
  return [
    new RegExp(`(${modules.join('|')})$`),
    new RegExp(`(${modules.join('|')})/(?!.*node_modules)`),
  ]
}

const includes = generateIncludes([
  'd3',
  'd3-array',
  'd3-axis',
  'd3-brush',
  'd3-chord',
  'd3-color',
  'd3-contour',
  'd3-delaunay',
  'd3-dispatch',
  'd3-drag',
  'd3-dsv',
  'd3-ease',
  'd3-fetch',
  'd3-force',
  'd3-format',
  'd3-geo',
  'd3-hierarchy',
  'd3-interpolate',
  'd3-path',
  'd3-polygon',
  'd3-quadtree',
  'd3-random',
  'd3-scale',
  'd3-scale-chromatic',
  'd3-selection',
  'd3-shape',
  'd3-time',
  'd3-time-format',
  'd3-timer',
  'd3-transition',
  'd3-zoom',
  'internmap',
  'delaunator',
  'robust-predicates',
  'react-children-utilities',
])

const config = {
  webpack: (config) => {
    // ここは関係ない
    // config.module.rules.push({
    //  test: /\.css$/,
    //  use: 'raw-loader',
    //})
    config.externals = config.externals.map((external) => {
      if (typeof external !== 'function') return external
      return (context, request, callback) => {
        return includes.find((i) =>
          i.test(request.startsWith('.') ? path.resolve(context, request) : request)
        )
          ? callback() // i.e., not an external
          : external(context, request, callback)
      }
    })

    return config
  },
}

// module.exports = withTM(config)
module.exports = config

Discussion