普通视图

发现新文章,点击刷新页面。
昨天以前颜海镜

揭秘自定义 ESLint 插件开发,打造高效开发环境

2024年8月21日 08:00

本文已收录到《jsmini系列文章

在工作中,我们会沉淀了一些最佳实践,一般工作中的一个项目可能由多个开发者负责,在这样的背景下,很难做到每个开发者对最佳实践都了然于胸,在遇到人员更迭的时候,就更难受了。

虽然可以通过代码审查发现问题,但是代码审查存在两个问题:一个是滞后问题,代码审查时已经开发完了;另一个是靠人来审查,难以 100%保证质量。

如何保障团队代码风格,最佳实践的一致性,让代码看起来就是一个人写的,本身就是一个难题。

如果能有一个智能助手,实时提示代码中的哪些部分可以使用工具库中的函数代替就好了。对于前端来说,这个助理就是 ESLint。

那么如何让 ESLint 支持我们的最佳实践呢,这可以通过 ESLint 的自定义插件来实现。要开发 ESLint 插件需要一些知识储备和经验,本文我将通过一个实例来教大家如何写一个 ESLint 插件。

本文通过一个真实案例来讲解,这个案例来源于我的实际工作,通过编写 ESLint 插件,并集成到项目,帮我解决了最佳实践的推广落地问题。

背景知识

下面先来介绍下背景知识,在我之前的文章《如何回答面试中的JavaScript获取变量类型问题》中,提到过使用 typeof 和 instanceof 来判断变量类型是存在很多坑的,不信你看下面的例子,如果你对这个问题感兴趣,欢迎阅读我上面的文章:

typeof []; // 'object'
typeof {}; // 'object' typeof c; // 'object'

[] instanceof Array // true
[] instanceof Object // true 注意这里

下面将写两个 ESLint 插件来解决对上面两个问题的校验。

插件

创建 ESLint 插件,ESLint 推荐使用 Yeoman generator。首先需要安装 Yeoman,安装命令如下:

$ npm i -g yo

Yeoman 是一款通用的初始化工具,想要初始化 ESLint 插件,需要安装 ESLint 模板,安装命令如下:

$ npm i -g generator-eslint

接下来,新建一个目录,目录名字按照自己喜好就行,命令如下:

$ mkdir eslint-plugin-utils

切换到上面新建的目录,执行“yo eslint:plugin”命令会进入交互界面,询问作者、插件名字等,输入如图所示的内容即可。

稍等片刻即可完成自动初始化,初始化成功后的目录结构如下所示。其中,lib/rules 目录存放自定义规则,tests/lib/rules 目录存放规则对应的单元测试代码。

.
├── .eslintrc.js
├── README.md
├── lib
│   ├── index.js
│   └── rules
├── package-lock.json
├── package.json
└── tests
    └── lib
        └── rules

ESLint 推荐使用测试驱动开发,要求每个规则都有完整的单元测试。

type-typeof-limit

使用 typeof 操作符判断一个变量为对象时可能存在问题,如下面的 3 行代码都返回 true:

typeof {} === 'object';
typeof [] === 'object';
typeof null === 'object';

下面写一个新规则,当发现“typeof * === ‘object’”时给出报错提示。首先使用“yo eslint:rule”命令新建一个规则,在询问界面中输入如图所示的内容。

完成上述操作后,会生成两个文件,分别是 lib/rules/type-typeof-limit.js 和 tests/lib/
rules/type-typeof-limit.js。打开前一个文件,其内容如下:

module.exports = {
  meta: {
    type: null, // `problem`, `suggestion`, or `layout`
    docs: {
      description: 'typeof不能用于对象和数组,请使用@jsmini/type',
      category: 'Fill me in',
      recommended: false,
      url: null, // URL to the documentation page for this rule
    },
    fixable: null, // Or `code` or `whitespace`
    schema: [], // Add a schema if the rule has options
  },

  create(context) {
    return {
      // visitor functions for different types of nodes
    };
  },
};

其中,meta 是规则的元数据,这里需要关注的字段的含义如下,更多字段可以查看 ESLint 官网。

  • type:规则的类型,problem 代表报错,这里需要将 type 的值修改为 problem。
  • docs:存放规则文档信息。
    • description:指定规则的简短描述,需要填写。
    • category:指定规则的分类信息,包括 Possible Errors、Best Practices、Variables 等,这里可以填入 Best Practices。
  • fixable:表示这个规则是否提供自动修复功能,当其值被设置为 true 时,还需要提供自动修复的代码。

create 函数里面是具体的逻辑,其返回一个对象,该对象的属性名表示节点类型,在向下遍历树时,当遍历到和属性名匹配的节点时,ESLint 会调用属性名对应的函数。例如,我们要写的这个规则的 create 函数如下,其含义是每次遇到 BinaryExpression 节点,都会调用传递给 BinaryExpression 属性的函数。

module.exports = {
  create(context) {
    return {
      BinaryExpression: (node) => {},
    };
  },
};

现在读者可能还不理解 BinaryExpression 的含义,这里需要介绍 ESLint 的原理。ESLint 会将每个 JavaScript 文件解析为抽象语法树(Abstract Syntax Tree,AST),简称语法树。ESLint 官网提供了一款工具,可以查看指定代码解析后的 AST。例如,下面的代码:

typeof a === 'object';

ESLint 解析上述代码后会返回一个嵌套的 AST,每个节点中的 type 属性表示当前节点的类型,观察下面的 AST,上面的判断表达式可以用下面的逻辑来判断:

  • BinaryExpression 节点。
  • left.operator 为 typeof。
  • operator 为===或==。
  • right 为 Literal,并且 value 为 object。

ESLint 会把 JavaScript 代码解析为 AST,该 AST 使用 JSON 格式表示的代码如下:

{
  "type": "Program",
  "start": 0,
  "end": 21,
  "body": [
    {
      "type": "ExpressionStatement",
      "start": 0,
      "end": 21,
      "expression": {
        "type": "BinaryExpression",
        "start": 0,
        "end": 21,
        "left": {
          "type": "UnaryExpression",
          "start": 0,
          "end": 8,
          "operator": "typeof",
          "prefix": true,
          "argument": {
            "type": "Identifier",
            "start": 7,
            "end": 8,
            "name": "a"
          }
        },
        "operator": "===",
        "right": {
          "type": "Literal",
          "start": 13,
          "end": 21,
          "value": "object",
          "raw": "'object'"
        }
      }
    }
  ],
  "sourceType": "module"
}

ESLint 遍历到 BinaryExpression 节点后会执行传递给 BinaryExpression 属性的函数,并将 BinaryExpression 节点传递给这个函数,然后进行上面的逻辑判断,如果为 true,则使用 context.report 报告错误。示例代码如下:

module.exports = {
  create(context) {
    return {
      BinaryExpression: (node) => {
        const operator = node.operator;
        const left = node.left;
        const right = node.right;

        if (
          (operator === '==' || operator === '===') &&
          left.type === 'UnaryExpression' &&
          left.operator === 'typeof' &&
          right.type === 'Literal' &&
          right.value === 'object'
        ) {
          context.report({
            node,
            message: 'typeof不能用于对象和数组,请使用 @jsmini/type',
          });
        }
      },
    };
  },
};

前面提到了 ESLint 推荐使用测试驱动开发,上面的代码可以通过写单元测试来快速验证结果,修改 tests/lib/rules/type-typeof-limit.js 文件中的内容如下,其中包括三个单元测试:一个合法的单元测试和两个非法的单元测试。

const rule = require('../../../lib/rules/type-typeof-limit'),
  RuleTester = require('eslint').RuleTester;

const msg = 'typeof不能用于对象和数组,请使用@jsmini/type';

const ruleTester = new RuleTester();
ruleTester.run('type-typeof-limit', rule, {
  valid: [{ code: 'typeof a == "number"' }, { code: 'a == "object"' }],

  invalid: [
    {
      code: 'typeof a == "object"',
      errors: [
        {
          message: msg,
        },
      ],
    },
    {
      code: 'typeof a === "object"',
      errors: [
        {
          message: msg,
        },
      ],
    },
  ],
});

写好单元测试后,执行“npm test”命令即可运行测试,如果看到如图所示的输出,则表示单元测试通过了。

下面在真实实验环境下新建插件,由于我们的插件还没有发布,因此需要通过 link 的方式使用。

首先在插件目录下执行如下命令,这会将本地的插件链接到本地的 npm 全局目录。

$ npm link

新建一个空项目 eslint-plugin-utils-demo,并初始化 ESLint 配置,接下来,在 eslint-
plugin-utils-demo 根目录下执行下面的命令,这会在 node_modules 目录下创建一个软链接。

$ npm link @jsmini/eslint-plugin-utils

接下来,修改 eslint-plugin-utils-demo 根目录下的.eslintrc.js 文件,添加如下代码:

module.exports = {
  plugins: ['@jsmini/utils'],
  rules: {
    '@jsmini/utils/type-typeof-limit': 2,
  },
};

在本地新建一个 xxx.js 文件,并在该文件中输入如下代码:

typeof a === 'object';

如果能够看到如图所示的红色波浪线,当将鼠标指针悬停到波浪线上时,显示如图所示的错误信息,则表示成功了。

type-instanceof-limit

参考上面 type-typeof-limit 插件的内容,可以实现校验如下的代码:

a instanceof Object;

新建一个名字为 type-instanceof-limit 的插件,这部分就不再展开介绍了,该插件的核心代码如下:

module.exports = {
  create(context) {
    function check(node) {
      const operator = node.operator;

      if (operator === 'instanceof') {
        context.report({
          node,
          message: 'instanceof操作符可能存在问题,请使用@jsmini/type',
        });
      }
    }

    return {
      BinaryExpression: check,
    };
  },
};

recommended

现在已经有 2 个规则了,随着规则的增多,需要用户手动修改 rules。ESLint 配置示例如下:

module.exports = {
  plugins: ['@jsmini/utils'],
  rules: {
    '@jsmini/utils/type-typeof-limit': 2,
    '@jsmini/utils/type-instanceof-limit': 2,
  },
};

其实插件可以提供推荐的配置,类似 eslint:recommended,用户直接使用推荐的配置即可。修改 lib/index.js 文件中的 exports,添加 configs 配置,示例代码如下:

