[WIP] Run cra-to-next codemod to be on Nextjs

I'm interested in ejecting from Vercel, so I'm trying to get off their proprietary-ish create-react-app + Vercel API thing, and onto Nextjs, which is very similar in shape, but more portable.

I had to disable `craCompat` in `next.config.js` to stop us from crashing on their webpack config, see https://github.com/vercel/next.js/discussions/25858#discussioncomment-1573822

The frontend seems to work at a basic level, but network requests fail, and images don't seem to be working. I'll work on those next!

Note that this commit was forced through despite failing lint checks. We'll need to fix that up too!

Also, after the codemod, I moved `src/pages` to the more canonical location `pages`. Lint tooling seemed surprised to not find a `pages` directory, and I didn't see a config that was making it work correctly in the other location, so I figured it's that Next is willing to check `pages` or `src/pages`? But this is more canonical so yeah!
This commit is contained in:
Emi Matchu 2021-11-01 21:48:09 -07:00
parent 12d525e3ab
commit 567e333f9e
11 changed files with 1494 additions and 9125 deletions

20
.eslintrc.json Normal file
View file

@ -0,0 +1,20 @@
{
"extends": "next/core-web-vitals",
"rules": {
"no-console": [
"warn",
{
"allow": ["debug", "info", "warn", "error"]
}
],
"import/first": "off",
"import/no-webpack-loader-syntax": "off",
"no-unused-vars": [
"warn",
{
"varsIgnorePattern": "^unused",
"argsIgnorePattern": "^_+$|^e$"
}
]
}
}

10
.gitignore vendored
View file

@ -22,4 +22,12 @@ npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
.vercel .vercel
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# next.js
/.next/
/out/
*.pem
# debug
# local env files
# vercel

6
next-env.d.ts vendored Normal file
View file

@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

8
next.config.js Normal file
View file

@ -0,0 +1,8 @@
module.exports = {
env: {
PUBLIC_URL: "",
},
eslint: {
dirs: ["src"],
},
};

View file

