你的 Node 服务端用路径别名了吗?一文理清如何启用路径别名

1,076 阅读6分钟

前言

大家好!我是 嘟老板路径别名 对于广大前端小伙伴来说,必然是耳熟能详,常用的前端构建工具基本都提供了路径别名相关的配置,比如 viteWebpack 提供的 resolve.alias 配置项。那你在 Node 服务端项目用过路径别名吗?今天我们就来聊聊 ZimuAdmin 启用路径别名的全过程。

ZimuAdmin 服务端基于以下技术构建:

阅读本文您将收获:

  1. 了解路径别名的原理及作用。
  2. 了解 Node 项目集成 module-alias 详细过程。
  3. 了解如何在现有项目中重构路径别名。

介绍

什么是路径别名

开发前端应用时,经常看到类似 @utils/@components/ 的引入路径,如:

import request from '@utils/request'

通常这种引入路径就是路径别名,因为在实际的文件系统中,基本不会存在像 @utils/ 的文件路径。如果你的项目中有用到,可以去查看 Webpack/Vite 配置文件是否配置了 resolve.alias

所以路径别名,故名思意,就是为引入模块的路径定义一个新的、简化的名字,然后 import/require 时使用该别名作为引入路径,而程序运行时,别名路径会经由相关工具处理,转换为原始文件路径,以正确加载对应资源。

路径别名的作用

了解下来,好像不用路径别名,程序一样可以正常运行,那为什么还要多此一举,整个别名出来呢?

个人认为,原因有以下几点:

  • 提高可读性,路径别名与某个目录或文件存在映射关系,引入的模块位于哪个目录,一目了然。
  • 提高编码效率,一个别名可以到处使用,无论是文件结构嵌套多少层,相比之下,无数个 ../ 写起来麻烦还不好看。
  • 重构简单,若项目结构变化,只需要修改别名配置即可,无需全局搜索挨个修改引入路径,极大的减少工作量。
  • 避免路径冲突,在大型项目中可能存在相同的文件或目录,通过路径可以明确区分某个模块属于哪个目录。
  • 工具支持度高,目前主流的构建工具,如 viteWebpack 等,都支持路径别名配置。

启用路径别名

ZimuAdmin 通过处理以下两部分来启用路径别名:

TypeScript 配置

tsconfig paths 配置项可设置路径别名,定义 TS 如何解析 require/import 的导入。

tsconfig.json 配置示例如下:

{
    ...
    "paths": {
        "@controllers/*": ["./src/controllers/*"],
        "@services/*": ["./src/services/*"],
        "@entities/*": ["./src/entities/*"],
    },
    ...
}

以上配置定义了几个路径别名:

  • @controllers:映射到 ./src/controllers 目录。
  • @services:映射到 ./src/services 目录。
  • @entities:映射到 ./src/entities 目录。

比如引入 import { UserController } from '@controllers/user.controller',实际引入的是 ./src/controllers/user.controller

路径映射规则:

  • tsconfig.json 配置了 baseUrl,则 paths 配置的文件路径相对于 baseUrl 配置的路径;

  • 若未配置 baseUrl,则相对于 tsconfig.json 文件位置。

集成 module-alias

然而配置了 TypeScript paths,虽然 TypeScript 检验通过,但在程序运行时,仍然会报 "找不到模块" 的错误。

image.png

这是因为 paths 仅在 TypeScript 编译时有效,而运行时,Nodejs 无法识别这些别名。

所以只要 Nodejs 识别路径别名就 OK 啦,module-alias 可以帮助完成这项任务。

安装依赖

服务端目录下,终端属于以下命令,回车执行:

pnpm add module-alias -S

配置

module-alias 别名在 package.json 中配置,添加一个_moduleAliases 配置项。

{
    ...
    "_moduleAliases": {
        "@controllers": "./src/controllers",
        "@services": "./src/services",
        "@entities": "./src/entities",
    },
    ...
}

别名配置已完成,然后在应用的入口文件 app.ts 首行 引入 _moduleAliases/register,以注册别名。

import 'module-alias/register'
// ...

OK,现在可以愉快使用路径别名啦。

应用

我们改造一下 ZimuAdmin 的用户服务 UserService ,将 UserEntity 引入路径由原本的 '../entities/user.entity' 改为别名 '@entities/user.entity'

import { User } from '@entities/user.entity'
import { BaseService } from './base-service'

export class UserService extends BaseService {
  constructor() {
    super(User)
  }

  // ...
}

启动服务,控制台打印如下日志:

image.png

OK,服务正常启动,无报错,看来 Nodejs 已经识别路径别名了。

调用下用户查询接口:

image.png

数据正常返回,引入的 UserEntity 已被正常检索。

现有项目重构

到这,路径别名的使用方法想必大家已经清楚了,若是新项目,直接用就可;然而也存在已有项目重构的情况,若是一处一处修改,工作量显然不小,也极其考验开发小伙伴的细心及耐心程度。

那有没有办法批量处理呢?当然有,送你一个工具 - relative-to-alias

全局安装

终端输入以下命令,回车执行:

npm install -g relative-to-alias

安装完成后,终端输入 relative-to-alias --help,查看命令行选项:

image.png

选项说明

  • --version:显示版本号。
  • --root-path, -r:项目根路径,默认为 ./import/require 基于此路径解析。
  • --src, -s:脚本可以修改的目录或文件。
  • --alias, -a:路径别名。
  • --alias-path, --ap:要被替换为别名的路径。
  • --extensions, -e:解析的文件扩展名,默认为 js,jsx
  • --language, -l:项目使用的类型语言(可选:flow/typescript),默认 flow
  • --include-alias-path-directory, -i:是否修改别名路径下的文件。若为 true,则所有引用 alias-path 的路径都会修改。
  • --ignore:排除解析的路径,默认不解析 node_modules/**/*

批处理命令

现在我们批量修改下 ZimuAdmin utils 的别名:

终端输入以下命令,回车执行:

relative-to-alias --src src --alias '@utils' --alias-path './src/utils' --extensions 'ts,tsx'  --language 'typescript' --include-alias-path-directory true

执行后,输出已调整的文件路径:

image.png

打开 login.controller.ts 文件,看源代码是否修改:

image.png

O...K!utils 路径已成功从 '../utils/*' 调整为 '@utils/*'

结语

本文重点介绍了 Node 服务端启用路径别名的详细流程及相关工具实操过程,旨在帮助同学们加深对其的应用理解。希望对您有所帮助。相关代码已上传至 GitHub,欢迎 star

如您对文章内容有任何疑问或想深入讨论,欢迎评论区留下您的问题和见解。

技术简而不凡,创新生生不息。我是 嘟老板,咱们下期再会。


往期推荐