Closed1

Remix 2 + Turso + Cloudflare workers + Vercel スタックのメモ

knaka Tech-Blogknaka Tech-Blog

概要

Remix + Turso 使うメモになります。

  • テストは、vercelにデプロイする例です。
  • Workers + TursoのAPIと連携する構成です。
  • 前の Workers + Turso 記事の続編になります。

[ 公開: 2024/04/11 ]


環境

  • Remix v2
  • vercel
  • Cloudflare Workers
  • Turso

関連

https://zenn.dev/knaka0209/scraps/3092c20e49cbb6

https://zenn.dev/knaka0209/scraps/fda5606127c464


作成したコード

https://github.com/kuc-arc-f/remix47/tree/main/sample/turso_test


Stackblitz


  • app/routes/TursoTest.tsx
  • loaderで、 workers連携します。
TursoTest.tsx
import {useState, useEffect}  from 'react';
import type { MetaFunction } from "@remix-run/node";
import { json, redirect } from "@remix-run/node";
import {
  Form,
  Link,
  Links,
  Meta,
  NavLink,
  Outlet,
  Scripts,
  ScrollRestoration,
  useLoaderData,
  useNavigation,
} from "@remix-run/react";
import type {
  ActionFunctionArgs,
  LoaderFunctionArgs,
} from "@remix-run/node";
import CrudIndex from './TursoTest/CrudIndex';
//
export const meta: MetaFunction = () => {
  return [
    { title: "New Remix App" },
    { name: "description", content: "Welcome to Remix!" },
  ];
};
//
export const loader = async () => {
  const resulte = await CrudIndex.getList();
//console.log(resulte);
  return json({
     contacts: resulte, data: resulte
  });
};
//
export const action = async ({
  params,
  request,
}: ActionFunctionArgs) => {
  let formData = await request.formData();
  let title = formData.get("title");
  const item = {
    title: title,
    content: "c1",
  }
  const resulte = await CrudIndex.addItem(item);
  console.log(resulte);
console.log("title=", title);
  return redirect(`/tursotest`);
//  return json({ result: 'OK' })
}
//
export default function Index() {
  const { contacts, data } = useLoaderData<typeof loader>();
console.log(contacts);
  //
  return (
    <div className="container mx-auto my-2 px-8 bg-white" >
      <h1 className="text-4xl font-bold">Test.tsx</h1>
      <hr />
      <Form method="post" name="form3" id="form3" 
      className="remix__form">
        <label>
          <div>title:</div>
          <input  className="input_text"
          name="title" id="title" type="text" />
        </label>
        <div>
          <button type="submit" className="btn my-2"
          >Save</button>
        </div>
      </Form>
      <hr />
      <ul>
        {contacts.map(item => (
          <li key={item.id} className="remix__page__resource">
            <h3 className="text-3xl font-bold">{item.title}</h3>
            <p>ID :{item.id}</p>
            <hr className="my-2" />
          </li>
        ))}
        </ul>
    </div>
  );
}


  • package.json
{
  "name": "remix47",
  "private": true,
  "sideEffects": false,
  "type": "module",
  "scripts": {
    "build": "remix vite:build",
    "dev": "remix vite:dev",
    "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .",
    "start": "remix-serve ./build/server/index.js",
    "typecheck": "tsc"
  },
  "dependencies": {
    "@remix-run/node": "^2.8.1",
    "@remix-run/react": "^2.8.1",
    "@remix-run/serve": "^2.8.1",
    "axios": "^1.6.8",
    "isbot": "^4.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@remix-run/dev": "^2.8.1",
    "@types/react": "^18.2.20",
    "@types/react-dom": "^18.2.7",
    "@typescript-eslint/eslint-plugin": "^6.7.4",
    "@typescript-eslint/parser": "^6.7.4",
    "autoprefixer": "^10.4.19",
    "eslint": "^8.38.0",
    "eslint-import-resolver-typescript": "^3.6.1",
    "eslint-plugin-import": "^2.28.1",
    "eslint-plugin-jsx-a11y": "^6.7.1",
    "eslint-plugin-react": "^7.33.2",
    "eslint-plugin-react-hooks": "^4.6.0",
    "postcss": "^8.4.38",
    "tailwindcss": "^3.4.3",
    "typescript": "^5.1.6",
    "vite": "^5.1.0",
    "vite-tsconfig-paths": "^4.2.1"
  },
  "engines": {
    "node": ">=18.0.0"
  }
}

このスクラップは18日前にクローズされました