hozana / next-translate-routes

Flexible and translated routes for Next.js without custom server
MIT License
115 stars 30 forks source link

Vercel Functions : No routes tree defined. #6

Closed antoninbeaufort closed 2 years ago

antoninbeaufort commented 2 years ago

Hi,

I'm currently migrating the frontend of my NextJS app from Amplify to Vercel and I have an error on SSR page that is converted by Vercel to a Function.

Environment :

Here you can see the SSR part :

export async function getServerSideProps(context) {
  const { Auth, API } = withSSRContext(context)
  let orders
  try {
    const user = await Auth.currentAuthenticatedUser()
    try {
      orders = await API.graphql({
        query: orderByUser,
        authMode: "AMAZON_COGNITO_USER_POOLS",
        variables: {
          userId: user.username,
          sortDirection: "DESC",
        },
      });
    } catch (err) {
      console.log("error fetching orders: ", err)
    }
  } catch (error) {
    context.res.writeHead(302, { Location: '/connexion' })
    context.res.end()
  }
  return {
    props: {
      ...(await serverSideTranslations(context.locale, ['common', 'orders'], nextI18NextConfig)),
      orders: orders ? orders.data.orderByUser.items.map(order => ({ ...order, cart: JSON.parse(order.cart) })) : null
    }
  }
}

This part was running fine on Amplify, but know on the Vercel Function logs I can see this error :

2021-12-12T18:10:55.595Z    2b1d4e33-0e24-433d-aa7b-219045d4bacc    ERROR   Error: > next-translate-routes - No routes tree defined. next-translate-routes plugin is probably missing from next.config.js
    at withTranslateRoutes(undefined) (/var/task/node_modules/next-translate-routes/index.js:308:19)
    at d (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:33:498)
    at bb (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:16)
    at a.b.render (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:42:43)
    at a.b.read (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:41:83)
    at Object.exports.renderToString (/var/task/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:52:138)
    at Object.renderPage (/var/task/node_modules/next/dist/server/render.js:686:46)
    at Object.defaultGetInitialProps (/var/task/node_modules/next/dist/server/render.js:316:51)
    at Function.getInitialProps (/var/task/.next/server/chunks/859.js:544:20)
    at Object.loadGetInitialProps (/var/task/node_modules/next/dist/shared/lib/utils.js:69:29)
2021-12-12T18:10:55.604Z    2b1d4e33-0e24-433d-aa7b-219045d4bacc    ERROR   Error: ENOENT: no such file or directory, scandir '/var/task/public/locales/en'
    at Object.readdirSync (fs.js:1047:3)
    at getLocaleNamespaces (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:175:23)
    at /var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:181:20
    at Array.map (<anonymous>)
    at getNamespaces (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:180:44)
    at createConfig (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:221:29)
    at _callee$ (/var/task/node_modules/next-i18next/dist/commonjs/serverSideTranslations.js:199:53)
    at tryCatch (/var/task/node_modules/regenerator-runtime/runtime.js:63:40)
    at Generator.invoke [as _invoke] (/var/task/node_modules/regenerator-runtime/runtime.js:294:22)
    at Generator.next (/var/task/node_modules/regenerator-runtime/runtime.js:119:21) {
  errno: -2,
  syscall: 'scandir',
  path: '/var/task/public/locales/en',
  page: '/mes-commandes'
}
RequestId: 2b1d4e33-0e24-433d-aa7b-219045d4bacc Error: Runtime exited with error: exit status 1
Runtime.ExitError

This is my next.config.js :

const WindiCSSWebpackPlugin = require('windicss-webpack-plugin')
// const { i18n } = require('./next-i18next.config');
const withTranslateRoutes = require('next-translate-routes/plugin')

module.exports = withTranslateRoutes({
  // i18n,
  i18n: {
    defaultLocale: 'fr',
    locales: ['fr', 'en'],
  },
  images: {
    domains: ['localhost', 'images.unsplash.com'],
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
    imageSizes: [16, 32, 48, 64, 94, 149, 256, 400],
  },
  env: {
    NEXT_PUBLIC_URL: process.env.NEXT_PUBLIC_URL,
    STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
    STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
    MJ_APIKEY_PUBLIC: process.env.MJ_APIKEY_PUBLIC,
    MJ_APIKEY_PRIVATE: process.env.MJ_APIKEY_PRIVATE,
  },
  webpack(config) {
    config.plugins.push(new WindiCSSWebpackPlugin())
    return config
  },
})

The rest of the site works correctly with the translation of the routes. Do you have any idea why this error occurs?

Thanks in advance!

cvolant commented 2 years ago

In order to get the translations client side, the withTranslateRoutes plugin sets a public env var containing your routes tree. The next-translate-routes/link reads from this env var to translate the route. You get the > next-translate-routes - No routes tree defined. next-translate-routes plugin is probably missing from next.config.js error if this env var is not found.

Do you have any idea why this env var is not set on the Vercel Function?

dperetti commented 2 years ago

Having the same issue of empty NEXT_PUBLIC_ROUTES environment variable. So I tried to manually set it in Vercel's interface and got this. image Then I tried to manually set it in next.config.js but using a fake, smaller one and it worked. So it definitely appears that we've got a size limit issue. The problem is that with route definitions, it can happen easily. Any suggestion welcome!

