netlify / next-runtime

The Next.js Runtime allows Next.js to run on Netlify with zero configuration
https://www.npmjs.com/package/@netlify/plugin-nextjs
641 stars 85 forks source link

Build fails with target: serverless and experimental topLevelAwait #630

Closed remotesynth closed 2 years ago

remotesynth commented 3 years ago

Describe the bug I have a simple demo repository built using Next.js that currently is generating only static files and has only two pages. The plugin was installed by default, causing the about.js page to generate the following error:

1:28:32 PM: Error: Build optimization failed: found pages without a React Component as default export in
1:28:32 PM: pages/
1:28:32 PM: pages/about

However, the page does have a default export and works running npm run build locally. If I remove the Essential Next.js plugin, the build succeeds.

To Reproduce

In order to run the code from the demo repo, you'd need an environment variable, but I have tried removing the LaunchDarkly library code from about.js as below and still get the error during build:

import matter from "gray-matter";
import ReactMarkdown from "react-markdown";
import styles from "../styles/Home.module.css";
import Head from "next/head";

export default function About({ frontmatter, markdownBody }) {
  return (
    <div className={styles.container}>
      <Head>
        <title>Basic Example</title>
        <meta name="description" content="Using LaunchDarkly flags" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>{frontmatter.title}</h1>
        <ReactMarkdown>{markdownBody}</ReactMarkdown>
      </main>
    </div>
  );
}

export async function getStaticProps() {
  let loadPage = "about.md";
  const content = await import(`../content/${loadPage}.md`);
  const data = matter(content.default);
  return {
    props: {
      frontmatter: data.data,
      markdownBody: data.content,
    },
  };
}

Expected behavior

This should build the same as it does with npm run build

Versions

If you're using the CLI to build

lindsaylevine commented 3 years ago

@remotesynth heyo will take a look at this asap!

remotesynth commented 3 years ago

@lindsaylevine after messing around with this for some time, I have narrowed it down to that it doesn't like the ld-server.js. If I remove that from any pages it builds, though I still don't get why it would work using npm run build and not work using netlify build since that runs npm run build unless I am misunderstanding how it works.

lindsaylevine commented 3 years ago

@remotesynth i havent had a chance to clone and run quite yet, but just took a guick glance at the file. are you able to do this await (https://github.com/remotesynth/ld-nextjs-basics/blob/main/lib/ld-server.js#L9) in the scope of an async function, instead of on the export line? maybe in _app or in getStaticProps itself?

remotesynth commented 3 years ago

Yeah, I am thinking maybe if I move it into getInitialProps or something. I was trying to make it so that it doesn't need to be loaded onto every page but only as needed but I will see if that causes the issue.

Fwiw, I am able to use that await because in the next.config.js I added config.experiments = { topLevelAwait: true }; which allows a top level await. Maybe that's what's causing the issue in the build failing with the plugin on versus off? Perhaps it doesn't support that experimental feature?

lindsaylevine commented 3 years ago

@remotesynth hey, was just able to clone. i can confirm that removing the top level await in ld-server resolves the issue. however it seems the build is failing on netlify separately from our plugin (aka it's the next build step that fails, not a plugin step) so i thought maybe it was something with netlify's prod environment. but i went to confirm your note about the build succeeding without the plugin, and i can also confirm that next build does succeed when the plugin is uninstalled. this made me realize that the problem is setting target to serverless in next.config.js, which our plugin currently forces on all next.js sites. it doesn't surprise me that an experimental feature like topLevelAwait would not be compatible with target serverless, which has become increasingly unsupported by next. ALL that said, we are in the middle of a plugin rewrite that will support target = 'server' (aka what target defaults to and what runs successfully with your original src). so here's what i suggest:

  1. hang tight and try to avoid topLevelAwait until we can get the plugin rewrite out, which is our number 1 priority right now
  2. i'm gonna rename the issue to be more discoverable and reduce the priority level

lmk if you need anything else!

remotesynth commented 3 years ago

Thank you so much Lindsay! I think I can refactor this to remove the top level await.

ascorbic commented 2 years ago

I'm closing this because the plugin now doesn't use target: serverless. Please open a new issue if you're still having trouble.