用真心打造一个沉淀知识的工具,为学渣如我的道友们,提供助力
学的快,忘得快,我要总结原因
没有第一时间的沉淀经验
编程是个经验活,搬砖能有多难么?但是不运用经验,那会相当累,这是肯定的,就算你曾经做过的功能,过一阵不用再捡起来,可能跟没做过差不多,而且往往还不如没做过,零星的记忆反而会让你麻痹大意,放弃了思考,从而陷入泥潭,所以经验的沉淀是相当重要的,对于我们这个工种。
学的多,但是不成系统
见到啥学啥,本身没什么错,这是一种积累能量的办法,只不过,这些零散的能量如果不能及时内化形成自身实力,那么就会原模原样的还回去,风过无痕,所以一定要构筑自己的知识体系,这样便可以将知识网住。
学习漫无目的,没有方向
学习没有目标,学一个东西,没坚持几天,又去学别的了,总是东一榔头西一棒槌,最后到头来一场空,样样学,样样瘟,问题出在哪?就出在你没有方向,你迷了,要“正”过来,所以需要时刻提醒自己,你的方向是啥,结硬寨打呆仗。
说说我的解决方案
要有文章,但不能全是文章
首先肯定要有文章,但要全是文章的话,那直接做个静态Blog得了,不能是静止的东西,要“活”的,而且文章太线性了,知识是存在脑子里的,是线性的?我觉得更应该是立体发散的知识网才对。
成果展示:
要有知识体系,并且是自动生成的
要有一个知识体系,一个基于众多经验文章生成的,具象化的网,文章目录将脑海里发散的知识点串成了线,而知识体系需要采用一种非线性的方式,来把知识网表达出来。
成果展示:
em~~~这不是我心里的样子,我就是在antv上的多看了一眼,就选ta试试,颜值真不错。
文章和知识体系进行关联
众多文章就如同物质,生发出来了知识体系,二者互为表里,相互关联,通过不断更新调整这个知识体系,不断的将脑海里的知识投射出来并具像化,方便推敲,又利于记忆。
成果展示:
可以在线编写代码块,并且可以预览
在描述一段代码的功用时,光用文字就会显得很苍白,相比之下,直接可以运行并能预览效果就显得更直观,整一个可以在线代码预览工具,就变得很有必要。
成果展示:
要有成果展示,要学以致用
光学不出成果,肯定不行,要知行合一,真刀真枪的干,同时又能加强成就感,也是一个正向反馈,激励自己继续努力。
成果展示:
制定计划,并记录进步情况
我们在修行的时候,需要制定目标,在实现这个目标的时候,可能还需要制定其他目标,这样时间跨度就会拉长,那么初心可能真就容易忘了,所以你需要知道自己从哪来,这样你才能知道你接下来要去哪,可能有些豪言壮语没做成,也许就是忘了你要干嘛了,所以我们需要把目标管理起来。
效果图:
还在开发中,构思怎么做好~~~
技术栈
首先项目是用React写的,组件库用的Mui。
选React的原因:我喜欢React,JS浓度大,不用总翻api,现有的api组合就能搞大部分的业务,越写越灵活。
选Mui的原因:首先我有调整样式的需求,Mui
本身就推崇css in js
,主题设置这块相当强,能够很轻松的把控方方面面的表现细节,这对于一个有视觉需求的项目,非常有用。
接下来,概览一下,项目关键功能都是咋做的,具体实现细节后续我会单写文章深入说。
文章呈现
文章要采用markdown格式,所以我选择了react-markdown
这个库,这个库超强的。
使用方式
大体如下
import ReactMarkdown from 'react-markdown'
import rehypeRaw from 'rehype-raw'
import rehypeComponents from './plugins/rehype-components'
import codeBlock from "./codeBlock";
...
<ReactMarkdown
children={md} // md就是你传入的md文档内容
rehypePlugins={[rehypeRaw]}
remarkPlugins={[gfm]}
components={{ ...codeBlock(rest) }}
/>
...
react-markdown
用下来,我最钟意的几点就是:
-
有插件系统:对应了上面的
rehypePlugins
和remarkPlugins
参数。- rehype?是啥:有了ta,你在Markdown里就能写html了
- remark?是啥:有了ta,你就能用更多的标签。
- 有了rehype,remark才能生效。
-
可以定制组件:对应了components参数。
-
比如你在Markdown文档中写了一个
# 测试文档 <dddd></dddd>
-
然后在
components
配置一下dddd
-
效果:
-
所以说,靠react-markdown
这两手儿,能玩出花儿~
这块非常有趣,我会写一篇好好说说~~~
生成知识体系
知识体系的呈现
使用的是Antv中一个示例,由于颜值高,而且还比较符合我的需求,就直接拿来用了,这里不展开说,先聊聊驱动显示的数据结构吧。
能够看出,存在edges
和nodes
两个数据,顾名思义,一个是边一个是节点。
但是这么多数据,如果考手敲,那可有的维护了,文章有变动,我就得同步修改知识体系,这简直无法接受,如果能够根据众多文章本身,分析出来知识体系,岂不是妙哉~
根据现有文章,生成知识体系数据
-
在文章中,我加入自定义标签
参数分别是:
- title:文章标题
- cover:文章封面
- subhead:副标题
- date:文章创建日期
- tags:分类,这个可是生成知识体系的关键
-
然后,在服务端,对文章内容进行解析,用正则表达式取得相关信息
const parseDoc = async (path, id) => { var text = ""; let toReadFile = () => { return new Promise((res, req) => { fs.readFile(path, (err, data) => { text = data.toString(); res("异步"); }); }); }; await toReadFile(); // 先截取 describe 优化后面 匹配性能 let describe = text.match(/<describe>([\d\D]*?)<\/describe>/)[1]; let title = describe.match(/title:\s*(.*?)\s*\n/)[1]; let subhead = describe.match(/subhead:\s*(.*?)\s*\n/)[1]; let cover = describe.match(/cover:\s*(\S*?)\s*\n/)[1]; let date = describe.match(/date:\s*(.*?)\n/)[1]; let tags0 = describe.match(/tags:\s*(\S*?)\s*\n/)?.[1]; let desJson = { title, subhead, cover, date, tags: [tags0], }; return desJson; };
然后就会根据这些信息,去生成知识体系,这块设计了不少环节,非常值得拿出来好好讲,这里先不展开说。
在线代码块预览
跟着大佬的思路,做出了我的版本:
-
一个可以后台动态配置代码块的。
配置数据,如下const describe = { title: "React Router v6 demo", cover: "r6.png", subhead: "辅助强化 React-router v6 的功能", date: "2022/4/2", tags: "react" } const getReactCode = () => { let a = `const { useRoutes, useNavigate, MemoryRouter: Rouer } = ReactRouterDOM const { Button } = antd const LoginPage = () => { const navigateTo = useNavigate() return ( <div> <div >React Router v6 Demo</div> <div> <Button type="primary" onClick={() => { navigateTo('center') }} > 跳回 </Button> </div> </div> ) } const CenterPage = () => { const navigateTo = useNavigate() return ( <div> <div>includes useRoutes and useNavigate api</div> <div> <Button type="primary" onClick={() => { navigateTo('/') }} > 跳转 </Button> </div> </div> ) } const App = () => { const Routes = () => { return useRoutes([ { path: '/', element: <LoginPage /> }, { path: '/center', element: <CenterPage /> } ]) } return <Routes></Routes> } const Index = () => { return ( <Rouer> <App /> </Rouer> ) } ReactDOM.render( <h1> <div className={'title'} >Hello Moderate, let's play!</div> <Index /> </h1>, document.getElementById('root') )`; return a; }; const config = { describe, template: { js: getReactCode(), css: `.title{ color: red; font-weight:bold; font-size:50px; }`, html: `<div id="root"></div>`, }, resources: { css: [ { name: "antd-css", url: "https://cdn.bootcdn.net/ajax/libs/antd/4.19.4/antd.css", }, ], js: [ { name: "React", url: "https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js", }, { name: "react-dom", url: "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js", }, { name: "history", url: "https://cdnjs.cloudflare.com/ajax/libs/history/5.3.0/history.production.min.js", }, { name: "react-router", url: "https://cdnjs.cloudflare.com/ajax/libs/react-router/6.0.1/react-router.production.min.js", }, { name: "react-router-dom", url: "https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/6.0.1/react-router-dom.production.min.js", }, { name: "antd", url: "https://cdnjs.cloudflare.com/ajax/libs/antd/4.23.5/antd.min.js", }, ], }, }; module.exports = config
-
一个可以前端展示所有代码块的。
-
一个可以良好显示,兼容手机和pc两端的。
而且更有趣的是,我可以在md文档插入代码块,这样就可以在阅读文章的同时,还能直观的预览代码的效果,这样对代码的意图会有更直观的理解。
而且自己实现的代码编辑工具,虽然在技术力不足以跟专业的比较,但是在满足基本的功能之外,可以很大程度上根据自己的想法去做演化,这块是可以玩出花儿的~,这块非常值得细说,这里就先不展开讲。
运维devops和自动化ci/cd
有必要学学运维了
首先这个项目是需要部署到服务器上的,而且还是前后端分离的项目,为此就需要有一些运维的知识,笔者不才,略懂皮毛,仅仅是为了实现我的几个需求:
- 部署我的服务端项目,用Nodejs写的,框架是koa,数据是mongodb。
- 部署我的前端项目
- 前后端分离,解决跨域问题
- https
- 域名
- 服务器
- ....
运维真的好多事,经过一系列的折腾,我整理出了一套非常适合新手如我的运维解决方案:
-
docker启动服务程序,并配置
docker-compose
,串联起项目及数据库等相关服务的部署流程。(不会?我也不咋会,面向百度,主要能实现功能就好了,先跑起来再说)-
配置docker,简单理解根据这个文件就能把项目构建成一个镜像。
FROM node:14 WORKDIR /app COPY . /app # 构建镜像时,一般用于做一些系统配置,安装必备的软件。可以多个run RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone #安装 RUN npm set registry https://registry.npm.taobao.org RUN npm install RUN npm install pm2 -g # CMD 启动容器 只能有一个 CMD (阻塞控制台) CMD echo $SERVER_NAME && echo $AUTHOR_NAME && npm run prd && pm2 log # 环境变量 ENV SERVER_NAME="moderate-server" ENV AUTHOR_NAME="qanglee"
-
配置docker-compose,可以简单理解为,一个个镜像代表了对应的服务程序,docker-compose把这些镜像加载过程串联了起来。
version: '3' services: moderate-server: build: context: . dockerfile: dockerfile image: moderate-server container_name: moderate-server volumes: - '/home/play/projects/myUniverse:/myUniverse' # 数据持久化 - '/home/play/projects/myUniverse/docs:/docs' # 数据持久化 ports: - 3061:3060 moderate-redis: image: redis container_name: moderate-redis ports: - 6378:6379 environment: - TZ=Asia/Shanghai moderate-mongo: image: mongo # 引用官网 mongo 镜像 container_name: moderate-mongo restart: always volumes: - '.docker-volumes/mongo/data:/data/db' # 数据持久化 environment: - MONGO_INITDB_ROOT_USERNAME=。。。 - MONGO_INITDB_ROOT_PASSWORD=。。。 - TZ=Asia/Shanghai # 设置时区 ports: - '27016:27017' # 宿主机可以用 127.0.0.1:27016 即可连接容器中的数据库
- 执行
docker-compose up -d --build
,这就启动了整个部署过程了。
-
配置docker,简单理解根据这个文件就能把项目构建成一个镜像。
-
宝塔,你懂的,贼好用
可以很方便整很多事儿,比如:
- 部署网站
- https证书
- 通过
nginx
反向代理解决跨域问题 - 域名绑定
- ...
github actions实现自动化部署,这功能可是相当重要
首先我们构建的知识体系,如果无法实现全自动的去演化,而是通过手动的去增增减减,修修补补,那么积极性很容易在如此枯燥的过程中消磨掉,所以:
一个可以把主要精力关注在沉淀经验知识上,省去枯燥费神的维护过程的方法,就变得非常关键。
那么github actions就可以轻松办到,仅仅通过配置一个文件,就能实现仅仅push文件内容到github,就能全自动的服务构建,非常的方便。
配置如下,有兴趣可以看看。# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
# github actions 中文文档 https://docs.github.com/cn/actions/getting-started-with-github-actions
name: deploy for main
on:
push:
branches:
- 'main' # 只针对 dev 分支
paths:
- '.github/workflows/*'
- 'src/**'
- 'Dockerfile'
- 'docker-compose.yml'
- 'bin/*'
- 'docs/*'
- 'config/*'
- 'records/*'
jobs:
deploy-dev:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: set ssh key # 临时设置 ssh key
run: |
mkdir -p ~/.ssh/
echo "${{secrets.MODERATE_SSH_KEY_PC}}" > ~/.ssh/id_rsa # secret 在这里配置 https://github.com/imooc-lego/biz-editor-server/settings/secrets
chmod 600 ~/.ssh/id_rsa
ssh-keyscan "你的服务ip" >> ~/.ssh/known_hosts
- name: deploy # 部署
run: |
ssh root@你的服务ip "
cd /projects/moderate-server;
git checkout dev
git pull;
yarn;
docker-compose up -d --build
"
- name: delete ssh key # 删除 ssh key
run: rm -rf ~/.ssh/id_rsa
这样提交完之后,就会触发github actions
搞运维遇到的坑可老多了,这一块实际上还有很多值得探索和分享的经验,以后可以单读写一下排坑记录,在此就先不展开说了~~~
成果展示
效果图:
制定作战计划,记录成长点滴
这个是我当下在思考的功能模块,哈哈哈,苦于自己的想法太多,很多点子没想好怎么组织起来,但大体的思路,就是记录自己的成长轨迹,因为我觉得:
不念过去,不见未来
不记住自己的过往,不反思,不总结,不接受,那么你又怎么看的见自己的未来,找到前进的方向。
所以,基于我的感悟,我觉得人应该制定目标,并把目标裱起来,时刻的提醒自己,我在做什么,我做完了什么,我要做什么。
所以,我画出了这个原型图。
上方的点图跟github类似,记录自己进步的情况,很好的感知自己的学习周期。
任务分为:
- 主题任务:当下的奋斗目标,可以适机切换,一点一点前进。
- 持续任务:天天都要做的,不能间断的,比如修身齐家,学英语啥的。
- 娱乐任务:非功利的,兴趣使然的,不求回报的。
结尾
至此,用真心打造的知识沉淀工具,就差不多介绍到这里了,之后我会挑出几个我觉得有价值,能帮到别人的功能点进行深入分享,敬请期待。
有问题可以随时咨询我,或者留言,我有个群叫闲D岛,群号是551406017,结识一帮志同道合的伙伴,交流技术,欢迎水群,共同进步。
题外话
虽然总是保持上进,但却时常患得患失,感觉自己会的多了,就越发的觉得自己弱爆了,虽然这很合理,但这不应是停止进步的理由,停下来可以有很多种理由,但不应该是因为见识到了大,就因自己的小而停下来,如果一个人发出的光,让你睁不开眼睛,无法正视前方的路,那就别看,正经儿的光是会让你振奋,会给予你能量,而且也不妨再天真一点,这样也许你就可以做你自己了,而只有自己能让自己放光,至少我是这么觉得的。