花楹一间

HuaYing Notes blog

前言

收集并分类有用的链接。


前言

任何导出的函数都将被注册到 gulp 的任务系统中。

每个 gulp 任务都是一个异步 JavaScript 函数 - 接受 错误优先回调
返回 promise事件触发器子进程可观察对象的 函数

注意📢:
由于某些平台限制,不支持同步任务,尽管有一个非常漂亮的 alternative(可替代的)。


私有任务与公有任务

任务可以被视为 公共私有

  • 公共任务从 gulpfile 中导出,这允许它们通过 gulp 命令运行。
  • 私有任务供内部使用,通常用作 series()parallel() 组合的一部分。

私有任务的外观和行为与任何其他任务类似,但终端用户无法独立执行它。


任务注册

gulpfile 导出

任何导出的函数都将被注册到 gulp 的任务系统中。

1
2
3
4
5
function test(cb) {
cb()
}

exports.test = test

task API 注册

  • 命令行
1
gulp --task
  • task() 函数
1
2
3
4
5
async function dev() {
console.log('dev task done...');
}

task('dev', dev);

过去,task() 用于将函数注册为任务。
虽然该 API 仍然可用,但导出应该是主要的注册机制,除非在导出不起作用的边缘情况下。

引言

Gulp 4.x 中,任务可以是异步的,支持多种处理方式,包括 Promiseasync/awaitStream 等。
当任务完成时,必须通知 Gulp,否则任务会挂起,导致后续任务无法执行。

Gulp 是基于 Node.js 的任务运行器,使用 异步 操作来处理文件流。自动化并增强工作流程的工具包。
利用 Gulp 和 JavaScript 的灵活性来自动执行缓慢、重复的工作流,并将其组合成高效的构建管道。


安装

1
2
3
4
5
6
7
8
# 安装 gulp 命令行工具
npm install --global gulp-cli

# 安装 gulp 作为开发时依赖项
npm install --save-dev gulp

# 验证版本
gulp --version

配置文件

  1. 示例

    在项目根目录中创建一个名为 gulpfile.js 的文件。任何导出的函数都将被注册到 gulp 的任务系统中。

    1
    2
    3
    4
    5
    6
    function defaultTask(cb) {
    cb();
    }

    /* 默认任务导出 */
    exports.default = defaultTask
    1
    2
    # 执行默认任务
    gulp

    注意📢: 将所有逻辑添加到 gulpfile 中,如果文件太大,可以将其重构为单独的文件。
    每个任务都可以拆分成自己的文件,然后导入到 gulpfile 中进行组合。

  2. gulpfile 详解

    • gulpfile 是项目目录下名为 gulpfile.js (或者首字母大写 Gulpfile.js)的文件,在运行 gulp 命令时会被自动加载。
    • Node 的模块的解析功能允许将 gulpfile.js 文件替换为同样命名为 gulpfile.js 的目录,
      该目录中包含了一个名为 index.js 的文件,该 index.js 文件将被当作 gulpfile.js 使用。
    • 如果使用了转译器(transpiler),需要给文件夹和目录相应地命名。
  3. 配置文件转移

    Node 的大多数新版本都支持 TypeScript 或 Babel 所提供的大多数功能,但 import/export 语法除外。

    如果只需要改语法的话,重命名为 gulpfile.esm.js 并安装 esm 模块。

    当使用 TypeScript 或 Babel 编写 gulpfile 文件时,需要进行转译。
    通过修改 gulpfile.js 文件的扩展名来表明所用的编程语言并安装对应的转译模块。

    • 对于 TypeScript,重命名为 gulpfile.ts 并安装 ts-node 模块。
    • 对于 Babel,重命名为 gulpfile.babel.js 并安装 @babel/register 模块。
    • 使用 ESModule 语法,重命名为 gulpfile.esm.js 并安装 esm 模块。
    1
    2
    3
    4
    5
    6
    7
    8
    # 安装 ts-node 模块
    npm install --save-dev ts-node

    # 安装 @babel/register 模块
    npm install --save-dev @babel/register

    # 安装 esm 模块
    npm install --save-dev esm

