mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
5499 字
14 分钟
我的技术博客之路
2020-12-12

打开一个写了半年的技术文档,发现之前的思路已经完全想不起来了。翻遍笔记,只找到几个零散的关键词,无法还原当时的推理过程。这种”学了就忘”的困境,是很多技术人开始写博客的起点。我也曾以为只要理解了就能记住,但跨领域知识越来越多之后,零碎的记忆根本撑不起复杂的推理链。写博客不是为了”教别人”,而是为了”救自己”——把知识从短期记忆固化到长期记忆,把模糊的直觉变成经得起推敲的文字。

一、写作工具的选择#

正所谓,磨刀不误砍柴工。为了让自己有更好的写作体验,让读者有更好的阅读体验,我考察了很多写作平台和工具。在自己写作的过程中也总结了很多需求,这包括且不限于:

  • 轻松嵌入多媒体的能力(图片、视频、PPT 等)
  • 文章分类管理和查看的能力(分类、标签、时间线、系列等)
  • SEO(Search Engine Optimization)、站点地图、RSS(Really Simple Syndication) 订阅等
  • 多平台发布的能力(简书、语雀、掘金、思否、公众号、博客园、CSDN 等)
  • 博客主题(主要包括配色、字体、大小)
  • 多语言支持

可惜的是目前并不存在满足以上所有要求且能开箱即用的产品,并且我个人认为与其把个人创作完全放在互联网上,放在本地更让人放心。幸运的是目前存在很多静态站点生成器和博客相关的主题,利用这些工具使得能以较低的成本在本地管理自己产出的文章。

  • 在服务器方面,为了降低站点维护成本,我使用了 GitHub Page,因为目前它完全能满足我的需求。
  • 在编写格式方面,我采用了 Markdown 的格式,它兼顾了低学习成本和高度的灵活性。图片则通过 PicGo 存在云端(目前我考虑是否用 base64 编码的图片直接嵌入文章更方便管理,编写时折叠或转码 base64 就行了)。
  • 在编辑器方面,我使用了 VSCode,通过安装相关插件,编码写作两不误。
  • 在站点生成器方面,我选用了 Hugo,因为它速度快,并且有一些不错的主题可以开箱即用。
  • 在站点监控方面,我使用了 Umami,这需要一定的服务器成本,但是即使服务器到期也不会影响文章的加载。
  • 在绘图方面,我主要使用 ExcalidrawProcessOn
  • 在代码分享方面,我主要使用 Carbon,它支持导出图片和嵌入文章。
Info

互联网是开放的,但同时也是私有的。各个互联网厂商为了一定的竞争优势都会建立一条护城河,将城中的资产「保护」起来,即使那资产本就不属于它。

二、一般性写作流程#

写作的一般性流程可以分为以下六步:

  1. 确定主题:为文章确定一个大致范围,比如体系性的技术介绍、疑难杂症的记录和解决、人物传记或技术史话、官方资料的翻译或解读、技术资料的整理或推荐等。
  2. 调研学习和材料积累:这其实就是个信息挖掘和学习的过程,需要注意的是这一步最好利用便签或知识库等工具将平时的灵感或想法记录下来。
  3. 确定大纲:编写前最好明确文章的整体脉络,比如根据思维导图列文章标题等。
  4. 完成主体内容的编写
  5. 审阅、校正和补充:让自己或朋友以读者的角度通读一遍,看是否存在表达不清、描述不当;看是否存在过于啰嗦能用图片替代的地方等。
  6. 发布和迭代:将文章发布到互联网,并且根据内容进行小幅度的修订。

三、写作素材的积累#

写作是一种创造的过程,任何事物都是不可能无中生有的。所以要想「有货」就得多阅读、多实践。具体的实施方案就是建造和管理自己的信息源。信息源从根到叶可以分为以下几类:

  • 官方文档:在学习任何技术之前,最好先知道技术的来源。官方文档的撰写者一般都是该技术的创始人或者直接维护者,他们提供一门技术最权威的资料。但是我们无法确保他们的写作水平,所以一般还会阅读其它资料进行学习。
  • 经典作品(书籍、论文、文章等):经典作品也就是大部分人都认同的作品,专业性与阅读体验都比较上乘,比较适合深入阅读。
  • 博客、知识问答平台:技术博主写的文章,实时性较高,但质量参差不齐,更容易进行接触,平时利用碎片化的时间也能进行阅读。

