likes
comments
collection
share

用真心打造一个沉淀知识的工具,为学渣如我的道友们,提供助力

作者站长头像
站长
· 阅读数 13

学的快,忘得快,我要总结原因

没有第一时间的沉淀经验

编程是个经验活,搬砖能有多难么?但是不运用经验,那会相当累,这是肯定的,就算你曾经做过的功能,过一阵不用再捡起来,可能跟没做过差不多,而且往往还不如没做过,零星的记忆反而会让你麻痹大意,放弃了思考,从而陷入泥潭,所以经验的沉淀是相当重要的,对于我们这个工种。

学的多,但是不成系统

见到啥学啥,本身没什么错,这是一种积累能量的办法,只不过,这些零散的能量如果不能及时内化形成自身实力,那么就会原模原样的还回去,风过无痕,所以一定要构筑自己的知识体系,这样便可以将知识网住。

学习漫无目的,没有方向

学习没有目标,学一个东西,没坚持几天,又去学别的了,总是东一榔头西一棒槌,最后到头来一场空,样样学,样样瘟,问题出在哪?就出在你没有方向,你迷了,要“正”过来,所以需要时刻提醒自己,你的方向是啥,结硬寨打呆仗。

说说我的解决方案

要有文章,但不能全是文章

首先肯定要有文章,但要全是文章的话,那直接做个静态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用下来,我最钟意的几点就是:

  • 有插件系统:对应了上面的rehypePluginsremarkPlugins参数。

    • rehype?是啥:有了ta,你在Markdown里就能写html了
    • remark?是啥:有了ta,你就能用更多的标签
    • 有了rehype,remark才能生效。
  • 可以定制组件:对应了components参数。

    • 比如你在Markdown文档中写了一个

      # 测试文档
      <dddd></dddd>
      
    • 然后在components配置一下dddd

      用真心打造一个沉淀知识的工具,为学渣如我的道友们,提供助力
    • 效果:

      用真心打造一个沉淀知识的工具,为学渣如我的道友们,提供助力

所以说,靠react-markdown这两手儿,能玩出花儿~

这块非常有趣,我会写一篇好好说说~~~

生成知识体系

知识体系的呈现

使用的是Antv中一个示例,由于颜值高,而且还比较符合我的需求,就直接拿来用了,这里不展开说,先聊聊驱动显示的数据结构吧。

用真心打造一个沉淀知识的工具,为学渣如我的道友们,提供助力

能够看出,存在edgesnodes两个数据,顾名思义,一个是边一个是节点。

用真心打造一个沉淀知识的工具,为学渣如我的道友们,提供助力

但是这么多数据,如果考手敲,那可有的维护了,文章有变动,我就得同步修改知识体系,这简直无法接受,如果能够根据众多文章本身,分析出来知识体系,岂不是妙哉~

根据现有文章,生成知识体系数据

  • 在文章中,我加入自定义标签 用真心打造一个沉淀知识的工具,为学渣如我的道友们,提供助力

    参数分别是:

    • 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,这就启动了整个部署过程了。
  • 宝塔,你懂的,贼好用

    用真心打造一个沉淀知识的工具,为学渣如我的道友们,提供助力

    可以很方便整很多事儿,比如:

    • 部署网站
    • 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,结识一帮志同道合的伙伴,交流技术,欢迎水群,共同进步。

题外话

虽然总是保持上进,但却时常患得患失,感觉自己会的多了,就越发的觉得自己弱爆了,虽然这很合理,但这不应是停止进步的理由,停下来可以有很多种理由,但不应该是因为见识到了大,就因自己的小而停下来,如果一个人发出的光,让你睁不开眼睛,无法正视前方的路,那就别看,正经儿的光是会让你振奋,会给予你能量,而且也不妨再天真一点,这样也许你就可以做你自己了,而只有自己能让自己放光,至少我是这么觉得的。