引言

要实现 Git 提交规范配置,通常会结合使用 commitlint 配合 husky 来确保提交信息符合约定的格式。
避免不规范的提交信息进入代码库。不仅提高了代码的可维护性,还能使团队协作更顺畅。


安装依赖

需要在项目中安装 commitlinthusky,这两个工具能够帮助实现提交信息的规范化。

  • @commitlint/cli: 是 commitlint 的命令行工具。
  • @commitlint/config-conventional: 是一组常用的提交信息规范规则。
  • husky: 用于在 Git 钩子(如 pre-commitcommit-msg)中添加钩子功能。
1
2
# 安装 commitlint 和 husky
npm install --save-dev @commitlint/{config-conventional,cli} husky

配置 Commitlint

在项目根目录下创建一个 commitlint 配置文件,通常是 .commitlintrc.jscommitlint.config.js
.commitlintrc.json,用于定义提交规范。

1
2
3
4
5
6
7
// commitlint.config.js
module.exports = {
extends: [
/* 表示遵循 `@commitlint/config-conventional` 中的默认规则。*/
'@commitlint/config-conventional'
]
};

@commitlint/config-conventional 常见规则包括:

  • type 必须是以下几种之一:
    • feat(新功能)
    • fix(修复)
    • docs(文档)
    • style(代码风格)
    • refactor(代码重构)
    • perf(性能优化)
    • test(增加测试)
    • build(构建工具相关)
    • ci(CI 配置相关)
    • chore(杂项任务)
    • revert(回滚)。
  • scope 可选,描述修改的范围。
  • subject 是提交的简短描述。

合规的提交信息示例:

1
2
# message:  type(scope): subject
git commit -m "feat(user): add login functionality"

配置 Husky

Husky 允许在 Git 钩子中添加自定义的行为,比如在提交时检查提交信息。

初始化 Husky 配置

1
npx husky

commit-msg hook

添加 commit-msg 钩子,这个钩子会在每次提交时检查提交信息是否符合规范。

配置 .husky/commit-msg 文件:

1
2
3
4
5
#!/usr/bin/env sh
#. "$(dirname "$0")/_/husky.sh"
echo "$0"

npx --no-install commitlint --edit "$1"

该钩子会在每次提交时自动调用 commitlint,确保提交信息符合规范。
如果提交信息不符合规则,提交会被拒绝,用户需要修改提交信息后再提交。


(可选) 自定义提交规范

如果需要自定义提交规范,可以在配置文件中进行修改。
可以更改 type 的可选值,或者自定义 subject 的最大长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// type-enum: 定义提交类型
'type-enum': [
2,
'always',
[
'feat' /* 新功能 */,
'fix' /* 修补 bug */,
'docs' /* 文档 */,
'style' /* 代码风格 | 样式 */,
'refactor' /* 代码重构 */,
'perf' /* 性能优化 */,
'test' /* 增加测试 */,
'build' /* dep - 工具性依赖的安装与配置 | 构建工具相关 */,
'ci' /* CI 配置相关 */,
'chore' /* 杂项任务 */,
'revert' /* 回滚 */,
'workflow' /* 工作流 */,
'mod' /* 不明确类型的代码或模块调整 */,
'wip' /* 开发进行中 */,
'types' /* 类型定义文件 */,
'release' /* 版本发布相关 */,
'merge' /* 分支合并操作 */,
'bug' /* 修正非功能性问题 */,
'del' /* 删除 */,
'log' /* 日志类型 */,
'assets' /* 资源 */,
'base' /* 项目基础 */,
'editor' /* 编辑器配置 */
]
],
// subject-case: 定义主题的大小写格式
'subject-case': [
2,
'never',
[
'sentence-case',
'start-case',
'pascal-case',
'upper-case'
]
],
// subject-full-stop: 定义主题是否以句号结尾
'subject-full-stop': [2, 'never', '.'],
// header-max-length: 定义头部的最大长度
'header-max-length': [2, 'always', 72]
}
};

前言


引言