module.exports = {
  rules: requireIndex(__dirname + '/rules'),
  configs: {
    plugins: ['@jsmini/utils'],
    rules: {
      '@jsmini/utils/type-typeof-limit': 'error',
      '@jsmini/utils/type-instanceof-limit': 'error',
    },
  },
};

接下来,用户就可以直接像下面这样使用,而不需要单独配置 plugins 和 rules 了。

module.exports = {
  extends: ['@jsmini/utils:recommended'],
};

总结

在本文中,我们探讨了如何通过编写自定义 ESLint 插件来保障团队代码风格和最佳实践的一致性。我们首先介绍了 ESLint 插件开发的背景知识,然后详细讲解了如何使用 Yeoman generator 创建 ESLint 插件。通过具体案例,我们编写了两个 ESLint 插件:type-typeof-limittype-instanceof-limit,并展示了如何在项目中集成和测试这些插件。此外,我们还讨论了如何为插件提供推荐配置,以简化用户的配置过程。

通过这些步骤,我们可以确保团队代码风格统一,减少代码审查中的问题,提高代码质量。

欢迎大家阅读和分享这篇文章,如果有任何疑问或建议,欢迎在评论区留言。感谢大家的支持和阅读!

如何优雅的安装Node.js和npm

2024年5月1日 08:00

🚀 极速安装指南 (TL;DR)

如果你不想深究原理,只想在 Mac (Zsh) 上快速搞定 无 sudo 权限烦恼 的 Node.js 环境,请直接在终端执行以下命令:

# 1. 确保已安装 Homebrew
brew install n

# 2. 配置 n 的目录与环境变量 (解决安装 Node 需要 sudo 的问题)
mkdir -p $HOME/.n
echo 'export N_PREFIX=$HOME/.n' >> ~/.zshrc
echo 'export PATH=$N_PREFIX/bin:$PATH' >> ~/.zshrc
source ~/.zshrc

# 3. 安装最新的 LTS 版 Node.js
n lts

# 4. 配置 npm 全局安装路径 (解决 npm i -g 需要 sudo 的问题)
mkdir -p $HOME/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

📚 详细讲解

我之前写过一篇小白的 Mac 上手指南(干货),受到了很多掘友好评,最近重新安装环境,我发现以前安装 Node 和 npm 的方法还有优化空间,原来老司机也有翻车的时候。

所以我决定重写一篇文章,本文的技巧一定会让你效率翻倍,老规矩本文不止告诉你怎么做,还告诉你为什么这么做。

Node.js 是现代 Web 开发中不可或缺的工具,随着项目需求的变化,可能需要使用不同版本的 Node.js。因此,优雅地管理和切换 Node.js 版本显得尤为重要。本文将介绍如何在 Mac 上使用 Homebrew 安装n工具来管理多个 Node.js 版本,并解决 npm 全局安装包时需要sudo权限的问题。

开始之前先说明下,我的系统是 macOS 14.x,本文中介绍的工具安装方法,可能具有时效性,比如 brew 的安装可能会过时,如果遇到问题,可以去官网查看最新安装方法。

优雅地安装n

n是一个 Node.js 版本管理工具,允许你轻松地安装、管理和切换多个 Node.js 版本。它的使用简单直观,非常适合开发者。通过n,你可以在不同版本的 Node.js 之间快速切换,以满足不同项目的需求。

为什么选择 Homebrew?

Homebrew 是 macOS 上的一个包管理工具,它使得软件的安装和管理变得非常方便。通过 Homebrew 安装n,可以简化安装过程,并确保环境的整洁和一致性。

使用 Homebrew 安装n

第 1 步,安装 Homebrew,如果你还没有安装 Homebrew,可以通过以下命令在终端中安装:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

第 2 步,使用 Homebrew 安装n

brew install n

安装完成后,你就可以使用n来管理 Node.js 版本了。

优雅的管理 Node.js 多版本

为什么使用n来管理 Node.js 版本?

不同项目可能依赖于不同版本的 Node.js,手动管理这些版本不仅麻烦,而且容易出错。n简化了这个过程,使得安装、切换和卸载 Node.js 版本变得非常方便。

类似的工具还有 nvm,这里不对二者的优缺点做评价,笔者平时比较习惯使用 n,所以这里介绍的是 n,当然 nvm 也可以解决这个问题。

设置 N_PREFIX 环境变量

默认情况下,n 会将 Node.js 安装到 /usr/local 目录下,这通常需要管理员权限。为了避免权限问题,我们可以设置 N_PREFIX 环境变量,将 n 安装的 Node.js 版本放在用户目录下。

这个小技巧我最近才知道,再也需要 sudo 了,^_^。

创建自定义目录

首先,为n创建一个目录来存放 Node.js 版本:

mkdir -p $HOME/.n

设置环境变量

如果现在使用 n 安装了 Node.js,你会发现在命令行里执行 node 命令会说找不到 node 命令,这是因为我们改变了 n 的默认安装路径,需要将新的路径加入到 PATH 中,在你的 shell 配置文件中(如.bashrc.zshrc)添加以下行:

export N_PREFIX=$HOME/.n
export PATH=$N_PREFIX/bin:$PATH

保存并执行以下命令使配置生效:

source ~/.bashrc   # 对于Bash用户
source ~/.zshrc    # 对于Zsh用户