dperetti commented 2 years ago

I'm afraid passing the stringified json routes via the NEXT_PUBLIC_ROUTES env is a dead end. It probably has to be revamped so routes are loaded globally like next-translate does with i18nConfig.

dperetti commented 2 years ago

Actually it would even make sense to inject the routes into a property of i18nConfig and modify getRoutesTree() so it makes use of it.

cvolant commented 2 years ago

Very interesting. You are probably right about the env var being a dead end...

The problem with config injection by an app hoc is that it should be imported from a file. If I understand correctly, next-translate uses this method to make user-made config available client side, but in next-translate-routes case, it is some computed data.

dperetti commented 2 years ago

Unfortunately it's not 4KB per variable, it's 4KB in total!

Anyway, I had to find a quick and dirty workaround for the website I'm working on and here is what I did.

I forked your project and just changed getRouteTree() like this:

declare global {
  var i18nConfig: any & { routesTree: TRouteBranch }

  interface Window {
    i18nConfig: Object & { routesTree: TRouteBranch };
  }
}

export const getRoutesTree = () => {
  if (typeof window === 'undefined') {
    return global.i18nConfig?.routesTree || {}
  }
  return window.i18nConfig?.routesTree || {}
}

Now, in my project I have a command line script that generates a routesTree.json file.

image

And routesTree is injected into i18n.js.

image

And it does the trick!

cvolant commented 2 years ago

Unfortunately it's not 4KB per variable, it's 4KB in total!

Ok, so env var id definitely a dead end. I think webpack DefinePlugin could do the job. I will try it, and if it does not, I will try something close to your solution.

cvolant commented 2 years ago

@AntoninBeaufort, @dperetti, @wangwailok, could you try with next-translate-routes@next and tell me if it works for you?

antoninbeaufort commented 2 years ago

I was just trying it out, the first mistake is gone, but the second one remains:

2021-12-29T18:58:54.091Z    143f8f3a-631a-4859-8048-9251ab38b006    ERROR   Error: ENOENT: no such file or directory, scandir '/var/task/public/locales/fr'
    at Object.readdirSync (fs.js:1047:3)
    at getLocaleNamespaces (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:175:23)
    at /var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:181:20
    at Array.map (<anonymous>)
    at getNamespaces (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:180:44)
    at createConfig (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:221:29)
    at _callee$ (/var/task/node_modules/next-i18next/dist/commonjs/serverSideTranslations.js:199:53)
    at tryCatch (/var/task/node_modules/regenerator-runtime/runtime.js:63:40)
    at Generator.invoke [as _invoke] (/var/task/node_modules/regenerator-runtime/runtime.js:294:22)
    at Generator.next (/var/task/node_modules/regenerator-runtime/runtime.js:119:21) {
  errno: -2,
  syscall: 'scandir',
  path: '/var/task/public/locales/fr',
  page: '/mes-commandes'
}
RequestId: 143f8f3a-631a-4859-8048-9251ab38b006 Error: Runtime exited with error: exit status 1
Runtime.ExitError

But it looks like it's related to the next-i18next package now. (See https://github.com/isaachinman/next-i18next/issues/1552)

wangwailok commented 2 years ago

I was trying the 1.7.0-1 image

error - ./pages/_app.tsx Error: [next-translate-routes] - No withTranslateRoutes high order component found in _app.

cvolant commented 2 years ago

I was just trying it out, the first mistake is gone, but the second one remains:

2021-12-29T18:58:54.091Z  143f8f3a-631a-4859-8048-9251ab38b006    ERROR   Error: ENOENT: no such file or directory, scandir '/var/task/public/locales/fr'
    at Object.readdirSync (fs.js:1047:3)
    at getLocaleNamespaces (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:175:23)
    at /var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:181:20
    at Array.map (<anonymous>)
    at getNamespaces (/var/task/node_modules/next-i18next/dist/commonjs/config/createConfig.js:180:44)
    at createConfig (/var/task/node_modules/next-i18next/dist/com
   [...]
   Error: Runtime exited with error: exit status 1
Runtime.ExitError

But it looks like it's related to the next-i18next package now. (See https://github.com/isaachinman/next-i18next/issues/1552)

Yes, it comes from next-i18next. If you remove next-translate-routes, do you still have the error? Did you see this one: https://github.com/isaachinman/next-i18next/issues/1553

cvolant commented 2 years ago

I was trying the 1.7.0-1

error - ./pages/_app.tsx Error: [next-translate-routes] - No withTranslateRoutes high order component found in _app.

Ops, I see. I will fix it soon. For now you can try importing 'next-translate-routes' with single quotes.

antoninbeaufort commented 2 years ago

Yes, it comes from next-i18next. If you remove next-translate-routes, do you still have the error? Did you see this one: isaachinman/next-i18next#1553

I don't know because I didn't need it, I've just added localePath in my next.config.js and it's fully working now. Like this :

module.exports = {
    i18n: {
      defaultLocale: 'fr',
      locales: ['fr', 'en'],
      localePath: path.resolve('./public/locales')
    },
  };