@ -41,6 +41,7 @@
"jwks-rsa": "^1.9.0", "jwks-rsa": "^1.9.0",
"lru-cache": "^6.0.0", "lru-cache": "^6.0.0",
"mysql2": "^2.1.0", "mysql2": "^2.1.0",
"next": "12.0.2",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"playwright-core": "^1.14.0", "playwright-core": "^1.14.0",
"react": "^17.0.1", "react": "^17.0.1",
@ -49,23 +50,22 @@
"react-icons": "^4.2.0", "react-icons": "^4.2.0",
"react-router-dom": "^5.1.2", "react-router-dom": "^5.1.2",
"react-router-hash-link": "^2.4.3", "react-router-hash-link": "^2.4.3",
"react-scripts": "^4.0.1",
"react-transition-group": "^4.3.0", "react-transition-group": "^4.3.0",
"react-virtualized": "^9.22.3", "react-virtualized": "^9.22.3",
"simple-markdown": "^0.7.2", "simple-markdown": "^0.7.2",
"tweenjs": "^1.0.2", "tweenjs": "^1.0.2",
"typescript": "^4.1.3", "typescript": "^4.4.4",
"xmlrpc": "^1.3.2" "xmlrpc": "^1.3.2"
}, },
"scripts": { "scripts": {
"prepare": "husky install", "prepare": "husky install",
"start": "TS_NODE_COMPILER=typescript-cached-transpile vercel dev", "start": "TS_NODE_COMPILER=typescript-cached-transpile next start",
"dev": "yarn build-cached-data && REACT_APP_IMPRESS_LOG_IN_AS=$IMPRESS_LOG_IN_AS react-scripts start", "dev": "yarn build-cached-data && REACT_APP_IMPRESS_LOG_IN_AS=$IMPRESS_LOG_IN_AS TS_NODE_COMPILER=typescript-cached-transpile next dev",
"build": "yarn build-cached-data && react-scripts build", "build": "yarn build-cached-data && next build",
"vercel-build": "yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/", "vercel-build": "yum install libuuid-devel libmount-devel && cp /lib64/{libuuid,libmount,libblkid}.so.1 node_modules/canvas/build/Release/",
"test": "react-scripts test --env=jsdom", "test": "jest test --env=jsdom",
"lint": "next lint",
"cypress": "cypress open", "cypress": "cypress open",
"eject": "react-scripts eject",
"mysql": "mysql --host=impress.openneo.net --user=$(dotenv -p IMPRESS_MYSQL_USER) --password=$(dotenv -p IMPRESS_MYSQL_PASSWORD) --database=openneo_impress", "mysql": "mysql --host=impress.openneo.net --user=$(dotenv -p IMPRESS_MYSQL_USER) --password=$(dotenv -p IMPRESS_MYSQL_PASSWORD) --database=openneo_impress",
"mysql-dev": "mysql --host=localhost --user=impress_2020_dev --password=impress_2020_dev --database=impress_2020_dev", "mysql-dev": "mysql --host=localhost --user=impress_2020_dev --password=impress_2020_dev --database=impress_2020_dev",
"mysql-admin": "mysql --host=impress.openneo.net --user=matchu --password --database=openneo_impress", "mysql-admin": "mysql --host=impress.openneo.net --user=matchu --password --database=openneo_impress",
@ -78,38 +78,9 @@
"delete-user": "ts-node --compiler=typescript-cached-transpile --transpile-only -r dotenv/config scripts/delete-user.js", "delete-user": "ts-node --compiler=typescript-cached-transpile --transpile-only -r dotenv/config scripts/delete-user.js",
"export-users-to-auth0": "ts-node --compiler=typescript-cached-transpile --transpile-only -r dotenv/config scripts/export-users-to-auth0.js" "export-users-to-auth0": "ts-node --compiler=typescript-cached-transpile --transpile-only -r dotenv/config scripts/export-users-to-auth0.js"
}, },
"eslintConfig": {
"extends": [
"react-app",
"plugin:cypress/recommended"
],
"rules": {
"no-console": [
"warn",
{
"allow": [
"debug",
"info",
"warn",
"error"
]
}
],
"import/first": "off",
"import/no-webpack-loader-syntax": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{
"varsIgnorePattern": "^unused",
"argsIgnorePattern": "^_+$|^e$"
}
]
}
},
"lint-staged": { "lint-staged": {
"*.{js,ts,tsx}": [ "*.{js,ts,tsx}": [
"eslint --max-warnings=0 --fix" "next lint --max-warnings=0 --fix"
] ]
}, },
"browserslist": { "browserslist": {
@ -132,6 +103,8 @@
"cypress-plugin-snapshots": "^1.4.4", "cypress-plugin-snapshots": "^1.4.4",
"dotenv-cli": "^3.1.0", "dotenv-cli": "^3.1.0",
"es6-promise-pool": "^2.5.0", "es6-promise-pool": "^2.5.0",
"eslint": "<8.0.0",
"eslint-config-next": "12.0.2",
"eslint-plugin-cypress": "^2.11.2", "eslint-plugin-cypress": "^2.11.2",
"husky": "^6.0.0", "husky": "^6.0.0",
"imports-loader": "^1.2.0", "imports-loader": "^1.2.0",
@ -143,7 +116,6 @@
"react-is": "^16.13.1", "react-is": "^16.13.1",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript-cached-transpile": "^0.0.6", "typescript-cached-transpile": "^0.0.6",
"typescript-eslint": "^0.0.1-alpha.0", "typescript-eslint": "^0.0.1-alpha.0"
"vercel": "^21.2.3"
} }
} }

15
pages/[[...slug]].tsx Normal file
View file

@ -0,0 +1,15 @@
// import NextIndexWrapper from '../src'
// next/dynamic is used to prevent breaking incompatibilities
// with SSR from window.SOME_VAR usage, if this is not used
// next/dynamic can be removed to take advantage of SSR/prerendering
import dynamic from "next/dynamic";
// try changing "ssr" to true below to test for incompatibilities, if
// no errors occur the above static import can be used instead and the
// below removed
const NextIndexWrapper = dynamic(() => import("../src"), { ssr: false });
export default function Page(props) {
return <NextIndexWrapper {...props} />;
}

14
pages/_app.tsx Normal file
View file

@ -0,0 +1,14 @@
import Head from 'next/head'
export default function MyApp({ Component, pageProps}) {
return (
<>
<Head>
<title>Dress to Impress</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<Component {...pageProps} />
</>
)
}

View file

