3
头图

Recently, I saw Remix.run (hereinafter referred to as Remix) at JavaScript Weekly that it is preparing to release version 1.0 as an open source. Within two days, I saw Remix soaring to the top of the Github Trending trend list. It feels like it's already on fire. I don't know how it compares with Next.js. But it doesn't look too complicated, many things are encapsulated, and the syntax is very light. So prepare to study and take some study notes by the way.

Create project

Download the latest version of remix from npm and generate the project.

npx create-remix@latest

? Where would you like to create your app? my-cv

I am going to make a web application that displays resumes and dynamically display project experience. This is still a bit demanding, otherwise it's just a demo. After all, there is no need to study in depth. Moreover, the feature of SSR (Server Side Render) is to facilitate SEO, and it is most suitable to be an application that displays dynamic data. Named my-cv .

? Where do you want to deploy? Choose Remix if you're unsure, it's easy to change deployment targets.
  • Remix App Server
  • Express Server
  • Architect (AWS Lambda)
  • Fly.io
  • Netlify
  • Vercel
  • Cloudflare Workers
    Of course choose the original Remix App Server
? TypeScript or JavaScript?
TypeScript
  • JavaScript
    I chose TypeScript. In fact, I generally don't choose TypeScript for my personal projects, but I still need to learn the following this time, so I try to simulate it more formally. For individual developers, TypeScript does more harm than good. Although it can effectively reduce errors and the time cost of finding errors, it takes more time to prepare when starting projects such as defining types. There are also unpopular libraries that are hard to find that do not support TS. risk.
? Do you want me to run npm install? Y
Finally, install it.

Startup project

Enter the project directory

cd my-cv

Start up and have a look

npm run dev

Here Node version 12 will report an error, 16 is no problem.

"Could not locate @remix-run/serve. Please verify you have it installed to use the dev command."

Can visit http://localhost:3000 now.
Directly comes with a Demo, which shows the various states of the route, such as 404, 401, and routes with parameters. You can keep it for reference or delete it.

Create page

This Demo style is okay, so I just keep it. Anyway, writing styles by myself doesn't make much sense for learning Remix. So I changed the navigation to Chinese, and then changed the second page to a new route, which can be created later to display resumes. Then the third Github link was changed to my own.

<ul>
  <li>
    <Link to="/">首页</Link>
  </li>
  <li>
    <Link to="/resume">简历</Link>
  </li>
  <li>
    <a href="https://github.com/tychio">GitHub</a>
  </li>
</ul>

Then, create the corresponding page.

mkdir app/routes/resume
touch app/routes/resume/index.tsx

Then fill in some static text, name and introduction. There are also skills, this can be done by loading dynamic data, first do the front-end part, and return directly from the literal. Use useLoaderData to return data.

import type { LoaderFunction } from "remix";
import { useLoaderData, json } from "remix";
type ResumeData = {
  skills: Array<{ name: string }>;
};
export const loader: LoaderFunction = () => {
  const data: ResumeData = {
    skills: [
      'JavaScript', 'CSS/HTML', 'React', 'Remix'
    ]
  };
  return json(data);
}

export default function ResumeIndex() {
  const resume = useLoaderData<ResumeData>();
  return (
    <div>
      <h1>Zhang Zhengzheng</h1>
      <p>
        A full-stack developer, Senior consultant, Freelancer.
      </p>
      <p>
        {resume.skills.map((skill, index) => (
          <span>{index !== 0 ? ', ' : ''}{skill.name}</span>
        ))}
      </p>
    </div>
  );
}
Note: The loader here is called by the back-end API hook useLoaderData , so you can’t see the usage

I also defined the ResumeData for the dynamic data of the page, which includes skills .

Use database ORM

Next, find an ORM and put the data completely in the database. I chose Prisma,

npm install --save-dev prisma

npm install @prisma/client

Initialize ORM

npx prisma init --datasource-provider mysql

I chose mysql, you can use SQL Lite npx prisma init --datasource-provider sqlite directly.

Then add .env settings file DATABASE_URL

mysql://<username>:<password>@<host | localhost>:<port>/<database_name>

Then execute npx prisma db pull read the database and automatically generate the schema.

Then execute npx prisma generate generate the client.
In this way, ORM can be used with the following code.

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

Create table

I created the skills table in advance, so when I prisma/schema.prisma it just now, there was a model in the 061a6043ec17f2 file.

model skills {
  id   Int     @id @default(autoincrement())
  name String? @db.VarChar(30)
}

If there is no table in the database, write the model schema here first, and then execute npx prisma db push to create the corresponding table in the database.

Remember .gitignore added in .env . If you are using SQLite, there is also /prisma/xxx.db .

Insert data

Create the prisma/seed.ts file for the initial data.

import { PrismaClient } from "@prisma/client";
let db = new PrismaClient();

async function seed() {
  await Promise.all(
    getSkills().map(joke => {
      return db.skills.create({ data: joke });
    })
  );
}

seed();

function getSkills() {
  return [
    {    
        name: 'JavaScript'
    },
    ...
  ]
}

Install the ts-node package and execute the seed.

npm install --save-dev ts-node

For convenience, add package.json

"prisma": {
  "seed": "ts-node prisma/seed.ts"
},

Then execute seed

npx prisma db seed

Use data

Create a utils directory under the app directory, and file utils/db.server.ts

import { PrismaClient } from "@prisma/client";

let db: PrismaClient;

declare global {
  var __db: PrismaClient | undefined;
}

if (process.env.NODE_ENV === "production") {
  db = new PrismaClient();
  db.$connect();
} else {
  if (!global.__db) {
    global.__db = new PrismaClient();
    global.__db.$connect();
  }
  db = global.__db;
}

export { db };
development environment is that the connection instance is cached so that it will not restart every time

Use it on the previous resume/index.tsx

import { db } from "~/utils/db.server";

~ is configured by default in tsconfig.json in the Remix template, which represents the app directory.

Update loader method

export const loader: LoaderFunction = async () => {
  const data: ResumeData = {
    skills: await db.skills.findMany()
  };
  return data;
}

In this way, the basic Remix process goes through. From database to page.

In addition, I also replaced the original logo. Google drawing makes svg pretty easy to use.

code put on Github, and it will be continued later, there may be differences from the text.


Tychio
3.4k 声望139 粉丝

软件工程师,Web前端工程师,高级软件咨询师,远程自由职业开发