0%

CommonJS

  • 同步加载
  • 运行时确定依赖
  • Node.js 标准
1
2
3
4
5
6
// 导出
module.exports = { ... }
exports.func = func

// 导入
const module = require('./module')

ES6 Modules

  • 静态分析
  • 编译时确定依赖
  • 浏览器和 Node.js 支持
1
2
3
4
5
6
7
// 导出
export { func }
export default func

// 导入
import { func } from './module'
import func from './module'

主要差异

加载时机

  • CommonJS:运行时
  • ES6:编译时

语法

  • CommonJS:require() / module.exports
  • ES6:import / export

循环依赖

  • CommonJS:支持,但可能有问题
  • ES6:静态分析,避免问题

Tree Shaking

  • CommonJS:不支持
  • ES6:支持

互操作

1
2
3
4
5
// CommonJS 导入 ES6
const esModule = require('./es-module').default

// ES6 导入 CommonJS
import cjsModule from './cjs-module'

总结

ES6 Modules 更现代化,推荐新项目使用。CommonJS 在 Node.js 生态仍重要。

实际案例分析

在一个混合项目中,部分模块仍使用 CommonJS,而新模块采用 ES6。通过 Babel 的转换和 rollup 的 commonjs 插件,可以平滑过渡。

性能对比测试

  • 使用 Chrome Lighthouse 测试打包体积
  • ES modules 样本项目体积比 CommonJS 小约 20%

工具链配置示例

1
2
3
4
5
// babel.config.js
{
"presets": ["@babel/preset-env"],
"plugins": ["@babel/plugin-transform-modules-commonjs"]
}

模块系统历史回顾

JavaScript 最初没有模块概念,随着大型应用出现,CommonJS 由 Node.js 团队提出。随后 ES2015 标准化了模块语法。浏览器支持跟进较晚。

模块加载安全

  • 避免从不可信源加载脚本
  • 使用子资源完整性(SRI)与模块一起使用

FAQ

  • 如何处理第三方库依然使用 CommonJS?
    大多数打包工具都会自动转换,或通过 require() 动态导入。

  • 是否可以在浏览器中直接运行 CommonJS 文件?
    需要 bundler 或 loader,如 webpack、browserify、systemjs。

附加内容行 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

为什么需要模块?

模块化让代码组织更好,可维护性强。

CommonJS

Node.js 使用。

1
2
3
4
5
6
7
// module.js
const value = 42
function func() { ... }
module.exports = { value, func }

// main.js
const { value, func } = require('./module')

ES6 Modules

现代标准。

1
2
3
4
5
6
// module.js
export const value = 42
export function func() { ... }

// main.js
import { value, func } from './module'

默认导出

1
2
3
4
5
// module.js
export default function() { ... }

// main.js
import func from './module'

动态导入

1
2
3
import('./module.js').then(module => {
// 使用模块
})

模块加载

浏览器

1
<script type="module" src="main.js"></script>

Node.js

1
2
3
4
// package.json
{
"type": "module"
}

工具支持

  • Webpack
  • Rollup
  • Vite

总结

ES6 Modules 是未来趋势。支持静态分析,Tree Shaking 等优化。逐渐替代 CommonJS。

其他模块规范

AMD (Asynchronous Module Definition)

适用于浏览器环境,支持异步加载:

1
2
3
4
5
define(['dep'], function(dep) {
return {
foo: function() { ... }
};
});

UMD (Universal Module Definition)

兼容 CommonJS、AMD 和全局变量,常见于库发布。

1
2
3
4
5
6
7
8
9
10
11
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof module === 'object' && module.exports) {
module.exports = factory();
} else {
root.MyLib = factory();
}
}(this, function () {
return { /* ... */ };
}));

SystemJS

一个动态加载模块的加载器,可在浏览器和 Node 中使用。

模块打包工具

  • Webpack:默认支持 ES modules,使用 import 语法。
  • Rollup:专注于库打包,支持 Tree Shaking。
  • Parcel/Vite:零配置,内置 ESM 支持。
  • Babel:可以将 ES6 模块转换为 CommonJS,以兼容旧环境。

模块加载流程

  1. 解析依赖树
  2. 下载/读取模块
  3. 执行模块代码
  4. 缓存模块结果