使用n安装 Node.js 版本

安装最新的稳定版

通过以下命令安装最新的稳定版 Node.js:

n stable

安装最新的 LTS(长期支持)版

LTS 版本通常更稳定,适合在生产环境中使用。通过以下命令安装最新的 LTS 版本:

n lts

安装指定版本(例如 14.17.0)

有时你可能需要特定版本的 Node.js,可以使用以下命令安装:

n 14.17.0

切换 Node.js 版本

列出已安装的版本并选择一个进行切换:

n

卸载不需要的 Node.js 版本

为了保持系统整洁,可以卸载不再需要的 Node.js 版本:

n rm 14.17.0

解决 npm 全局命令需要 sudo 的问题

为什么 npm 全局安装需要 sudo?

默认情况下,如果你安装的 npm 包会创建一个全局命令的话,比如安装 pnpm,会涉及到权限问题。

这是因为 npm 全局安装包会写入系统目录(例如/usr/local),这通常需要管理员权限。因此,在安装全局包时需要使用sudo,这可能会带来一些不便和安全问题。

解决方案:创建用户目录用于全局安装

为了解决这个问题,我们可以为 npm 全局包创建一个用户目录,这样可以避免使用sudo安装全局包。

创建自定义目录

首先,为全局 npm 包创建一个目录:

mkdir -p $HOME/.npm-global

设置 npm 配置以使用自定义目录

然后,配置 npm 使用这个新的全局目录:

npm config set prefix '~/.npm-global'

修改环境变量

为了确保系统能够找到全局安装的 npm 包,需要将新目录的bin子目录添加到PATH环境变量中。在你的 shell 配置文件中添加以下行:

export PATH="$HOME/.npm-global/bin:$PATH"

保存并执行以下命令使配置生效:

source ~/.bashrc   # 对于Bash用户
source ~/.zshrc    # 对于Zsh用户

总结

通过本文,你学会了如何优雅地在 Mac 上使用 Homebrew 安装n,并使用n来管理多个 Node.js 版本。同时,你还学会了如何解决 npm 全局安装包时需要sudo的问题。希望这些技巧能帮助你在开发过程中更加高效。

这下终于告别 sudo 了,太开心了(^▽^)。

原创不易,感谢阅读,你还知道什么 Node.js 和 npm 的技巧,欢迎评论区交流。

世界读书日:ChatGPT 时代你多久没读书了?

2024年4月22日 08:00

4.23世界读书日,今天我想和大家聊聊关于我和书籍的故事,以及我对读书的认识。在开始之前我想先问读者一个问题,你有多久没读书了?欢迎在评论区留言。

最近我观察到一个现象,就是身边的同事朋友,读书的变少了,特别是那些刚步入职场的新人,也不爱读书了。这与我刚开始工作时的情况形成了鲜明对比,那时候,几乎每个人都有几本正在读的书,我们之间经常会互相推荐书籍,讨论观点。我印象特别深刻的是,公司给的读书经费,每到电商平台搞活动,每个人都会买好几本书。

在我的大学时代,图书馆成了我最常去的地方。那里的前端开发书籍,我几乎一一阅读过。这种全面而深入的学习方法,为我的前端技术打下了坚实的基础。当然在大模型时代的今,这种学习方式可能被认为低效。然而,对我而言,这种能够全面掌握一门技术的方法,不仅没有浪费时间,反而是一种幸福。我能够在不浪费任何一个知识点的情况下阅读书籍,这让我感到非常满足和快乐。

能够很浪费时间的去读书是一件很幸福的事,这在工作后变的非常奢侈。

工作后,我保持了这种阅读习惯。我开始自己购买书籍,大约买了几百本。单在图灵出版社,我购买了80多本书。我特别喜欢图灵书籍扉页上的那句话:“站在巨人的肩膀上”。读书确实让我站在了巨人的肩膀上,使我在前端技术领域取得了飞速的进展,各种技术手法都变得信手拈来。

image.png

我的书籍之旅不止于此。随着时间的推移,我开始尝试写作,包括撰写博客、进行技术分享和编写开源库。最终,我还出版了自己的技术书籍《React状态管理与同构实战》《现代JavaScript库开发:技术、原理与实战》。这是年轻时的我从未敢想象的成就。书籍不仅丰富了我的知识,也实现了我的梦想,给我的生活带来了巨大的变化。关于写书的更多故事,我希望在未来有机会再与大家分享。

读书不香了?

在个人层面,我发现尽管我依然热爱阅读,我的阅读频率却逐年下降。如今,不用为了买书而省吃俭用,想要的书,出版社基本都会送我。但实际上,我发现自己的阅读量减少主要是由于几个方面的原因:首先,工作的忙碌占据了我大部分时间,空闲时间变得更加宝贵。其次,随着年龄的增长,家庭责任也随之增加,不仅要照顾年幼的孩子,还要关心年长的父母。此外,随着年龄的增长,我的体力和精力也有所下降,我开始更多地感受到身体对休息的需求。

我感觉全世界都在找我要时间,工作要,家庭要,连我的身体也向我要休息的时间

