Git Product home page Git Product logo

remix-bun's Introduction

remix-bun

Bun server adapter for remix

bun + remix.run

Get Started

Prerequirements

Now either

Create a new remix app

Use the example in examples/basic (Easiest way!)

$ git clone [email protected]:patlux/remix-bun.git
$ cd remix-bun/examples/basic
$ bun install

You are ready to go!

Just run bun run dev to start the development server.

Use create-remix

Create a new project with the following commands:

$ bunx create-remix@latest --no-install --typescript

# Where would you like to create your app?
# -> my-remix-bun-app
# What type of app do you want to create?
# -> Just the basics
# Where do you want to deploy? Choose Remix App Server if you're unsure; it's easy to change deployment targets.
# -> Remix App Server
# 💿 That's it! `cd` into "<..>/my-remix-bun-app" and check the README for development and deploy instructions!

$ cd my-remix-bun-app

Continue with the steps below in Add to existing project

Add to existing project

Add remix-bun to your existing project with the following commands:

$ bun add remix-bun
$ bun add -d bun-types npm-run-all
# See below in "Setup project" for further instructions

Setup project

Make sure you followed the instructions above before you continue.

  1. Add server.ts in the root of your project:
// <root-folder>/server.ts

import type { ServeOptions } from 'bun';
import { createRequestHandler } from 'remix-bun';

setInterval(() => Bun.gc(true), 9000);

const bunServeOptions: ServeOptions = {
  port: parseInt(process.env.PORT ?? '3000', 10),
  fetch:
    process.env.NODE_ENV === 'production'
      ? createRequestHandler({
        build: require('./build'),
        mode: 'production',
      })
      : async (request: Request) => {
        const build = require('./build');
        const requestHandler = createRequestHandler({ build, mode: 'development' });
        return requestHandler(request);
      },
};

export default bunServeOptions;
  1. tsconfig.json

Make the following changes:

diff --git a/tsconfig.json b/tsconfig.json
index 20f8a38..92db692 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,13 +1,14 @@
 {
   "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
   "compilerOptions": {
-    "lib": ["DOM", "DOM.Iterable", "ES2019"],
+    "lib": ["DOM", "DOM.Iterable", "ESNext"],
+    "module": "esnext",
+    "target": "esnext",
     "isolatedModules": true,
     "esModuleInterop": true,
     "jsx": "react-jsx",
     "moduleResolution": "node",
     "resolveJsonModule": true,
-    "target": "ES2019",
     "strict": true,
     "allowJs": true,
     "forceConsistentCasingInFileNames": true,
@@ -15,7 +16,6 @@
     "paths": {
       "~/*": ["./app/*"]
     },

     // Remix takes care of building everything in `remix build`.
     "noEmit": true
   }
  1. remix-env.d.ts

Make the following changes:

diff --git a/remix.env.d.ts b/remix.env.d.ts
index dcf8c45..a2385a1 100644
--- a/remix.env.d.ts
+++ b/remix.env.d.ts
@@ -1,2 +1,4 @@
+/// <reference lib="DOM" />
+/// <reference lib="DOM.Iterable" />
+/// <reference types="bun-types" />
 /// <reference types="@remix-run/dev" />
-/// <reference types="@remix-run/node" />
  1. package.json

Add the following scripts to your package.json:

diff --git a/package.json b/package.json
index fb04c8d..c1b8e17 100644
--- a/package.json
+++ b/package.json
@@ -2,8 +2,10 @@
   "private": true,
   "sideEffects": false,
   "scripts": {
+    "dev:remix": "bun run node_modules/@remix-run/dev/dist/cli.js watch",
+    "dev:server": "NODE_ENV=development bun --hot ./server.ts",
+    "dev": "run-p dev:*",
     "build": "remix build",
-    "dev": "remix dev",
-    "start": "remix-serve build",
+    "start": "NODE_ENV=production bun run ./server.ts",
     "typecheck": "tsc -b"
   },
  1. <root-folder>/app/entry.server.ts

Check the content of your <root-folder>/app/entry.server.ts.

If you are using renderToString, you are fine but you can replace it as below if you want.

If you are using renderToPipeableStream then replace your entry.server.ts with the following:

import type { EntryContext } from "@remix-run/node";
import { Response } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import isbot from "isbot";
import { renderToReadableStream } from "react-dom/server";

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(async (resolve, reject) => {
    const stream = await renderToReadableStream(
      <RemixServer context={remixContext} url={request.url} />,
      {
        onError(error) {
          console.error(error);
          reject(error);
        },
      }
    );

    resolve(
      new Response(stream, {
        status: responseStatusCode,
        headers: responseHeaders,
      })
    );
  });
}

function handleBrowserRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  return new Promise(async (resolve, reject) => {
    const stream = await renderToReadableStream(
      <RemixServer context={remixContext} url={request.url} />,
      {
        onError(error) {
          console.error(error);
          reject(error);
        },
      }
    );

    resolve(
      new Response(stream, {
        status: responseStatusCode,
        headers: responseHeaders,
      })
    );
  });
}

Development

From your terminal:

bun run dev

This starts your app in development mode, rebuilding assets on file changes.

Troubleshooting

TypeError: undefined is not a function (near '...(0 , import_server.renderToPipeableStream)...')

You need to adjust the entry.server.ts as suggested in "Setup project".

TODO

Support remix's --template

bunx create-remix@latest --template patlux/remix-bun --typescript

Would be nice for a better way of bootstraping new remix projects with bun.

But it's currently not possible because bun doesn't support the bun config get command like npm or yarn.

$ bunx create-remix@latest --template patlux/remix-bun --typescript
# Where would you like to create your app? ./my-remix-app
# Do you want me to run `bun install`? Yes
# ⠏ Creating your app…error: script not found "config"
# Command failed: bun config get @remix-run:registry
# error: script not found "config"

# error: "create-remix" exited with code 1 (SIGHUP)

Credits

Created by @de_patwoz

remix-bun's People

Contributors

patlux avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.