路径 alias 在 Node 中的最佳姿势

更新日期: 2019-11-28 阅读: 3.4k 标签: node

周末在家闲来无事,捣鼓自己荒废很久的新博客系统的Node端时,突然发现一个以前没有太注意,但是现在越看越不爽的问题。

import config from '../../../src/config'

这个 ../../../ 我越看越觉得它不顺眼,众所周知,(有追求的)程序员是很懒的,能不多写绝不多写,能用程序解决的绝不自己动手,现在就想办法干掉它。

一般而言,正常流程是

  1. google / bing
  2. 愣着干嘛,赶紧抄啊

但是,作为一个有追求的程序员,应该做的是:

根据当前自己已有的知识体系,先想想有哪几种解决方案,然后再去查找业界的解决方案,这样,我们才能不断完善自己的知识体系,培养足够的思维能力。

熟悉 webpack 的都知道它提供了一个叫 resolve 的功能,可以解决这个问题,但是如果项目中没有使用 webpack 或者我就是不想用 webpack 怎么办?


想法

我们来想想有没有其他解决方案,假定当前项目目录结构为

├── src
|   ├── config
|   └── controller
├── node_modules
├── index.js
└── package.json


1. 全局变量

第一反应,在 Node 程序里面,我们可以直接通过

global.BASE_PATH = __dirname + '/'

之后就可以这么使用

import config from BASE_PATH + 'src/config'

emmmm,太丑了,而且也没方便到哪去,抬走


2. symlink

再一想,想起来在系统中有一个符号链接的东西,再利用 Node 的模块加载机制,我们可以在项目的 node_modules 下建一个链接到项目目录的符号链接。

  1. Linux / MacOS (其实就是 unix 内核的系统)

    ln -nsf node_modules src
  2. Windows

    mklink \D src node_modules

然后就可以这么使用

import config from 'src/config'

看起来不错,但是也有一些槽点

  • 不同平台创建命令不一致
  • 每个clone仓库的人都要手动添加符号链接

既然有槽点,那就解决一下,印象中 Node 的 fs 模块提供了创建 symlink 的方法: fs.symlinkSync ,我们把具体代码写出来,第一个问题迎刃而解。

const src='../src'
const dir='node_modules/src'
const fs = require('fs')
fs.exists(dir, function (e) { e || fs.symlinkSync(src, dir, 'dir') })

第二个问题就简单了,我们利用 package.json scripts 中的 postinstall 钩子,它会在 npm run install 之前被执行,我们把前面写好的代码浓缩一下放进去用 node 执行即可。

{
  "scripts": {
    "postinstall": "node -e \"var src='../src',dir='node_modules/src',fs=require('fs');fs.exists(dir,function(e){e||fs.symlinkSync(src,dir,'dir')});\""
    }
}

到这里看起来就很不错了,不过仔细一想,还有个小问题。当我们想再加一个 alias,比如 @controller -> src/controller 的时候,喔霍,又得改 postinstall 脚本。

更好一点的做法是将 postinstall 中的脚本抽出来保存成一个单独的文件,但是还是无法避免新增时要修改脚本的问题。

我们可以再通过命令行参数来解决这个问题,但是需要引入新的命令,整个流程就比较繁琐了,新人接手可能还要花点时间才能搞懂这里的逻辑。


3. 环境变量

想了想,又想起来一个知识点,我们可以通过设置环境变量 NODE_PATH 指向对应的路径

export NODE_PATH='项目路径'

之后就可以直接使用

import config from 'src/config'

原理和Node模块加载机制有关,感兴趣的自行查阅,这里就不多说了。

这个方案的缺点也很明显,没错, NODE_PATH 只有一个,因此生成的 alias 只有该路径下的最顶层,没办法添加 src/controller -> controller 这样的 alias。


业界方案

自己的思考大概结束了,我们来看看业界的实现方案。搜了一圈之后,聚焦在一个轮子上: module-alias

看了下源码是通过 hack 原生模块 module 的方法实现的,Node在引入模块时其实就是调用的module 模块。具体源码就不多说了,我们直接来看最佳实践(我认为的)