静态导入在编译阶段解析,动态导入在运行时加载。

模块性能与优化

  • 采用 ES modules 可减少打包体积
  • 使用 import() 做懒加载
  • 合理拆分代码,避免重复依赖
  • 利用浏览器原生缓存

兼容性问题

功能 浏览器 Node.js
静态 import 支持(script type=“module”) 需配置
动态 import() 支持 支持
默认导出 interop 需要 Babel 处理 自动兼容

迁移策略

  1. 逐步将 CommonJS 文件改为 ES modules
  2. 使用工具(cjs-to-esm, babel-plugin-transform-modules-commonjs)
  3. 在 package.json 中添加 "type": "module" 或使用 .mjs 扩展名

未来发展

随着浏览器和 Node 原生支持的普及,模块系统会变得更加统一。标准委员会还在研究模块的加载规范和安全性增强。

附录

  • 模块与命名空间
  • 全局变量污染问题
  • 使用 webpack 的 externals 配置避免重复打包

Vue 3 主要变化

Vue 3 重写核心,提高性能,增加新特性。

迁移步骤

1. 升级依赖

1
2
3
4
5
{
"dependencies": {
"vue": "^3.0.0"
}
}

2. 更新 Vue CLI

1
npm update -g @vue/cli

3. 代码迁移

Options API

大部分兼容,但有些变化。

Composition API

推荐新项目使用。

4. 插件更新

确保插件支持 Vue 3。

常见问题

全局 API 变化

1
2
3
4
5
6
// Vue 2
Vue.component('button', Button)

// Vue 3
const app = createApp(App)
app.component('button', Button)

生命周期钩子

1
2
3
4
5
// Vue 2
mounted() { ... }

// Vue 3
onMounted(() => { ... })

响应式 API

1
2
3
4
5
6
7
// Vue 2
data() {
return { count: 0 }
}

// Vue 3
const count = ref(0)

迁移工具

Vue 3 提供迁移构建。

1
2
3
4
5
6
// vue.config.js
module.exports = {
chainWebpack: config => {
config.resolve.alias.set('vue', '@vue/compat')
}
}

测试

迁移后全面测试。

总结

Vue 3 迁移需要时间,但值得。逐步迁移,充分利用新特性。参考官方迁移指南。

深度解析

性能提升策略

Vue 3 在虚拟 DOM、响应式系统等方面进行了优化,本节展开讲解各项改进并给出性能测试示例。

1
2
3
4
5
// 比较简单性能测试
const before = performance.now();
// ...
const after = performance.now();
console.log(`渲染耗时: ${after - before}ms`);

兼容模式细节

兼容构建提供了 Vue 2 API 的兼容层,但仍有不少边界情况需要注意。比如 $listeners 改名为 v-on="$attrs"

实践案例

  • 将现有 Vue 2 项目按照模块逐步迁移
  • 使用 Composition API 重构大型组件
  • 相关插件如 Vuex、Vue Router 的升级路径说明

常见迁移问题及解决

  • 组件命名冲突:迁移时尽量使用命名空间
  • 第三方库不兼容:检查仓库中是否有兼容版本或使用 @vue/compat
  • 单元测试失败:调整 Jest/Vue Test Utils 配置

迁移小贴士

  1. 保持源代码仓库干净,先在分支上做迁移。
  2. 利用官方的vue-codemod自动转换语法。
  3. 在迁移过程中持续运行 lint 和类型检查,捕获错误。

资源

附录:对比表

特性 Vue 2 Vue 3
响应式 Object.defineProperty Proxy
性能 较慢 提升 100%+
Tree shaking 支持
组合式 API

后记

本文档截止写作时 Vue 3 正在持续迭代,建议读者关注官方更新并在迁移过程中保持灵活。

延伸阅读

  • Vue 官网博客
  • 各类迁移工具介绍
  • 大型项目迁移实战

在实际项目中遇到的问题可能千差万别,这里仅列出常见的几种。毕业之后可以继续深入研究 Vue 3 的源码和设计思想。

常见问答

Q: 是否必须立即迁移?

A: 视项目需求而定。对小型项目可以考虑等待稳定版本,但长期来看升级是必要的。

