准中年程序猿の部落格
总结是, 可以使用 roo code 进行自动编写代码.
总结是, 可以使用. 但同时带来大量的技术债务.
在过去的周末, 由于客户突然要求我们把手机应用端改成使用网页端并尽量在 3月 15日 前部署. 在考量了目前的人力和想要尝鲜的心态, 上级主管决定向公司请款使用钞能力使用 Roo Code 进行自动编写代码. ps: 关于 Roo Code 可以 点击这里 去查看, 我暂时跳过这玩意的介绍. 之后再补上 (哈).
首先, 这项目的后端本来就是全 API 导向的应用, 所以在开发网页端的时候能无缝的使用现有的 API. 另外前端是使用 Angular 19
进行开发, 没使用 React 或 Vue. 由于事出突然所以没有特地为网页端准备 UI 设计, 所以直接就是使用手机应用端的figma 截图, 喂给 Roo Code 进行自动编写代码.
整体还原度必须说很棒! 但令人头疼的问题随之而来:
如一开始的简要所说, ai 自动编写代码这概念是可行的 (国外称为 Ai Pair Programming). 它的确能生成可用的代码, 但同一时间它也带来的巨量的技术债务. 这在赶时间的情况可以暂时忽视但返回来要把整个项目修正回来可能要花更多时间. 这时候我可能会说不如重建整个项目, 然后把整个网页端的架构慢慢掰回来.
这两天, google 公布了新一代的多元模型: Gemma3
. 号称有更好的效能和能子啊单一 cpu / gpu 下部署, 支援 1B, 4B, 12B, 27B.
看到这么牛逼的介绍, 就忍不住去下载来玩一下. 部署方式为 Ollama 最新版本, 由于手头上的机器只有一张 RTX 3080 10G 版本, 所以只能玩玩看 4B 版本. 同时间横比了 阿里的 qwen2.5:3b. 大家可以看看同一个问题的输出结果如何:
请你作为 nodejs 的开发专家, 协助我进行无头部落格系统的开发.
我想使用 express + sqlite + typeorm + typescipt 作为基本框架. 请你列出每一步骤的操作
浅浅的体验了一下, gemma3 输出细节比 qwen2.5 来得仔细一些. 但实际完全跟着步骤去做, 两个模型都需要额外的进行修改才能顺利执行. 那今天的体验就到此为止.
好的,作为 Node.js 开发专家,我很乐意协助你开发无头部落格系统。我们将使用 Express + SQLite + TypeORM + TypeScript 构建这个系统。以下是详细的步骤,并附带一些建议和最佳实践:
**第一阶段:项目初始化与基础配置 (约 2-4 小时)**
1. **创建项目目录:**
bash
mkdir headless-blog
cd headless-blog
2. **初始化 TypeScript 项目:**
bash
npm init -y
npm install --save-dev typescript ts-node @types/node
3. **创建 TypeScript 配置文件 (tsconfig.json):**
bash
npx tsc --init
* **重要配置:**
* `compilerOptions.target`: `ES6` 或更高版本 (推荐 `ES2017` 或更高)
* `compilerOptions.module`: `CommonJS` 或 `ESNext` (推荐 `ESNext` 以支持最新的 TypeScript 功能)
* `compilerOptions.esModuleInterop`: `true` (允许 CommonJS 模块与 TypeScript 模块之间的互操作)
* `compilerOptions.strict`: `true` (启用严格模式,有助于发现潜在的错误)
* `compilerOptions.sourceMap`: `true` (生成 source map 文件,方便调试)
4. **安装依赖:**
bash
npm install express sqlite3 typeorm @types/express @types/sqlite3
5. **创建 `src` 目录:** 用于存放 TypeScript 代码。
bash
mkdir src
6. **创建 `index.ts` 文件 (主文件):** 这是你的 Express 应用的入口点。
typescript
import express, { Request, Response } from 'express';
import sqlite3 from 'sqlite3';
import { DataSource, EntityTarget, Repository } from 'typeorm';
import { Blog, Post } from './entity'; // 导入你的实体
const app = express();
app.use(express.json()); // 允许解析 JSON 请求体
// 配置 TypeORM
const db = new DataSource({
type: 'sqlite',
database: 'database.db', // 数据库文件
synchronize: false, // 生产环境应设置为 false
logging: false,
entities: [Blog, Post],
});
db.initialize().then(() => {
console.log('数据库连接成功');
});
// 路由示例
app.get('/', (req, res) => {
res.send('Hello, Headless Blog!');
});
// 启动服务器
const port = 3000;
app.listen(port, () => {
console.log(`Server listening at http://localhost:${port}`);
});
**第二阶段:数据库模型设计与 TypeORM 配置 (约 2-4 小时)**
1. **定义实体 (Blog 和 Post):** 在 `src/entity` 目录下创建 `Blog.ts` 和 `Post.ts` 文件。
* **Blog.ts:**
typescript
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
@Entity()
export class Blog {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
description: string;
}
* **Post.ts:**
typescript
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from 'typeorm';
import { Blog } from './Blog';
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
content: string;
@Column()
blogId: number;
@ManyToOne(() => Blog, (blog: Blog) => blog.posts)
blog: Blog;
}
2. **配置 TypeORM:** 在 `src/index.ts` 中配置 `DataSource`,指定数据库类型、数据库文件、同步设置等。 `synchronize: false` 非常重要,在生产环境不要启用同步,否则会带来安全风险。
3. **创建数据库文件:** `database.db` (TypeORM 会自动创建这个文件)。
**第三阶段:添加基本 API 路由 (约 4-8 小时)**
1. **创建路由文件 (例如 `src/routes/blogs.ts` 和 `src/routes/posts.ts`)** 将路由逻辑分离可以提高代码可维护性。
2. **实现博客 API 路由:**
* `src/routes/blogs.ts`:
typescript
import { Router } from 'express';
import { Blog } from '../entity/Blog';
import { DataSource } from 'typeorm';
const blogsRouter = Router();
// 创建博客
blogsRouter.post('/', async (req, res) => {
const { name, description } = req.body;
const newBlog = new Blog();
newBlog.name = name;
newBlog.description = description;
const savedBlog = await dataSource.getRepository(Blog).save(newBlog);
res.status(201).json(savedBlog);
});
// 获取所有博客
blogsRouter.get('/', async (req, res) => {
const blogs = await dataSource.getRepository(Blog).find();
res.json(blogs);
});
export { blogsRouter };
3. **实现帖子 API 路由:** 类似地,实现创建和获取帖子的路由。
4. **将路由合并到 `index.ts` 中:**
typescript
import { blogsRouter } from './routes/blogs';
import { postsRouter } from './routes/posts';
import express from 'express';
const app = express();
app.use(express.json());
app.use('/', blogsRouter);
app.use('/', postsRouter);
// ... (其他路由)
**第四阶段:测试与优化 (持续)**
1. **测试 API:** 使用 Postman 或 curl 等工具测试你的 API 路由。
2. **错误处理:** 添加适当的错误处理机制,例如使用 try...catch 块来捕获异常,并返回适当的错误响应。
3. **日志记录:** 使用日志记录库 (例如 Winston) 记录应用程序的活动,方便调试和监控。
4. **代码风格和文档:** 遵循一致的代码风格,并编写清晰的文档。
5. **安全性:** 考虑安全性问题,例如防止 SQL 注入、跨站脚本攻击 (XSS) 等。
**关键注意事项:**
* **TypeScript 的类型安全:** 充分利用 TypeScript 的类型系统,可以减少运行时错误,提高代码可维护性。
* **TypeORM 的 ORM 功能:** TypeORM 提供了强大的 ORM 功能,可以简化数据库操作。
* **异步编程:** 使用 `async/await` 简化异步编程。
* **模块化:** 将代码分解成小的、可重用的模块。
* **版本控制:** 使用 Git 进行版本控制。
**下一步建议:**
* **添加身份验证和授权:** 保护你的 API。
* **添加分页:** 处理大量数据。
* **添加搜索功能:** 允许用户搜索博客和帖子。
* **添加富文本编辑器:** 允许用户创建和编辑帖子内容。
* **部署到云平台:** 例如 Heroku, AWS, Google Cloud。
希望这个详细的步骤列表能帮助你开始开发你的无头博客系统。 祝你开发顺利! 如果你在开发过程中遇到任何问题,随时可以向我提问。
当然,很高兴帮助你构建一个基于 Express、SQLite 和 TypeORM 的无头博客系统。我们将逐步完成这个过程,并确保每个步骤都清晰明了。
### 第一步:安装必要的依赖
首先,你需要在你的开发环境中安装 Node.js 和 npm(Node Package Manager)。然后创建一个新的项目目录并初始化 npm 项目:
bash
mkdir blog-system
cd blog-system
npm init -y
接下来,我们需要安装一些基本的依赖包。我们将使用 `express`、`sqlite3`、`typeorm` 和 `typescript`。
bash
npm install express sqlite3 typeorm typescript --save
### 第二步:设置 TypeScript
为了确保代码质量并提高开发效率,我们首先需要在项目中启用 TypeScript。
1. 创建一个 `.tsconfig.json` 文件:
json
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["src"]
}
2. 创建一个 `tsconfig.json` 文件:
json
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["src"]
}
3. 创建一个 `tsconfig.json` 文件:
json
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"outDir": "./dist"
},
"include": ["src"]
}
### 第三步:设置 SQLite 数据库
我们将使用 `sqlite3` 来管理数据库。首先,创建一个 SQLite 文件:
bash
npm install sqlite3 --save
然后在项目中创建一个 SQLite 数据库文件(例如 `blog.db`)。
### 第四步:配置 TypeORM
TypeORM 是一个 ORM 框架,用于与数据库交互。我们将使用它来管理我们的 SQLite 数据库和实体模型。
1. 创建一个新的 TypeScript 文件 `ormconfig.json`:
json
{
"type": "sqlite",
"database": "./blog.db",
"entities": ["src/entities/*.ts"],
"synchronize": true,
"logging": false
}
2. 在项目中创建一个 `typeorm.config.ts` 文件来配置 TypeORM:
typescript
import { DataSource } from 'typeorm';
export const AppDataSource = new DataSource({
type: 'sqlite',
database: './blog.db',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
});
3. 在 `src` 目录下创建一个 `entities` 文件夹,并在其中创建一些基本的实体模型文件(例如 `Post.ts`)。
typescript
import { Entity, Column } from 'typeorm';
@Entity()
export class Post {
@Column({ primary: true })
id: number;
@Column()
title: string;
@Column()
content: string;
}
### 第五步:设置 Express 应用
我们将使用 `express` 来创建我们的服务器。
1. 创建一个新的 TypeScript 文件 `app.ts`:
typescript
import express from 'express';
import { AppDataSource } from './typeorm.config';
const app = express();
AppDataSource.initialize()
.then(async () => {
console.log('Database initialized!');
})
.catch((err) => {
console.error(err);
});
// 使用 TypeORM 的 Postgres 驱动来查询数据库
import { Post } from './entities';
import { getConnection } from 'typeorm';
app.get('/posts', async (req, res) => {
const posts = await getConnection().getRepository(Post).find();
res.json(posts);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
### 第六步:创建路由和控制器
我们将为我们的博客系统添加一些基本的路由。
1. 在 `src` 目录下创建一个 `controllers` 文件夹,并在其中创建一个新的 TypeScript 文件 `posts.controller.ts`:
typescript
import { Controller, Get } from '@nestjs/common';
import { AppDataSource } from '../typeorm.config';
@Controller('posts')
export class PostsController {
constructor(private readonly postsService: PostsService) {}
@Get()
async findAll(): Promise<Post[]> {
return await this.postsService.findAll();
}
}
2. 创建一个新的 TypeScript 文件 `posts.service.ts`:
typescript
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Post } from './entities/post.entity';
@Injectable()
export class PostsService {
constructor(
@InjectRepository(Post)
private readonly postsRepository: Repository<Post>,
) {}
async findAll(): Promise<Post[]> {
return await this.postsRepository.find();
}
}
### 第七步:运行应用
现在,你可以通过以下命令启动你的服务器:
bash
npm run start
这将启动一个简单的 Express 应用,并连接到 SQLite 数据库。你可以在浏览器中访问 `http://localhost:3000/posts` 来查看所有帖子。
### 第八步:扩展功能
根据你的需求,你可以继续添加更多的路由、控制器和实体模型来扩展你的博客系统。例如:
- 添加用户管理
- 添加评论功能
- 添加文章分类
- 添加搜索功能等
希望这些步骤能帮助你开始构建你的无头博客系统!如果有任何问题或需要进一步的帮助,请随时提问。
简单探讨生产环境中, 是否应该使用 container 容器.
通常情况下, 服务器并不会只运行单一的服务. 但有的时候想要部署不同服务会因为环境依赖的冲突或不支持, 又或者被繁杂的设定搞得头昏眼花. 身为懒惰的程序猿, 我会选择使用 container 来简化我的部署作业.
首先最烦人的, 是不同作业系统之间的不相容. 比如 windows <> *nix 系统之间的一些小问题如大小写敏感, 档案路径等等. 另外就是一些项目的依赖只存在某个作业系统的问题. 这种情况下我更宁愿牺牲一丢丢的服务器效能, 生成一个可用的容器来部署我的项目. 再来就是保持服务器的环境干净, 不会因为安装太多的依赖而导致出现一些奇奇怪怪的问题.
优点:
缺点:
使用 container容器 作为生产环境我认为是可行的, 但要考虑应用程序的量级. 如果量级太大(比如每分钟超百万请求)也许 K8s 群集可能会更适合.