2

聊聊这个维护了三年的博客

前端 2 946 0
发表于: 2022-08-25 06:54:56

简介: 具代表性的项目之一

前言

时间过得好快,距离博客第一天上线到现在,不知不觉三年了,期间经历了无数的维护、优化以及重构,博客的功能渐渐的完善,用户以及开发体验也不断提升,但是好像从来没有详细的介绍过这个博客,因此,准备好好写一篇文章详细的介绍一下这个博客的所有内容~

经历的变迁

技术栈

  1. 前台技术栈重大变化:vue2 + vuecli + elementui —> nuxt2 + elementui
    https://resource.hsslive.cn/image/1662007497845__IDGR__dfdf.jpg
  2. 后台技术栈重大变化:vue2 + vuecli + vue-element-template —> vue2 + vuecli + iview —> vue2 + webpack5 + iview —> vue3 + webpack5/vite2 + naiveui + typescript
    https://resource.hsslive.cn/image/1662007511376__jn00__23.jpg
  3. 后端技术栈重大变化:node + express + mysql —> node + koa2 + mysql + redis + typescript
    https://resource.hsslive.cn/image/1662007533235__MGiR__sdsd.jpg
  4. ci/cd重大变化:本地构建 —> jenkins构建部署
    https://resource.hsslive.cn/image/1662007559449__47OL__2323.jpg
    https://resource.hsslive.cn/image/1662007573015__pmQ5__jenk.jpg
    https://resource.hsslive.cn/image/1662007583679__qrru__dssd.jpg

细节

  1. 首先最明显的变化是域名变了,博客最初的域名是:zhengbeining.com(如果有老用户的话应该知道),后面域名过期了,就换成了现在的:hsslive.cn
  2. 其次是服务器配置变了,最初是用的阿里云的学生机,配置好像是 1核1g内存,博客最初的时候仅仅打包成是静态页面,而且也只有这一个博客项目,因此学生机也没啥问题;后面随着博客的重构改版,以及部署其他项目的增加,就跟着域名一起统一换成了腾讯云,配置升级成 1核2g内存,后面活动免费升级成了 2核4g内存带宽8m,支撑起了目前线上的所有项目。
  3. 然后这博客也见证了我从学生到社畜hhh

博客简介

线上地址

前台:https://www.hsslive.cn

后台:https://admin.hsslive.cn

后端接口:apifox

github仓库

前台:https://github.com/galaxy-s10/nuxt-blog-client

后台:https://github.com/galaxy-s10/vue3-blog-admin

后端:https://github.com/galaxy-s10/vue3-blog-server

项目截图

前台

主页

https://resource.hsslive.cn/image/1662008424303__NKtJ__gds.jpg

后台

登录(支持qq、github以及邮箱验证码登录)

https://resource.hsslive.cn/image/1662032407712__6Ml7__23.jpg

主页(基本所有的前台的数据都可在后台配置)

https://resource.hsslive.cn/image/1662032418231__8j9e__sff.jpg

后端

启动初始化信息打印:
https://resource.hsslive.cn/image/1662034244771__dXUD__11.jpg

启动成功:
https://resource.hsslive.cn/image/1662034272755__y11N__22.jpg

完善的错误捕获:
https://resource.hsslive.cn/image/1662034208997__34Fv__1662033967402.jpg

学到了什么

大致总结

前台:基于nuxt2

业务层

常量提取

同一个变量,在超过两处地方使用了,就提取成一个常量。更准确的说,同一个变量,在两个以上的文件使用了,就提取成一个常量,统一的放在一个常量文件进行管理,这样不仅方便进行统一修改,而且还方便了代码的可阅读性。

https://resource.hsslive.cn/image/1662040002740__PiMg__555.jpeg

如果上面的变量没有提取成常量,一旦要修改,那么将是噩梦!

组件复用/二次封装

只要是重复性的代码,都根据业务抽离成组件,好处就不用多说了,不仅能打磨自己抽取组件的能力,还能提高后续的开发(搬砖)效率!

博客后台的表单二次封装:
https://resource.hsslive.cn/image/1662040786171__kl6C__333.jpg

