Part 8: 使用模块的Alias别名来增强Jest的可配置度(完结)

Enhance Jest configuration with Module Aliases

使用模块的Alias别名来增强Jest的可配置度

Learn how to use Module Aliases Jest configuration to avoid using relative paths.
学习如何用模块别名来配置Jest,这样可以避免使用相对地址。

The module managers we have in the JavaScript community, mainly ES Modules and CommonJS, don’t support project-based paths. They only support relative paths for our own modules, and paths for the node_modules folder. When a project grows a bit, it’s common to see paths such:
在Js社区内我们可以用的模块管理工具,比如ES模块化或者CommonJS,都不太支持基于项目目录的路径,而是仅支持我们自己模块的相对路径,以及node_modules文件夹。如果项目结构越来越复杂,我们可能会看到如下长长的路径:

import SomeComponent from '../../../../components/SomeComponent'

Luckily, we have different ways to cope with this, in a way that we can define aliases for folders relative to the project root, so we could the above line like:
还好,我们有各种方法来应对这种情况,一种方法就是我们设置某些相对于根目录的文件夹的别名,就像上面的引用,就可以变为如下表示:

import SomeComponent from '@/components/SomeComponent'

The @ here is an arbitrary character to define the root project, you can define your own. Let’s see what solutions we have to apply module aliasing. Let’s start from where we left it on the last article.
这里的@符号是定义项目根目录的字符,你也可以定制自己想要的别名。来看一下我们如何设置模块别名,这就是我们最后一篇文章要讲的。

Webpack aliases

Webpack别名

Webpack aliases are very simple to set up. You just need to add a resolve.alias property in your webpack configuration. If you take a look at the build/webpack.base.conf.js, it already has it defined:
Webpack的别名设置非常简单。你只需要在配置文件中的resolve.alias里设置,文件路径是build/webpack.base.conf.js

{
  ...
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
    }
  }
}

Taking this as an entry point, we can add a simple alias that points to the src folder and use that as the root:
以此为切入点,我们可以添加一些简单的别名,指向根目录中的src文件夹:

{
  ...
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': path.join(__dirname, '..', 'src')
    }
  }
}

Just with this, we can access anything taking the root project as the @ symbol. Let’s go to src/App.vue and change the reference to those two components:
这样设置以后,我们可以访问到任何资源通过@标识符。我们试着用新方法引用资源:

  import MessageList from '@/components/MessageList'
  import Message from '@/components/Message'
  ...

And if we run npm start and open the browser at localhost:8080, that should work out of the box.
如果我们启动npm的服务,打开浏览器访问localhost:8080,可以发现之前的设置已经生效了。

However, if we try to run the tests by running npm t, we’ll see Jest doesn’t find the modules. We still didn’t configured Jest to do so. So let’s go to package.json where the Jest config is, and add "@/([^\\.]*)$": "<rootDir>/src/$1" to moduleNameMapper:
但是,如果我们尝试执行测试用例,运行npm t后,我们可以看到Jest报错说没有找到相关模块。我们至今还没搞清楚为什么Jest不支持这种配置。为了解决这个问题,我们去package.json中的Jest配置内容里添加一段代码:"@/([^\\.]*)$": "<rootDir>/src/$1" to moduleNameMapper:

    "jest": {
        "moduleNameMapper": {
          "@(.*)$": "<rootDir>/src/$1",
          "^vue$": "vue/dist/vue.common.js"
        }
    }
...

Let’s explain it:
让我解释下这段代码的用处:

@(.*)$: Whatever starts with @, and continues with literally whatever ((.*)$) till the end of the string, grouping it by using the parenthesis
@(.*)$:无论什么路径,只要以@开头,并且后面以((.*)$)结尾,这里使用括号对其进行正则分组。

<rootDir>/src/$1: <rootDir> is a special word of Jest, meaning the root directory. Then we map it to the src, and with 1 we append the whatever clause from the `(.*)` statement. `/src/1:其中<rootDir>是Jest中的一个关键字,代表着根目录。然后我们映射到src目录,并且$1代表着与前文中(.*)`匹配的分组。

For example, @/components/MessageList will be mapped to ../src/components/MessageList when you’re importing it from the src or test folders.
例如,当我们引入src或者test文件夹中的资源时,@/components/MessageList等价于../src/components/MessageList

That’s really it. Now you can even update your App.test.jsfile to use the alias as well, since it’s usable from within the tests:
用法就是这样。现在我们可以用别名的方式更新App.test.js文件了:

import { shallow } from "vue-test-utils"
import App from "@/App"
...

And it will work for both .vue and .js files.
这种方式对vue和js格式的文件都有效。

Multiple aliases

多个别名

Very often, multiple aliases are used for convenience, so instead of using just a @ to define your root folder, you use many. For example, let’s say you have a actions and models folder. If you create an alias for each one, and then you move the folders around, you just need to change the aliases instead of updating all the references to it in the codebase. That’s the power of module aliases, they make your codebase more maintainable and cleaner.
通常我们不会只用@来索引资源,我们可以设置多个别名来更方便的引入模块。举个例子,比如说你有一个actions和models的文件夹。如果你对他们分别设置别名,然后你挪动了文件夹,这时你只需要在配置文件中修改一次别名引用地址,就不用在代码中修复海量的引用地址的指向了。这就是模块别名的妙用。

Let’s add a components alias in build/webpack.base.conf.js:
让我们在build/webpack.base.conf.js中添加components文件夹的别名。

{
  ...
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': path.join(__dirname, '..', 'src')
      'components': path.join(__dirname, '..', 'src', 'components')
    }
  }
}

Then, we just need to add it as well to the Jest configuration in package.json:
然后我们只需要package.json中再次添加一些配置:

"jest": {
    "moduleNameMapper": {
      "@(.*)$": "<rootDir>/src/$1",
      "components(.*)$": "<rootDir>/src/components/$1",
      "^vue$": "vue/dist/vue.common.js"
    }
}
...

As simple as that. Now, we can try in App.vue to use both forms:
就这么简单。现在我们在App组件中试下这两种方式:

import MessageList from 'components/MessageList'
import Message from '@/components/Message'

Stop and re-run the tests, and that should work, as well as if you run npm start and try it.
不要反复试了,这两个方法都能生效。

Other solutions

其他解决办法

I’ve seen babel-plugin-webpack-alias, specially used for other testing frameworks such as mocha which doesn’t have a module mapper.
我已经调研过babel-plugin-webpack-alias了,特别是用在其他测试框架中,比如mocha等不支持模块映射的框架。

I haven’t tried it myself, since Jest already gives you that, but if you have or wanna try, please share how it went!
我没有亲自试,因为Jest已经提供这些功能了,但是如果你还是想亲自尝试一下,可以给大家分享一下!

Conclusion

总结

Adding module aliases is very simple and can keep your codebase much cleaner and easier to maintain. Jest makes it as well very easy to define them, you just need to keep in in sync with the Webpack aliases, and you can say bye-bye to the dot-hell references.
添加模块别名非常简单,而且可以让你的代码简洁高效。Jest让我们很简便地定义别名,你只需要让Jest和Webpack同步别名的设置,你就可以跟见鬼的'点点式'引用说拜拜了!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容