rsnext/packages/next-swc
Alex Kirszenberg f7f2db70bd Refactor the Next SSG transform to handle the inverse operation (vercel/turbo#2968)
## The original transform

The original behavior of the Next SSG transform is to remove `getServerSideProps`, `getStaticProps`, and `getStaticPaths` from Next.js page files so they can be bundled for the client. This is what enables the following code to work properly without advanced tree shaking:

```jsx
import db from "db";
import PostCounter from 

export default function Home(props) {
  return <>{props.posts.length} post(s)</>;
}

const postsPromise = db.getPosts();

export async function getStaticProps() {
  return {
    props: {
      posts: await postsPromise,
    },
  };
}
```

The transform is able to remove both `getStaticProps` and all its exclusive, transitive dependencies, so this is what the client would see:

```jsx
import PostCounter from "components/PostCounter";
export var __N_SSG = true;
export default function Home(props) {
    return __jsx(PostCounter, {
        count: props.posts.length
    });
}
```

## Adding the inverse operation

However, to support proper HMR for these data exports, we need to be able to execute somewhat of an inverse operation: remove the default component export, but preserve all the rest. This allows Turbopack to bundle server-side only declarations, only re-rendering when one of these changes, instead of re-rendering on any server-side and client-side change.

From our module above, the updated transform is now also able to generate the following:

```jsx
import db from "db";
const postsPromise = db.getPosts();
export async function getStaticProps() {
    return {
        props: {
            posts: await postsPromise
        }
    };
}
```

As you can see, this module is no longer importing the `PostCounter`, which means re-rendering will not invalidate when that counter changes. However, if the "db" module changes, we will still be able to detect a change and re-render.

## Other notes

* I renamed the transform from "next_ssg" to "next_transform_strip_page_exports". It's much more verbose, but hopefully also much clearer about what it does at a glance.
* I took the liberty to clean up and comment some parts of the transform to make it more easily understandable (at least for someone like me, who hasn't written a lot of SWC code). I also fixed a few bugs and edge cases.
* I brought over the tests from the transform in the Next.js and added a couple of them.
* For now, only the `StripDataExports` filter is used. A future PR will build on this and @ForsakenHarmony's https://github.com/vercel/turbo/pull/2949 PR to actually implement SSR/SSG HMR. 

## Reviewing guide

1. The crux of the change is the move (and refactor) of the next ssg transform from https://github.com/vercel/turbo/pull/2968/files#diff-133d73657647ed793ca4782a73552650b32ad565094b1e0faf452ad58705499b to https://github.com/vercel/turbo/pull/2968/files#diff-d6442fa6af9b66e581f062739dd6de2419f5e8f6f3d97cfa63518c72b0a9ee3e.
2. I also added the [errors.rs](https://github.com/vercel/turbo/pull/2968/files#diff-0f308375da4179c0ea5a0fcbd99593b56d6020cd7dec1694ed08f392f1637c09) and [fixture.rs](https://github.com/vercel/turbo/pull/2968/files#diff-6e23f34483fc17a27dfc630edb455ea95e28d5cb350468c2ba01384fbc3c116a) tests. I adapted fixture.rs to execute on the two transform filters: data exports and default export.
3. Most of the tests in `tests/` are copied from https://github.com/vercel/next.js/tree/canary/packages/next-swc/crates/core/tests. The changes I made are:
  i. https://github.com/vercel/turbo/pull/2968/files#diff-774abee6a1bf139c9ce55e226bf15b52e56ea091170ee5d6295c191fd8d793c7: made this one symmetric for both strip data and strip default transforms.
  ii. https://github.com/vercel/turbo/pull/2968/files#diff-4792266a264dc67da93748d2c6522917f860527a689891bd5f8f4add9841e7f6 wasn't supported before AFAIK.
  iii. https://github.com/vercel/turbo/pull/2968/files#diff-a3b12adbce1dec40f39ff8af13ffecbe7f6963e21bc402cef6332ecf5018877e similar to i.
2023-01-03 10:42:35 +00:00
..
crates Refactor the Next SSG transform to handle the inverse operation (vercel/turbo#2968) 2023-01-03 10:42:35 +00:00