TypeScriptJavaScript 的超集,通过添加静态类型系统和面向对象编程特性,旨在解决 JavaScript 在大型项目中存在的类型松散、代码维护困难等问题。

其核心优势包括:

  • 静态类型检查:

    编译时捕捉类型错误,减少运行时崩溃风险。

  • 代码可读性:

    类型注解可以明确变量、函数参数和返回值的用途,有助于开发者理解代码的意图,提升团队协作效率,并让代码更易于维护。

  • 生态兼容性:

    完全兼容 JavaScript,支持渐进式迁移,,降低了学习和转换成本

  • 面向对象编程特性:

    TypeScript 提供了类、接口、继承、泛型等面向对象编程(OOP)的特性,使得开发者能够编写更符合现代开发范式的代码。


原始类型

  • boolean: 布尔值,truefalse
  • number: 数字,包括整数与浮点数。
  • string: 字符串。
  • tuple: 元组,固定长度和类型的数组,例如: [number, string]
  • enum: 枚举,定义一组命名的常量。
  • any: 任何类型,可以赋值给任何变量。尽量避免使用,因为使用它会失去类型检查的优势。
  • void: 没有返回值,通常用于函数。
  • null: 空值。
  • undefined: 未定义的值。
  • never: 永不存在的值的类型,例如抛出异常的函数。
  • object: 非原始类型,例如对象、数组和函数。
  • unkown: unknown 是一种类型,它表示任何值的类型,但与 any 类型不同,它要求在使用之前进行类型检查。

联合类型与字面量

1
const name: 'typescript' | 'javascript' = 'typescript';

枚举

定义命名常量集合,增强代码可读性

1
2
enum Language  { ZH, EN };
const language: Language = Language.ZH;

函数类型与接口 - 规范代码的 “契约”

  1. 函数类型

    指定参数和返回值类型,避免意外行为。

    1
    2
    3
    function add(x: number, y: number): number {
    return x + y
    }
  2. 接口

    定义对象结构,强制实现一致性。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    interface User {
    /* 只读属性 */
    readonly id: number

    name: string
    username: string
    password: string

    /* 可选属性 */
    age?: number

    /* 广泛定义 */
    [key: string]: unknown
    }

    const user: User = {
    id: 802,
    name: '花楹一间',
    username: 'huaying',
    password: '123456789',
    age: 18,
    skill: 'code'
    };

类与面向对象编程 - 代码的 “组织艺术”

  1. 类与继承

    支持 publicprivateprotected 访问修饰符。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class Animal {
    constructor(public name: string) {
    }

    move() {
    console.log('name:', this.name);
    }
    }

    class Dog extends Animal {
    bark() {
    console.log('woof!');
    }
    }
  2. 实现接口

通过接口约束类行为。

1
2
3
4
5
6
7
8
9
interface Loggable {
log(): void
}

class Logger implements Loggable {
log(): void {
console.log('Log...')
}
}

高级类型与工具 - 解锁高阶玩法

泛型

泛型(Generics)是一种用于创建可重用组件的强大工具。它使得能够在定义函数、类、接口等时,提供一种方式来指定类型,而不需要预先指定具体的类型。

基本语法: 泛型使用尖括号 <> 来定义。

典型场景:

  • 集合操作:例如数组、链表等的操作,可以使用泛型来定义通用的集合处理函数。

  • 表单处理:在表单处理中,可能需要处理不同类型的字段和验证逻辑,泛型能够帮助保持类型安全并且避免重复代码。

  • API 请求响应:对于不同的 API 请求,响应可能是不同的类型,泛型可以帮助处理不同类型的请求和响应。

  • 泛型函数

    在函数中,泛型允许在函数的参数和返回值中使用类型占位符

    1
    2
    3
    4
    function identity<T>(id: T): T {
    return id
    }
    const id = identity(802); // 调用时,自动推断为 number 类型
  • 泛型接口

    泛型接口允许定义可以接受不同类型的函数签名或方法。

    1
    2
    3
    4
    5
    interface GenericIdentityFn<T> {
    (arg: T): T;
    }

    const identityFn: GenericIdentityFn<number> = (arg) => arg;
  • 泛型类

    类也可以使用泛型,这使得可以创建针对不同类型的实例化对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