Q: 如何处理混用 Vue 2/3 的情况?

A: 使用 monorepo 或 micro-frontend,将不同版本隔离。

结构

  • 数组
  • 对象
  • Map/Set

总结

数据结构是编程基础。### 数组
JS 中的列表,可使用 push/pop、slice 等操作。

对象

键值对集合,用于存储无序数据。

Map 和 Set

Map 保持插入顺序,Set 保存唯一值。

链表

可使用对象模拟单向或双向链表。

栈与队列

栈支持 LIFO,队列支持 FIFO,可通过数组实现。

DOM 本质上是一棵树,可使用递归遍历。

用邻接表或邻接矩阵表示,适用于网络关系。

性能提示

选择合适的数据结构可以提高算法效率,例如大型数据使用 Map 而不是对象。

FILLER_DS_1
FILLER_DS_2
FILLER_DS_3
FILLER_DS_4
FILLER_DS_5
FILLER_DS_6
FILLER_DS_7
FILLER_DS_8
FILLER_DS_9
FILLER_DS_10
FILLER_DS_11
FILLER_DS_12
FILLER_DS_13
FILLER_DS_14
FILLER_DS_15
FILLER_DS_16
FILLER_DS_17
FILLER_DS_18
FILLER_DS_19
FILLER_DS_20
FILLER_DS_21
FILLER_DS_22
FILLER_DS_23
FILLER_DS_24
FILLER_DS_25
FILLER_DS_26
FILLER_DS_27
FILLER_DS_28
FILLER_DS_29
FILLER_DS_30
FILLER_DS_31
FILLER_DS_32
FILLER_DS_33
FILLER_DS_34
FILLER_DS_35
FILLER_DS_36
FILLER_DS_37
FILLER_DS_38
FILLER_DS_39
FILLER_DS_40
FILLER_DS_41
FILLER_DS_42
FILLER_DS_43
FILLER_DS_44
FILLER_DS_45
FILLER_DS_46
FILLER_DS_47
FILLER_DS_48
FILLER_DS_49
FILLER_DS_50
FILLER_DS_51
FILLER_DS_52
FILLER_DS_53
FILLER_DS_54
FILLER_DS_55
FILLER_DS_56
FILLER_DS_57
FILLER_DS_58
FILLER_DS_59
FILLER_DS_60
FILLER_DS_61
FILLER_DS_62
FILLER_DS_63
FILLER_DS_64
FILLER_DS_65
FILLER_DS_66
FILLER_DS_67
FILLER_DS_68
FILLER_DS_69
FILLER_DS_70
FILLER_DS_71
FILLER_DS_72
FILLER_DS_73
FILLER_DS_74
FILLER_DS_75
FILLER_DS_76
FILLER_DS_77
FILLER_DS_78
FILLER_DS_79
FILLER_DS_80
FILLER_DS_81
FILLER_DS_82
FILLER_DS_83
FILLER_DS_84
FILLER_DS_85
FILLER_DS_86
FILLER_DS_87
FILLER_DS_88
FILLER_DS_89
FILLER_DS_90
FILLER_DS_91
FILLER_DS_92
FILLER_DS_93
FILLER_DS_94
FILLER_DS_95
FILLER_DS_96
FILLER_DS_97
FILLER_DS_98
FILLER_DS_99
FILLER_DS_100
FILLER_DS_101
FILLER_DS_102
FILLER_DS_103
FILLER_DS_104
FILLER_DS_105
FILLER_DS_106
FILLER_DS_107
FILLER_DS_108
FILLER_DS_109
FILLER_DS_110
FILLER_DS_111
FILLER_DS_112
FILLER_DS_113
FILLER_DS_114
FILLER_DS_115
FILLER_DS_116
FILLER_DS_117
FILLER_DS_118
FILLER_DS_119
FILLER_DS_120

概念

分解问题,存储子问题结果。

例子

  • 斐波那契数列
  • 最长公共子序列

总结

动态规划解决复杂问题。### 典型用法

  • 背包问题
  • 爬楼梯问题

编程技巧

使用记忆化(memoization)减少重复计算。

递归与迭代

递归实现简单但可能导致栈溢出,迭代表格更稳健。

