amannn/next-intl

Turbopack support

troshchenko opened this issue · 12 comments

Description

Running app with turbopack causes an error: Error during SSR Rendering
I use next@13.3.0 and next-intl@2.14.0-beta.2
The setup is done using this guide https://next-intl-docs.vercel.app/docs/next-13/server-components

Mandatory reproduction URL (CodeSandbox or GitHub repository)

https://next-intl-docs.vercel.app/docs/next-13/server-components

Reproduction description

Steps to reproduce:

  1. run an app on dev with --turbo flag
  2. Get an error: Error during SSR Rendering
    Debug info:

Expected behaviour

Expect app to work properly.

amannn commented

I tried to run https://github.com/amannn/next-intl/tree/main/packages/example-next-13 on the main branch with --turbo and am getting this error:

error - [typescript] tsconfig.json
  An issue occurred while parsing a tsconfig.json file.
  extends doesn't resolve correctly

warning - [other] 
  Could not resolve React Refresh runtime
  React Refresh will be disabled.
  To enable React Refresh, install the `react-refresh` and `@next/react-refresh-utils` modules.

  Could not resolve React Refresh runtime
  React Refresh will be disabled.
  To enable React Refresh, install the `react-refresh` and `@next/react-refresh-utils` modules.

  Could not resolve React Refresh runtime
  React Refresh will be disabled.
  To enable React Refresh, install the `react-refresh` and `@next/react-refresh-utils` modules.

error - [resolve] src/middleware.tsx
  Error resolving EcmaScript Modules request
  unable to resolve module "next" with subpath "/dist/server/future/route-modules/app-route/module"

[500] error (278ms): error during Next.js routing for /

Caused by:
- router evaluation failed: received error from javascript stream
- content is not available as task execution failed
- could not find app asset

Debug info:
- Execution of get_from_source failed
- Execution of resolve_source_request failed
- Execution of NextRouterContentSource::get failed
- error during Next.js routing for /
- router evaluation failed: received error from javascript stream
- Execution of get_evaluate_pool failed
- Execution of emit failed
- Execution of internal_assets failed
- Execution of separate_assets failed
- Execution of primary_referenced_assets failed
- Execution of NodeJsBootstrapAsset::references failed
- Execution of turbopack_core::chunk::ChunkGroupVc::chunks failed
- Execution of EcmascriptChunk::references failed
- Execution of ecmascript_chunk_content_single_entry failed
- content is not available as task execution failed
- Execution of NextEdgeTransition::process_module failed
- could not find app asset
[500] error (1.515ms): error during Next.js routing for /favicon.ico

Caused by:
- router evaluation failed: received error from javascript stream
- content is not available as task execution failed
- could not find app asset

Debug info:
- Execution of get_from_source failed
- Execution of resolve_source_request failed
- Execution of NextRouterContentSource::get failed
- error during Next.js routing for /favicon.ico
- router evaluation failed: received error from javascript stream
- Execution of get_evaluate_pool failed
- Execution of emit failed
- Execution of internal_assets failed
- Execution of separate_assets failed
- Execution of primary_referenced_assets failed
- Execution of NodeJsBootstrapAsset::references failed
- Execution of turbopack_core::chunk::ChunkGroupVc::chunks failed
- Execution of EcmascriptChunk::references failed
- Execution of ecmascript_chunk_content_single_entry failed
- content is not available as task execution failed
- Execution of NextEdgeTransition::process_module failed
- could not find app asset

Not sure what to do with this, Turbopack seems really alpha at this point.

I think middleware is generally not supported yet by Turbopack: vercel/next.js#42921

@amannn thanks for your review!
Yes, sounds like a backlog issue. Looking into Nextjs release notes - bit by bit they add more support for Turbopack.
Turbopack is a great feature, especially for massive projects, and especially with i18n, radically speeding up dev process.

I have this error with next 13.4.10 and 3.0.0-beta.8 with next dev --turbo --root / --show-all :

