husky是如何实现自动化代码管理的
前言
在日常的代码管理中,没有严格按照代码规范来编写代码,提交的git message不规范,很难从提交日志中看出调整了什么内容,其他同事使用的ide与我的不一致,其他同事与我的编码有空格冲突,又不能一口气直接替换,花费大量的时间来进行代码的合并,解决空格冲突等等,我们的编码工作,不应该是在这个重复的低效的工作上的!!👉 因此,**husky(哈士奇)**就闪亮 🌠 登场了!😕 第一次听到这个中文翻译时,有些许疑惑,按照 官方文档 所描述的!当您提交或推送时,您可以使用它来整理您的提交消息、运行测试、lint 代码等
什么是husky?
当您提交或推送时,您可以使用它来整理您的提交消息、运行测试、lint 代码等这个是官方的介绍,husky支持所有的git勾子,实际在使用的过程中,除了这个勾子动作之外,应该还可以支持到npm的相关勾子动作
如何使用husky(npm方式)husky-init是用husky快速初始化项目的一次性命令!
1npx nusky-init && npm install
☝ 上述这里的命令,将设置husky,同时修改package.js ...
hexo是如何工作的
前言官方文档
自己的博客运行了也有一段时间了,想了解一下自己的博客站点整体是如何工作的?以及自己可以做点什么,来往这个博客站点中植入自己的插件来满足自定义的需求!本文将具体分析一下hexo是如何工作的?它都有哪些组成?我们可以在这个框架上如何自定义自己的需求?以及这个框架给我们代码的可学习的地方!!!
hexo的组成
首先,不管怎么,代码到手,天下我有! 👉 先来看一下对应的hexo的代码目录结构:👾 通过package.json中的main,可以发现其中的入口在于bin/hexo文件
123#!/usr/bin/env node'use strict';require('hexo-cli')();
👾 而hexo则是调用的hexo-cli库来实现的,后面发现,hexo-cli则是反过来调用的hexo来进行 👉 创建一个Hexo对象,并最终调用这个Hexo对象的init()方法 !!
🌠 也就是说这个hexo-cli充当了一个执行者的作用!!
👽 而这里的Hexo对象,则是继承于EventEmitter对象,可针对其过程进行一系列的监听(也就是监听其生命周期过程方法) ...
如何在降级watchman
前言
😖 近期在调试这个react-native相关项目的时候,由于系统进行了升级,意味着所有的环境都的重来,而且像react-native这框架,对环境特别的敏感,花了接近3天的时间,来折腾这个环境的重建,编写此文档,以便于后续其他人避免重复踩这样的雷
brew的坑
首先,在macOS上的这个brew的源的管理,就算是拥有梯子来上网,估计也是心理一直在念F开头的单词吧,因此,我这边重新安装了完整的源,并设置了国内的源地址!
1、卸载原来的brew1/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"
🌠 期间可能需要输入密码,并同时忽略可能出现的warning,直到最后卸载成功!
2、安装新的源1/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
🌠 在提供的选项中选择这个“清华国内源”,感觉目前也就这个在国 ...
less的使用
前言
像JS般来思考less,即可 🈶 一定的深刻认识!!! 👇 是对应的官方文档
less官方文档
🌠 从官方的文档学习整理了 👇less组成
👽 这里仅针对常见的几个模块(场景)进行详细地介绍!!
变量
js中采用的let/const/var等关键词来定义一个变量而在less中,则采用@关键词来定义一个变量!
1234567@color: blue;.a{ color: @color;}p{ background-color: @color;}
变量的其他特殊用法变量插值
js中采用模版字符串的方式,来实现字符串与变量/常量的拼接而在less中,则采用@{...}的方式,来实现字符串规则的拼接,可以用在选择器名称、属性名称、URL、和@import语句!👉 变量作为选择器名称插槽
1234567@btn: btn;.@{btn}-blue{ background-color: blue;}.@{btn}-red{ background-color: red;}
👉 变量作为属性名称
123456@color: color;@bgColor: back ...
踩了marked.js的坑后,我选择了markdown-it
前言
近期在折腾这个chatGPT的时候,发现在进行字符串的拼接过程中,如果出现了代码的话, 😕 一旦在代码中出现换行符的时候,marked库就自动将其识别为一个code-block,导致我们在解析这个字符串内容的时候,一下子出现普通文字,一下子出现代码块,硬生生给自己找了坑!在经过两天的奋战后,问了一下chatGPT,然后它居然堂而皇之地承认了! 在经过一大段时间的调查与尝试,最后采用了markdown-it,个人觉得很有必要将这个给 ✏ 下来,以免其他人以及自己在未来的工作学习中又重复踩到这个雷!
👇 是对应的待验证的一段代码
123def fibonacci(n): if n < 0: return None
😕 大家会发现这是一段未结束的代码,而且在实际的字符串拼接过程中,它是没有代码块结束符号的,具体解析过程如下图所示:
🌠 从上述可以看出marked它会自动地将代码块中的一个换行符当作是一个代码块终止的标志,所以才会有这个代码块与普通的字符串来回切换的异常情况!!
🐛 那么应当如何来解决这个问题呢? 👉 最终,这边采用了markd ...
prettier的学习与使用
前言官方文档
既然已经有ESLint以及stylelint了,为啥还要有这个prettier呢?👽 我们都知道,项目团队在研发过程中,必须严格遵循统一的一个代码规范,即便是拥有了ESLint与stylelint的加持,在实际的编码过程中,也还是难免需要借助于插件、三方库来协助规范整个团队的项目开发,因此,我们需要在项目中通过统一提供的编码规则配置方案,由项目自身的开发依赖以及配置方案,完成项目自身的代码规范化自动控制,保证项目在不同的ide、环境,不同的人员手中都是采用的统一的一个配置的!!!
什么是prettier
prettier是一种自用的代码格式化程序,支持有:js、JSX、Vue、Flow等等语言,它删除了原始样式,并确保所有的输出都符合一致的格式!😕 比如 🈶 👇 1⃣ 个函数:
1234function foo(arg0, arg1, arg2, arg3){ // ... 此处隐藏代码的实现}
☝ 针对上述的函数,假如调用foo函数所传递的参数是较为简单的常量或者是变量的话,则一般一行是能够正常展示完整的,但是,如果传递的参数是一个函数的执行结果,而且这 ...
如何使用stylelint
前言Stylelint官方文档
与之前学习的 ESLint 相类似,Stylelint作为一个css linter,可帮助我们避免编写错误的css样式代码,并强制执行预先协商好的“约定”配置,配置可从标准的配置继承而来,也可重写!
Stylelint的相关特性
提供的现成的业界css语法和功能的自定义规则;
支持插件的方式,可创建自定义规则;
提供自我修复的能力,自动修复配置告知的预警规则;
可根据自己的习惯进行自定义;
可从html、markdown、css-in-js等文件中提取css进行校验;
可扩展至scss、sass、less、sugarSS
👉 Stylelint可有效帮助我们避免一些不必要的错误,比如有:
拼写错误的css属性;
重复的选择器;
畸形的grid布局区域
👉 Stylelint还可按照配置约定来执行,比如有:
设置适用单位;
强制命名模式,比如自定义属性;
设置限制,比如设置id选择器的数量;
指定符号,比如现代颜色函数;
如何使用?
关于Stylelint的使用,一般 🈶 👇 3⃣ 个步骤:
安装相关的环境以及配置
通过命令来安装 ...
如何使用eslint
前言ESLint官方文档
根据配置方案,来发现并报告 js中的问题以及提供建议的工具,目的是使代码风格更加一致,同时避免不必要的错误!👉 由于要发现代码中的错误,因此ESLint必不可少地需要解析代码文件(采用Espree,从Acorn基础上演变而来),对解析生成的AST树进行方案评估。另外,在配置文件中的每一个规则都是一个个的插件!!
😕 这里提及到配置方案,也就是我们所使用的配置文件,它是都包含有哪些成员呢?它是如何被使用的呢? 👇 将一一解释一下!!
ESLint集成
一般的,在现有项目中集成ESLint,无非 🈶 2⃣ 种方式:
1. 一键初始化
通过在项目中直接执行 👇 的命令,将自动在当前项目中安装对应的ESLint检测工具环境:
1npm install @eslint/config
2. 手动安装 + CommonJS + CLI
通过在项目中安装这个ESLint依赖,并创建对应的.eslintrc文件,如下所示:
1npm install --save-dev eslint
安装依赖完成后,采用CommonJS的方式来编写这个.eslintrc文 ...
使用express+hbs搭建自己的服务端渲染框架
前言
在刚开始接触这个express框架的时候,利用其脚手架命令,来创建项目的过程中,发现其中 🈶 一种渲染引擎: handlebars,这种引擎在之前的学习文档中 handlebars的学习与使用用 已经有具体提及到,本章节主要想将自己在使用express + hbs搭建这个SSR渲染页面的过程给记录下来,方便后续自己 🈶 来及时查阅!
一、express项目初始化
借助于express应用程序生成器,进行项目的初始化工作
1express --view=hbs express-hbs-demo
☝ 命令则在当前目录中创建了一个名为express-hbs-demo的express项目,进入该目录,并安装相应的依赖,然后执行对应的脚本程序,将程序运行起来:
1npm install && npm run start
运行结果如下:👾 与此相对应的生成的文件目录结构如下:
二、追加express-hbs库的支持
要让程序能够支持handlebars的相关特性(比如helper、partials),那么我们可以是借助于 express-hbs 三方库,通过在应用程 ...
chatGPT体验感悟
前言最近,任何行业都被chatGPT影响:一款好用到超出认知的聊天机器人,其强大的学习和处理收集能力,能够完美地编撰文案、编程的辅助(从咱这两次周末的分享会议总结得知)、语种翻译,还能进行绘制插画,提供法律知识工作等等!基本上是你要什么,他就给什么,而且还能够超出自己想象地来提供,可以说是目前人工智能界最靓的仔!
😕 那么,我们是不是需要担忧一个问题:我们怕不是要失业了吧?在倾佩chatGPT之余,再次感慨万千:这个激流勇进的时代,稳定已经成为过去时!比如我们的经验可能随时过时,我们的工作可能随时被取代或被更好的方式所折服!
我能够做点什么?感激生活/工作中的变化,所有一成不变的路,其实都是下坡路!从自身从事编码工作以来,前5年基本上是只做android应用开发,可以说自己在前1-2年的时间内,基本上是从入门到上手到应用实战,然后后面几年基本上是在重复前两年的工作,而且除了业务上的熟悉工作之外,每天的工作内容就是重复昨天的编码工作,能力上毫无进展,思维也比较呆板。这种一成不变的路线,诚然是不需要费劲思考,但也会让自己在生活中的改变面前丧失竞争力,唯有主动求变、提升自己的竞争力,才能够 ...
HtmlWebpackPlugin
前言官方文档
关于HtmlWebpackPlugin插件的时间,相信不少童鞋应该都是比较熟悉的了,在一些现成的脚手架(像vue-cli、react-cli等开源三方脚手架)中,都被集成进去成为其核心成员脚手架模块,负责将结果目标内容文件给输出出来, 0⃣ 配置的方式来快速开发这个业务项目, 😕 但是,在实际的项目开发过程中,避无可避地需要针对现有的采用脚手架搭建起来的项目进行定制化的配置,来满足不断变更的业务需求,提升编码的效率,因此,很有必要来对所使用的相关插件(HtmlWebpackPlugin)进行深入的了解!关于官方的解释是:HtmlWebpackPlugin 简化了 HTML 文件的创建,以便为你的 webpack 包提供服务。这对于那些文件名中包含哈希值,并且哈希值会随着每次编译而改变的 webpack 包特别有用。你可以让该插件为你生成一个 HTML 文件,使用 lodash 模板提供模板,或者使用你自己的 loader。👾 这里提及的使用默认的lodash模版来生成Html文件,还可以使用自己的loader,比如像handlerbars-loader、html-l ...
webpack中如何加载loader的
前言webpack官方loader介绍
关于webpack中的Loader,平时项目中可能比较少用到,一般的脚手架程序都自动集成相关的loader,但是如果我们能够将不同的loader给搭配起来,形成项目自身特色的loader集合体的话,在开发/编码过程中可以提升不少的效率,而且也让程序可以 🈶 更健壮的稳定性!😕 那么什么是Loader?如何使用Loader?Loader的加载执行过程是怎样的?一般都有哪些常用的Loader?如何自定义Loader来辅助工作?
什么是Loader?
loader用于对模块的源代码进行转换,可以让我们在使用import或者’load’模块时预处理文件,通过对loader的定义与使用,可以让我们在处理不同的文件格式时,采用不同的文件解析协议,比如像*.hbs、*.vue等文件,通过采用对应的loader来将其解析为不同的内容!比如将typescript转换为普通的js,活着将内联图像转换为data URL,甚至允许我们直接在js模块中直接导入css文件。😕 关键在于预处理,使得我们的所有的模块(文件)加载时都可以先处理转换一下,采用一些官方的公 ...
webpack中的模块管理
前言
本文主要着重介绍关于webpack中的模块是如何管理的,其实在网络上已经也有不少的文章关于ES6、CommonJS、AMD的相关介绍了,本文主要侧重于这个模块管理的使用方式!三者都是对模块进行依赖管理的目的,实现同步/异步加载的目标!
ESM
ESM主要包含 🈶 2⃣ 个关键词:import和export!
export
export 语句用于从模块中导出实时绑定的函数、对象或原始值,以便其他程序可以通过 import 语句使用它们。被导出的绑定值依然可以在本地进行修改。在使用 import 进行导入时,这些绑定值只能被导入模块所读取,但在 export 导出模块中对这些绑定值进行修改,所修改的值也会实时地更新。存在 🈶 种方式的导出:
命名导出(每个模块包含任意数量)
默认导出(每个模块包含一个)
语法规则:
123456789101112131415161718192021222324252627// 导出单个特性export let name1, name2, …, nameN; // also var, constexport let name1 = …, ...
DefinePlugin在webpack中是如何使用的
前言DefinePlugin官网链接
允许在编译时将你代码中的变量替换为其他值或表达式,它并不是变量赋值,而是在编译期间进行字符串的精准匹配与替换!可以理解为,我们在webpack打包的项目中,通过在配置文件(webpack.config.js)中使用插件DefinePlugin,并传递给该插件对应的变量/表达式,都可以在项目中的*.js文件中访问到这些变量/表达式的定义,而无需重复地在所有的文件中进行二次定义!这意味着我们可以定义全局开关等控制,来对代码进行区别式运行的操作!
用法123456789// webpack.config.jsmodule.exports = { plugins: [ new webpack.DefinePlugin({ // 此处是相关的变量/表达式的配置 a: 999 }) ]}
关于该插件中每个健值对可以 🈶 👇 的定义方式:
如果该值为字符串,它将被作为代码片段来使用;
如果该值不是字符串,则将被转换成字符串(包括函数方法);
如果值是一个对象,则它所有的键将使用相同方法定义(也就是遍历key来替换); ...
AssetModulesPlugin.js
我是谁
webpack中与assets资源进行交互的模块,逐渐通过对NormalModuleFacotry.hooks.createParser、NoemalModuleFactory.createGenerator、Compilation.hooks.renderManifest等几个钩子容器函数的监听!
干预的钩子函数
通过提供的干预的钩子函数,创建对应的Parser以及Generator对象,来处理webpack中的默认的对asset资源加载的统一配置,也就是对配置的实现!
1、NormalModuleFactory.hooks.createParser
针对不同类型的createParser创建对应的Parser对象,主要由以下 👇 几种类型的asset:
asset类型
对应创建的Parser
asset
AssetParser
asset/inline
AssetParser
asset/resource
AssetParser
asset/source
AssetSourceParser
2、NormalModuleFactory.ho ...
webpack中的代码生成插件
前言
作为webpack中的代码生成器插件,主要负责将对应的chunk生成对应的结果字符串内容!在开始具体解析之前,首先,现看一下 👇 2⃣ 个最简单的结果生成情况对比!
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657 (() => { // webpackBootstrap var __webpack_modules__ = ({/***/ "./src/module1.js":/*!************************!*\ !*** ./src/module1.js ***! \************************//***/ ((module) => {module.exports = function test() { console.info("我是来自于模块一中的test方法");};/***/ }) });/************************ ...
Module与其家族们
前言
Module,作为webpack中的基本模块单元,继承于DependenciesBlock,使其具备缓存其他模块而形成的依赖关系,也就是说,webpack中的关于模块的定义声明皆来自于此!我们所定义的一个个文档都是一个个的模块,模块之间允许互相依赖,而依赖在程序中的表现形式,则是以DependenciesBlock中的Dependency[]数组来存储的
DependenciesBlock
作为抽象的模块基类,允许添加/删除依赖,就像是Array数组般一样!
通过其成员属性dependencies(Dependency数组类型),来维护引用依赖的其他模块,主要用与同步加载的其他模块;
通过其成员属性block(AsyncDependenciesBlock数组类型),来维护引用依赖的其他模块,采用异步分割代码加载的方式来加载的其他模块;
parent属性,指向父模块;
Dependency
作为依赖模块形成的基本单元,是一个模块关系的基本单元,可以认为是依赖的代码位置描述对象,其成员属性/方法主要有:
loc: 是一个DepencencyLocation对象,代表依赖形成 ...
EntryOptionPlugin
前言
作为实际开始编译的入口,该插件由webpack的核心默认插件自动加载,无需额外通过配置文件引入!
入口的开始
通过对该插件的代码阅读后发现,该插件主要针对两个钩子容器函数设置监听动作
compiler.hooks.compilation
compiler.hooks.make
🌠 下面我们关键分析一下这个compiler.hooks.make触发时,做了什么动作!
一切编译动作的源头
在compiler.hooks.make方法触发时,在该插件中通过调用compilation.addEntry来从入口文件加载相关的依赖文件!一切回到了 Compilation.js
webpack中的AsyncQueue
前言
在阅读到Compilation的代码执行过程时,发现有一个隐藏的异步队列执行者,😕 这里为啥要单独整一篇文章来阐述这个异步队列执行者呢?我觉得应该是在于它的一个比较独特的设计理念打动了我,下面就来具体分析一下并尝试来使用这个异步队列的执行者!添加完成一个元素后,自动执行一个对应的回调动作,并能够实现与父AsyncQueue对象共享的“线程队列”资源
如何使用?1234567891011121314151617const AsyncQueue = require("../../lib/util/AsyncQueue");let child = new AsyncQueue({ name: "test", parallelism: 2, processor: () => { console.info("我是来自于processor的执行动作"); }});child.add({}, err => { console.info("我是来自于添加失败后的回调!");});child.add({}, err => { console.info("我是 ...