class GenericBox<T> {
value: T;

constructor(value: T) {
this.value = value;
}

getValue(): T {
return this.value;
}
}

let boxNumber = new GenericBox<number>(123);
  • 泛型约束

    使用 extends 关键字来实现泛型约束,对泛型添加一些限制,确保符合特定的结构。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    interface Person { 
    name: string
    }

    // 泛型约束:T 必须是一个包含 name 属性的对象
    function greet<T extends Person>(person: T): string {
    return `Hello, ${person.name}`;
    }

    const person = { name: "John", age: 30 };
    console.log(greet(person));
  • 默认泛型类型

    可以为泛型提供一个默认类型,如果调用时没有提供类型参数,则使用默认类型。

    1
    2
    3
    4
    function wrap<T = string>(value: T): T {
    return value;
    }
    console.log(typeof wrap(123));
  • 泛型的多个类型参数

    可以为泛型函数、接口或类指定多个类型参数。

    1
    2
    3
    4
    5
    6
    function merge<T, U>(object1: T, object2: U): T & U {
    return { ...object1, ...object2 };
    }

    const merged = merge({ name: "John" }, { age: 30 });
    console.log(merged); // 输出 { name: 'John', age: 30 }
  • 使用 keyofin 限制泛型

    1
    2
    3
    4
    5
    6
    7
    // keyof 限制:T 必须是一个对象类型,并且 key 需要是对象的键
    function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
    }

    const person = { name: "John", age: 30 };
    console.log(getValue(person, "name")); // 输出 "John"

类型别名与交叉类型

1
2
type Person = { name: string };
type Developer = Person & { expertise: string };

类型断言

可以通过类型断言强制将一个值转换为特定的类型,而 TypeScript 不会对其进行进一步的类型检查。

  • 尖括号语法(只在 TSX 中不可用)

    1
    2
    let someValue: unknown = "Hello, world!";
    const len: number = (<string>input).length;
  • as 语法(推荐)

    1
    2
    const input: unknown = 'hello world!';
    const len: number = (input as string).length;

类型守卫

类型守卫是 TypeScript 提供的一种方式,用于细化类型检查,并确保某个变量的类型符合预期。

类型守卫通常会使用 typeofinstanceof 或自定义的类型保护函数来做类型判断。

  • typeof 类型守卫

    typeof 运算符用于判断原始类型(如 string、number、boolean、symbol、undefined)。

    1
    2
    3
    4
    5
    6
    7
    function printLength(value: string | number) {
    if (typeof value === "string") {
    console.log(value.length); // `value` 在这里被推断为 `string` 类型
    } else {
    console.log(value.toFixed(2)); // `value` 在这里被推断为 `number` 类型
    }
    }
  • instanceof 类型守卫

    instanceof 运算符用于检查某个对象是否是某个类的实例,通常用来检查类的实例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class Dog {
    bark() {
    console.log("Woof!");
    }
    }

    class Cat {
    meow() {
    console.log("Meow!");
    }
    }

    function makeSound(animal: Dog | Cat) {
    if (animal instanceof Dog) {
    animal.bark(); // `animal` 被推断为 `Dog` 类型
    } else {
    animal.meow(); // `animal` 被推断为 `Cat` 类型
    }
    }