拥有自己优质的信息源后,需要用一种高效的方法对其进行食用和消化:

  • 分清主次
    • 官方文档和经典作品可以进行深度阅读,表述不清或理解不到位的地方再在互联网上查询相关资料进行比对浏览。
    • 跳过不必要阅读的部分,比如文章中的部分案例与例子,已经非常熟悉的基础知识等。
  • 学会联想:把自己已知的事物和阅读材料联系起来,这样既能回顾一遍之前的内容,还能触类旁通,打开思路。
  • 随时记录:在阅读时,我们经常会有所想和有所悟,而这些灵感就像梦境一样,是转瞬即逝的,所以需要利用电脑和手机的便签功能,把阅读时的灵感和想法记录下来。

看一本书前,可以对自己提问:

  1. 为什么要看这本书?想要搞清楚什么问题?
  2. 这本书的内容呈现思路和框架是怎样的?
  3. 作者提供了哪些观点,哪些是核心论点,哪些是分论点?
  4. 他是如何阐述自己观点的?论证真的充分可信吗?
  5. 看到这些观点,能不能联想到生活中的场景?
  6. 他用了什么精妙的表现手法?为什么精妙?
  7. 书看完了,最初的疑惑解决了吗?
  8. 以上问题,都记录下来了吗?

四、怎样写出引人入胜的文章#

明确了主题,调研和学习了相当多的素材,有了一个大致的大纲,最后写出来的东西读起来和别人相比还是有一些差距,但又不知道差距具体在哪。我想很多人都经历过这个问题。其实解决这个问题也很简单,就如同优化代码一样,可以对优秀的文章进行解剖学习,扬长避短来迭代自己的文章。

首先,从整体入手,需要了解如何评价一篇文章。可以从以下三点入手:

  • 行文节奏:文字简单干练,段落分明,层层深入,避免冗余的描述。
  • 文字表述:首先保证用词的准确,再进行推敲,用更加形象的辞藻替换冰冷的刻画。
  • 主题刻画:鲜明主题,突出立意。读者通常都是带着目标去进行阅读的。

写一篇好文章,除了用于吸引眼球的标题和摘要,内容质量方面最重要的就是以上三点了,它们直接决定了阅读的感受。

然后在审阅修订时,有几个小技巧:

  1. 对内容先增后减:没解释清楚的概念和细节需要做补充,接着再删除表意重复和冗余的部分。
  2. 查看论据是否得当:论据一般可分为事实论据、道理论据和数据论据。
    • 事实论据和道理论据要经得起推敲,需要和主题呈强关联关系。
    • 数据论据推荐用平均数替代大数或用参照物来解释数据,这样的数据更加形象。然后列举数据论据时不要太频繁,突出关键即可。
  3. 设计好路标:路标可以理解为转场,也就是文章从一部分发展到另一部分的句子或段落。需要在过于跳跃的两个段落间增加路标,并且替代或删除路标中细小而多余的结构(比如人人都知道的常识)。

五、写作的未来趋势#

谈到写作的未来趋势便不得不谈互联网思维开源

自前几年 MOOC 线上教学模式成功之后,使得人们更加关注线上资源了。在质量上,除了无法实时和老师交流之外和线下别无二致(可以通过 email 或者留言交流);在能效比上,只需要一次录制便可以无视地域和时间的限制无数次进行播放。去年的疫情更是加速了这一进程,互联网思维使得线上资源的获取更加广泛和便捷。

开源行为最早是出现在程序员之间,用于互相修改并分享代码用的,但开源行为很明显不仅仅可以用于程序迭代,在写作或者翻译工作中也能很好地套用,比如开源书籍-计算机体系结构-关于本书的在线版本。开源能将一本书的制作、修订与维护变得透明,开源能让一本死书变成一本能快速迭代的活书,开源能使作品更容易得到传播和使用。

依赖合适的计算机写作工具能极大提升写作效率,依赖合适的互联网平台能极大提高传播和迭代效率,依赖类似于 Umami 之类的网站分析器能让你知道读者的分布、数量和热度。这是以前无法想象的事情。数字不会骗人,它让你更加接近真相。

六、技术博客的写作原则#

写技术博客和写学术论文、写新闻稿有本质区别。技术博客的读者是同行或者后辈,他们带着问题来,希望带着答案走。所以在动笔之前,有几条原则值得反复咀嚼。

6.1 面向读者写作#