在大众层面,阅读传统纸质书的习惯同样受到多种因素的影响:

  1. 多样化的学习媒介:随着技术的发展,人们有更多选择来获取知识,如在线课程、教育视频等,这些都在一定程度上替代了传统的书籍阅读。
  2. 算法驱动的内容分发:社交媒体和视频平台的算法优化了用户的内容消费习惯,使得短视频等形式的内容更能吸引用户的注意力,占据了原本可能用于阅读的时间。
  3. 信息过载:现代社会信息泛滥,人们每天都被大量信息所包围,这不仅分散了人们的注意力,也使得他们难以有足够的时间和精力来进行深度阅读。
  4. 阅读习惯的改变:数字化阅读逐渐取代纸质阅读,尽管便捷,但也可能影响人们的阅读深度和持久性。

通过上述分析,我们可以看到,不爱读书的原因是多方面的,涉及个人生活的变化以及更广泛的社会文化影响。这些因素共同作用,导致了当代社会阅读传统书籍的习惯逐渐减少。

多读书

对我个人而言,阅读一直是获取知识、启发思考和个人成长的重要途径。通过阅读,我能够不断吸收新知识,拓宽视野,这不仅帮助我在技术领域保持领先,也促进了我的思维方式的多样化。此外,阅读也是我放松和减压的方式之一。在阅读的过程中,我可以暂时脱离日常工作的压力,享受沉浸在书籍世界的平静。

阅读对技术人员来说,不仅是一种学习新技术的方式,更是一种积累深厚专业知识和智慧的方法。以下是几个关键点:

  1. 专业性和权威性,相比网络上零散和未经验证的信息,专业书籍提供的内容经过严格的审稿和校对,具有较高的权威性。技术书籍通常由领域内的专家撰写,这些作者往往拥有丰富的实战经验和深厚的理论基础,能提供最新、最准确的技术知识。对技术人员而言,这意味着他们可以依靠这些书籍来构建可靠和稳固的专业基础。

  2. 结构化的知识体系,书籍通常按照从浅入深的方式组织内容,提供清晰的结构化知识。这种结构化的学习方式可以帮助技术人员系统地理解复杂概念,按照逻辑顺序建立知识框架,从而更有效地掌握技术细节和应用场景。此外,系统的结构也便于读者回顾和巩固已学知识,增强学习效果。

  3. 站在巨人的肩膀上,通过阅读书籍,技术人员可以以较低的成本快速吸收行业内先驱和专家的经验和见解。这种经验的传承,使他们能够避免在实际工作中重复别人的错误,加速自己的成长和成功。花费几十元购买一本书,实际上是在以极低的成本获取作者多年甚至数十年的经验和智慧积累,这在任何其他形式的学习资源中都是难以比拟的。

这些好处表明,对于渴望在技术领域深入发展和保持竞争力的专业人员而言,阅读不仅是一种知识获取的手段,更是一种投资自己的方式。通过阅读,技术人员能够在技术革新的浪潮中保持领先,不断推动个人和职业的成长。

AI与读书

在人工智能,尤其是大模型如ChatGPT的兴起下,我们不禁要问:在这样一个“无所不知”的AI时代,读书是否还有意义?首先,尽管AI可以提供广泛的知识和数据,但它主要依赖于已有的信息库和编程算法,其回答和解析通常缺乏深度的批判性思考和人类独到的见解。因此,书籍的价值在于它们提供了深度、反思和批判性分析——这些是AI在当前技术水平下难以完全复制的。此外,阅读书籍的过程本身就是一种思维训练,能够促进思考的深度和广度,这在AI的答案中往往无法得到。

在AI如此发达的时代,适应新技术同时保持有效的阅读习惯也显得尤为重要。首先,利用AI进行预筛选和信息摘要可以帮助读者更快地找到所需的书籍和资料,提高阅读的效率。例如,可以使用AI推荐系统根据个人的阅读历史和偏好推荐书籍,或者使用AI工具来摘要长篇书籍的关键内容,帮助读者决定哪些内容值得深入阅读。

同时,结合AI技术和传统的深度阅读,可以形成一种新的学习模式。在获取初步信息和知识框架后,读者应该深入阅读原始书籍或文献,以获得更深层次的理解和批判性思考。此外,AI也可以用于辅助理解复杂概念和术语,通过交互式学习增强阅读体验。

总的来说,尽管AI提供了许多便利,但它不应取代传统的阅读和学习方法。相反,应将其视为一个有力的辅助工具,帮助人们以更高效、更有针对性的方式进行学习和研究。这样的结合不仅可以保持阅读的传统价值,也能够充分利用现代技术的优势。

总结

在纪念世界读书日之际,通过回顾个人与书籍的深厚联系以及分析现代阅读习惯的变迁,我们得以重新审视在快速发展的技术环境中,阅读的不朽价值。尽管我们面临着时间紧迫、信息过载以及新媒介的挑战,书籍仍然在我们的职业成长、知识积累和思维发展中扮演着无可替代的角色。书籍不仅是知识的源泉,更是智慧的灯塔,指引我们在复杂世界中导航。

此外,随着AI技术如ChatGPT的发展,我们被赋予了新的工具来增强我们的学习过程。这些技术,虽然提供便利和效率,但不应视为替代传统阅读的手段。相反,我们应该看到AI的辅助角色,利用它来筛选信息、优化阅读选择,并通过深度阅读补充那些AI无法提供的批判性思维和深层次理解。

