-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit be93db6
Showing
22 changed files
with
5,237 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module.exports = { | ||
env: { | ||
browser: true, | ||
es2021: true, | ||
}, | ||
extends: ["plugin:react/recommended", "standard", "prettier", "eslint:recommended"], | ||
parser: "@typescript-eslint/parser", | ||
parserOptions: { | ||
ecmaFeatures: { | ||
jsx: true, | ||
}, | ||
ecmaVersion: 12, | ||
sourceType: "module", | ||
}, | ||
plugins: ["react", "@typescript-eslint"], | ||
rules: { | ||
// note you must disable the base rule as it can report incorrect errors | ||
"no-use-before-define": "off", | ||
"@typescript-eslint/no-use-before-define": ["error"], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
lib-cov | ||
*.seed | ||
*.log | ||
*.csv | ||
*.dat | ||
*.out | ||
*.pid | ||
*.gz | ||
*.swp | ||
|
||
pids | ||
logs | ||
results | ||
tmp | ||
|
||
# Build | ||
public/css/main.css | ||
|
||
# Coverage reports | ||
coverage | ||
|
||
# API keys and secrets | ||
.env | ||
|
||
# Dependency directory | ||
node_modules | ||
bower_components | ||
|
||
# Editors | ||
.idea | ||
*.iml | ||
|
||
# OS metadata | ||
.DS_Store | ||
Thumbs.db | ||
|
||
# Ignore built ts files | ||
dist/**/* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module.exports = { | ||
printWidth: 120, | ||
semi: true, | ||
singleQuote: false, | ||
trailingComma: "all", | ||
bracketSpacing: true, | ||
jsxBracketSameLine: false, | ||
arrowParens: "avoid", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Vite Typescript React 17 | ||
|
||
ImageConverter uses a mix of Vite, TypeScript, and React 17 to create a modern web application. It also server renders its pages. | ||
It also imports Tailwind CSS for the CSS framework | ||
|
||
## Development | ||
|
||
``` | ||
yarn | ||
yarn dev | ||
``` | ||
|
||
That should be enough to get started. It will open to http://localhost:7456 | ||
|
||
## Building | ||
|
||
``` | ||
yarn build | ||
yarn serve | ||
``` | ||
|
||
yarn build will create the assets in `dist` - a `client` and `server` folder. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<meta content="width=device-width,initial-scale=1,maximum-scale=10,minimum-scale=.25,user-scalable=yes" name="viewport"> | ||
<meta content="text/html; charset=utf-8" http-equiv="content-type"> | ||
</head> | ||
<body> | ||
<div id="app" style="height: 100%;width: 100%;"><!--app-html--></div> | ||
<script type="module" src="/src/client/entry-client.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
{ | ||
"name": "vite-typescript-ssr-react", | ||
"version": "1.0.0", | ||
"description": "Boilerplate for a modern web stack", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/Microsoft/TypeScript-Node-Starter" | ||
}, | ||
"author": "JonLuca DeCaro", | ||
"license": "MIT", | ||
"scripts": { | ||
"dev": "tsc && concurrently 'yarn watch:tsc' 'yarn watch:server' 'yarn watch:static'", | ||
"watch:server": "nodemon --watch dist/server.js --watch dist/src/server dist/server.js", | ||
"watch:static": "nodemon --watch static --watch index.html --exec yarn copy-files", | ||
"watch:tsc": "tsc -w", | ||
"build": "yarn build:client && yarn build:server && yarn copy-files", | ||
"build:client": "vite build --outDir dist/client", | ||
"build:server": "vite build --ssr src/client/entry-server.tsx --outDir dist/server", | ||
"serve": "yarn build && cross-env NODE_ENV=production node --experimental-modules dist/server.js", | ||
"clean": "rimraf dist/", | ||
"copy-files": "copyfiles static/* dist/assets && copyfiles index.html dist" | ||
}, | ||
"dependencies": { | ||
"async": "3.2.0", | ||
"autoprefixer": "^10.2.5", | ||
"compression": "1.7.4", | ||
"cross-env": "^7.0.3", | ||
"eslint-config-airbnb": "^18.2.1", | ||
"express": "4.17.1", | ||
"nodemon": "^2.0.7", | ||
"react": "^17.0.2", | ||
"react-dom": "^17.0.2", | ||
"react-router": "^5.2.0", | ||
"react-router-dom": "^5.2.0", | ||
"serve-static": "^1.14.1" | ||
}, | ||
"devDependencies": { | ||
"@types/compression": "1.7.0", | ||
"@types/concurrently": "6.0.1", | ||
"@types/eslint": "7.2.10", | ||
"@types/express": "4.17.11", | ||
"@types/node": "15.3.0", | ||
"@types/react": "^17.0.5", | ||
"@types/react-dom": "^17.0.5", | ||
"@types/react-router-dom": "^5.1.7", | ||
"@typescript-eslint/eslint-plugin": "^4.23.0", | ||
"@typescript-eslint/parser": "^4.23.0", | ||
"@vitejs/plugin-react-refresh": "^1.3.3", | ||
"concurrently": "6.1.0", | ||
"copyfiles": "^2.4.1", | ||
"eslint": "^7.26.0", | ||
"eslint-config-prettier": "^8.3.0", | ||
"eslint-config-standard": "^16.0.2", | ||
"eslint-plugin-import": "^2.23.2", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^5.1.0", | ||
"eslint-plugin-react": "^7.23.2", | ||
"postcss": "8.2.15", | ||
"prettier": "^2.3.0", | ||
"rimraf": "^3.0.2", | ||
"tailwindcss": "2.1.2", | ||
"typescript": "4.3.1-rc", | ||
"vite": "2.3.2", | ||
"vite-plugin-legacy": "^2.1.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// postcss.config.cjs | ||
module.exports = { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {}, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import fs from "fs"; | ||
import path from "path"; | ||
import express from "express"; | ||
import { createServer as createViteServer } from "vite"; | ||
import serveStatic from "serve-static"; | ||
import compression from "compression"; | ||
import { getApi } from "./src/server/routes/api"; | ||
|
||
const isTest = process.env.NODE_ENV === "test" || !!process.env.VITE_TEST_BUILD; | ||
|
||
const createServer = async (root = process.cwd(), isProd = process.env.NODE_ENV === "production") => { | ||
const resolve = (p: string) => path.resolve(__dirname, p); | ||
|
||
const indexProd = isProd ? fs.readFileSync(resolve("./client/index.html"), "utf-8") : ""; | ||
|
||
const app = express(); | ||
|
||
app.use(express.json()); | ||
app.use(express.urlencoded({ extended: true })); | ||
|
||
let vite: any; | ||
|
||
if (!isProd) { | ||
vite = await createViteServer({ | ||
root, | ||
logLevel: isTest ? "error" : "info", | ||
server: { | ||
middlewareMode: true, | ||
watch: { | ||
// During tests we edit the files too ft and sometimes chokidar | ||
// misses change events, so enforce polling for consistency | ||
usePolling: true, | ||
interval: 100, | ||
}, | ||
}, | ||
}); | ||
// use vite's connect instance as middleware | ||
app.use(vite.middlewares); | ||
} else { | ||
app.use(compression()); | ||
app.use( | ||
serveStatic(resolve("./client"), { | ||
index: false, | ||
}), | ||
); | ||
} | ||
|
||
app.use("/api", getApi); | ||
|
||
app.use("*", async ({ originalUrl }, res) => { | ||
try { | ||
const url = originalUrl; | ||
|
||
let template; | ||
let render; | ||
if (!isProd) { | ||
// always read fresh template in dev | ||
template = fs.readFileSync(resolve("index.html"), "utf-8"); | ||
template = await vite.transformIndexHtml(url, template); | ||
render = (await vite.ssrLoadModule("/src/client/entry-server.tsx")).render; | ||
} else { | ||
template = indexProd; | ||
const entryServer = require("./server/entry-server.js"); | ||
render = entryServer.render; | ||
} | ||
|
||
const context: any = {}; | ||
const appHtml = render(url, context); | ||
|
||
if (context.url) { | ||
// Somewhere a `<Redirect>` was rendered | ||
return res.redirect(301, context.url); | ||
} | ||
|
||
const html = template.replace(`<!--app-html-->`, appHtml); | ||
|
||
res.status(200).set({ "Content-Type": "text/html" }).end(html); | ||
} catch (e) { | ||
!isProd && vite.ssrFixStacktrace(e); | ||
console.error(e.stack); | ||
res.status(500).end(e.stack); | ||
} | ||
}); | ||
|
||
return { app, vite }; | ||
}; | ||
|
||
createServer().then(({ app }) => { | ||
const port = process.env.PORT || 7456 | ||
app.listen(Number(port), "0.0.0.0", () => { | ||
console.log(`App is listening on port ${port}`); | ||
}); | ||
}); | ||
|
||
// for test use | ||
export { createServer }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from "react"; | ||
import Main from "./pages/Main"; | ||
import { ContextWrapper } from "./Context"; | ||
|
||
export const App = () => { | ||
return ( | ||
<ContextWrapper> | ||
<Main /> | ||
</ContextWrapper> | ||
); | ||
}; | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React, { useContext, useState } from "react"; | ||
|
||
export interface Context { | ||
name: string; | ||
setName: (val: string) => void; | ||
} | ||
const defaultVal = { | ||
name: '', | ||
setName: () => {} | ||
} as Context; | ||
|
||
const context = React.createContext(defaultVal); | ||
|
||
const { Provider } = context; | ||
|
||
export const ContextWrapper = ({ children }: { children: any }) => { | ||
const [name, setName] = useState(defaultVal.name); | ||
return <Provider value={{ name,setName }}>{children}</Provider>; | ||
}; | ||
|
||
export const useAppContext = () => useContext(context); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from "react"; | ||
|
||
export const Footer = () => { | ||
return ( | ||
<footer className={"justify-center items-center"}> | ||
© {new Date().getFullYear()} - <a href={"https://jonlu.ca"}>JonLuca DeCaro</a> -{" "} | ||
<a className={"p-1"} href={"mailto:[email protected]"}> | ||
Support | ||
</a> | ||
</footer> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from "react"; | ||
import ReactDOM from "react-dom"; | ||
import { BrowserRouter } from "react-router-dom"; | ||
import { App } from "./App"; | ||
import "./index.css"; | ||
|
||
ReactDOM.hydrate( | ||
<BrowserRouter> | ||
<App /> | ||
</BrowserRouter>, | ||
document.getElementById("app"), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import React from "react"; | ||
import ReactDOMServer from "react-dom/server"; | ||
import { StaticRouter } from "react-router-dom"; | ||
import { App } from "./App"; | ||
import { StaticRouterContext } from "react-router"; | ||
import "./index.css"; | ||
|
||
export function render(url: string, context: StaticRouterContext) { | ||
return ReactDOMServer.renderToString( | ||
<StaticRouter location={url} context={context}> | ||
<App /> | ||
</StaticRouter>, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
@import "tailwindcss/base"; | ||
|
||
@import "tailwindcss/components"; | ||
|
||
@import "tailwindcss/utilities"; | ||
|
||
body { | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import React from "react"; | ||
import { Footer } from "../components/Footer"; | ||
import { useAppContext } from "../Context"; | ||
|
||
const Main = () => { | ||
const { name, setName } = useAppContext(); | ||
return ( | ||
<div className="flex bg-white-100 font-sans items-center flex-col justify-between"> | ||
<div className="flex items-center flex-col h-screen"> | ||
<h1 className="font-bold text-gray-900 text-5xl lg:text-7xl text-center ">Hi{name ? `, ${name}!` : ""}</h1> | ||
<h2 className={"w-2/5 p-5 items-center flex align-middle text-center min-w-[320px]"}> | ||
This is a Vite React SSR Tailwind boilerplate! | ||
</h2> | ||
<input | ||
placeholder={"Enter your name"} | ||
onChange={e => setName(e.currentTarget.value)} | ||
className="focus:ring-indigo-500 focus:border-indigo-500 block w-full text-2xl border-gray-300 rounded-md p-2" | ||
/> | ||
</div> | ||
<Footer /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Main; |
Oops, something went wrong.