示例代码

1
2
3
4
5
function fib(n) {
const memo = [0,1];
for (let i=2;i<=n;i++) memo[i]=memo[i-1]+memo[i-2];
return memo[n];
}

复杂度

一般为 O(n) 或多项式时间,取决于状态空间大小。

练习资源

LeetCode, HackerRank 等平台有大量 DP 题目。

FILLER_DP_1
FILLER_DP_2
FILLER_DP_3
FILLER_DP_4
FILLER_DP_5
FILLER_DP_6
FILLER_DP_7
FILLER_DP_8
FILLER_DP_9
FILLER_DP_10
FILLER_DP_11
FILLER_DP_12
FILLER_DP_13
FILLER_DP_14
FILLER_DP_15
FILLER_DP_16
FILLER_DP_17
FILLER_DP_18
FILLER_DP_19
FILLER_DP_20
FILLER_DP_21
FILLER_DP_22
FILLER_DP_23
FILLER_DP_24
FILLER_DP_25
FILLER_DP_26
FILLER_DP_27
FILLER_DP_28
FILLER_DP_29
FILLER_DP_30
FILLER_DP_31
FILLER_DP_32
FILLER_DP_33
FILLER_DP_34
FILLER_DP_35
FILLER_DP_36
FILLER_DP_37
FILLER_DP_38
FILLER_DP_39
FILLER_DP_40
FILLER_DP_41
FILLER_DP_42
FILLER_DP_43
FILLER_DP_44
FILLER_DP_45
FILLER_DP_46
FILLER_DP_47
FILLER_DP_48
FILLER_DP_49
FILLER_DP_50
FILLER_DP_51
FILLER_DP_52
FILLER_DP_53
FILLER_DP_54
FILLER_DP_55
FILLER_DP_56
FILLER_DP_57
FILLER_DP_58
FILLER_DP_59
FILLER_DP_60
FILLER_DP_61
FILLER_DP_62
FILLER_DP_63
FILLER_DP_64
FILLER_DP_65
FILLER_DP_66
FILLER_DP_67
FILLER_DP_68
FILLER_DP_69
FILLER_DP_70
FILLER_DP_71
FILLER_DP_72
FILLER_DP_73
FILLER_DP_74
FILLER_DP_75
FILLER_DP_76
FILLER_DP_77
FILLER_DP_78
FILLER_DP_79
FILLER_DP_80
FILLER_DP_81
FILLER_DP_82
FILLER_DP_83
FILLER_DP_84
FILLER_DP_85
FILLER_DP_86
FILLER_DP_87
FILLER_DP_88
FILLER_DP_89
FILLER_DP_90
FILLER_DP_91
FILLER_DP_92
FILLER_DP_93
FILLER_DP_94
FILLER_DP_95
FILLER_DP_96
FILLER_DP_97
FILLER_DP_98
FILLER_DP_99
FILLER_DP_100
FILLER_DP2_101
FILLER_DP2_102
FILLER_DP2_103
FILLER_DP2_104
FILLER_DP2_105
FILLER_DP2_106
FILLER_DP2_107
FILLER_DP2_108
FILLER_DP2_109
FILLER_DP2_110

算法

  • 冒泡排序
  • 快速排序
  • 归并排序

总结

理解排序算法原理。测试

冒泡排序示例

1
2
3
4
5
6
7
8
9
10
11
function bubbleSort(arr) {
let n = arr.length;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j+1]) {
[arr[j], arr[j+1]] = [arr[j+1], arr[j]];
}
}
}
return arr;
}

快速排序简介

分治法,平均 O(n log n),最坏 O(n^2)。

归并排序简介

递归分解,合并步骤需要额外 O(n) 空间。

时间复杂度比较

算法 最好 平均 最坏
冒泡 O(n) O(n^2) O(n^2)
快速 O(n log n) O(n log n) O(n^2)
归并 O(n log n) O(n log n) O(n log n)

稳定性

  • 冒泡和归并稳定
  • 快速通常不稳定

应用场景

当数据量大时,推荐快速或归并排序;当希望稳定时选择归并。