在我们追求技术进步的同时,让我们不忘回顾那些塑造了我们思想和文化的书页。愿每个人都能在忙碌的生活中找到书籍的宁静角落,继续通过阅读来探索、学习和成长。

在未来的日子里,让我们一起用书籍连接过去与未来,用阅读桥接现实与理想。让阅读成为每天不可或缺的一部分,不仅因为它的实用性,更因为它带给我们的无穷乐趣和深刻启示。

书籍推荐

对于希望深化技术理解的读者,我推荐《JavaScript高级程序设计》以及《你不知道的JavaScript》系列。对于想要了解前端库开发的读者,可以阅读我的作品《现代JavaScript库开发:原理、技术与实践》。

程序员的出路:技术变迁与时代背景的双重挑战

2024年3月30日 08:00

在这个充满不确定性的时代,焦虑似乎成了每个人心中不可避免的情绪,准备好,我要开始贩卖焦虑了 😂😂😂。

最近,裁员的消息真的太多了,下面是我最近看到的裁员消息:

  • 2024 年 3 月份,字节内部公开信曝光,飞书裁员或 20%。
  • 2024 年 1 月份,网传网易裁员 1600 人,相当于总员工的六分之一。

我认识的一个百度朋友和我说他们部门裁员了,裁的全是高 T;一个图森未来的朋友也跟我说,他们部门裁员了。

前段时间看到一个好玩的编程方式,叫做防御式编程,这里可不是说写健壮的代码,相反而是写屎山代码,从而增加自己的不可替代性。更有意思的是,在裁员的大背景下,防御式编程已经不好使了,因为产品不能盈利,代码也就没有价值了。

作为一名程序员,我感受到了前所未有的压力。我们常说,技术是金钱的保障,但在这个动荡的时代,似乎连技术也难以为我们带来安全感。每一个被裁的消息都像一记重锤,敲打着我们脆弱的心灵。

然而,我不想只是停留在传播焦虑之中。是时候面对现实,思考我们该如何在这个充满挑战的时代中找到自己的立足点。我们需要的不仅仅是技术的积累,更需要一份对未来的规划和对现实的勇敢面对。

让我们一起探讨,作为程序员,我们该如何在这个充满变数的世界中寻找稳定,构建自己的职业生涯,不仅仅为了生存,更为了在波动中找到自己的价值和意义。

程序员的悲哀

我们先来分析下为什么程序员会陷入这种困境,我总结了如下几点:

首先,技术变迁的速度是惊人的。在信息技术领域,新技术层出不穷,旧技术迅速被淘汰。我们必须不断学习和适应,否则很容易被行业淘汰。十年前流行的技术,今天可能已经成为过去式。这种快速变化给程序员带来了巨大的压力和挑战。我们的专业积累可能在短时间内就变得不再有价值,这对于那些投入大量时间和精力学习技术的人来说无疑是一种打击。

其次,社会对程序员的认知存在一定的偏差。虽然程序员的收入普遍较高,但社会对我们的专业技能和工作内容了解不足。与医生、律师等职业相比,程序员往往不被视为“高端职业”。这种认知上的偏差影响了程序员的社会地位,也削弱了我们的职业自豪感。

最后,尽管我们掌握了众多技术,如 Python、Java、JavaScript、Rust、C 等,但在技术壁垒不断降低的今天,我们仍面临着被裁员的风险。这种风险不仅来自于技术的快速迭代,也来自于市场的不确定性和公司战略的调整。即使是最优秀的程序员,也可能因为外部因素而失去工作。

怎么办

面对程序员职业的挑战和不确定性,破局和提前规划是至关重要的。

1. 如何破局

首先,持续学习是破局的关键。技术的迭代更新速度越来越快,只有不断学习,才能跟上时代的步伐。无论是通过在线课程、技术论坛还是专业书籍,都要保持对新技术的敏锐洞察力和学习能力。

其次,专业深化与技术广泛是另一个重要的破局策略。选择一个或几个领域深耕,成为该领域的专家,同时保持对其他技术领域的广泛了解,以便能够灵活应对技术变化和跨领域的项目需求。

此外,提升软技能,如沟通、团队协作和问题解决能力,也是破局的重要一环。这些技能在任何职业生涯中都是宝贵的资产,可以帮助我们更好地与他人合作,提高工作效率。

最后,建立个人品牌,通过撰写技术博客、参加技术社区活动、演讲等方式,提升个人在行业中的影响力和知名度,也是破局的重要策略之一。

2. 如何提前做好规划

对于程序员来说,提前做好规划意味着设定明确的职业目标,制定详细的学习计划,拓展人脉网络,关注行业动态,以及定期审视和调整自己的职业规划。

设定职业目标时,应根据个人兴趣和行业趋势,设定短期和长期的职业发展目标。明确的目标可以帮助我们有针对性地学习和积累经验。

制定学习计划时,应包括要学习的技术领域、学习资源、时间安排等。一个详细的学习计划可以帮助我们更有效地学习和掌握新技术。

拓展人脉网络是另一个重要的规划策略。加入行业协会、参加技术大会和线下聚会,可以帮助我们结识更多的行业人士,获取更多的信息、资源和机会。