@ -1,28 +1,16 @@
<!DOCTYPE html> import Document, { Html, Head, Main, NextScript } from 'next/document'
<html lang="en">
<head> class MyDocument extends Document {
<meta charset="utf-8" /> render() {
<link return (
rel="icon" <Html lang="en">
type="image/png" <Head>
sizes="32x32" <meta charSet="utf-8" />
href="%PUBLIC_URL%/favicon-32x32.png" <link rel="icon" type="image/png" sizes="32x32" href={`${process.env.PUBLIC_URL}/favicon-32x32.png`} />
/> <link rel="icon" type="image/png" sizes="16x16" href={`${process.env.PUBLIC_URL}/favicon-16x16.png`} />
<link <meta name="theme-color" content="#000000" />
rel="icon" <link rel="apple-touch-icon" sizes="180x180" href={`${process.env.PUBLIC_URL}/apple-touch-icon.png`} />
type="image/png" <style type="text/css" dangerouslySetInnerHTML={{ __html: `
sizes="16x16"
href="%PUBLIC_URL%/favicon-16x16.png"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="%PUBLIC_URL%/apple-touch-icon.png"
/>
<title>Dress to Impress</title>
<style type="text/css">
/* A font by Jos Buivenga (exljbris) -> www.exljbris.com */ /* A font by Jos Buivenga (exljbris) -> www.exljbris.com */
@font-face { @font-face {
font-family: "Delicious"; font-family: "Delicious";
@ -37,35 +25,11 @@
font-weight: 800 1000; font-weight: 800 1000;
src: url(/fonts/Delicious-Heavy.otf); src: url(/fonts/Delicious-Heavy.otf);
} }
</style> ` }} />
<script <script async="" defer="" data-domain="impress-2020.openneo.net" src="https://plausible.io/js/plausible.js" dangerouslySetInnerHTML={{ __html: `` }} />
async <link rel="preload" href="/fonts/Delicious-Heavy.otf" type="font/otf" as="font" crossOrigin="" />
defer <link rel="preload" href="/fonts/Delicious-Bold.otf" type="font/otf" as="font" crossOrigin="" />
data-domain="impress-2020.openneo.net" <script dangerouslySetInnerHTML={{ __html: `
src="https://plausible.io/js/plausible.js"
></script>
<link
rel="preload"
href="/fonts/Delicious-Heavy.otf"
type="font/otf"
as="font"
crossorigin
/>
<link
rel="preload"
href="/fonts/Delicious-Bold.otf"
type="font/otf"
as="font"
crossorigin
/>
</head>
<body>
<!--
Hi!! Writing a user script? Our CSS class names aren't super stable, sorry.
Send me an email at matchu@openneo.net about what you're trying to do,
and I'll see if I can add hooks for you!
-->
<script>
// HACK: This is copy-pasted output from Chakra's <ColorModeScript />. It // HACK: This is copy-pasted output from Chakra's <ColorModeScript />. It
// initializes our color mode to match the system color mode. The // initializes our color mode to match the system color mode. The
// component is built for a special Document element like in // component is built for a special Document element like in
@ -98,8 +62,18 @@
root.style.setProperty("--chakra-ui-color-mode", colorMode); root.style.setProperty("--chakra-ui-color-mode", colorMode);
} }
})("system"); })("system");
</script> ` }} />
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div> </Head>
</body>
</html> <body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument

View file

@ -1,9 +1,11 @@
import React from "react"; import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import App from "./app/App"; import App from "./app/App";
ReactDOM.render(
<React.StrictMode> export default function NextIndexWrapper() {
<App /> return (
</React.StrictMode>, <React.StrictMode>
document.getElementById("root") <App />
); </React.StrictMode>
);
}

View file

@ -7,11 +7,7 @@
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"noFallthroughCasesInSwitch": true, "noFallthroughCasesInSwitch": true,
@ -19,7 +15,8 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "preserve",
"incremental": true
}, },
"ts-node": { "ts-node": {
"compilerOptions": { "compilerOptions": {
@ -27,7 +24,6 @@
"module": "commonjs" "module": "commonjs"
} }
}, },
"include": [ "include": ["src"],
"src" "exclude": ["node_modules"]
]
} }

10376
yarn.lock

File diff suppressed because it is too large Load diff