规格驱动开发

我花了一下午让 Claude Code 遵循"规格驱动开发",结果出乎意料 本文由 Claude Code 基于我与她的真实开发对话总结撰写,所有数据和引用均来自公开研究。 先说结论 Vibe coding 不是坏习惯,它就是 AI 编程的默认形态,而且会越来越普及。 看看趋势:GitHub 说 2026 年 41% 的代码是 AI 生成的;RedMonk 预测这个比例还会涨。未来产品经理、设计师都能用自然语言写代码,专业程序员会变少,但编程的总量会爆炸。 所以 SDD(Spec-Driven Development)的定位不是"取代 vibe coding",而是让 vibe coding 更可控。就像开车:自动挡让驾驶变简单,但学会看路、懂交规才能开得好。 简单任务——内部工具、原型、个人项目——纯 vibe coding 够用 复杂任务——生产系统、团队协作、长期维护——SDD 能帮你少踩坑 ...

2026年3月1日 · 4 分钟 · 佘炜帆

如何在webpack中同时使用element v1和v2

背景介绍 “webpack”: “^1.13.2”, “element-ui”: “^1.4.11”, n年前的项目 超过200个路由无法升级 v1部分功能老旧,希望在需要的时候可以使用v2的功能 代码实现 compatibleElementV2.js module.exports = function (source) { return source.replace(/element-ui\//g, "element-v2/"); }; webpack.config.js module.exports = { ... module: { loaders: [ { test: /\.(js|vue)(\?.*$|$)/, include: /node_modules\/element-v2/, loader: path.resolve(__dirname, "./compatibleElementV2.js") }, ] }, ... resolve: { alias: { "element-v2": path.resolve(__dirname, './node_modules/element-v2'), } } ... }; package.json { ... "dependencies": { ... "element-v2": "npm:element-ui@2.15", } ... } 测试代码(官方demo) <template> <div> <el-table :data="tableData" :span-method="arraySpanMethod" border style="width: 100%"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="name" label="姓名"> </el-table-column> <el-table-column prop="amount1" sortable label="数值 1"> </el-table-column> <el-table-column prop="amount2" sortable label="数值 2"> </el-table-column> <el-table-column prop="amount3" sortable label="数值 3"> </el-table-column> </el-table> <el-table :data="tableData" :span-method="objectSpanMethod" border style="width: 100%; margin-top: 20px"> <el-table-column prop="id" label="ID" width="180"> </el-table-column> <el-table-column prop="name" label="姓名"> </el-table-column> <el-table-column prop="amount1" label="数值 1(元)"> </el-table-column> <el-table-column prop="amount2" label="数值 2(元)"> </el-table-column> <el-table-column prop="amount3" label="数值 3(元)"> </el-table-column> </el-table> </div> </template> <script> export default { data() { return { tableData: [{ id: '12987122', name: '王小虎', amount1: '234', amount2: '3.2', amount3: 10 }, { id: '12987123', name: '王小虎', amount1: '165', amount2: '4.43', amount3: 12 }, { id: '12987124', name: '王小虎', amount1: '324', amount2: '1.9', amount3: 9 }, { id: '12987125', name: '王小虎', amount1: '621', amount2: '2.2', amount3: 17 }, { id: '12987126', name: '王小虎', amount1: '539', amount2: '4.1', amount3: 15 }] }; }, methods: { arraySpanMethod({ row, column, rowIndex, columnIndex }) { if (rowIndex % 2 === 0) { if (columnIndex === 0) { return [1, 2]; } else if (columnIndex === 1) { return [0, 0]; } } }, objectSpanMethod({ row, column, rowIndex, columnIndex }) { if (columnIndex === 0) { if (rowIndex % 2 === 0) { return { rowspan: 2, colspan: 1 }; } else { return { rowspan: 0, colspan: 0 }; } } } } }; </script> 测试:

2023年8月24日 · 2 分钟 · 佘炜帆

azure openai如何做流式输出(打字效果)

区别 openai和azure openai最大的区别就是不需要科学上网,且据azure openai代理商介绍,微软在国内已经完成了合规化备案,只要不上传用户数据,无需担心法律问题。 如何从openai 切换到 azure openai 调用方式不同(基于npm仓 openai@3.3.0) azure版本的api不再需要在调用时传入OPENAI_API_KEY,而是在请求中带在header里 basePath也需要根据新建的EndPoint(终结点)以及Studio中新建的model(模型)来决定,大致是${EndPoint}openai/deployments/${modelName} 以axios为例 const { Configuration, OpenAIApi } = require('openai') const axios = require('axios') const http = axios.create({ headers: { 'api-key': process.env.OPENAI_API_KEY }, params: { 'api-version': '2023-05-15' } }) const OPENAI_BASE_PATH = `${EndPoint}openai/deployments/${modelName}` const openai = new OpenAIApi(undefined, OPENAI_BASE_PATH, http) module.exports = openai stream流区别 由于azure的接口目前虽然支持stream的参数,但是返回的时候不想openai那样,而是卡顿一会,一次返回一大段,而且输出格式也很奇葩,流是中断的 如图,返回的数据格式化后是数组,且JSON.parse报错,原因是数据最后一段数据可能需要下一个数组的第一段数据合并后才算完整的JSON string… 解决办法,拼接流 const handleStream = (completion, stream) => { let cache = Buffer.from('') let preSend = '' completion.data.on('data', data => { cache = Buffer.concat([cache, data]) const lines = cache ?.toString() ?.split('\n') .filter(line => line.trim() !== '') let result = '' let isEnd = false for (const line of lines) { const message = line .toString() .trim() .replace(/^data: /, '') // 流结束 if (message === '[DONE]') { console.log('流结束') // stream.end() isEnd = true // return } // 解析数据 try { const parsed = JSON.parse(message) // 打印有效内容 // console.log('=>', parsed.choices[0].delta) if (parsed.choices[0].delta && parsed.choices[0].delta.content) { result += parsed.choices[0].delta.content } } catch (e) { console.log(`e`, e) } } result && stream.write(result.replace(preSend, '')) isEnd && stream.end() preSend = result }) } handleStream(completion, stream)

2023年7月2日 · 1 分钟 · 佘炜帆

SSR 如何做状态透传

Node.js的domain API可以用于处理异步操作中的错误,避免因为一个未处理的错误导致整个进程崩溃。以下是一些常用的domain API: domain.create():创建一个新的域。 domain.run(fn):在当前域的上下文中运行给定的函数。 domain.add(emitter):将事件发射器添加到当前域中。 domain.remove(emitter):从当前域中删除事件发射器。 domain.bind(callback):返回一个函数,在调用时将其参数绑定到当前域。 domain.intercept(callback):返回一个函数,在调用时将其参数绑定到当前域,并且任何错误都会被捕获并传递给提供的回调函数。 domain.enter():将当前域设置为活动域。 domain.exit():将当前域恢复为先前的活动域。 使用domain API的示例: const domain = require('domain'); const server = require('http').createServer(); const express = require('express'); const app = express(); server.on('request', app); // 创建一个新的域 const d = domain.create(); // 捕获服务器异常 d.on('error', err => { console.error(err.stack); }); // 将服务器套接字添加到域中 d.add(server); // 在域的上下文中运行服务器 d.run(() => { server.listen(3000); }); 在以上示例中,domain.create()创建了一个新的域。通过将服务器套接字添加到该域中,可以捕获服务器发生的异常,避免因为未处理的异常导致整个进程崩溃。使用domain.run()函数在当前域的上下文中运行代码,保证任何异步操作都在该域中执行,从而捕获所有的错误。

2023年2月2日 · 1 分钟 · 佘炜帆

微信小程序如何捕获返回

需求背景 在开发过程中,总会有需求是在用户返回前做一些事情,而目前小程序提供的并没有直接支持,需要点奇淫巧技才可以。 解决方案 利用page-component的bind:beforeleave来捕获到页面返回。整体思路: ...

2022年12月7日 · 1 分钟 · 佘炜帆

webpack1 升级到 webpack5

项目背景 一个五年持续迭代但是构建没有升级过的项目,页面多达265个。用vue-cli1开出来的项目,基于webpack1,新增插件基本无法兼容。构建速度持续递增。 优化结果 时间统计于统一配置下的容器内打包 | |首次|第二次无修改|第二次路由页面修改| |—-|—-|—-| |webpack1|6 分 7 秒|4 分 0 秒|3 分 56 秒| |webpack5|1 分 57 秒|13 秒| 57 秒| ...

2022年2月28日 · 1 分钟 · 佘炜帆

用webview快速构建小程序

背景 一开始产品找我的时候,说需求很简单,「要把常规业务的完整流程搬上小程序」,我第一时间想到的是套webview,实现一个原生小程序只是时间问题,我担心的是后续版本都需要改两套代码。这不是我的风格。加上所在业务本身就运行在多端,微信/浏览器/APPx3,本身bridge底子好,所以如果能实现一套类似native app的小程序壳,业务兼容小程序并不是很难。而且我对这个小程序业务上有更多的展望,后面会说到。 ...

2020年11月7日 · 1 分钟 · 佘炜帆

webpack 文件内联

背景 日常开发过程中很多 html 文件只有短短几行 html。而一些细碎的 css,js 引用造成首屏请求数过多。 希望有一个机制来把这些细碎文件内联进 html。 搜索了 webpack 拓展库并没有插件很好的匹配当前的需求,所以需要自己写 plugin。 需求 自动的对 webpack 打包出来的文件做内联,通过传入最大内联尺寸来限制。 另外可以通过传入其他非打包文件,这些文件需要跳过最大内联尺寸限制。 ...

2020年5月5日 · 1 分钟 · 佘炜帆

如何避免线上显示vconsole

问题背景 在现在普遍前端工程化环境下,有时候会使用vconsole来作为移动端调试的工具,但在上线前忘记注释掉vconsole等原因,导致线上显示出vconsole的问题,在看到OA的第n个关于vconsole线上显示的事故报告之后,我觉得应该要有一种手段来自动化的做这样一件事。 改进构建 解决方向很显然从构建入手。 ...

2019年6月7日 · 1 分钟 · 佘炜帆

ssr-内部分享

首屏 ...

2019年2月7日 · 1 分钟 · 佘炜帆