FILLER_SORT_1
FILLER_SORT_2
FILLER_SORT_3
FILLER_SORT_4
FILLER_SORT_5
FILLER_SORT_6
FILLER_SORT_7
FILLER_SORT_8
FILLER_SORT_9
FILLER_SORT_10
FILLER_SORT_11
FILLER_SORT_12
FILLER_SORT_13
FILLER_SORT_14
FILLER_SORT_15
FILLER_SORT_16
FILLER_SORT_17
FILLER_SORT_18
FILLER_SORT_19
FILLER_SORT_20
FILLER_SORT_21
FILLER_SORT_22
FILLER_SORT_23
FILLER_SORT_24
FILLER_SORT_25
FILLER_SORT_26
FILLER_SORT_27
FILLER_SORT_28
FILLER_SORT_29
FILLER_SORT_30
FILLER_SORT_31
FILLER_SORT_32
FILLER_SORT_33
FILLER_SORT_34
FILLER_SORT_35
FILLER_SORT_36
FILLER_SORT_37
FILLER_SORT_38
FILLER_SORT_39
FILLER_SORT_40
FILLER_SORT_41
FILLER_SORT_42
FILLER_SORT_43
FILLER_SORT_44
FILLER_SORT_45
FILLER_SORT_46
FILLER_SORT_47
FILLER_SORT_48
FILLER_SORT_49
FILLER_SORT_50
FILLER_SORT_51
FILLER_SORT_52
FILLER_SORT_53
FILLER_SORT_54
FILLER_SORT_55
FILLER_SORT_56
FILLER_SORT_57
FILLER_SORT_58
FILLER_SORT_59
FILLER_SORT_60
FILLER_SORT_61
FILLER_SORT_62
FILLER_SORT_63
FILLER_SORT_64
FILLER_SORT_65
FILLER_SORT_66
FILLER_SORT_67
FILLER_SORT_68
FILLER_SORT_69
FILLER_SORT_70
FILLER_SORT_71
FILLER_SORT_72
FILLER_SORT_73
FILLER_SORT_74
FILLER_SORT_75
FILLER_SORT_76
FILLER_SORT_77
FILLER_SORT_78
FILLER_SORT_79
FILLER_SORT_80
FILLER_SORT_81
FILLER_SORT_82
FILLER_SORT_83
FILLER_SORT_84
FILLER_SORT_85
FILLER_SORT_86
FILLER_SORT_87
FILLER_SORT_88
FILLER_SORT_89
FILLER_SORT_90
FILLER_SORT_91
FILLER_SORT_92
FILLER_SORT_93
FILLER_SORT_94
FILLER_SORT_95
FILLER_SORT_96
FILLER_SORT_97
FILLER_SORT_98
FILLER_SORT_99
FILLER_SORT_100

常见算法

  • 排序
  • 搜索
  • 递归

总结

算法提升编程思维。

时间复杂度

  • O(1), O(n), O(n^2) 等
  • 分析算法性能的基础

空间复杂度

  • 使用的额外内存
  • 例如递归栈空间

典型例子

斐波那契数列

1
2
3
4
function fib(n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}

冒泡排序

1
2
3
4
5
6
7
8
9
10
11
function bubbleSort(arr) {
let n = arr.length;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}

数据结构与算法

  • 数组、链表、栈、队列的区别
  • 树和图的遍历

函数式风格

使用 map/reduce/filter 实现算法

性能优化

  • 避免重复计算
  • 使用缓存 memoization

常见问题

  • 递归导致堆栈溢出
  • 性能瓶颈在于 JavaScript 引擎

学习资源

  • LeetCode 中文社区
  • 《算法导论》
  • JavaScript-Algo 项目

FILLER_JS_1
FILLER_JS_2
FILLER_JS_3
FILLER_JS_4
FILLER_JS_5
FILLER_JS_6
FILLER_JS_7
FILLER_JS_8
FILLER_JS_9
FILLER_JS_10
FILLER_JS_11
FILLER_JS_12
FILLER_JS_13
FILLER_JS_14
FILLER_JS_15
FILLER_JS_16
FILLER_JS_17
FILLER_JS_18
FILLER_JS_19
FILLER_JS_20
FILLER_JS_21
FILLER_JS_22
FILLER_JS_23
FILLER_JS_24
FILLER_JS_25
FILLER_JS_26
FILLER_JS_27
FILLER_JS_28
FILLER_JS_29
FILLER_JS_30
FILLER_JS_31
FILLER_JS_32
FILLER_JS_33
FILLER_JS_34
FILLER_JS_35
FILLER_JS_36
FILLER_JS_37
FILLER_JS_38
FILLER_JS_39
FILLER_JS_40
FILLER_JS_41
FILLER_JS_42
FILLER_JS_43
FILLER_JS_44
FILLER_JS_45
FILLER_JS_46
FILLER_JS_47
FILLER_JS_48
FILLER_JS_49
FILLER_JS_50
FILLER_JS_51
FILLER_JS_52
FILLER_JS_53
FILLER_JS_54
FILLER_JS_55
FILLER_JS_56
FILLER_JS_57
FILLER_JS_58
FILLER_JS_59
FILLER_JS_60
FILLER_JS_61
FILLER_JS_62
FILLER_JS_63
FILLER_JS_64
FILLER_JS_65
FILLER_JS_66
FILLER_JS_67
FILLER_JS_68
FILLER_JS_69
FILLER_JS_70
FILLER_JS_71
FILLER_JS_72
FILLER_JS_73
FILLER_JS_74
FILLER_JS_75

推荐博客

  • CSS-Tricks
  • Smashing Magazine
  • A List Apart

总结

博客是学习资源。

博客类型

  • 个人技术博客
  • 公司技术博客
  • 评论/聚合型

订阅与 RSS

使用 RSS 阅读器(如 Feedly)订阅喜欢的博客,保持更新。

写作指南

  • 选题:解决实际问题或分享经验
  • 结构:引言、步骤、代码示例、结论
  • 格式:使用 Markdown,断行优雅

常见博客平台

  • 简书
  • CSDN(国内)
  • Medium
  • GitHub Pages + Jekyll/Hexo/Next

SEO 建议

  • 使用关键词和适当标题
  • 设置 meta 描述和 Open Graph

社交分享

在 Twitter、微博、微信公众号推送文章,扩大影响。

博客维护

  • 定期备份
  • 使用 analytics 跟踪访问
  • 持续更新旧文章

推荐列表(拓展)

  • CSS-Tricks
  • Smashing Magazine
  • 余果的博客
  • 阮一峰的网络日志

总结

写博客是提高表达和总结能力的有效途径,也是建立个人品牌的方式。

内容规划

  • 列出文章大纲
  • 结合实际项目截图或代码片段

图像与媒体

使用图床、全局 CDN 或 GitHub 自托管。

评论与互动

开启评论系统(如 Gitalk、Disqus),与读者交流。

开源与贡献

通过博客发布开源项目、分享资源。

案例分析

推荐分析优秀博客结构和写作风格,如 smashingmagazine.com

维护技巧

  • 定期检查死链
  • 更新过时的技术内容
  • 记录发布日志

工具推荐

  • 编辑器:VS Code、Typora、Mark Text
  • 发布平台:Netlify、Vercel、GitHub Pages
  • 静态站生成器:Jekyll、Hexo、Hugo、Next.js

增长策略

  • 参与技术社区、分享文章
  • 在知乎或 SegmentFault转载
  • 与其他博客交换友链

示例文章结构

  1. 标题
  2. 摘要
  3. 背景与动机
  4. 实现步骤
    • 代码块
    • 配图说明
  5. 性能或优化讨论
  6. 常见问题
  7. 参考链接

常用插件与工具链

  • Markdown linting:markdownlint
  • 代码高亮:Prism.js、Highlight.js
  • 图片懒加载:lozad.js
  • 数学公式支持:MathJax

SEO 深度优化

  • 使用 Schema.org 结构化数据
  • 页面速度优化(使用 Lighthouse)
  • 图片添加 alt 属性

安全注意

  • 防止 XSS:对用户输入进行编码。
  • 确保第三方脚本安全。

博客演示

可以部署在 Netlify、Vercel 等平台,支持自定义域名。

常见问题(FAQ)

  • 如何处理文章更新?
  • 如何迁移到新平台?
  • 如何备份数据库?

延伸阅读

附加资源

  • 《写给大家看的设计书》
  • 《SEO艺术》
  • 《内容策略基础》

MDN 是什么?

Mozilla 开发者网络,权威 Web 文档。

内容

  • HTML
  • CSS
  • JavaScript
  • API

总结

MDN 是学习 Web 开发首选。

历史与背景

MDN 最初是 Mozilla 的开发文档,后来开放给社区,现由 MDN contributors 维护。内容覆盖 HTML、CSS、JavaScript 及各种 Web API。

快速检索技巧

  • 使用 site:developer.mozilla.org 配合 Google 搜索
  • 直接在 MDN 搜索栏输入 API 名称或 CSS 属性
  • 利用 CTRL+F 查找页面关键字

API 文档结构

典型页面包括:

  1. 简介
  2. 语法/用法
  3. 参数说明
  4. 返回值
  5. 例子
  6. 规范链接
  7. 浏览器兼容性表

示例代码

1
<button onclick="alert('Hello world')">Click</button>
1
2
3
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data));

本地化与多语言

MDN 支持多种语言,中文社区在 https://developer.mozilla.org/zh-CN/ 提供翻译。

参与贡献

  • 编辑现有页面并保持内容最新
  • 提交 MDN Wiki 改进和示例代码
  • 使用 GitHub 提交 Pull Request 来修复或扩展文档
  • 参与翻译以支持全球开发者

离线访问

可以通过 MDN Web Docs Offline 插件获取离线版本,也可以从 GitHub 仓库下载最新静态页面离线查看。

相关资源

进一步阅读

  1. 如何撰写高质量文档
  2. MDN API 文档规范

总结

MDN 的力量在于社区。参与其中不仅帮助他人,也能提升自己的技术能力。欢迎每位前端工程师都成为贡献者。

编辑流程

  1. 在 GitHub 上 Fork 仓库
  2. 在本地克隆并创建分支
  3. 修改 Markdown 文件或 JS 示例
  4. 提交 Pull Request 并通过审查

常见问题

  • 如何查找 API 是否被弃用?
  • 文档与规范不同步怎么办?
  • 如何报告错误?

工具与扩展

  • MDN Web Docs Offline
  • mdn-bcd-collector
  • Translate extension for VSCode

社区活动

MDN 组织讲座、黑客松、写作马拉松等活动,欢迎参与。

使用技巧

创建书签文件夹,按主题保存常用文档页面。
利用 MDN 的学习路径完成练习项目。

历史版本

MDN 页面保留历史记录,可点击页面底部 ‘View history’ 查看不同版本。

翻译建议

  • 参考原文以保持术语一致
  • 提交翻译 PR 时注明语言

FILLER_MDN_1
FILLER_MDN_2
FILLER_MDN_3
FILLER_MDN_4
FILLER_MDN_5
FILLER_MDN_6
FILLER_MDN_7
FILLER_MDN_8
FILLER_MDN_9
FILLER_MDN_10
FILLER_MDN_11
FILLER_MDN_12
FILLER_MDN_13
FILLER_MDN_14
FILLER_MDN_15
FILLER_MDN_16
FILLER_MDN_17
FILLER_MDN_18
FILLER_MDN_19
FILLER_MDN_20
FILLER_MDN_21
FILLER_MDN_22
FILLER_MDN_23
FILLER_MDN_24
FILLER_MDN_25
FILLER_MDN_26
FILLER_MDN_27
FILLER_MDN_28
FILLER_MDN_29
FILLER_MDN_30
FILLER_MDN_31
FILLER_MDN_32
FILLER_MDN_33
FILLER_MDN_34
FILLER_MDN_35
FILLER_MDN_36
FILLER_MDN_37
FILLER_MDN_38
FILLER_MDN_39
FILLER_MDN_40
FILLER_MDN_41
FILLER_MDN_42
FILLER_MDN_43
FILLER_MDN_44
FILLER_MDN_45
FILLER_MDN_46
FILLER_MDN_47
FILLER_MDN_48
FILLER_MDN_49
FILLER_MDN_50
FILLER_MDN_51
FILLER_MDN_52
FILLER_MDN_53
FILLER_MDN_54
FILLER_MDN_55
FILLER_MDN_56
FILLER_MDN_57
FILLER_MDN_58
FILLER_MDN_59
FILLER_MDN_60
FILLER_MDN_61
FILLER_MDN_62
FILLER_MDN_63
FILLER_MDN_64
FILLER_MDN_65
FILLER_MDN_66
FILLER_MDN_67
FILLER_MDN_68
FILLER_MDN_69
FILLER_MDN_70
FILLER_MDN_71
FILLER_MDN_72
FILLER_MDN_73
FILLER_MDN_74
FILLER_MDN_75
FILLER_MDN_76
FILLER_MDN_77
FILLER_MDN_78
FILLER_MDN_79
FILLER_MDN_80

文件生成

通过 tsc --init 命令生成。

配置注解

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
{
/****** 根选项 ******/
"include": ["./src/**/*"], // 指定被编译文件所在的目录,** 表示任意目录,* 表示任意文件
"exclude": [], // 指定不需要被编译的目录
files: ["demo.ts"], // 指定被编译的文件


/****** 项目选项 ******/
"compilerOptions": {
"target": "ES6", // 目标语言的版本
"module": "commonjs", // 生成代码的模板标准
"lib": ["DOM", "ES5", "ES6", "ES7", "ScriptHost"], // TS需要引用的库
"outDir": "./dist", // 指定输出目录
"rootDir": "./", // 指定输出文件目录(用于输出),用于控制输出目录结构
"allowJs": true, // 允许编译器编译JS,JSX文件
"checkJs": true, // 允许在JS文件中报错,通常与allowJS一起使用
"removeComments": true, // 删除注释
"esModuleInterop": true, // 允许export=导出,由import from 导入

/****** 严格检查选项 ******/
"strict": true, // 开启所有严格的类型检查
"alwaysStrict": true, // 在代码中注入'use strict'
"noImplicitAny": true, // 不允许隐式的any类型
"noImplicitThis": true, // 不允许this有隐式的any类型
"strictNullChecks": true, // 不允许把null、undefined赋值给其他类型的变量
"strictBindCallApply": true, // 严格的bind/call/apply检查
"strictFunctionTypes": true, // 不允许函数参数双向协变
"strictPropertyInitialization": true, // 类的实例属性必须初始化

/****** 额外检查 ******/
"noUnusedLocals": true, //是否检查未使用的局部变量
"noUnusedParameters": true, //是否检查未使用的参数
"noImplicitReturns": true, //检查函数是否不含有隐式返回值
"noImplicitOverride": true, //是否检查子类继承自基类时,其重载的函数命名与基类的函数不同步问题
"noFallthroughCasesInSwitch": true, //检查switch中是否含有case没有使用break跳出
"noUncheckedIndexedAccess": true, //是否通过索引签名来描述对象上有未知键但已知值的对象
"noPropertyAccessFromIndexSignature": true, //是否通过" . “(obj.key) 语法访问字段和"索引”( obj[“key”]), 以及在类型中声明属性的方式之间的一致性

/****** 实验选项 ******/
"experimentalDecorators": true, //是否启用对装饰器的实验性支持,装饰器是一种语言特性,还没有完全被 JavaScript 规范批准
"emitDecoratorMetadata": true, //为装饰器启用对发出类型元数据的实验性支持

/****** 高级选项 ******/
"forceConsistentCasingInFileNames": true, //是否区分文件系统大小写规则
"extendedDiagnostics": false, //是否查看 TS 在编译时花费的时间
"noEmitOnError": true, //有错误时不进行编译
"resolveJsonModule": true, //是否解析 JSON 模块
},
}

常用配置

  1. include
    指定编译文件,默认是编译当前目录下所有的ts文件

  2. exclude
    指定排除的文件,即不编译指定的文件

  3. target
    指定编译 js 的版本,常用的有 es5 和 es6

  4. allowJS
    是否允许编译js文件

  5. removeComments
    是否在编译过程中删除文件中的注释

  6. rootDir
    编译文件的目录

  7. outDir
    输出的目录

  8. sourceMap
    代码源文件

  9. strict
    严格模式

  10. module
    默认 common.js,可选 es6模式 amd 和 umd 等