技术文章不是给自己看的笔记,是给读者看的指南。每写一段话,都要问自己:读者能看懂吗?读者需要什么前置知识?我是否默认了读者知道某些「常识」?

举个常见的反面例子,很多技术文章会这样写:

Info

使用 Redux 管理状态,然后通过 middleware 处理副作用。

这句话对熟悉 React 生态的人来说没问题,但对刚入门的读者来说,“状态管理""副作用""middleware” 都是陌生概念,堆在一起只会让人一头雾水。

更好的做法是分层引入:先说为什么需要状态管理(State Management)(组件间共享数据),再说 Redux 的角色(集中式存储),然后解释 middleware(中间件) 的含义(在 action 到达 reducer 之前插入逻辑)。

6.2 代码先行,概念跟进#

技术文章的核心价值在于可操作性。读者看到一段能跑的代码,比看三段抽象描述更有收获。推荐的结构是:

  1. 先给完整可运行的代码
  2. 逐段解释关键部分
  3. 最后提炼设计思想

反过来,先讲一大堆理论再给代码,读者很可能会在理论部分就流失了。这不是说理论不重要,而是理论需要实践来锚定。没有代码支撑的概念就像没有地基的楼,看着高,站不住。

6.3 一文一事#

一篇技术文章只解决一个问题。如果你发现自己在写 “Vue + TypeScript + Pinia + Vitest 全栈开发指南”,那大概率应该拆成四篇文章。原因很简单:

  • 读者搜索时往往只关注某个具体问题
  • 文章越长,完成度越低,烂尾的概率越高
  • 单一主题的文章更容易被引用和传播

6.4 保持准确,标注时效#

技术文章最怕过时。一个 2020 年写的 Vue 2 教程,到 2025 年可能已经完全不适用了。有几个做法能减缓过时的速度:

  • 在文章开头标注写作日期和所用技术版本
  • 用相对稳定的概念(设计模式、算法原理)代替易变的 API
  • 文章更新后在末尾记录修订历史

七、文章结构模板#

不同类型的技术文章有不同的最佳结构。下面给出几种常见类型的模板。

7.1 教程类#

# 标题:如何在 X 中实现 Y
## 前置条件
- 环境、版本、依赖
## 快速开始
- 最少步骤跑通 Hello World
## 详细步骤
### 步骤一:xxx
### 步骤二:xxx
...
## 常见问题
- 报错 A 怎么办
- 报错 B 怎么办
## 总结

7.2 原理解析类#

# 标题:深入理解 X 的底层原理
## 背景:为什么需要了解这个
## 整体架构:一张图说清楚
## 核心机制一
## 核心机制二
## 实际案例
## 与同类方案对比
## 总结与延伸

7.3 问题解决类#

# 标题:解决 X 场景下的 Y 问题
## 问题描述
- 现象、报错信息
## 排查过程
- 排除法,逐步定位
## 根因分析
- 问题的本质原因
## 解决方案
- 修复步骤
- 验证方法
## 经验总结
- 以后如何避免

7.4 评测对比类#

# 标题:X vs Y:哪个更适合 Z 场景
## 评测维度
## 维度一:性能
## 维度二:易用性
## 维度三:生态
...
## 综合评分
## 选型建议

八、常见写作错误#

写了一年多技术博客后,我总结了一些最常见的写作问题,也经常在别人的文章里看到它们。

8.1 错误一:直接贴代码不解释#

有些文章的代码占了全文 80% 以上,注释几乎没有,解释也寥寥几句。这种文章本质上是一份代码仓库的副本,读者完全可以直接去看源码。代码应该是文章的佐证,不是文章本身。

改进方法:每段代码之前说明它解决什么问题,之后解释关键实现思路。注释写在代码中不容易说清的地方。

8.2 错误二:只说 What 不说 Why#

“在配置文件中添加 strict: true” 这句话告诉了读者做什么,但没说为什么。读者下次遇到类似场景时还是不知道该不该加。

改进方法:每条操作都附带原因。比如:“在配置文件中添加 strict: true,启用严格模式后 TypeScript 会在潜在的类型错误处给出警告,而不是静默通过。这在大型项目中能有效减少运行时错误。“

8.3 错误三:忽略错误处理#

教程类文章经常只写 happy path(正常路径),仿佛一切都会按预期工作。但真实开发中,网络会超时、文件会不存在、权限会不够。只展示成功路径的文章,读者照着做却遇到了错误时就会很沮丧。

