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.
This commit is contained in:
parent
87e4a467f9
commit
f7f2db70bd
148 changed files with 2377 additions and 1 deletions
|
@ -157,7 +157,9 @@ pub async fn add_next_transforms_to_pages(
|
|||
]),
|
||||
]),
|
||||
vec![ModuleRuleEffect::AddEcmascriptTransforms(
|
||||
EcmascriptInputTransformsVc::cell(vec![EcmascriptInputTransform::NextJsPageSsr]),
|
||||
EcmascriptInputTransformsVc::cell(vec![
|
||||
EcmascriptInputTransform::NextJsStripPageDataExports,
|
||||
]),
|
||||
)],
|
||||
));
|
||||
Ok(module_options_context.cell())
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
[package]
|
||||
name = "next-transform-strip-page-exports"
|
||||
version = "0.1.0"
|
||||
description = "SWC transform to selectively strip Next.js page data or default exports"
|
||||
license = "MPL-2.0"
|
||||
edition = "2021"
|
||||
autobenches = false
|
||||
|
||||
[lib]
|
||||
bench = false
|
||||
|
||||
[dependencies]
|
||||
fxhash = "0.2.1"
|
||||
tracing = "0.1.37"
|
||||
|
||||
swc_core = { workspace = true, features = [
|
||||
"ecma_ast",
|
||||
"common",
|
||||
"common_concurrent",
|
||||
"common_sourcemap",
|
||||
"ecma_codegen",
|
||||
"ecma_parser",
|
||||
"ecma_preset_env",
|
||||
"ecma_transforms",
|
||||
"ecma_transforms_module",
|
||||
"ecma_transforms_react",
|
||||
"ecma_transforms_typescript",
|
||||
"ecma_quote",
|
||||
"ecma_visit",
|
||||
"ecma_visit_path",
|
||||
"ecma_utils",
|
||||
"testing",
|
||||
"base",
|
||||
] }
|
||||
|
||||
[dev-dependencies]
|
||||
swc_core = { workspace = true, features = ["testing_transform"] }
|
||||
testing = "0.31.14"
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,32 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use next_transform_strip_page_exports::{next_transform_strip_page_exports, ExportFilter};
|
||||
use swc_core::ecma::{
|
||||
parser::{EsConfig, Syntax},
|
||||
transforms::testing::{test_fixture, FixtureTestConfig},
|
||||
};
|
||||
use testing::fixture;
|
||||
|
||||
fn syntax() -> Syntax {
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
#[fixture("tests/errors/**/input.js")]
|
||||
fn next_transform_strip_page_exports_errors(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|_tr| {
|
||||
next_transform_strip_page_exports(ExportFilter::StripDataExports, Default::default())
|
||||
},
|
||||
&input,
|
||||
&output,
|
||||
FixtureTestConfig {
|
||||
allow_error: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export async function getStaticPaths() {}
|
||||
export const getServerSideProps = function getServerSideProps() {};
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
x You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps
|
||||
,-[input.js:1:1]
|
||||
1 | export async function getStaticPaths() {}
|
||||
2 | export const getServerSideProps = function getServerSideProps() {};
|
||||
: ^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -0,0 +1,2 @@
|
|||
export const getStaticProps = async () => {};
|
||||
export { a as getServerSideProps };
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
x You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps
|
||||
,-[input.js:1:1]
|
||||
1 | export const getStaticProps = async () => {};
|
||||
2 | export { a as getServerSideProps };
|
||||
: ^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -0,0 +1,2 @@
|
|||
export { a as getServerSideProps } from "./input";
|
||||
export { getStaticPaths } from "a";
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
x You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps
|
||||
,-[input.js:1:1]
|
||||
1 | export { a as getServerSideProps } from "./input";
|
||||
2 | export { getStaticPaths } from "a";
|
||||
: ^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -0,0 +1 @@
|
|||
export { getStaticProps, getServerSideProps };
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
x You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps
|
||||
,-[input.js:1:1]
|
||||
1 | export { getStaticProps, getServerSideProps };
|
||||
: ^^^^^^^^^^^^^^^^^^
|
||||
`----
|
|
@ -0,0 +1,68 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
use next_transform_strip_page_exports::{next_transform_strip_page_exports, ExportFilter};
|
||||
use swc_core::{
|
||||
common::{chain, comments::SingleThreadedComments, Mark},
|
||||
ecma::{
|
||||
parser::{EsConfig, Syntax},
|
||||
transforms::{
|
||||
react::jsx,
|
||||
testing::{test, test_fixture},
|
||||
},
|
||||
},
|
||||
};
|
||||
use testing::fixture;
|
||||
|
||||
fn syntax() -> Syntax {
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn run_test(input: &Path, output: &Path, mode: ExportFilter) {
|
||||
test_fixture(
|
||||
syntax(),
|
||||
&|tr| {
|
||||
let top_level_mark = Mark::fresh(Mark::root());
|
||||
let jsx = jsx::<SingleThreadedComments>(
|
||||
tr.cm.clone(),
|
||||
None,
|
||||
swc_core::ecma::transforms::react::Options {
|
||||
next: false.into(),
|
||||
runtime: None,
|
||||
import_source: Some("".into()),
|
||||
pragma: Some("__jsx".into()),
|
||||
pragma_frag: Some("__jsxFrag".into()),
|
||||
throw_if_namespace: false.into(),
|
||||
development: false.into(),
|
||||
use_builtins: true.into(),
|
||||
use_spread: true.into(),
|
||||
refresh: Default::default(),
|
||||
},
|
||||
top_level_mark,
|
||||
);
|
||||
chain!(
|
||||
next_transform_strip_page_exports(mode, Default::default()),
|
||||
jsx
|
||||
)
|
||||
},
|
||||
input,
|
||||
output,
|
||||
Default::default(),
|
||||
);
|
||||
}
|
||||
|
||||
#[fixture("tests/fixtures/**/output-data.js")]
|
||||
fn next_transform_strip_page_exports_fixture_data(output: PathBuf) {
|
||||
let input = output.parent().unwrap().join("input.js");
|
||||
|
||||
run_test(&input, &output, ExportFilter::StripDefaultExport);
|
||||
}
|
||||
|
||||
#[fixture("tests/fixtures/**/output-default.js")]
|
||||
fn next_transform_strip_page_exports_fixture_default(output: PathBuf) {
|
||||
let input = output.parent().unwrap().join("input.js");
|
||||
|
||||
run_test(&input, &output, ExportFilter::StripDataExports);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export default class Page {
|
||||
static async getInitialProps() {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div />;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export default class Page {
|
||||
static async getInitialProps() {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return __jsx("div", null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export default function Page() {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
Page.getInitialProps = function () {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
export default function Page() {
|
||||
return __jsx("div", null);
|
||||
}
|
||||
|
||||
Page.getInitialProps = function () {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
export default function Page() {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
Page.getInitialProps = () => {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
export default function Page() {
|
||||
return __jsx("div", null);
|
||||
}
|
||||
|
||||
Page.getInitialProps = () => {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
Page.getInitialProps = function () {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
Page.getInitialProps = function () {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
||||
|
||||
export default function Page() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export default function Page() {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
Page.getInitialProps = function getInitialProps() {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
export default function Page() {
|
||||
return __jsx("div", null);
|
||||
}
|
||||
|
||||
Page.getInitialProps = function getInitialProps() {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
export default function Page() {
|
||||
return <div />;
|
||||
}
|
||||
|
||||
const getInitialProps = (Page.getInitialProps = function getInitialProps() {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
const getInitialProps = function getInitialProps() {
|
||||
return {
|
||||
prop: true,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
export default function Page() {
|
||||
return __jsx("div", null);
|
||||
}
|
||||
const getInitialProps = Page.getInitialProps = function getInitialProps() {
|
||||
return {
|
||||
prop: true
|
||||
};
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
import fs from "fs";
|
||||
import other from "other";
|
||||
|
||||
const [a, b, ...rest] = fs.promises;
|
||||
const [foo, bar] = other;
|
||||
|
||||
export async function getServerSideProps() {
|
||||
a;
|
||||
b;
|
||||
rest;
|
||||
bar;
|
||||
}
|
||||
export default function Home() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import fs from "fs";
|
||||
import other from "other";
|
||||
const [a, b, ...rest] = fs.promises;
|
||||
const [foo, bar] = other;
|
||||
export async function getServerSideProps() {
|
||||
a;
|
||||
b;
|
||||
rest;
|
||||
bar;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import other from "other";
|
||||
const [foo] = other;
|
||||
export var __N_SSP = true;
|
||||
export default function Home() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
export async function getServerSideProps({ query }) {
|
||||
return { props: { prop: query.prop } };
|
||||
}
|
||||
|
||||
export default function GspPage({ prop }) {
|
||||
return <div id="prop">{prop}</div>;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
export async function getServerSideProps({ query }) {
|
||||
return {
|
||||
props: {
|
||||
prop: query.prop,
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
export var __N_SSP = true;
|
||||
export default function GspPage({ prop }) {
|
||||
return __jsx(
|
||||
"div",
|
||||
{
|
||||
id: "prop",
|
||||
},
|
||||
prop
|
||||
);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import fs from "fs";
|
||||
import other from "other";
|
||||
|
||||
const [a, b, ...rest] = fs.promises;
|
||||
const [foo, bar] = other;
|
||||
|
||||
export async function getStaticProps() {
|
||||
a;
|
||||
b;
|
||||
rest;
|
||||
bar;
|
||||
}
|
||||
export default function Home() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import fs from "fs";
|
||||
import other from "other";
|
||||
const [a, b, ...rest] = fs.promises;
|
||||
const [foo, bar] = other;
|
||||
export async function getStaticProps() {
|
||||
a;
|
||||
b;
|
||||
rest;
|
||||
bar;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import other from "other";
|
||||
const [foo] = other;
|
||||
export var __N_SSG = true;
|
||||
export default function Home() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import fs from "fs";
|
||||
import other from "other";
|
||||
|
||||
let a, b, rest;
|
||||
[a, b, ...rest] = fs.promises;
|
||||
let foo, bar;
|
||||
[foo, bar] = other;
|
||||
|
||||
export async function getStaticProps() {
|
||||
a;
|
||||
b;
|
||||
rest;
|
||||
bar;
|
||||
}
|
||||
export default function Home() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import fs from "fs";
|
||||
import other from "other";
|
||||
let a, b, rest;
|
||||
[a, b, ...rest] = fs.promises;
|
||||
let foo, bar;
|
||||
[foo, bar] = other;
|
||||
export async function getStaticProps() {
|
||||
a;
|
||||
b;
|
||||
rest;
|
||||
bar;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import other from "other";
|
||||
let foo;
|
||||
[foo] = other;
|
||||
export var __N_SSG = true;
|
||||
export default function Home() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import fs from "fs";
|
||||
import other from "other";
|
||||
|
||||
const { readFile, readdir, access: foo } = fs.promises;
|
||||
const { a, b, cat: bar, ...rem } = other;
|
||||
|
||||
export async function getStaticProps() {
|
||||
readFile;
|
||||
readdir;
|
||||
foo;
|
||||
b;
|
||||
cat;
|
||||
rem;
|
||||
}
|
||||
export default function Home() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import fs from "fs";
|
||||
import other from "other";
|
||||
const { readFile, readdir, access: foo } = fs.promises;
|
||||
const { a, b, cat: bar, ...rem } = other;
|
||||
export async function getStaticProps() {
|
||||
readFile;
|
||||
readdir;
|
||||
foo;
|
||||
b;
|
||||
cat;
|
||||
rem;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import other from "other";
|
||||
const { a, cat: bar } = other;
|
||||
export var __N_SSG = true;
|
||||
export default function Home() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
export default function Home({}) {
|
||||
return (
|
||||
<div>
|
||||
<p>Hello World</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
await import("_http_common").then((http) => console.log(http));
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export async function getStaticProps() {
|
||||
await import("_http_common").then((http) => console.log(http));
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export var __N_SSG = true;
|
||||
export default function Home({}) {
|
||||
return __jsx("div", null, __jsx("p", null, "Hello World"));
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
export const revalidateInSeconds = 5 * 60;
|
||||
|
||||
export const getStaticProps = async () => {
|
||||
return {
|
||||
props: {},
|
||||
revalidate: revalidateInSeconds,
|
||||
};
|
||||
};
|
||||
|
||||
export default function Home({}) {
|
||||
return (
|
||||
<div>
|
||||
<p>Hello World</p>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
export const revalidateInSeconds = 5 * 60;
|
||||
export const getStaticProps = async () => {
|
||||
return {
|
||||
props: {},
|
||||
revalidate: revalidateInSeconds,
|
||||
};
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
export var __N_SSG = true;
|
||||
export const revalidateInSeconds = 5 * 60;
|
||||
export default function Home({}) {
|
||||
return __jsx("div", null, __jsx("p", null, "Hello World"));
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return <h1>Hello World!</h1>;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
export default function Home() {
|
||||
return __jsx("h1", null, "Hello World!");
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
function getStaticPaths() {
|
||||
return [];
|
||||
}
|
||||
|
||||
export { getStaticPaths };
|
||||
|
||||
export class MyClass {}
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
function getStaticPaths() {
|
||||
return [];
|
||||
}
|
||||
export { getStaticPaths };
|
||||
export class MyClass {}
|
|
@ -0,0 +1,5 @@
|
|||
export var __N_SSG = true;
|
||||
export class MyClass {}
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
function Function1() {
|
||||
return {
|
||||
a: function bug(a) {
|
||||
return 2;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function Function2() {
|
||||
var bug = 1;
|
||||
return { bug };
|
||||
}
|
||||
|
||||
export { getStaticProps } from "a";
|
|
@ -0,0 +1,14 @@
|
|||
function Function1() {
|
||||
return {
|
||||
a: function bug(a) {
|
||||
return 2;
|
||||
},
|
||||
};
|
||||
}
|
||||
function Function2() {
|
||||
var bug = 1;
|
||||
return {
|
||||
bug,
|
||||
};
|
||||
}
|
||||
export { getStaticProps } from "a";
|
|
@ -0,0 +1,11 @@
|
|||
function Function1() {
|
||||
return {
|
||||
a: function bug(a) {
|
||||
return 2;
|
||||
},
|
||||
};
|
||||
}
|
||||
function Function2() {
|
||||
var bug = 1;
|
||||
return { bug };
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export function getStaticProps() {
|
||||
return { props: {} };
|
||||
}
|
||||
|
||||
export function Noop() {}
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export function getStaticProps() {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
}
|
||||
export function Noop() {}
|
|
@ -0,0 +1,5 @@
|
|||
export var __N_SSG = true;
|
||||
export function Noop() {}
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
export const getStaticPaths = () => {
|
||||
return [];
|
||||
},
|
||||
foo = 2;
|
||||
|
||||
export const getStaticProps = function () {
|
||||
return { props: {} };
|
||||
};
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export const getStaticPaths = () => {
|
||||
return [];
|
||||
},
|
||||
foo = 2;
|
||||
export const getStaticProps = function () {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
export var __N_SSG = true;
|
||||
export const foo = 2;
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { foo, bar } from "thing";
|
||||
|
||||
export default function Home() {
|
||||
foo;
|
||||
return <div />;
|
||||
}
|
||||
|
||||
export function otherExport() {
|
||||
foo;
|
||||
bar;
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
bar;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import { foo, bar } from "thing";
|
||||
|
||||
export function otherExport() {
|
||||
foo;
|
||||
bar;
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
bar;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
import { foo, bar } from "thing";
|
||||
|
||||
export var __N_SSG = true;
|
||||
export default function Home() {
|
||||
foo;
|
||||
return __jsx("div", null);
|
||||
}
|
||||
|
||||
export function otherExport() {
|
||||
foo;
|
||||
bar;
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
Root,
|
||||
Children,
|
||||
JSXMemberExpression,
|
||||
AttributeValue,
|
||||
AttributeJSX,
|
||||
ValueInRender,
|
||||
ValueInEffect,
|
||||
UnusedInRender,
|
||||
} from "../";
|
||||
|
||||
export default function Test() {
|
||||
const [x, setX] = useState(ValueInRender.value);
|
||||
useEffect(() => {
|
||||
setX(ValueInEffect.value);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Root x={x}>
|
||||
<div>
|
||||
<Children attr={AttributeValue} jsx={<AttributeJSX />} />
|
||||
<JSXMemberExpression.Deep.Property />
|
||||
</div>
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
// simulate import usage inside getStaticProps
|
||||
used: [
|
||||
// these import references should not be removed
|
||||
Root.value,
|
||||
Children.value,
|
||||
AttributeValue.value,
|
||||
AttributeJSX.value,
|
||||
ValueInRender.value,
|
||||
ValueInEffect.value,
|
||||
JSXMemberExpression.value,
|
||||
// this import reference should be removed
|
||||
UnusedInRender.value,
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import {
|
||||
Root,
|
||||
Children,
|
||||
JSXMemberExpression,
|
||||
AttributeValue,
|
||||
AttributeJSX,
|
||||
ValueInRender,
|
||||
ValueInEffect,
|
||||
UnusedInRender,
|
||||
} from "../";
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
// simulate import usage inside getStaticProps
|
||||
used: [
|
||||
// these import references should not be removed
|
||||
Root.value,
|
||||
Children.value,
|
||||
AttributeValue.value,
|
||||
AttributeJSX.value,
|
||||
ValueInRender.value,
|
||||
ValueInEffect.value,
|
||||
JSXMemberExpression.value,
|
||||
// this import reference should be removed
|
||||
UnusedInRender.value,
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
Root,
|
||||
Children,
|
||||
JSXMemberExpression,
|
||||
AttributeValue,
|
||||
AttributeJSX,
|
||||
ValueInRender,
|
||||
ValueInEffect,
|
||||
} from "../";
|
||||
export var __N_SSG = true;
|
||||
export default function Test() {
|
||||
const [x, setX] = useState(ValueInRender.value);
|
||||
useEffect(() => {
|
||||
setX(ValueInEffect.value);
|
||||
}, []);
|
||||
return __jsx(
|
||||
Root,
|
||||
{
|
||||
x: x,
|
||||
},
|
||||
__jsx(
|
||||
"div",
|
||||
null,
|
||||
__jsx(Children, {
|
||||
attr: AttributeValue,
|
||||
jsx: __jsx(AttributeJSX, null),
|
||||
}),
|
||||
__jsx(JSXMemberExpression.Deep.Property, null)
|
||||
)
|
||||
);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
function funfun() {}
|
||||
(function funfunfun() {});
|
|
@ -0,0 +1,2 @@
|
|||
function funfun() {}
|
||||
(function funfunfun() {});
|
|
@ -0,0 +1,2 @@
|
|||
function funfun() {}
|
||||
(function funfunfun() {});
|
|
@ -0,0 +1,5 @@
|
|||
export { getStaticPaths, a as getStaticProps } from ".";
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export { getStaticPaths, a as getStaticProps } from ".";
|
|
@ -0,0 +1,4 @@
|
|||
export var __N_SSG = true;
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export { getStaticPaths, a as getStaticProps, foo, bar as baz } from ".";
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export { getStaticPaths, a as getStaticProps, foo, bar as baz } from ".";
|
|
@ -0,0 +1,5 @@
|
|||
export var __N_SSG = true;
|
||||
export { foo, bar as baz } from ".";
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export async function getStaticPaths() {
|
||||
return [];
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
return { props: {} };
|
||||
}
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
export async function getStaticPaths() {
|
||||
return [];
|
||||
}
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export var __N_SSG = true;
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export function getStaticPaths() {
|
||||
return [];
|
||||
}
|
||||
|
||||
export function getStaticProps() {
|
||||
return { props: {} };
|
||||
}
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
export function getStaticPaths() {
|
||||
return [];
|
||||
}
|
||||
export function getStaticProps() {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export var __N_SSG = true;
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export const getStaticPaths = async () => {
|
||||
return [];
|
||||
};
|
||||
|
||||
export const getStaticProps = async function () {
|
||||
return { props: {} };
|
||||
};
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
export const getStaticPaths = async () => {
|
||||
return [];
|
||||
};
|
||||
export const getStaticProps = async function () {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
export var __N_SSG = true;
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
export const getStaticPaths = () => {
|
||||
return [];
|
||||
};
|
||||
|
||||
export const getStaticProps = function () {
|
||||
return { props: {} };
|
||||
};
|
||||
|
||||
export default function Test() {
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
export const getStaticPaths = () => {
|
||||
return [];
|
||||
};
|
||||
export const getStaticProps = function () {
|
||||
return {
|
||||
props: {},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
export var __N_SSG = true;
|
||||
export default function Test() {
|
||||
return __jsx("div", null);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
import keep_me from "hello";
|
||||
import { keep_me2 } from "hello2";
|
||||
import * as keep_me3 from "hello3";
|
||||
|
||||
import data_only1 from "data_only1";
|
||||
import { data_only2 } from "data_only2";
|
||||
import { data_only3, shared4 } from "shared4";
|
||||
import * as data_only4 from "data_only4";
|
||||
|
||||
import default_only1 from "default_only1";
|
||||
import { default_only2 } from "default_only2";
|
||||
import { default_only3, shared5 } from "shared5";
|
||||
import * as default_only4 from "default_only4";
|
||||
|
||||
var leave_me_alone = 1;
|
||||
function dont_bug_me_either() {}
|
||||
|
||||
const data_inception = "hahaa";
|
||||
|
||||
var data_var1 = 1;
|
||||
let data_var2 = 2;
|
||||
const data_var3 = data_inception + data_only4;
|
||||
|
||||
function data_inception1() {
|
||||
data_var2;
|
||||
data_only2;
|
||||
}
|
||||
|
||||
function data_abc() {}
|
||||
const data_b = function () {
|
||||
data_var3;
|
||||
data_only3;
|
||||
};
|
||||
const data_b2 = function data_apples() {};
|
||||
const data_bla = () => {
|
||||
data_inception1;
|
||||
};
|
||||
|
||||
function getStaticProps() {
|
||||
data_abc();
|
||||
data_only1;
|
||||
data_b;
|
||||
data_b2;
|
||||
data_bla();
|
||||
return { props: { data_var1 } };
|
||||
}
|
||||
|
||||
export { getStaticProps };
|
||||
|
||||
const default_inception = "hahaa";
|
||||
|
||||
var default_var1 = 1;
|
||||
let default_var2 = 2;
|
||||
const default_var3 = default_inception + default_only4;
|
||||
|
||||
function default_inception1() {
|
||||
default_var2;
|
||||
default_only2;
|
||||
}
|
||||
|
||||
function default_abc() {}
|
||||
const default_b = function () {
|
||||
default_var3;
|
||||
default_only3;
|
||||
};
|
||||
const default_b2 = function default_apples() {};
|
||||
const default_bla = () => {
|
||||
default_inception1;
|
||||
};
|
||||
|
||||
export default function Test() {
|
||||
default_abc();
|
||||
default_only1;
|
||||
default_b;
|
||||
default_b2;
|
||||
default_bla();
|
||||
const props = { default_var1 };
|
||||
return <div />;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
import keep_me from "hello";
|
||||
import { keep_me2 } from "hello2";
|
||||
import * as keep_me3 from "hello3";
|
||||
import data_only1 from "data_only1";
|
||||
import { data_only2 } from "data_only2";
|
||||
import { data_only3, shared4 } from "shared4";
|
||||
import * as data_only4 from "data_only4";
|
||||
import { shared5 } from "shared5";
|
||||
var leave_me_alone = 1;
|
||||
function dont_bug_me_either() {}
|
||||
const data_inception = "hahaa";
|
||||
var data_var1 = 1;
|
||||
let data_var2 = 2;
|
||||
const data_var3 = data_inception + data_only4;
|
||||
function data_inception1() {
|
||||
data_var2;
|
||||
data_only2;
|
||||
}
|
||||
function data_abc() {}
|
||||
const data_b = function () {
|
||||
data_var3;
|
||||
data_only3;
|
||||
};
|
||||
const data_b2 = function data_apples() {};
|
||||
const data_bla = () => {
|
||||
data_inception1;
|
||||
};
|
||||
function getStaticProps() {
|
||||
data_abc();
|
||||
data_only1;
|
||||
data_b;
|
||||
data_b2;
|
||||
data_bla();
|
||||
return {
|
||||
props: {
|
||||
data_var1,
|
||||
},
|
||||
};
|
||||
}
|
||||
export { getStaticProps };
|
|
@ -0,0 +1,39 @@
|
|||
import keep_me from "hello";
|
||||
import { keep_me2 } from "hello2";
|
||||
import * as keep_me3 from "hello3";
|
||||
import { shared4 } from "shared4";
|
||||
import default_only1 from "default_only1";
|
||||
import { default_only2 } from "default_only2";
|
||||
import { default_only3, shared5 } from "shared5";
|
||||
import * as default_only4 from "default_only4";
|
||||
var leave_me_alone = 1;
|
||||
function dont_bug_me_either() {}
|
||||
const default_inception = "hahaa";
|
||||
var default_var1 = 1;
|
||||
let default_var2 = 2;
|
||||
const default_var3 = default_inception + default_only4;
|
||||
function default_inception1() {
|
||||
default_var2;
|
||||
default_only2;
|
||||
}
|
||||
function default_abc() {}
|
||||
const default_b = function () {
|
||||
default_var3;
|
||||
default_only3;
|
||||
};
|
||||
const default_b2 = function default_apples() {};
|
||||
const default_bla = () => {
|
||||
default_inception1;
|
||||
};
|
||||
export var __N_SSG = true;
|
||||
export default function Test() {
|
||||
default_abc();
|
||||
default_only1;
|
||||
default_b;
|
||||
default_b2;
|
||||
default_bla();
|
||||
const props = {
|
||||
default_var1,
|
||||
};
|
||||
return __jsx("div", null);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue