typescript中函数
During your daily coding session, I’m pretty sure you end up creating “deep architecture” when you put your sources in the src
folder following by services
and sub other folders…
在您的日常编码会话中,我很确定当您将源放在src
文件夹中,然后是services
和其他子文件夹时,您最终将创建“深度架构”。
Surprisingly, we end up importing our modules with a very long way and this is particularly true when you write your tests in the test
folder close to your src
with the same folder architecture.
出乎意料的是,最终我们导入模块的过程非常漫长,当您使用相同的文件夹体系结构在靠近src
的test
文件夹中编写测试时,尤其如此。
import { GoogleService } from '../../../../services/clients/google/google.service.ts'
Before starting anything, I’ll use the repo from this article as a base to follow the change I’m making. And of course, you can find all the example in this repo https://github.com/vschoener/say-bye-to-relative-path-typescript
在开始任何事情之前,我将以本文中的存储库为基础来遵循我所做的更改。 当然,您可以在此仓库中找到所有示例https://github.com/vschoener/say-bye-to-relative-path-typescript
在tsconfig中设置路径 (Set your paths in the tsconfig)
Edit the file and set your list of paths you want to use. In this example, I just want to have a shortcut to access my src folder from anywhere but I also added “services” as an example if you want more.
编辑文件并设置要使用的路径列表。 在此示例中,我只想拥有一个从任何地方访问我的src文件夹的快捷方式,但是如果您想要更多,我还添加了“服务”作为示例。
更新eslint配置 (Update eslint config)
Right after, update the eslint config and add typescript as a import/resolver
If you don’t do that, it will complain saying it can’t resolve the module
之后,更新eslint配置并将typescript添加为import/resolver
如果不这样做,它会抱怨说它无法解析该模块
练习时间 (Practice time)
Now let’s try it out, we will just modify the main.ts
file to change the import using the path alias.
现在尝试一下,我们将修改main.ts
文件以使用路径别名更改导入。
At this step, eslint should not complain about resolving the imports.
在这一步,埃斯林特不应抱怨解决进口问题。
But now, for the fun, let’s try to build and run the main.js
但是现在,为了好玩,让我们尝试构建和运行main.js
> node ./dist/src/main.js
internal/modules/cjs/loader.js:1088
throw err;
^Error: Cannot find module '@src/services/google.service'
Require stack:
- /Users/vincentschoener/work/perso/medium/say-bye-to-relative-path/dist/src/main.js
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:1085:15)
at Function.Module._load (internal/modules/cjs/loader.js:928:27)
at Module.require (internal/modules/cjs/loader.js:1145:19)
at require (internal/modules/cjs/helpers.js:75:18)
at Object.<anonymous> (/Users/vincentschoener/work/perso/medium/say-bye-to-relative-path/dist/src/main.js:3:26)
at Module._compile (internal/modules/cjs/loader.js:1256:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1277:10)
at Module.load (internal/modules/cjs/loader.js:1105:32)
at Function.Module._load (internal/modules/cjs/loader.js:967:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/Users/vincentschoener/work/perso/medium/say-bye-to-relative-path/dist/src/main.js'
]
}
Yeah, sadly we can’t run our production code using node this way, we still need to modify a few things
是的,很遗憾,我们无法以这种方式使用节点运行生产代码,我们仍然需要修改一些内容
修复我们的构建 (Fix our build)
There is a couple of solutions to make this work but I tried a few of them and things get really “complicated” and even it still doesn’t work at all.
有两种解决方案可以使此工作正常进行,但是我尝试了其中的一些解决方案,结果确实变得“复杂”,甚至仍然无法使用。
-模块别名? (- module-alias?)
You can go for module-alias package, maybe it’s the cleaner solution, but I personally don’t like repeating myself. If you go for it, you will have to duplicate all the path in the tsconfig.json file to package.json and it’s not convenient and error-prone in my opinion. You can also find a dynamic way using the API to register these paths first.
您可以使用模块别名软件包,也许这是更干净的解决方案,但我个人不喜欢重复自己的做法。 如果要这样做 ,则必须将tsconfig.json文件中的所有路径复制到package.json ,我认为这样做不方便且容易出错 。 您还可以找到一种使用API的动态方式来首先注册这些路径。
-ts-node和ts-config-paths (- ts-node and ts-config-paths)
The one I decided to go with is a combination of ts-node with tsconfig-paths. Yes, most of the time we use ts-node and tsconfig-paths as a dev-dependencies, but in our case, we also need them in production. This is not a big deal, it works very well as we don’t rely on ts-node for the execution of the code and we don’t have to deal with caching issues and so on…
我决定使用的是ts-node和tsconfig-paths的组合 。 是的,在大多数情况下,我们将ts-node和tsconfig-paths用作dev-dependencies,但在我们的情况下,我们在生产中也需要它们。 这没什么大不了的,它很好用,因为我们不依赖ts-node来执行代码,也不必处理缓存问题,等等。
pros:
优点 :
- Less work to provide over the settings 提供设置所需的工作更少
- Work directly with TypeScript file 直接使用TypeScript文件
- Convenient to use it during your tests and development phase as well 方便在测试和开发阶段使用
Can directly be used in production keeping
node
command可以直接用于生产保持
node
命令
cons:
缺点:
- Include development package for a production build 包括用于生产构建的开发包
And quickly to explain each one
并快速解释每个
ts-nodeTypeScript execution and REPL. Transpile your code over tsc with ease without writing the file in your hard drive. In fact, you can directly execute your code from the
.ts
filets-node TypeScript执行和REPL。 轻松通过tsc转换代码,而无需将文件写入硬盘。 实际上,您可以直接从
.ts
文件执行代码tsconfig-pathsThis package helps us loading our module by reading the
paths
in the tsconfig and both loadings at run-time and via API are supported (as the doc says).tsconfig路径这个包可以帮助我们通过阅读我们的加载模块
paths
在运行时间,并通过API在tsconfig两个载荷和支持(作为医生说)。
Enough talking, let’s fix it! First, install the packages
聊够了,让我们解决它! 首先,安装软件包
npm install --save tsconfig-paths ts-node
Then, add this new line in the “scripts” entry of package.json to run the code in production 😏
然后,在package.json的“ scripts”条目中添加此新行以在生产环境中运行代码
// ...
"start:prod": "node -r ts-node/register/transpile-only -r tsconfig-paths/register ./dist/src/main.js",
/// ...
Then try to build and run the code
然后尝试构建并运行代码
npm run build && npm run start:prod
At this step, you should see the code running 🎉
在这一步,您应该看到代码正在运行
As you may have found out, this technique compiles again (2 times) the ts files to make this work.
您可能已经发现,该技术再次编译(两次)ts文件以使其工作。
那发展呢? (And what about development?)
For development, everything gets easier. I recommend using ts-node to transpile and run your code as it’s really efficient. Add this command in the package.json file and run it
对于开发而言,一切都会变得容易。 我建议使用ts-node来转换和运行您的代码,因为它非常有效。 在package.json文件中添加此命令并运行
"start:dev": "ts-node -r tsconfig-paths/register ./src/main.ts",
You can set this up with your favorite watcher to reload the code of course 😉
您可以使用自己喜欢的观察者进行设置,以重新加载代码😉
结论 (Conclusion)
I know the solution above is not really perfect at this stage and there are multiple ways to accomplish this (with a lot of pain…). But until the TypeScript team and/or other big team find a better way, we will have to trick it a bit to make it works, especially for the production part, or, we could try to request a nice change 😎.
我知道上述解决方案在目前阶段还不是很完美,并且有多种方法可以完成此任务(非常痛苦……)。 但是在TypeScript团队和/或其他大型团队找到更好的方法之前,我们将不得不对其进行一些欺骗以使其能够正常工作,尤其是对于生产部分,或者,我们可以尝试请求一个不错的更改😎。
In my opinion, it would be easier to have the path resolved during the compilation but as the TS team says, it gets complicated in some environment with symlink usage.
我认为,在编译期间解析路径会更容易,但是正如TS小组所说,在某些使用symlink的环境中,它变得很复杂。
As a note, in this tsconfig-path issue, there is a nice documented comment about what’s possible and the drawbacks https://github.com/dividab/tsconfig-paths/issues/61#issuecomment-623077578
需要注意的是,在此tsconfig-path问题中,有一篇很好的记录在案的评论,关于有什么可能和缺点https://github.com/dividab/tsconfig-paths/issues/61#issuecomment-623077578
You can find the all of this in this repo https://github.com/vschoener/say-bye-to-relative-path-typescript
您可以在此回购中找到所有这一切https://github.com/vschoener/say-bye-to-relative-path-typescript
Hope you enjoy this read, if you have a better way to make it works, let me hear you!
希望您喜欢这篇读物,如果您有更好的方法使它生效,请让我听听!
翻译自: https://medium.com/@VincentSchoener/say-bye-to-relative-paths-in-typescript-7242b6e6f252
typescript中函数