vercel / next.js

The React Framework
https://nextjs.org
MIT License
124.36k stars 26.53k forks source link

middleware matcher should support template literals #56398

Open stefanprobst opened 10 months ago

stefanprobst commented 10 months ago

Link to the code that reproduces this issue

https://github.com/stefanprobst/issue-next-middleware-matcher

To Reproduce

  1. clone https://github.com/stefanprobst/issue-next-middleware-matcher
  2. pnpm install && pnpm run dev
  3. see error message in console: 'Next.js can't recognize the exported config field in route "/middleware": Unsupported template literal with expressions at "config.matcher[1]".'

Current vs. Expected behavior

i would want to be able to do this:

const locales = ["de", "en"] as const;

export const config = {
  matcher: ["/", `/(${locales.join("|")})/:path*`],
};

Verify canary release

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #26~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Jul 13 16:27:29 UTC 2
Binaries:
  Node: 18.18.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.8.0
Relevant Packages:
  next: 13.5.4
  eslint-config-next: N/A
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.2.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Middleware / Edge (API routes, runtime)

Additional context

No response

Davy-F commented 9 months ago

Also experiencing this issue. Is there an update on this?

bobvdvalk commented 8 months ago

Same issue here, any update?

Edit by maintainers: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

GVALFER commented 8 months ago

Same issue here...

Edit by maintainers: Comment was automatically minimized because it was considered unhelpful. (If you think this was by mistake, let us know). Please only comment if it adds context to the issue. If you want to express that you have the same problem, use the upvote 👍 on the issue description or subscribe to the issue for updates. Thanks!

hydRAnger commented 8 months ago

same here, as I'd like to organize some complex matcher rules with js. then I faced this issue.

arduano commented 8 months ago

A simpler reproduction:

const base = '/api';
export const config = {
  matcher: `${base}/:path*`,
};

Substituting ${base} with the string directly works.

SalahAdDin commented 6 months ago

Same issue here:

import createMiddleware from "next-intl/middleware";

import { DEFAULT_LOCALE, LOCALES, LOCALES_TO_MATCH } from "./common/constants";

export default createMiddleware({
  locales: LOCALES,

  defaultLocale: DEFAULT_LOCALE,
});

export const config = {
  matcher: [
    "/",
    `/(${LOCALES_TO_MATCH})/:path*`,
    "/((?!_next|_vercel|.*\\..*).*)",
  ],
};

Yeah, same issue here, required for most of the current internationalization packages.

gmbrown commented 6 months ago

fwiw, these docs do state pretty clearly that you cannot do this https://nextjs.org/docs/messages/invalid-page-config

That being said, I'm not sure why and I ended up here because I want to be able to

SalahAdDin commented 6 months ago

fwiw, these docs do state pretty clearly that you cannot do this https://nextjs.org/docs/messages/invalid-page-config

That being said, I'm not sure why and I ended up here because I want to be able to

We need a workaround on it, since, just for instance, our project will contain a minimum of 30 locales, and we cannot add them manually.

gg-hsi commented 5 months ago

Is there any way to do this? Having a lot of locales and updating them manually is too much hassle.

SalahAdDin commented 5 months ago

A simpler reproduction:

const base = '/api';
export const config = {
  matcher: `${base}/:path*`,
};

Substituting ${base} with the string directly works.

You say this solution works, right?

aryankarim commented 4 months ago

Can somebody remind us when there is support for string matutation? As of today, there is no support.

mwx0621 commented 11 hours ago

This problem also occurs to me when trying to migrate from i18next to next-intl. In my case, different locales are supported in different deployment. Matchers need to be set from config file. I solved this by manually matching pathname in middleware function.

import createMiddleware from "next-intl/middleware";
import { LOCALES } from "./i18n";
import { NextRequest, NextResponse } from "next/server";

const reg = new RegExp(`^/$|^/(${LOCALES.join("|")})`);

const intlMiddleware = createMiddleware({
  locales: LOCALES,
  defaultLocale: "en",
});

const middleware = (req: NextRequest) => {
  const { pathname } = new URL(req.url);
  if (pathname.match(reg)) {
    return intlMiddleware(req);
  } else return NextResponse.next();
};
export default middleware;

// Which I wish it could be 
// export const config = {
//   matcher: ["/", `/(${LOCALES.join("|"))/:path*`],
// };

This works for me.

SalahAdDin commented 6 hours ago

This problem also occurs to me when trying to migrate from i18next to next-intl. In my case, different locales are supported in different deployment. Matchers need to be set from config file. I solved this by manually matching pathname in middleware function.

import createMiddleware from "next-intl/middleware";
import { LOCALES } from "./i18n";
import { NextRequest, NextResponse } from "next/server";

const reg = new RegExp(`^/$|^/(${LOCALES.join("|")})`);

const intlMiddleware = createMiddleware({
  locales: LOCALES,
  defaultLocale: "en",
});

const middleware = (req: NextRequest) => {
  const { pathname } = new URL(req.url);
  if (pathname.match(reg)) {
    return intlMiddleware(req);
  } else return NextResponse.next();
};
export default middleware;

// Which I wish it could be 
// export const config = {
//   matcher: ["/", `/(${LOCALES.join("|"))/:path*`],
// };

This works for me.

Where is the export const config = {} there?