添加文章表单:
https://resource.hsslive.cn/image/1662041105879__1n62__444.jpg

二次封装表单,再配合表单配置项抽离,就可以使业务代码的结构更加清晰,而且复用到其他业务的表单也非常方便。

待定?

基建层

给项目添加git信息

如何确定线上的代码是哪个版本?如果是静态页面,你如何能保证你构建部署上线后,线上的页面就是最新的,可能你会在每次构建都在控制台打印一个特殊的东西,你部署上线后,在线上看控制台的打印是不是你最新的打印,根据这个来确定版本,虽然这个方法可行,但是在欠缺优雅,
当下很多项目基本都是基于git做的版本管理,我们可以在每次部署上线的时候,将当前提交的git信息打印到控制台,这样就可以非常优雅的解决这个问题!

以我当前的博客后台为例,我的博客后台是基于webpack搭建的,因此我们可以在webpack构建的时候,借助node的能力读取当前的git信息:

https://resource.hsslive.cn/image/1662042424720__9A6i__642.jpg

然后利用webpack.DefinePlugin将读取到的git信息写入到全局变量里:

https://resource.hsslive.cn/image/1662042584684__h8dc__1662042525093.jpg

然后将打印git信息封装成一个方法,在入口文件引入改方法即可,这样每次在构建的时候,都会读取并且写入git信息为全局变量,我们就可以将他们打印到控制台:

https://resource.hsslive.cn/image/1662042789810__yFuE__1662042766222.jpg

后台控制台打印效果:
https://resource.hsslive.cn/image/1662008439004__aDbT__sd.jpg

后台控制台打印效果:
https://resource.hsslive.cn/image/1662042911335__Qq04__1662042882332.jpg

CDN加载

如果项目对页面加载速度有要求,可以将项目的所有静态资源全部打包上传到cdn,这样可以加速用户的访问站点速度,缺点就是cdn要钱,如果用户是内部的人用的,对稳定性要求不是第一位的,可以将一些常用的库使用类似:unpkgjsdelivr 这些免费的cdn,这样既不用cdn,也不用部署到自己的服务器占用带宽。

压缩图片

具体看这里:https://github.com/galaxy-s10/mini-img

脚手架

具体看这里:https://github.com/galaxy-s10/billd-cli

项目模板

具体看这里:https://github.com/galaxy-s10/vue3-webpack5-template

monorepo

具体看这里:https://github.com/galaxy-s10/billd-monorepo

代码规范

首先当然是eslint,个人认为eslint比绝大部分人更懂写代码哈哈哈,个人推荐一个对导入导出排序的eslint插件:eslint-plugin-import,他最实用的就是对你的import进行排序,让你的import更加的美观。

另外附上我自己收集的通用的eslint规则:

// rules优先级最高,会覆盖上面的
rules: {
  /**
   * 0 => off
   * 1 => warn
   * 2 => error
   */
  camelcase: 1, // 强制执行驼峰命名约定
  'no-console': 0, // 此规则不允许调用console对象的方法。
  'spaced-comment': ['error', 'always', { exceptions: ['-', '+'] }], // 该规则强制注释中 // 或 /* 后空格的一致性
  'no-var': 2, // 要求let或const代替var
  'no-shadow': 2, // 禁止变量声明与外层作用域的变量同名
  'no-param-reassign': 2, // 禁止对 function 的参数进行重新赋值
  'no-nested-ternary': 2, // 禁止嵌套三元
  'no-plusplus': 2, // 禁用一元操作符 ++ 和 --
  'no-unused-vars': 2, // 禁止出现未使用过的变量
  'vars-on-top': 2, // 要求所有的 var 声明出现在它们所在的作用域顶部
  'prefer-const': 2, // 要求使用 const 声明那些声明后不再被修改的变量
  'prefer-template': 2, // 要求使用模板字符串代替字符串连接
  'new-cap': 2, // 要求构造函数名称以大写字母开头
  'no-restricted-syntax': [
    // 禁用一些语法
    'error',
    // 'ForInStatement',
    // 'ForOfStatement',
    {
      selector: 'ForInStatement',
      /**
       * 用 map() / every() / filter() / find() / findIndex() / reduce() / some() / ... 遍历数组,
       * 和使用 Object.keys() / Object.values() / Object.entries() 迭代你的对象生成数组。
       * 拥有返回值得纯函数比这个更容易解释
       */
      message:
        'for in会迭代遍历原型链(__proto__),建议使用map/every/filter等遍历数组,使用Object.{keys,values,entries}等遍历对象',
    },
    {
      selector: 'ForOfStatement',
      message:
        '建议使用map/every/filter等遍历数组,使用Object.{keys,values,entries}等遍历对象',
    },
  ], // https://github.com/BingKui/javascript-zh#%E8%BF%AD%E4%BB%A3%E5%99%A8%E5%92%8C%E5%8F%91%E7%94%9F%E5%99%A8
  'no-iterator': 2, // 禁止使用__iterator__迭代器
  'require-await': 2, // 禁止使用不带 await 表达式的 async 函数
  'no-empty': 2, // 禁止空块语句
  'guard-for-in': 2, // 要求for-in循环包含if语句
  'global-require': 2, // 此规则要求所有调用require()都在模块的顶层,此规则在 ESLint v7.0.0中已弃用。请使用 中的相应规则eslint-plugin-node:https://github.com/mysticatea/eslint-plugin-node
  'no-underscore-dangle': 1, // 此规则不允许在标识符中使用悬空下划线。
  'class-methods-use-this': 0, // 类方法如果不使用this的话会报错
  'no-unused-expressions': [
    2,
    {
      allowShortCircuit: true, // 允许短路
      allowTernary: true, // 允许三元
    },
  ], // 禁止未使用的表达式,即let a = true && console.log(1)允许,但是true && console.log(1)不行
  'object-shorthand': ['error', 'always'], // (默认)希望尽可能使用速记。var foo = {x:x};替换为var foo = {x};

  // eslint-plugin-import插件
  'import/order': [
    'error',
    {
      groups: [
        'builtin',
        'external',
        'internal',
        ['sibling', 'parent'],
        'index',
        'object',
        'type',
      ],
      'newlines-between': 'always', // 强制或禁止导入组之间的新行:
      // 根据导入路径按字母顺序对每个组内的顺序进行排序
      alphabetize: {
        order: 'asc' /* 按升序排序。选项:['ignore', 'asc', 'desc'] */,
        caseInsensitive: false /* 忽略大小写。选项:[true, false] */,
      },
    },
  ],
  'import/newline-after-import': 2, // 强制在最后一个顶级导入语句或 require 调用之后有一个或多个空行
  'import/no-extraneous-dependencies': 2, // 禁止导入未在package.json中声明的外部模块。
  'import/prefer-default-export': 0, // 当模块只有一个导出时,更喜欢使用默认导出而不是命名导出。
  'import/extensions': 0, // 确保在导入路径中一致使用文件扩展名。在js/ts等文件里引其他文件都不能带后缀,这样的话就没办法引其他类型文件,因此关掉
  'import/no-unresolved': 0, // 不能解析带别名的路径的模块,但实际上是不影响代码运行的。找不到解决办法,暂时关掉。
  'import/no-named-as-default-member': 1, // import vue from 'vue';console.log(vue.version),如果vue有导出version,会提示替换为import { version } from 'vue';
  'import/named': 2, // 如:import { version } from 'vuex',会验证vuex有没有具名导出version
},

服务器操作

具体可以看我的这篇文章:https://hsslive.cn/article/102

未完待补充!

JavaScript Node Sequelize vue webpack nginx git CI/CD Nuxt2 性能优化

最后更新于:2022-09-20 01:27:08

欢迎评论留言~
0/400
支持markdown
Comments | 2 条留言
按时间
按热度
栗子~ VIP用户
2 年前

vscode 是什么主题啊,求回复呀

0 点赞
回复
福建省 - 厦门市 undefined undefined
-
2 年前

One Dark Pro

0 点赞
回复
广东省 - 广州市 undefined undefined
共1条回复
已加载所有留言~