TS 项目配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/*
tsconfig.json
@link https://www.tslang.cn/docs/handbook/compiler-options.html
@link https://www.typescriptlang.org/tsconfig/
*/
{
/* 继承其他配置 */
// "extends": "",

/* 编译器选项 */
"compilerOptions": {
/*
启用严格模式 - 启用所有严格类型检查选项
启用 --strict 相当于启用:
--noImplicitAny,
--noImplicitThis,
--alwaysStrict,
--strictNullChecks,
--strictFunctionTypes,
--strictPropertyInitialization
*/
"strict": true,

/* 禁用函数参数双向协变检查 */
// "strictFunctionTypes": true,

/* 在表达式和声明上有隐含的 any 类型时报错 */
// "noImplicitAny": true,

/* 当 this 表达式的值为 any 类型的时候,生成一个错误 */
// "noImplicitThis": true,

/* 以严格模式解析并为每个源文件生成 "use strict"语句 */
// "alwaysStrict": true,

/* 确保类的非 undefined 属性已经在构造函数里初始化若要令此选项生效,需要同时启用 --strictNullChecks */
// "strictPropertyInitialization": true,

/*
在严格的 null 检查模式下, null 和 undefined 值不包含在任何类型里,
只允许用它们自己和 any来赋值(有个例外, undefined可以赋值到 void)
*/
// "strictNullChecks": true,

/* 不对具有 @internal JSDoc 注解的代码生成代码 (实验性) */
// "stripInternal": false,

/* 重定向输出目录 */
// "outDir": "",

/* 仅用来控制输出的目录结构 */
// "rootDir": "",

/*
根(root)文件夹列表,表示运行时组合工程结构的内容 (tsconfig.json 配置)
@link https://www.tslang.cn/docs/handbook/module-resolution.html#virtual-directories-with-rootdirs
*/
// "rootDirs": [],

/*
将输出文件合并为一个文件
合并的顺序是根据传入编译器的文件顺序和 ///<reference``>和 import的文件顺序决定的
只有 "AMD"和 "System"能和 --outFile一起使用
*/
// "outFile": "",

/* 指定 ECMAScript 目标版本 - 指示 TypeScript 编译器生成符合指定标准的代码。 */
"target": "ESNext",

/* 是否允许编译 javascript 文件 */
"allowJs": false,

/* 启用 javascript 检查 - 与 allowJs 配合使用 */
// "checkJs": false,

/* 启用 ES 模块与 CommonJS 模块之间的相容性特性 */
"esModuleInterop": true,

/* 指定类型声明文件所在位置 - 要包含的类型声明文件路径列表 */
"typeRoots": ["./types", "./node_modules/@types"],

/* 指定包含的 @types 类型 - 要包含的类型声明文件名列表 */
// "types": ["node", "express", "react", "react-dom", "react-router-dom"],

/* 允许不报告执行不到的代码错误 */
"allowUnreachableCode": true,

/* 允许不报告未使用的标签错误 */
"allowUnusedLabels": true,

/* 若有未使用的局部变量则抛错 */
"noUnusedLocals": true,

/* 若有未使用的参数则抛错 */
"noUnusedParameters": true,

/* 解析非相对模块名的基准目录 */
"baseUrl": ".",

/* 生成相应的 .d.ts文件 */
"declaration": true,

/* 生成声明文件的输出路径 */
// "declarationDir": "dist/types",

/* 显示诊断信息 */
"diagnostics": true,

/* 显示详细的诊段信息 */
"extendedDiagnostics": true,

/* 禁用 JavaScript 工程体积大小的限制 */
// "disableSizeLimit": false,

/* 在输出文件的开头加入 BOM 头(UTF-8 Byte Order Mark) */
// "emitBOM": false,

/* 给源码里的装饰器声明加上设计类型元数据 (实验性) */
// "emitDecoratorMetadata": false,

/* 启用 ES 装饰器(实验性) */
"experimentalDecorators": true,

/*
禁止对同一个文件的不一致的引用
文件名完全匹配,要求所有的导入语句中的文件路径(包括模块和类型声明文件)必须与实际文件系统中的文件名大小写完全匹配
*/
"forceConsistentCasingInFileNames": true,

/* 从 tslib 导入辅助工具函数(比如 __extends, __rest等) */
// "importHelpers": false,

/*
启用 JSX
@link https://www.tslang.cn/docs/handbook/jsx.html
*/
"jsx": "react",

/* 指定生成目标为 react JSX 时,使用的 JSX 工厂函数,比如 React.createElement 或 h */
"jsxFactory": "React.createElement",

/* 生成单个 sourcemaps 文件,而不是将每 sourcemaps 生成不同的文件 */
// "inlineSourceMap": false,

/* 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性 */
// "inlineSources": false,

/* 将每个文件作为单独的模块 */
"isolatedModules": true,

/*
编译过程中需要引入的库文件的列表
默认注入的库为:
► 针对于--target ES5:DOM,ES5,ScriptHost
► 针对于--target ES6:DOM,ES6,DOM.Iterable,ScriptHost
*/
"lib": [
"ESNext",
"DOM",
"DOM.Iterable",
"WebWorker",
"ScriptHost"
],

/* 不使用默认的库文件 */
"noLib": false,

/* 打印出编译后生成文件的名字 */
// "listEmittedFiles": false,

/* 编译过程中打印文件名 */
// "listFiles": false,

/*
为调试器指定指定 sourcemap 文件的路径,而不是使用生成时的路径
当 .map 文件是在运行时指定的,并不同于 js 文件的地址时使用这个标记
指定的路径会嵌入到 sourceMap 里告诉调试器到哪里去找它们
*/
// "mapRoot": "./map",

/* 生成相应的 .map文件 */
"sourceMap": true,

/*
指定 TypeScript 源文件的路径,以便调试器定位
当 TypeScript 文件的位置是在运行时指定时使用此标记
路径信息会被加到 sourceMap里
*/
// "sourceRoot": "./src",

/* 生成 .d.ts 文件相应的 map 映射文档 */
// "declarationMap": true,

/*
node_modules 依赖的最大搜索深度并加载 JavaScript 文件
仅适用于 --allowJs
*/
// "maxNodeModuleJsDepth": 0,

/* 指定生成(输出)目标模块系统代码 target === "ES6" ? "ES6" : "commonjs" */
"module": "ESNext",

/* 指定模块解析策略 - 决定如何处理模块 module === "AMD" or "System" or "ES6" ? "Classic" : "Node" */
"moduleResolution": "node",

/* 当生成文件时指定行结束符: "crlf"(windows)或 "lf"(unix) */
"newLine": "lf",

/* 不生成输出文件 */
// "noEmit": false,

/* 不在输出文件中生成用户自定义的帮助函数代码,如 __extends */
// "noEmitHelpers": false,

/* 报错时不生成输出文件 */
"noEmitOnError": true,

/* 不截短错误消息 */
// "noErrorTruncation": false,

/*
报告switch语句的fallthrough错误
(即,不允许 switch 的 case 语句贯穿)
在 switch 语句中,如果一个 case 后面没有 break 并且直接跟着另一个 case,编译器会发出错误
*/
"noFallthroughCasesInSwitch": true,

/*
不是函数的所有返回路径都有返回值时报错
在函数体中检查是否存在返回值,如果一个函数缺少显式的返回语句,或者某个执行路径没有返回值,TypeScript 将会发出警告或错误
*/
"noImplicitReturns": true,

/* 模块输出中不包含 "use strict"指令 */
// "noImplicitUseStrict": false,

/* 不把 /// <reference``>或模块导入的文件加到编译文件列表 */
// "noResolve": false,

/* 禁用在函数类型里对泛型签名进行严格检查 */
// "noStrictGenericChecks": false,

/*
模块名到基于 baseUrl 的路径映射的列表 (tsconfig.json 配置)
@link https://www.tslang.cn/docs/handbook/module-resolution.html#path-mapping
*/
"paths": {
// "@e/*": ["./electron/*"],
// "@s/*": ["./src/*"],
// "@/*": ["./electron/*", "./src/*"]
},

/* 保留 const 和 enum 声明 */
// "preserveConstEnums": false,

/* 不把符号链接解析为其真实路径;将符号链接文件视为真正的文件 */
// "preserveSymlinks": false,

/* 保留 watch 模式下过时的控制台输出 */
// "preserveWatchOutput": false,

/* 给错误和消息设置样式,使用颜色和上下文 (实验性) */
// "pretty": false,

/*
编译指定目录下的项目
这个目录应该包含一个 tsconfig.json 文件来管理编译
*/
// "project": "",

/* 当目标为生成 "react" JSX时,指定 createElement 和 __spread 的调用对象 */
// "reactNamespace": "React",

/* 删除所有注释,除了以 /!*开头的版权信息 */
"removeComments": true,

/* 忽略库的默认声明文件的类型检查 */
"skipDefaultLibCheck": true,

/* 忽略所有的声明文件( *.d.ts)的类型检查 */
"skipLibCheck": true

/* 阻止对对象字面量的额外属性检查 (实验性) */
// "suppressExcessPropertyErrors": false,

/* 阻止对缺少的属性检查 - 阻止 --noImplicitAny 对缺少索引签名的索引对象报错 */
// "suppressImplicitAnyIndexErrors": false,

/* 生成模块解析日志信息 */
// "traceResolution": false
}

/* 指定编译的文件范围 */
// "include": ["source/**/*"],

/* 排除不需要编译的文件夹 */
// "exclude": ["node_modules", "backup", "app"]
}