关注行业动态,定期阅读行业新闻、技术博客和市场报告,可以帮助我们及时了解行业发展趋势和技术变化,以便及时调整自己的学习方向和职业规划。

最后,定期审视和调整自己的职业规划,根据行业发展和个人成长情况,适时做出调整,以确保我们的职业发展始终保持在正确的轨道上。

关于职业规划

想做好职业规划,需要先了解程序员的职业发展路径。程序员的职业规划路径可以整理为以下几种:

  • 工作: 这是大多数程序员的选择,风险和心理压力相对较小。可以选择专家线路(技术深化)或管理线路(团队管理)。
  • 一个人的公司: 即自由职业者或小老板,适合不想长期钻研技术或在公司难以混下去的人。风险和收益都较高,建议打造自己的产品或个人品牌。
  • 创业: 追求规模和快速扩张,需要持续融资。适合有冒险精神、善于与各种角色打交道的人。可以选择成为 CEO 或 CTO。
  • 投资: 适合财务自由或拥有一定资本的人。可以考虑投资股市、房产、加密货币或进行天使投资。需要注意风险控制,可能需要投资多个项目以分散风险。

其实这个规划我是从网上找的,一图胜千言,可以总结为如下图所示:

目前我觉得对于大多数普通程序员来说,选择工作和一个人的公司的方式是比较容易的。剩下的两条路,创业和投资,需要更多的勇气和运气。

总结

挑战不可怕,要敢于面对。不要停止学习和积累,做好自己的职业规划。

感谢大家的阅读和支持。希望这篇文章能够对你有所帮助。期待大家在评论区分享自己的想法和经验,让我们共同进步!

另外,我想推荐一本书给大家,《软技能2 软件开发者职业生涯指南》。这本书分享了丰富的职业经验,涵盖技术技能提升、个人品牌塑造、职业规划等多个方面,这本书能为你的职业生涯提供宝贵的指导和启发。

《现代JavaScript库开发:原理、技术与实战》狼叔推荐序

2023年1月1日 08:00

2023年1月,我和侯策老师共同打磨的书籍《现代JavaScript库开发:原理、技术与实战》终于正式出版了!

在书籍定稿之际,我把底稿寄给了狼叔,感谢狼叔在百忙之中抽时间阅读了底稿,并为我写了推荐序,一下是推荐序的内容。

狼叔推荐序

我和海镜、侯策认识很久了,他们之前写的那本《React状态管理与同构实战》是新手入门React的好书,我非常喜欢。

海镜不仅是大厂工程师、技术博主,还是开源爱好者。他开源了很多JavaScript库,如zepto.fullpage、template.js等。他搞的jsmini可圈可点,尤其难能可贵的是,他还编写了jslib-base——一个可以帮助开发者编写JavaScript库的工具库,这个库的特性涵盖了库开发的各个方面,非常实用。

我对海镜很熟悉,对他做的事也比较熟悉,所以当我得知他正在写这本书的时候,我是非常开心且放心的。开心是因为,目前前端领域和Node.js领域都缺少这样的专精内容,我在《狼书》里是写过如何开发JavaScript库的,但限于篇幅未能深入介绍,这本书弥补了我的遗憾。放心是因为,他一直是一线的、热爱开源的前端专家,无论是能力、眼界、判断力还是协作能力,都非常不错,鉴于他之前所写的那本《React状态管理与同构实战》的情况,我相信他能够将JavaScript库开发技术讲清楚。

事实上,本书的初稿也确实和我想的一样,章节分布清楚,内容详略得当,基本覆盖了所有读者想要看到的知识点,甚至还有扩展。

很多人在学习编写代码时都很迷茫,对此,我给的建议是:每天看10个npm模块(JavaScript库)。对于学习大前端(含Node.js)相关技术时感到迷茫的人来说,学习JavaScript库是消除迷茫的最好方式。当你不知道如何做时,可以通过学习JavaScript库积累对以后实际开发有益处的技能。与其不知道学什么,不如先通过学习JavaScript库每天积累几个技巧。只要坚持每天积累几个库开发技巧,并累计学习一万小时,你的个人编程能力一定会有质的飞跃。

当你掌握了很多开发技巧后,就会慢慢地想要自己去实现JavaScript库,这是一个创造的过程,也是一个自我实现的过程,这个过程非常容易带给人成就感。你编写的JavaScript库,可能是React这样的大框架或Vite这样的大型构建工具,也可能是is-number、debug这样的小模块。对于个人成长来说,无论模块大小,都能使人进步。当然,如果你编写的JavaScript库能够获得更多开发者和使用者的认可,那将是更值得开心的事。

以上就是我对开发和开源JavaScript库的简单理解,其实,我个人也是这样一步一步走过来的。

海镜和侯策写的这本书从多个维度介绍了JavaScript库开发和开源的技巧及注意事项,并列举了几个非常典型的库辅以实战,内容非常实用。希望大家能够通过这本书掌握更多的JavaScript库开发技巧,并通过刻意练习自我提高,成为自己想成为的人——技术大牛!

——Node.js布道者、《狼书》系列图书作者
桑世龙(狼叔)

总结