module-alias 提供了两种 alias 添加模式

  1. 配置package.json

    通过配置 _moduleAliases 字段添加 alias

    // package.json
    {
      "_moduleAliases": {
        "@src": "src",
        "@config": "src/config"
      }
    }
    // index.js
    import 'module-alias/register'
  2. 在项目代码中添加

    import { addAlias } from 'module-alias'
    
    addAlias('@root', __dirname)
    addAliases({
     '@src': __dirname + 'src',
     '@config': __dirname + 'src/config'
    })

之后就可以使用配置的 alias 进行开发了,但是还有一个问题,我们在 VSCode 中的引用没办法点击跳转,引用的模块提示也不能正常加载。

这是因为 VSCode 并不知道这个路径解析的配置,所以需要额外添加配置。只需要配置一下 jsconfig.json (使用 typescript 的修改 tsconfig.json )的 compilerOptions

{
  "compilerOptions": {
    "moduleResolution": "node",
    "baseUrl": ".",
    "rootDir": ".",
    "paths": {
      "@config": ["src/config"],
      "@src/*": ["src/*"]
    }
  }
}

需要注意的是,jsconfig.json更改后需要重新打开 VSCode 配置才会生效

以上配置完即可愉快的进行开发了,提高效率、治好强迫症的同时代码提示、引用跳转等都可以正常使用。

原文 https://quincychen.cn/path-alias/

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

链接: https://fly63.com/article/detial/6664

相关推荐

怎么卸载nodejs?

Node.js是一个Javascript运行环境,可以使Javascript这类脚本语言编写出来的代码运行速度获得极大提升,那么安装后该如何卸载呢?下面本篇文章就来给大家介绍一下Windows平台下卸载node.js的方法,希望对大家有所帮助。

happypack提升项目构建速度

运行在 Node.js 之上的 Webpack 是单线程模型的,也就是说 Webpack 需要处理的任务需要一件件挨着做,不能多个事情一起做。happypack把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。

nodejs 异步转同步

nodej项目在微信环境开发,nodejs的异步特效,会导致请求没有完成就执行下面的代码,出现错误。经过多方查找,可以使用async模块来异步转同步,只有前一个function执行callback,下一个才会执行。

node.js反向代理的实现

在实际工程开发中,会有前后端分离的需求。使用node.js反向代理的目的:实现前后端分离,前端减少路径请求的所需的路由文件;通过http-proxy-middleware中间件、Http Proxy 模块这2种方式实现node.js的反向代理

Ubuntu 上 Node.js 安装和卸载

Ubuntu 安装 Node.Js:执行检查可更新的软件,先用普通的apt工具安装低版本的node,然后再升级最新。更换淘宝的镜像,这个是必须的,用过的node的人都知道。安装更新版本的工具N

nodejs 文本逐行读写功能的实现

利用nodejs实现:逐行读写(从一个文件逐行复制到另外一个文件);逐行读取、处理和写入(读取一行,处理后,写入另一个文件)1.所需要的模块: fs,os,readline。功能的实现:readWriteFileByLine.js,功能的调用:index.js

使用pkg打包Node.js应用的方法步骤

Node.js应用不需要经过编译过程,可以直接把源代码拷贝到部署机上执行,确实比C++、Java这类编译型应用部署方便。然而,Node.js应用执行需要有运行环境,意味着你需要先在部署机器上安装Node.js

query和params在前后端中的区别

最近在学node,试着做一个前后端都有的项目,然后就遇到了query和parmas这俩兄弟,你说他们俩长得也不像吧,可这用法实在是太类似了,专门写篇文章来区分这哥俩,分别会从vue路由和Node接收两个角度讲

用node.js开发一个可交互的命令行应用

在这个教程中,我们会开发一个命令行应用,它可以接收一个 CSV 格式的用户信息文件,教程的内容大纲:“Hello,World”,处理命令行参数,运行时的用户输入,异步网络会话,美化控制台的输出,封装成 shell 命令,JavaScript 之外

Node.js 应用:Koa2 使用 JWT 进行鉴权

在前后端分离的开发中,通过 Restful API 进行数据交互时,如果没有对 API 进行保护,那么别人就可以很容易地获取并调用这些 API 进行操作。那么服务器端要如何进行鉴权呢?

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!