相关链接🔗

前言

Hexo 是一个快速、简洁且高效的博客框架。

Hexo 使用 Markdown(或其他标记语言)解析文章,在几秒内,即可利用靓丽的主题生成静态网页。

优点:

  • 超快速度: Node.js 所带来的超快生成速度。 上百个页面在几秒内完成渲染。
  • 一键部署: 只需一条指令即可部署到 GitHub Pages, Heroku 或其他平台。
  • 支持 Markdown: Hexo 支持 GitHub Flavored Markdown 的所有功能,甚至可以整合 Octopress 的大多数插件。
  • 插件: 支持数种模板引擎(EJSPugNunjucks等)。 可以与现有的NPM包 (Babel, PostCSS, Less/Sass 等) 轻松地集成。

安装与初始化

  1. 安装

    1
    2
    3
    4
    5
    6
    7
    8
    # 全局安装(命令工具)
    npm install hexo-cli -g

    # 局部安装(hexo 包)
    npm install hexo

    # 执行 hexo 命令
    npx hexo [command]
  2. 初始化

    1
    hexo init blog

创建新文章

1
hexo new "我的新文章"

更多信息: Writing


使用草图

草图是未发布的文章,可以通过以下命令查看和发布草图:

1
2
3
4
5
6
7
8
# 创建草稿
hexo draft "草稿标题"