本书主要涵盖三部分内容,可以满足读者不同阶段的学习诉求。

  • 第1~5章 介绍如何开发和开源一个现代JavaScript库,这部分内容可以帮助读者快速达成库开发目标。
  • 第6~7章 介绍现代JavaScript库的设计最佳实践和安全最佳实践,这部分内容可以极大提高读者开发JavaScript库的质量。
  • 第8~11章 为实战部分,本书精选了9个典型库作为案例,带领读者了解不同类型的JavaScript库的开发要点。

如今,本书已全面上线,如果你也想开发属于自己的JavaScript库,提升开发技能,精进自身开发技术,一定不可以错过本书哦~~

有兴趣的读者可以点击下面的链接购买,再次感谢各位的支持与鼓励!恳请各位批评指正!

我还给大家准备了签名版,免费赠送直播课和周边,想要签名版的可以通过微信公众号联系我:颜海镜

京东:https://u.jd.com/7QlXVqN

当当:http://product.dangdang.com/29494845.html

十年磨一剑(我的新书自序)

2023年1月1日 08:00

2023年1月,我和侯策老师共同打磨的书籍《现代JavaScript库开发:原理、技术与实战》终于正式出版了!

在书籍定稿之际,有太多话想和大家说一下,思绪万千,不知从何说起。最终决定写一篇自序,记录一下这本书的由来,以及我在写作过程中的一些感悟。

十年磨一剑

十年,弹指一挥间。

回首过去十年,我一直致力于开源库的开发和维护,一路走来,我也从这个领域的“小白”慢慢成长为“专家”。这十年,支撑我坚持在库开发领域耕耘的原因是热爱分享,我特别希望能把自己做的东西分享给别人,分享的内容既可以是课程、博客文章,也可以是代码。在我看来,一份分享出去的代码片段,就是一个开源库。

十年来,前端技术推陈出新,新的开源库如雨后春笋般涌现,相信大部分读者都曾从这些开源库中受益。平日里,我们更多关注的是库的使用,很少关注库开发技术。其实,JavaScript库开发技术在这十年中也经历了快速发展,其中基于新的技术标准开发而成的库,我将其称为“现代JavaScript库”。

由于前端技术发展迅速,如今开发一个现代JavaScript库并不容易,其中涉及非常多的知识、工具和经验。比如,库如何兼容日益复杂的前端环境,库如何使用打包工具,库的单元测试如何做,等等。正因为这种复杂性,目前npm上的开源库并不都是现代JavaScript库,很多开源库还在使用十几年前的相对比较原始的技术。

除了依赖开发技术,将一个库开源还需要很多准备工作。一个库开源后的运营和维护也涉及很多知识。由于缺乏经验,很多库开源后并没有被推广开来。

总之,开发和开源一个现代JavaScript库并非易事,上述困难阻碍了很多读者开发自己的JavaScript库,我也曾被这些困难深深折磨过。经过十年的摸爬滚打,我不禁想:如果能有一个师傅手把手教我该多好,那我当初能少走多少弯路!基于此,我终于下定决心写一本现代JavaScript库开发领域的图书,将自己十年的经验总结沉淀,希望能够手把手教各位读者快速掌握现代JavaScript库开发技术。

人人都可以开发自己的JavaScript库

有人可能会问,为什么要学习JavaScript库开发技术呢?学会开发JavaScript库有什么好处呢?其实,开发JavaScript库能够带来非常多的好处。

我现身说法,开发和开源库不仅可以帮助他人解决问题,也能给自己带来很多成长。开发库的特殊要求,极大提升了我的技术深度;开发库涉及的技术非常多,极大拓宽了我的知识面;开源库使我融入了开源社区,在那里获得了很多技术之外的东西。总之,开发和开源现代JavaScript库可以带来非常大的收获,我希望每一个前端开发者都不要错过这个机会。

其实,我有一个愿望,那就是,人人都可以开发自己的JavaScript库。

再小的个体也应该有机会在社区中发声,社区不应该只要月亮的光辉,漫天繁星同样是美好世界的重要组成,只要我们愿意,每个人都可以开发属于自己的JavaScript库。

每一个前端开发者都身处两个世界,即业务世界和开源世界。大部分人熟悉业务世界,但对开源世界了解不多。所谓“技多不压身”,多了解开源世界,融入开源世界,你一定会有更多收获。

总结

本书主要涵盖三部分内容,可以满足读者不同阶段的学习诉求。

  • 第1~5章 介绍如何开发和开源一个现代JavaScript库,这部分内容可以帮助读者快速达成库开发目标。
  • 第6~7章 介绍现代JavaScript库的设计最佳实践和安全最佳实践,这部分内容可以极大提高读者开发JavaScript库的质量。
  • 第8~11章 为实战部分,本书精选了9个典型库作为案例,带领读者了解不同类型的JavaScript库的开发要点。

如今,本书已全面上线,如果你也想开发属于自己的JavaScript库,提升开发技能,精进自身开发技术,一定不可以错过本书哦~~

有兴趣的读者可以点击下面的链接购买,再次感谢各位的支持与鼓励!恳请各位批评指正!

我还给大家准备了签名版,免费赠送直播课和周边,想要签名版的可以通过微信公众号联系我:颜海镜

京东:https://u.jd.com/7QlXVqN

当当:http://product.dangdang.com/29494845.html

❌
❌