改进方法:在关键步骤补充可能的错误场景和应对方法。不需要面面俱到,但至少覆盖最常见的两三种错误。

8.4 错误四:术语不统一#

同一篇文章里一会儿用 “函数”,一会儿用 “方法”,一会儿用 “函数方法”,读者会困惑这到底是同一个东西还是三个不同的概念。

改进方法:在文章第一次出现术语时给出定义,后续统一使用同一个词。如果术语有英文原文,首次出现时标注英文,比如 “闭包(Closure)“。

8.5 错误五:缺乏可操作的结论#

文章写了很长,理论讲了很多,到最后却说 “具体实现因项目而异”。读者花时间看完,却不知道下一步该做什么。

改进方法:结论部分给出明确的行动建议。哪怕只是 “如果你的项目满足 A 条件,推荐方案 X;如果满足 B 条件,推荐方案 Y”,也比一句 “看情况” 有价值得多。

九、审阅清单#

写完初稿后,我一般会用下面这份清单逐项检查。不一定每项都完美,但至少不能有明显遗漏。

9.1 内容层面#

  • 标题是否准确反映了文章内容
  • 前置知识是否已说明
  • 每个概念第一次出现时是否有解释
  • 代码示例是否可以直接运行
  • 是否覆盖了常见的错误场景
  • 结论是否给出了可操作的建议

9.2 结构层面#

  • 文章是否有清晰的层次结构
  • 段落之间是否有合理的过渡
  • 是否存在与主题无关的内容
  • 代码和文字的比例是否合理

9.3 文字层面#

  • 术语是否前后一致
  • 中英文之间是否有空格(如 “使用 React 框架” 而非 “使用React框架”)
  • 是否有错别字和语法错误
  • 长句是否可以拆分
  • 被动语态是否可以改为主动语态

9.4 技术层面#

  • 技术版本和日期是否已标注
  • 链接是否有效
  • 代码是否经过实际测试
  • 是否有安全相关的敏感信息(密钥、密码等)

十、好的技术写作与差的技术写作#

最后,用两个具体的对比来展示差异。

10.1 对比一:介绍 Promise#

差的写法

Info

Promise 是 ES6 引入的异步编程解决方案,它有三种状态:pending、fulfilled、rejected。then 方法接受两个回调函数作为参数,catch 方法用于捕获错误。finally 方法无论成功失败都会执行。

这段话把 API 文档复述了一遍,但读者看完不知道为什么要用 Promise,也不知道什么场景下用。

好的写法

Info

假设你要依次读取三个文件:先读配置文件,再根据配置读数据文件,最后根据数据读日志文件。用回调写出来是三层嵌套,俗称”回调地狱”。Promise 用链式调用把嵌套变成了线性:

readFile('config.json')
  .then(config => readFile(config.dataPath))
  .then(data => readFile(data.logPath))
  .catch(err => console.error('读取失败:', err))

它的原理并不复杂:Promise 代表一个”未来的值”,你可以提前注册这个值成功或失败时的处理逻辑,等到值真正产生时自动触发。

10.2 对比二:解释闭包#

差的写法

Info

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式就是在一个函数内部创建另一个函数。

这个定义是正确的,但读者看完还是不知道闭包能干什么。

好的写法

Info

先看一个场景:你想写一个计数器函数,每次调用返回递增的数字。你可能会想用一个全局变量,但如果需要多个计数器呢?全局变量会互相干扰。

闭包让函数”记住”自己创建时的环境:

function createCounter() {
  let count = 0      // 这个变量对外部不可见
  return function() {
    return ++count   // 但内部函数可以访问它
  }
}

const counterA = createCounter()
const counterB = createCounter()
counterA() // 1
counterA() // 2
counterB() // 1 -- 独立的计数器

count 变量在 createCounter 执行完后本该被销毁,但因为返回的内部函数仍然引用它,所以它”活”了下来。这就是闭包:函数连同它创建时的词法环境(Lexical Environment) 被一并打包保留。

区别在于:好的技术写作从问题出发,用例子建立直觉,再给出原理。差的技术写作从定义出发,堆砌概念,缺少与实际场景的连接。

十一、参考资料#


参考#

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

我的技术博客之路
https://blog.souloss.com/posts/idea/idea-talking-about-writing/
作者
Souloss
发布于
2020-12-12
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时