# 生成包含草稿的静态文件以预览
hexo generate --draft

# 发布草稿
hexo publish draft 草稿文件ID

启动服务器

1
hexo server

更多信息: Server


生成静态文件

1
hexo generate

更多信息: Generating


部署到远程站点

1
hexo deploy

更多信息: Deployment

引言

ASAR(Archive for ASar)归档是一种专为 Electron 应用设计的简单扩展存档格式。
它旨在缓解 Windows 平台上的长路径名问题,提升require速度,并保护源代码不被轻易修改。

  • ASAR 通过将文件夹结构打包成一个二进制文件,简化了 Electron 应用的资源文件管理。
    这种格式便于分发和部署应用,同时也提供了性能和安全性方面的改善。
  • 使用 ASAR 格式的主要好处包括减少文件数量和大小,加快文件访问速度。
    在 Electron 应用中,由于模块加载机制,使用 ASAR 格式可以减少文件 I/O 操作,从而提高require速度。
  • ASAR 格式通过打包资源文件,可以防止用户直接修改应用的内部文件,从而提高安全性。
    然而,这并不意味着 ASAR 提供了高级别的安全防护,有经验的用户或攻击者仍然可能找到绕过的方法。

安装

1
2
3
4
5
# 全局安装
npm install -g asar

# 局部安装
npm install -D asar


常用命令

解压缩

  1. 解压:

    1
    2
    #  extract|e <archive>(asar 文件) <dest>(目标解压文件夹)
    asar extract [archive] [dest]
  2. 压缩:

    1
    2
    #  pack|p [options] <dir>(目标解压文件夹) <output>(asar 文件)
    asar pack [dir] [output]

其他命令

  1. 列出归档文件与目录:

    1
    2
    #  list|l [options] <archive>(asar 文件)
    asar list [archive]
  2. 提取单个文件:

    1
    2
    #  extract-file|ef <archive> <filename>(目标文件)
    asar extract-file [archive] [filename]

相关链接🔗

0%