diff options
author | 2023-04-04 16:26:40 -0700 | |
---|---|---|
committer | 2023-04-04 16:26:40 -0700 | |
commit | 76adc5be8a4f35730bbd81f06f043073e7160af8 (patch) | |
tree | a6e32fee2faf6418be6e6dc7c447086fa4c4ce13 | |
parent | f3ab445c3fcae6a5177eb89e710e47f83cd7db42 (diff) | |
download | bun-76adc5be8a4f35730bbd81f06f043073e7160af8.tar.gz bun-76adc5be8a4f35730bbd81f06f043073e7160af8.tar.zst bun-76adc5be8a4f35730bbd81f06f043073e7160af8.zip |
Add npm benchmark (#2555)
* Add install bench
* Update scripts and readme
* remove lockfiles
* Format bench
* Add dev instructions
-rw-r--r-- | bench/install/.eslintrc.js | 4 | ||||
-rw-r--r-- | bench/install/.gitignore | 10 | ||||
-rw-r--r-- | bench/install/README.md | 18 | ||||
-rw-r--r-- | bench/install/app/entry.client.tsx | 18 | ||||
-rw-r--r-- | bench/install/app/entry.server.tsx | 101 | ||||
-rw-r--r-- | bench/install/app/root.tsx | 20 | ||||
-rw-r--r-- | bench/install/app/routes/_index.tsx | 30 | ||||
-rw-r--r-- | bench/install/package.json | 31 | ||||
-rw-r--r-- | bench/install/public/favicon.ico | bin | 0 -> 16958 bytes | |||
-rw-r--r-- | bench/install/remix.config.js | 14 | ||||
-rw-r--r-- | bench/install/remix.env.d.ts | 2 | ||||
-rw-r--r-- | bench/install/tsconfig.json | 22 | ||||
-rw-r--r-- | package.json | 2 |
13 files changed, 271 insertions, 1 deletions
diff --git a/bench/install/.eslintrc.js b/bench/install/.eslintrc.js new file mode 100644 index 000000000..2061cd226 --- /dev/null +++ b/bench/install/.eslintrc.js @@ -0,0 +1,4 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], +}; diff --git a/bench/install/.gitignore b/bench/install/.gitignore new file mode 100644 index 000000000..eff95a8ce --- /dev/null +++ b/bench/install/.gitignore @@ -0,0 +1,10 @@ +node_modules + +/.cache +/build +/public/build +.env +package-lock.json +yarn.lock +pnpm-lock.yaml +bun.lockb
\ No newline at end of file diff --git a/bench/install/README.md b/bench/install/README.md new file mode 100644 index 000000000..e9b617995 --- /dev/null +++ b/bench/install/README.md @@ -0,0 +1,18 @@ +# `install` benchmark + +Requires [`hyperfine`](https://github.com/sharkdp/hyperfine) + +``` +$ hyperfine --prepare 'rm -rf node_modules' --warmup 1 --runs 3 'bun install' 'pnpm install' 'yarn' 'npm install' +``` + +To check that the app is working as expected: + +``` +$ bun run dev +$ npm run dev +$ yarn dev +$ pnpm dev +``` + +Then visit [http://localhost:3000](http://localhost:3000). diff --git a/bench/install/app/entry.client.tsx b/bench/install/app/entry.client.tsx new file mode 100644 index 000000000..186cd9344 --- /dev/null +++ b/bench/install/app/entry.client.tsx @@ -0,0 +1,18 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/docs/en/main/file-conventions/entry.client + */ + +import { RemixBrowser } from "@remix-run/react"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; + +startTransition(() => { + hydrateRoot( + document, + <StrictMode> + <RemixBrowser /> + </StrictMode>, + ); +}); diff --git a/bench/install/app/entry.server.tsx b/bench/install/app/entry.server.tsx new file mode 100644 index 000000000..fbea6220e --- /dev/null +++ b/bench/install/app/entry.server.tsx @@ -0,0 +1,101 @@ +/** + * By default, Remix will handle generating the HTTP Response for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/docs/en/main/file-conventions/entry.server + */ + +import { PassThrough } from "node:stream"; +import type { EntryContext } from "@remix-run/node"; +import { Response } from "@remix-run/node"; +import { RemixServer } from "@remix-run/react"; +import isbot from "isbot"; +import { renderToPipeableStream } from "react-dom/server"; + +const ABORT_DELAY = 5_000; + +export default function handleRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + return isbot(request.headers.get("user-agent")) + ? handleBotRequest(request, responseStatusCode, responseHeaders, remixContext) + : handleBrowserRequest(request, responseStatusCode, responseHeaders, remixContext); +} + +function handleBotRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + return new Promise((resolve, reject) => { + const { pipe, abort } = renderToPipeableStream( + <RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />, + { + onAllReady() { + const body = new PassThrough(); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(body, { + headers: responseHeaders, + status: responseStatusCode, + }), + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + console.error(error); + }, + }, + ); + + setTimeout(abort, ABORT_DELAY); + }); +} + +function handleBrowserRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext, +) { + return new Promise((resolve, reject) => { + const { pipe, abort } = renderToPipeableStream( + <RemixServer context={remixContext} url={request.url} abortDelay={ABORT_DELAY} />, + { + onShellReady() { + const body = new PassThrough(); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(body, { + headers: responseHeaders, + status: responseStatusCode, + }), + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + console.error(error); + responseStatusCode = 500; + }, + }, + ); + + setTimeout(abort, ABORT_DELAY); + }); +} diff --git a/bench/install/app/root.tsx b/bench/install/app/root.tsx new file mode 100644 index 000000000..4d0236fb2 --- /dev/null +++ b/bench/install/app/root.tsx @@ -0,0 +1,20 @@ +import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from "@remix-run/react"; + +export default function App() { + return ( + <html lang="en"> + <head> + <meta charSet="utf-8" /> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <Meta /> + <Links /> + </head> + <body> + <Outlet /> + <ScrollRestoration /> + <Scripts /> + <LiveReload /> + </body> + </html> + ); +} diff --git a/bench/install/app/routes/_index.tsx b/bench/install/app/routes/_index.tsx new file mode 100644 index 000000000..92fccd4ad --- /dev/null +++ b/bench/install/app/routes/_index.tsx @@ -0,0 +1,30 @@ +import type { V2_MetaFunction } from "@remix-run/node"; + +export const meta: V2_MetaFunction = () => { + return [{ title: "New Remix App" }]; +}; + +export default function Index() { + return ( + <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}> + <h1>Welcome to Remix</h1> + <ul> + <li> + <a target="_blank" href="https://remix.run/tutorials/blog" rel="noreferrer"> + 15m Quickstart Blog Tutorial + </a> + </li> + <li> + <a target="_blank" href="https://remix.run/tutorials/jokes" rel="noreferrer"> + Deep Dive Jokes App Tutorial + </a> + </li> + <li> + <a target="_blank" href="https://remix.run/docs" rel="noreferrer"> + Remix Docs + </a> + </li> + </ul> + </div> + ); +} diff --git a/bench/install/package.json b/bench/install/package.json new file mode 100644 index 000000000..02bb8e92f --- /dev/null +++ b/bench/install/package.json @@ -0,0 +1,31 @@ +{ + "private": true, + "sideEffects": false, + "scripts": { + "build": "remix build", + "dev": "remix dev", + "start": "remix-serve build", + "typecheck": "tsc", + "clean": "rm -rf node_modules", + "bench": "hyperfine --prepare 'rm -rf node_modules' --warmup 1 --runs 3 'bun install' 'pnpm install' 'yarn' 'npm install'" + }, + "dependencies": { + "@remix-run/node": "^1.15.0", + "@remix-run/react": "^1.15.0", + "@remix-run/serve": "^1.15.0", + "isbot": "^3.6.5", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@remix-run/dev": "^1.15.0", + "@remix-run/eslint-config": "^1.15.0", + "@types/react": "^18.0.25", + "@types/react-dom": "^18.0.8", + "eslint": "^8.27.0", + "typescript": "^4.8.4" + }, + "engines": { + "node": ">=14" + } +} diff --git a/bench/install/public/favicon.ico b/bench/install/public/favicon.ico Binary files differnew file mode 100644 index 000000000..8830cf682 --- /dev/null +++ b/bench/install/public/favicon.ico diff --git a/bench/install/remix.config.js b/bench/install/remix.config.js new file mode 100644 index 000000000..a1a396661 --- /dev/null +++ b/bench/install/remix.config.js @@ -0,0 +1,14 @@ +/** @type {import('@remix-run/dev').AppConfig} */ +module.exports = { + ignoredRouteFiles: ["**/.*"], + // appDirectory: "app", + // assetsBuildDirectory: "public/build", + // serverBuildPath: "build/index.js", + // publicPath: "/build/", + future: { + v2_errorBoundary: true, + v2_meta: true, + v2_normalizeFormMethod: true, + v2_routeConvention: true, + }, +}; diff --git a/bench/install/remix.env.d.ts b/bench/install/remix.env.d.ts new file mode 100644 index 000000000..dcf8c45e1 --- /dev/null +++ b/bench/install/remix.env.d.ts @@ -0,0 +1,2 @@ +/// <reference types="@remix-run/dev" /> +/// <reference types="@remix-run/node" /> diff --git a/bench/install/tsconfig.json b/bench/install/tsconfig.json new file mode 100644 index 000000000..20f8a386a --- /dev/null +++ b/bench/install/tsconfig.json @@ -0,0 +1,22 @@ +{ + "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2019"], + "isolatedModules": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "moduleResolution": "node", + "resolveJsonModule": true, + "target": "ES2019", + "strict": true, + "allowJs": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./app/*"] + }, + + // Remix takes care of building everything in `remix build`. + "noEmit": true + } +} diff --git a/package.json b/package.json index e488635c2..477f237e7 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "build-fallback": "esbuild --target=esnext --bundle src/fallback.ts --format=iife --platform=browser --minify > src/fallback.out.js", "postinstall": "bash .scripts/postinstall.sh", "typecheck": "tsc --noEmit", - "fmt": "prettier --write './test/**/*.{mjs,ts,tsx,js,jsx}' './src/*.{mjs,ts,tsx,js,jsx}' './src/*/*.{mjs,ts,tsx,js,jsx}' './src/*/*/*.{mjs,ts,tsx,js,jsx}' './bench/*.{mjs,ts,tsx,js,jsx}' --config .prettierrc.cjs", + "fmt": "prettier --write './test/**/*.{mjs,ts,tsx,js,jsx}' './src/*.{mjs,ts,tsx,js,jsx}' './src/*/*.{mjs,ts,tsx,js,jsx}' './src/*/*/*.{mjs,ts,tsx,js,jsx}' './bench/**/*.{mjs,ts,tsx,js,jsx}' --config .prettierrc.cjs", "lint": "eslint './**/*.d.ts' --cache", "lint:fix": "eslint './**/*.d.ts' --cache --fix" }, |