next.js: Error when accessing Typescript enum defined outside Next root in Next 9.4

Bug report

Accessing a typescript enum property when the file defining the enum is outside Next’s directory causes issues in Next 9.4.0 and Next 9.4.1, but not in Next 9.3.6.

Describe the bug

Defining a Typescript enum in a .ts file outside the root causes issues running next if any property is accessed on the enum.

The error implies that the file was not parsed correctly:

../lib/common/types.ts 1:7
Module parse failed: Unexpected token (1:7)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> export enum MyEnum {
|   OPTION_ONE = 1,
|   OPTION_TWO = 2,

This was not a problem in Next 9.3.6.

It’s hard to describe, so I put together a minimal reproduction: https://github.com/majelbstoat/nextjs-broken-enums

Expected behavior

Typescript is compiled correctly, and I can access properties on enums.

System information

  • OS: [macOS]
  • Version of Next.js: [9.4.0, 9.4.1]
  • Version of Node.js: [12.16.1]

Additional context

This broke in 9.4.0, and I originally thought it was the definition itself that caused the problem because that’s what the error implied (https://github.com/zeit/next.js/issues/12786) but that was a symptom, not the root issue.

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 23 (8 by maintainers)

Most upvoted comments

It seems as if this experimental configuration in next.config.js fixes the problem:

module.exports = {
  experimental: {
    externalDir: true,
  },
}

Here’s what worked for me, (based on @majelbstoat), using the function version of next.config.js

// This uses phases as outlined here: https://nextjs.org/docs/api-reference/next.config.js/introduction
module.exports = (phase, { defaultConfig }) => {
  return {
    ...defaultConfig, // This is important
    webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
      fixEnums(config); // This is important
      return config
    },
  }
}

function fixEnums(config) {
  config.module.rules.forEach(({ use }, i) => {
    if (!use) return
    const isBabelLoader = Array.isArray(use)
      ? use.findIndex((item) => item && item.loader && item.loader === 'next-babel-loader') !== -1
      : use.loader === 'next-babel-loader'
    if (isBabelLoader) {
      delete config.module.rules[i].include
    }
  })
}

@benwinding Your fixEnum method doesn’t seem to work with webpack5. Do you have a workaround?

Why Next.js 10 does not support const enums?

Hmm I still have a problem and I don’t know why…

  • Next.js version: 11.1.3
  • active experimental externalDir option