- info Loaded env from C:\Users\flame\WebstormProjects\workoutgen\apps\web-app\.env
>>> TURBOPACK (beta)

Thank you for trying Next.js v13 with Turbopack! As a reminder,
Turbopack is currently in beta and not yet ready for production.pps\web-app
We appreciate your ongoing support as we work to make it ready
for everyone.


Warning: Webpack is configured while Turbopack is not, which may cause problems.

  See instructions if you need to configure Turbopack:
  https://turbo.build/pack/docs/features/customizing-turbopack

Learn more about Next.js v13 and Turbopack: https://nextjs.link/with-turbopack
Please direct feedback to: https://nextjs.link/turbopack-feedback

ready - started server on [::]:3000, url: http://localhost:3000
error - [resolve] Users\flame\WebstormProjects\workoutgen\node_modules\.pnpm\next-intl@3.0.0-beta.8_next@13.4.10_react@18.2.0\node_modules\next-intl\plugin.js
  Users\flame\WebstormProjects\workoutgen\node_modules\.pnpm\next-intl@3.0.0-beta.8_next@13.4.10_react@18.2.0\node_modules\next-intl\plugin.js:50:50  Error resolving commonjs request
      46 |   }
      47 | 
      48 |   return Object.assign({}, nextConfig, {
      49 |     webpack(config, options) {
         +                                                   v-----------------------v
      50 +       config.resolve.alias['next-intl/config'] = require.resolve(i18nPath);
         +                                                   ^-----------------------^
      51 | 
      52 |       if (typeof nextConfig?.webpack === 'function') {
      53 |         return nextConfig.webpack(config, options);
      54 |       }

  unable to resolve dynamic or dynamic or dynamic

warning - [parse] Users\flame\WebstormProjects\workoutgen\node_modules\.pnpm\next-intl@3.0.0-beta.8_next@13.4.10_react@18.2.0\node_modules\next-intl\plugin.js
  Users\flame\WebstormProjects\workoutgen\node_modules\.pnpm\next-intl@3.0.0-beta.8_next@13.4.10_react@18.2.0\node_modules\next-intl\plugin.js:10:9  lint TP1004 fs.existsSync((???*0* | ???*1* | ???*2*)) is very dynamic
       6 | function initPlugin(i18nPath, nextConfig) {
       7 |   if (i18nPath) {
       8 |     i18nPath = path.resolve(i18nPath);
       9 | 
         +          v
      10 +     if (!fs.existsSync(i18nPath)) {
         +          ^
      11 |       throw new Error(
      12 |         `Could not find i18n config at ${i18nPath}, please provide a valid path.`
      13 |       );
      14 |     }

  - *0* arguments[0]
    ⚠️  function calls are not analysed yet
  - *1* i18nPath
    ⚠️  circular variable reference
  - *2* ???*3*((...) => fs["existsSync"](cur))
    ⚠️  unknown callee
  - *3* [???, ???, ???, ???, ???, ???, ???, ???]["find"]
    ⚠️  non-num constant property on array

  Users\flame\WebstormProjects\workoutgen\node_modules\.pnpm\next-intl@3.0.0-beta.8_next@13.4.10_react@18.2.0\node_modules\next-intl\plugin.js:26:20  lint TP1006 path.resolve(???*0*) is very dynamic
      22 |       './src/i18n.ts',
      23 |       './src/i18n.js',
      24 |       './src/i18n.jsx'
      25 |     ]
         +                     v
      26 +       .map((cur) => path.resolve(cur))
         +                     ^
      27 |       .find((cur) => fs.existsSync(cur));
      28 | 
      29 |     if (!i18nPath) {
      30 |       throw new Error(`\n\nCould not locate i18n config. Create one at \`./(src/)i18n.{js,jsx,ts,tsx}\` or specify a custom location:

  - *0* cur
    ⚠️  pattern without value

  Users\flame\WebstormProjects\workoutgen\node_modules\.pnpm\next-intl@3.0.0-beta.8_next@13.4.10_react@18.2.0\node_modules\next-intl\plugin.js:27:21  lint TP1004 fs.existsSync(???*0*) is very dynamic
      23 |       './src/i18n.js',
      24 |       './src/i18n.jsx'
      25 |     ]
      26 |       .map((cur) => path.resolve(cur))
         +                      v
      27 +       .find((cur) => fs.existsSync(cur));
         +                      ^
      28 | 
      29 |     if (!i18nPath) {
      30 |       throw new Error(`\n\nCould not locate i18n config. Create one at \`./(src/)i18n.{js,jsx,ts,tsx}\` or specify a custom location:
      31 | 

  - *0* cur
    ⚠️  pattern without value

  Users\flame\WebstormProjects\workoutgen\node_modules\.pnpm\next-intl@3.0.0-beta.8_next@13.4.10_react@18.2.0\node_modules\next-intl\plugin.js:50:49  lint TP1003 require.resolve((???*0* | ???*1* | ???*2*)) is very dynamic
      46 |   }
      47 | 
      48 |   return Object.assign({}, nextConfig, {
      49 |     webpack(config, options) {
         +                                                  v
      50 +       config.resolve.alias['next-intl/config'] = require.resolve(i18nPath);
         +                                                  ^
      51 | 
      52 |       if (typeof nextConfig?.webpack === 'function') {
      53 |         return nextConfig.webpack(config, options);
      54 |       }

  - *0* arguments[0]
    ⚠️  function calls are not analysed yet
  - *1* i18nPath
    ⚠️  circular variable reference
  - *2* ???*3*((...) => fs["existsSync"](cur))
    ⚠️  unknown callee
  - *3* [???, ???, ???, ???, ???, ???, ???, ???]["find"]
    ⚠️  non-num constant property on array

  Users\flame\WebstormProjects\workoutgen\node_modules\.pnpm\next-intl@3.0.0-beta.8_next@13.4.10_react@18.2.0\node_modules\next-intl\plugin.js:8:15  lint TP1006 path.resolve((???*0* | ???*1* | ???*2*)) is very dynamic
       4 | const path = require('path');
       5 | 
       6 | function initPlugin(i18nPath, nextConfig) {
       7 |   if (i18nPath) {
         +                v
       8 +     i18nPath = path.resolve(i18nPath);
         +                ^
       9 | 
      10 |     if (!fs.existsSync(i18nPath)) {
      11 |       throw new Error(
      12 |         `Could not find i18n config at ${i18nPath}, please provide a valid path.`

  - *0* arguments[0]
    ⚠️  function calls are not analysed yet
  - *1* i18nPath
    ⚠️  circular variable reference
  - *2* ???*3*((...) => fs["existsSync"](cur))
    ⚠️  unknown callee
  - *3* [???, ???, ???, ???, ???, ???, ???, ???]["find"]
    ⚠️  non-num constant property on array

any update ?

any update?

amannn commented

As mentioned in my comment above, Turbopack doesn't support middleware yet, so support in next-intl is blocked currently. For now, we have to wait for Turbopack to become more stable.

The issue is actually smaller than how it appears.

@amannn: I think the error in your comment is only related to Next.JS running in a monorepo. In such cases Turbopack needs to know the Monorepo root, see vercel/turbo#4763 (comment).

The "Couldn't find next-intl config file." error comes from the fact how next-intl is implemented: It just adds a webpack config to resolve next-intl/config to the local config file. In turbopack the equivalent is adding the following to the next.config.js:

experimental: {
	turbo: {
		resolveAlias: {
			'next-intl/config': './path/to/i18n.ts',
		},
	},
},

I however also get a strange error from the use of the use hook in next-intl. There also seems to be an issue with the middleware, but the middleware itself gets called, even with Turbopack.

amannn commented

@amannn: I think the error in your comment is only related to Next.JS running in a monorepo. In such cases Turbopack needs to know the Monorepo root, see vercel/turbo#4763 (comment).

Oh cool, thanks for the hint!

Thanks also for including the hint about resolveAlias, that should help!

It seems like the middleware is called now, but I still get strange behavior when running example-next-13 on main with pnpm dev --turbo --root ../../. The locale switcher somehow doesn't work correctly. When running without --turbo, everything works correctly.

Therefore I guess we need to wait for issues to be resolved on the Turbopack side first.

It's getting closer. vercel/next.js#58218

Experimental support for --turbo has just been added in #641! The examples in this repo already seem to work! 🚀

Please note that Turbopack is still in preview: https://areweturboyet.com/

The issue is actually smaller than how it appears.

@amannn: I think the error in your comment is only related to Next.JS running in a monorepo. In such cases Turbopack needs to know the Monorepo root, see vercel/turbo#4763 (comment).

The "Couldn't find next-intl config file." error comes from the fact how next-intl is implemented: It just adds a webpack config to resolve next-intl/config to the local config file. In turbopack the equivalent is adding the following to the next.config.js:

experimental: {
	turbo: {
		resolveAlias: {
			'next-intl/config': './path/to/i18n.ts',
		},
	},
},

I however also get a strange error from the use of the use hook in next-intl. There also seems to be an issue with the middleware, but the middleware itself gets called, even with Turbopack.

thanks for sharing, solved my problem!

Hello @amannn! I'm still experiencing a similar issue...! When compiling using

next dev --turbo

The compilier doesn't find/generate into the .next folder my middleware.ts located in src/middleware.ts... I have tried everything so far...

Example in the compiler when using --turbo

Screenshot 2023-12-17 at 11 45 11 AM

Example in the compiler when NOT using --turbo

Screenshot 2023-12-17 at 11 47 21 AM

Here is my setup:

  • "next": "^14.0.5-canary.16",

  • "react": "^18.3.0-next-fecc288b7-20221025",

  • "next-intl": "^3.3.2",

  • next.config.js:

/** @type {import('next').NextConfig} */
const config = {};

const nextConfig = withNextIntl(config);

module.exports = nextConfig;

File locations:

  • /src/i18n.ts
import { getRequestConfig } from 'next-intl/server';

import { LanguageEnums } from './shared/enums';

export const defaultLocale = LanguageEnums.EN;
export const locales = [defaultLocale, LanguageEnums.FR];
export const localePrefix = 'always';

export default getRequestConfig(async ({ locale }) => ({
  messages: (
    await (locale === 'en'
      ? // When using Turbopack, this will enable HMR for `en`
        import('../messages/en.json')
      : import(`../messages/${locale}.json`))
  ).default,
}));
  • /src/middleware.ts
/**
 * middleware.ts needs to be located under /src/ folder in order to be detected
 */

import createMiddleware from 'next-intl/middleware';

import { locales, localePrefix, defaultLocale } from './i18n';

export default createMiddleware({
  // A list of all locales that are supported
  locales,

  // Always use a locale prefix
  localePrefix,

  // If this locale is matched, pathnames work without a prefix (e.g. `/about`)
  defaultLocale,
});

export const config = {
  // Skip all paths that should not be internationalized
  matcher: ['/((?!api|_next|.*\\..*).*)'],
};
  • /src/navigation.ts
  • /messages/[x].json

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "preserve",
    "noFallthroughCasesInSwitch": true,
    "incremental": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"],
      "app/*": ["src/app/*"],
      "config/*": ["app/_config/*"],
      "shared/*": ["src/app/_shared/*"],
    },
    "plugins": [
      {
        "name": "next"
      }
    ]
  },
  "include": [
    "next-env.d.ts",
    "./**/*.ts",
    "./**/*.tsx",
    "./src/types",
    ".next/types/**/*.ts"
  ],
  "exclude": [
    "node_modules",
    "next-env.d.ts",
    ".next"
  ]
}

FYI: Without --turbo everything is working as expected.

GitHub issues or commits I looked into

Am I missing something... thanks for ya'll support!