Revert "Vercel middleware!"

This reverts commit 2a09008be2.
This commit is contained in:
EGOIST 2022-05-05 00:41:12 +08:00
parent 40039ced43
commit bed389213a
14 changed files with 130 additions and 3119 deletions

5
.dockerignore Normal file
View File

@ -0,0 +1,5 @@
/.cache
/.env
/build
/node_modules
/public/build

4
.gitignore vendored
View File

@ -9,7 +9,3 @@ node_modules
/public/build
/api/index.js
/api/**/*.js.map
dist
.vercel
.DS_Store
/app/generated.css

38
Dockerfile Normal file
View File

@ -0,0 +1,38 @@
### base
FROM node:16-bullseye-slim as base
# Install openssl for Prisma
RUN apt-get update && apt-get install -y openssl
### build
FROM base as build
RUN mkdir /app
WORKDIR /app
RUN npm i -g pnpm
ADD . .
RUN pnpm install
ENV NODE_ENV=production
RUN pnpm prisma generate
RUN pnpm build
# keep production dependencies only
RUN pnpm prune --production
# Finally, build the production image with minimal footprint
FROM base
ENV NODE_ENV=production
RUN mkdir /app
WORKDIR /app
COPY --from=build /app/node_modules /app/node_modules
COPY --from=build /app/build /app/build
COPY --from=build /app/public /app/public
ADD . .
CMD ["npm", "start"]

File diff suppressed because one or more lines are too long

View File

@ -1,51 +0,0 @@
const REDIRECTS = new Set([301, 302, 303, 307, 308])
export function validateURL(url: string | URL): string {
try {
return String(new URL(String(url)))
} catch (error: any) {
throw new Error(`URLs is malformed. Please use only absolute URLs`)
}
}
// Should kept in sync with Next.js https://cs.github.com/vercel/next.js/blob/4a8a3d2400a54448b615fbc75cd91ca8cfea256c/packages/next/server/utils.ts#L18
export function isBot(userAgent: string): boolean {
return /Googlebot|Mediapartners-Google|AdsBot-Google|googleweblight|Storebot-Google|Google-PageRenderer|Bingbot|BingPreview|Slurp|DuckDuckBot|baiduspider|yandex|sogou|LinkedInBot|bitlybot|tumblr|vkShare|quora link preview|facebookexternalhit|facebookcatalog|Twitterbot|applebot|redditbot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|ia_archiver/i.test(
userAgent
)
}
export const REWRITE_HEADER = "x-middleware-rewrite"
export const NEXT_HEADER = "x-middleware-next"
export class MiddlewareResponse extends Response {
static rewrite(destination: string | URL) {
return new MiddlewareResponse(null, {
headers: {
[REWRITE_HEADER]: validateURL(destination),
},
})
}
static next() {
return new MiddlewareResponse(null, {
headers: {
[NEXT_HEADER]: "1",
},
})
}
static redirect(url: string | URL, status = 307) {
if (!REDIRECTS.has(status)) {
throw new RangeError(
'Failed to execute "redirect" on "response": Invalid status code'
)
}
const destination = validateURL(url)
return new MiddlewareResponse(destination, {
headers: { Location: destination },
status,
})
}
}

View File

@ -1,21 +0,0 @@
import { MiddlewareResponse } from "./middleware-utils"
export default (req: Request) => {
const url = new URL(req.url)
const cookieHeader = req.headers.get("cookie") || ""
if (
url.pathname.startsWith("/dashboard") &&
!cookieHeader.includes(process.env.AUTH_COOKIE_NAME)
) {
const redirectUrl = new URL(req.url)
redirectUrl.pathname = "/"
return MiddlewareResponse.redirect(redirectUrl)
}
if (url.pathname === "/__test_middleware") {
return new Response("home")
}
return MiddlewareResponse.next()
}

View File

