前言
大家好!我是 嘟老板。路径别名 对于广大前端小伙伴来说,必然是耳熟能详,常用的前端构建工具基本都提供了路径别名相关的配置,比如 vite 和 Webpack 提供的 resolve.alias 配置项。那你在 Node 服务端项目用过路径别名吗?今天我们就来聊聊 ZimuAdmin 启用路径别名的全过程。
ZimuAdmin 服务端基于以下技术构建:
阅读本文您将收获:
- 了解路径别名的原理及作用。
- 了解 Node 项目集成 module-alias 详细过程。
- 了解如何在现有项目中重构路径别名。
介绍
什么是路径别名
开发前端应用时,经常看到类似 @utils/,@components/ 的引入路径,如:
import request from '@utils/request'
通常这种引入路径就是路径别名,因为在实际的文件系统中,基本不会存在像 @utils/ 的文件路径。如果你的项目中有用到,可以去查看 Webpack/Vite 配置文件是否配置了 resolve.alias。
所以路径别名,故名思意,就是为引入模块的路径定义一个新的、简化的名字,然后 import/require 时使用该别名作为引入路径,而程序运行时,别名路径会经由相关工具处理,转换为原始文件路径,以正确加载对应资源。
路径别名的作用
了解下来,好像不用路径别名,程序一样可以正常运行,那为什么还要多此一举,整个别名出来呢?
个人认为,原因有以下几点:
- 提高可读性,路径别名与某个目录或文件存在映射关系,引入的模块位于哪个目录,一目了然。
- 提高编码效率,一个别名可以到处使用,无论是文件结构嵌套多少层,相比之下,无数个 ../ 写起来麻烦还不好看。
- 重构简单,若项目结构变化,只需要修改别名配置即可,无需全局搜索挨个修改引入路径,极大的减少工作量。
- 避免路径冲突,在大型项目中可能存在相同的文件或目录,通过路径可以明确区分某个模块属于哪个目录。
- 工具支持度高,目前主流的构建工具,如 vite、Webpack 等,都支持路径别名配置。
启用路径别名
ZimuAdmin 通过处理以下两部分来启用路径别名:
- TypeScript 配置
- 集成 module-alias
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。
路径映射规则:
集成 module-alias
然而配置了 TypeScript paths,虽然 TypeScript 检验通过,但在程序运行时,仍然会报 "找不到模块" 的错误。
这是因为 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)
}
// ...
}
启动服务,控制台打印如下日志:
OK,服务正常启动,无报错,看来 Nodejs 已经识别路径别名了。
调用下用户查询接口:
数据正常返回,引入的 UserEntity 已被正常检索。
现有项目重构
到这,路径别名的使用方法想必大家已经清楚了,若是新项目,直接用就可;然而也存在已有项目重构的情况,若是一处一处修改,工作量显然不小,也极其考验开发小伙伴的细心及耐心程度。
那有没有办法批量处理呢?当然有,送你一个工具 - relative-to-alias。
全局安装
终端输入以下命令,回车执行:
npm install -g relative-to-alias
安装完成后,终端输入 relative-to-alias --help,查看命令行选项:
选项说明:
--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
执行后,输出已调整的文件路径:
打开 login.controller.ts 文件,看源代码是否修改:
O...K!utils 路径已成功从 '../utils/*' 调整为 '@utils/*'。
结语
本文重点介绍了 Node 服务端启用路径别名的详细流程及相关工具实操过程,旨在帮助同学们加深对其的应用理解。希望对您有所帮助。相关代码已上传至 GitHub,欢迎 star。
如您对文章内容有任何疑问或想深入讨论,欢迎评论区留下您的问题和见解。
技术简而不凡,创新生生不息。我是 嘟老板,咱们下期再会。
往期推荐
- TypeORM 知多少?来看看 Node 服务端如何基于 TypeORM 封装 BaseService
- 还在考虑 node 服务端如何管理环境变量?来试试 node-config
- 还在纠结 node 服务端缓存怎么做?来试试 Redis
- 听说过 BEM 吗?聊聊如何落地 BEM 规范
- 还在好奇 node 后端登录流程怎么做?进来聊聊吧
- 借助 CSS 动画,撸一个“平平无奇”的登录页
- express 基础入门
- 搞定 TS 装饰器,让你写 Node 接口更轻松
- 一文带你了解多数企业系统都在用的 RBAC 权限管理策略
- 还不会搭建 Node 服务?一文带你了解如何用 express + ts 搞定后端