最近剛在JavaScript Weekly看到了Remix.run(以下簡稱Remix)準備開源釋出1.0版本。沒過兩天就看到Remix飆到Github Trending趨勢榜第一了。感覺是已經火了啊,不知道後續跟Next.js比怎麼樣。不過看起來不算太複雜,很多東西都封裝起來了,語法很輕。所以準備學習一下,順便做點學習筆記。
建立專案
從npm下載remix最新版並生成專案。
npx create-remix@latest
? Where would you like to create your app?
my-cv
我準備做個展示簡歷的Web應用,動態顯示專案經歷,這樣還算有點需求,不然單純只是個Demo,畢竟沒有需求就沒法好好深入學習。而且SSR(Server Side Render服務端渲染)的特色就是方便SEO,做個展示動態資料類的應用是最適合的。命名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
當然選擇原汁原味的Remix App Server了
? TypeScript or JavaScript?
TypeScript
- JavaScript
我選擇了TypeScript。其實我個人的專案一般不選擇TypeScript,不過這次還需要學習以下,就儘量模擬的更正式一些。對於個人開發者來說TypeScript弊大於利,雖然確實可以有效減少錯誤,和找錯誤的時間成本,但是定義型別等啟動專案時準備的時間更多,還有好不容易找到的冷門庫不支援TS的風險。
? Do you want me to runnpm install
?Y
最後安裝就行了。
啟動專案
進入專案目錄
cd my-cv
啟動起來看看
npm run dev
這裡 Node版本12會報錯,16沒問題。
"Could not locate @remix-run/serve. Please verify you have it installed to use the dev command."
可以訪問http://localhost:3000
了。
直接帶有一個Demo,展示了路由的各種狀態,404,401之類的,還有帶引數的路由。可以留著參考,也可以刪掉。
建立頁面
這個Demo樣式還行,就留著了,反正自己寫樣式對於學習Remix沒有太大意義。所以我把導航改成中文,然後第二個頁面改成一個新路由,一會可以建立它,用來展示簡歷。然後第三個Github的連線改成自己的了。
<ul>
<li>
<Link to="/">首頁</Link>
</li>
<li>
<Link to="/resume">簡歷</Link>
</li>
<li>
<a href="https://github.com/tychio">GitHub</a>
</li>
</ul>
然後,建立對應的頁面。
mkdir app/routes/resume
touch app/routes/resume/index.tsx
然後填入一些靜態文字,名字和介紹。還有技能,這個可以用載入動態資料來做,先做前端部分,直接從字面量返回。利用useLoaderData
返回資料。
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>
);
}
注意:這裡的loader
是被後端API鉤子useLoaderData
呼叫的,所以看不到使用
我還定義了ResumeData
型別用於該頁面的動態資料,它包含了skills
。
使用資料庫ORM
下一步,找一個ORM,把資料徹底放在資料庫裡。我選擇了Prisma,
npm install --save-dev prisma
npm install @prisma/client
初始化ORM
npx prisma init --datasource-provider mysql
我選擇了mysql,你可以直接使用SQL Lite npx prisma init --datasource-provider sqlite
。
然後在新增的.env
檔案裡設定DATABASE_URL
mysql://<username>:<password>@<host | localhost>:<port>/<database_name>
然後執行 npx prisma db pull
讀取資料庫並自動生成schema。
再執行npx prisma generate
生成客戶端。
這樣就可以通過以下程式碼使用ORM。
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
建立表
我提前建立了skills表,所以剛才pull的時候,在prisma/schema.prisma
檔案裡就有了model。
model skills {
id Int @id @default(autoincrement())
name String? @db.VarChar(30)
}
如果資料庫中沒有的表,先在這裡寫上model schema,再執行npx prisma db push
就可以在資料庫中建立對應的表。
記得在.gitignore
裡新增.env
。如果使用的SQLite,還有/prisma/xxx.db
。
插入資料
建立prisma/seed.ts
檔案,用於最初的資料。
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'
},
...
]
}
安裝ts-node
包執行seed。
npm install --save-dev ts-node
方便起見,在package.json
中加入
"prisma": {
"seed": "ts-node prisma/seed.ts"
},
然後執行seed
npx prisma db seed
使用資料
在app目錄下建立utils目錄,以及檔案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
環境的區別是快取了連線例項,這樣不會每次重啟
在之前的resume/index.tsx
頁面使用它。
import { db } from "~/utils/db.server";
~
是預設在Remix的模板中tsconfig.json配置的,代表app目錄。
更新loader方法
export const loader: LoaderFunction = async () => {
const data: ResumeData = {
skills: await db.skills.findMany()
};
return data;
}
這樣基本的Remix流程就走通了。從資料庫到頁面。
另外我還替換了原來的logo。谷歌繪圖 製作svg還挺好用。
程式碼放到Github上了,後面還要繼續,和文中可能會有差異。