@ -16,7 +16,7 @@ import {
import LoginModal from "~/components/common/LoginModal"
import { createStore, StoreProvider } from "./lib/store"
import { Toaster } from "react-hot-toast"
import css from "./generated.css"
import css from "./main.css"
import { APP_NAME } from "./lib/config.shared"
export const meta: MetaFunction = () => {

41
fly.toml Normal file
View File

@ -0,0 +1,41 @@
# fly.toml file generated for proselog on 2022-05-02T21:19:40+08:00
app = "proselog"
kill_signal = "SIGINT"
kill_timeout = 5
processes = []
[env]
PORT = "8080"
[experimental]
allowed_public_ports = []
auto_rollback = true
[[services]]
http_checks = []
internal_port = 8080
processes = ["app"]
protocol = "tcp"
script_checks = []
[services.concurrency]
hard_limit = 25
soft_limit = 20
type = "connections"
[[services.ports]]
force_https = true
handlers = ["http"]
port = 80
[[services.ports]]
handlers = ["tls", "http"]
port = 443
[[services.tcp_checks]]
grace_period = "1s"
interval = "15s"
restart_limit = 0
timeout = "2s"

View File

@ -6,14 +6,14 @@
"sideEffects": false,
"scripts": {
"build-remix": "remix build",
"build": "pnpm build-css && pnpm build-remix && pnpm build-vercel",
"build-vercel": "node -r esbuild-register scripts/vercel-build.ts",
"dev-node": "nodemon build/index.js --watch build",
"dev-remix": "remix watch",
"build": "pnpm build-css && pnpm build-remix",
"dev-remix": "remix dev",
"dev": "pnpm generate-css && run-p dev-*",
"generate-css": "tailwindcss --input ./css/main.css --output ./app/generated.css --postcss",
"generate-css": "tailwindcss --input ./css/main.css --output ./app/main.css --postcss",
"dev-css": "pnpm generate-css --watch",
"build-css": "pnpm generate-css --minify"
"build-css": "pnpm generate-css --minify",
"start": "remix-serve build",
"deploy": "fly deploy --remote-only"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.81.0",
@ -26,7 +26,7 @@
"@prisma/client": "^3.13.0",
"@remix-run/node": "*",
"@remix-run/react": "*",
"@remix-run/vercel": "*",
"@remix-run/serve": "*",
"@uiw/react-codemirror": "^4.7.0",
"@vercel/node": "^1.14.0",
"clsx": "^1.1.1",
@ -48,23 +48,13 @@
"@remix-run/dev": "*",
"@remix-run/eslint-config": "*",
"@remix-run/serve": "*",
"@types/connect": "^3.4.35",
"@types/express": "^4.17.13",
"@types/fs-extra": "^9.0.13",
"@types/markdown-it": "^12.2.3",
"@types/react": "^17.0.24",
"@types/react-avatar-editor": "^12.0.0",
"@types/react-dom": "^17.0.9",
"@types/ua-parser-js": "^0.7.36",
"@types/uuid": "^8.3.4",
"@vercel/nft": "^0.18.2",
"dotenv": "^16.0.0",
"esbuild": "^0.14.38",
"esbuild-register": "^3.3.2",
"eslint": "^8.11.0",
"express": "^4.18.1",
"fs-extra": "^10.1.0",
"nodemon": "^2.0.16",
"npm-run-all": "^4.1.5",
"postcss-import": "^14.1.0",
"prisma": "^3.13.0",

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,8 @@
*/
module.exports = {
ignoredRouteFiles: ["**/.*"],
server:
process.env.NODE_ENV === "development"
? "./server-dev.ts"
: "./server-prod.ts",
// appDirectory: "app",
// assetsBuildDirectory: "public/build",
// serverBuildPath: "build/index.js",
// publicPath: "/build/",
}

View File

@ -1,77 +0,0 @@
import * as esbuild from "esbuild"
import dotenv from "dotenv"
import fs from "fs-extra"
import { nodeFileTrace } from "@vercel/nft"
async function main() {
const { parsed = {} } = dotenv.config()
const envKeys = Object.keys(parsed)
// Copy static file
await fs.copy("public", ".vercel/output/static")
// Edge function
await esbuild.build({
entryPoints: ["./app/middleware.ts"],
format: "esm",
platform: "node",
bundle: true,
outfile: ".vercel/output/functions/edge.func/index.js",
define: {
"process.env.NODE_ENV": JSON.stringify("production"),
},
})
fs.outputJSONSync(".vercel/output/functions/edge.func/.vc-config.json", {
runtime: "edge",
entrypoint: "index.js",
envVarsInUse: envKeys,
})
// Serverless function
await fs.copy("build", ".vercel/output/functions/render.func")
const { fileList } = await nodeFileTrace([
".vercel/output/functions/render.func/index.js",
])
for (const filepath of fileList) {
if (filepath.includes("node_modules")) {
await fs.copy(
filepath,
`.vercel/output/functions/render.func/${filepath}`
)
}
}
fs.outputJSONSync(".vercel/output/functions/render.func/.vc-config.json", {
runtime: "nodejs14.x",
handler: "index.js",
launcherType: "Nodejs",
})
// Routes
fs.outputJSONSync(".vercel/output/config.json", {
version: 3,
routes: [
{
src: `/build/.+`,
headers: {
"cache-control": "public, immutable, max-age=31536000",
},
},
{
handle: "filesystem",
},
{
src: "/.*",
middlewarePath: "edge",
continue: true,
},
{ src: "/.*", dest: "/render" },
].filter(Boolean),
})
}
main().catch((error) => {
console.error(error)
process.exit(1)
})

View File

@ -1,68 +0,0 @@
/**
* The dev server serve the Remix app and use ./app/middleware.ts as a middleware (Vercel)
* In production the middleware will be bundled to .vercel folder and Vercel will handle that
*/
import "dotenv/config"
import path from "path"
import express from "express"
import { createRequestHandler } from "@remix-run/vercel"
import { createRemixRequest, sendRemixResponse } from "@remix-run/vercel/server"
import { NEXT_HEADER, REWRITE_HEADER } from "~/middleware-utils"
const app = express()
const BUILD_DIR = path.resolve("build")
// Remix fingerprints its assets so we can cache forever.
app.use("/build", express.static("public/build"))
// Everything else (like favicon.ico) is cached for an hour. You may want to be
// more aggressive with this caching.
app.use(express.static("public"))
app.use(async (req, res, next) => {
const middleware = require("~/middleware").default
const request = createRemixRequest(req as any)
let response: Response = await middleware(request)
if (response.headers.has(NEXT_HEADER)) {
return next()
}
const rewriteTo = response.headers.get(REWRITE_HEADER)
if (rewriteTo) {
response = await fetch(rewriteTo)
response.headers.delete("content-encoding")
}
sendRemixResponse(res as any, response as any)
})
app.all("*", (req, res) => {
purgeRequireCache()
const handler = createRequestHandler({
build: require("@remix-run/dev/server-build"),
mode: process.env.NODE_ENV,
})
// @ts-expect-error
return handler(req, res)
})
const PORT = process.env.PORT || "3000"
app.listen(PORT)
console.log(`Open http://localhost:${PORT}`)
function purgeRequireCache() {
// purge require cache on requests for "server side HMR" this won't let
// you have in-memory objects between requests in development,
// alternatively you can set up nodemon/pm2-dev to restart the server on
// file changes, but then you'll have to reconnect to databases/etc on each
// change. We prefer the DX of this, so we've included it for you by default
for (let key in require.cache) {
if (key.startsWith(BUILD_DIR)) {
delete require.cache[key]
}
}
}

View File

@ -1,8 +0,0 @@
/**
* The production server is just a vercel serverless function
*/
import { createRequestHandler } from "@remix-run/vercel"
import * as build from "@remix-run/dev/server-build"
export default createRequestHandler({ build, mode: process.env.NODE_ENV })