ts-node加载node_modules中的源码

简介: ts-node加载node_modules中的源码

需求来源

安装了一个自己写的test-package,里面有一些可复用的代码,比如有个index.ts的代码如下:

export const msg = 'msg';
复制代码

想要在新项目里面import这些代码,

import {msg} from 'test-package/index'
复制代码

发现无法正常import,提示

网络异常,图片无法展示
|

定位问题

解析ts我这边使用的ts-node,对配置也不是太熟悉,根据报错堆栈开始追代码,发现import会调用require,而require会调用module.load,Module._extensions[extension]()这句代码会根据文件扩展名调用相应的

网络异常,图片无法展示
|

顺带看了下json的实现

网络异常,图片无法展示
|

原理就是读取字符串,然后JSONParse下,也不是太难

const {JSONParse} = primordials;
复制代码

ts文件的话,最终就会来到ts-node里面,这里有个非常重要的逻辑:

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|
网络异常,图片无法展示
|

其中shouleIgnore函数里面,有对node_modules的排除,同时options也是可以干扰这个结果的,其实在ts-node的文档里面也有说明这个参数

那么我们应该如何传递这个参数呢?

解决问题

ts-node的文档上也有写,会读取当前工作目录的tsconfig.json

它会从ts-node中读取需要的参数

tsconfig.json示例

{
    "ts-node":{
        "skipIgnore": true
    }
}
复制代码

这样就能完美的引入node_modules里面的代码了,至于有其他的什么问题,暂时没有多测试

优化实现

上述的这个解决方案能解决问题,但是我的需求是希望默认开始这个设置,不想要用户自己在tsconfig.json中手动增加这个配置。

我使用的是cli,所以可以通过代码控制这个参数,

require('ts-node')
    .register({
        skipIgnore: true,
    });
复制代码

但是我这里使用了一个第三方的库:rechoirinterpret,它可以根据不同的文件扩展名准备内置好的环境,对于ts文件,它内置了好几个环境,其中就有这个ts-node,最终也是会调用register函数, 这个库也是通过看vue-cli-server才知道的。

所以接下来,就看下怎么把register的参数传递进去

最终发现interpret的配置是写死的,也没有开放register的参数,看来通过api修改的路堵死了。

网络异常,图片无法展示
|

再读ts-node的源码,定义环境变量

发现options的数据有来自process.env

export const env = process.env as ProcessEnv;
export const DEFAULTS: RegisterOptions = {
  cwd: env.TS_NODE_CWD ?? env.TS_NODE_DIR,
  emit: yn(env.TS_NODE_EMIT),
  scope: yn(env.TS_NODE_SCOPE),
  scopeDir: env.TS_NODE_SCOPE_DIR,
  files: yn(env.TS_NODE_FILES),
  pretty: yn(env.TS_NODE_PRETTY),
  compiler: env.TS_NODE_COMPILER,
  compilerOptions: parse(env.TS_NODE_COMPILER_OPTIONS),
  ignore: split(env.TS_NODE_IGNORE),
  project: env.TS_NODE_PROJECT,
  skipProject: yn(env.TS_NODE_SKIP_PROJECT),
  skipIgnore: yn(env.TS_NODE_SKIP_IGNORE),
  preferTsExts: yn(env.TS_NODE_PREFER_TS_EXTS),
  ignoreDiagnostics: split(env.TS_NODE_IGNORE_DIAGNOSTICS),
  transpileOnly: yn(env.TS_NODE_TRANSPILE_ONLY),
  typeCheck: yn(env.TS_NODE_TYPE_CHECK),
  compilerHost: yn(env.TS_NODE_COMPILER_HOST),
  logError: yn(env.TS_NODE_LOG_ERROR),
  experimentalReplAwait: yn(env.TS_NODE_EXPERIMENTAL_REPL_AWAIT) ?? undefined,
};
复制代码

其中yn模块可以快速的将一些含义非常相似的数据转换为js可识别的值,比如:

  • yn('y')=> true
  • yn(true)=> true

TS_NODE_SKIP_IGNORE环境变量就是我们要找的目标。

只要我们在process.env上定义这个变量也可以达到同样的效果,通过dotenvdotenv-expand来操作环境变量也可以达到预期的效果。

总结

一路看下来,还是学到了不少的新知识,遇到问题从源码入手解决问题,是有点浪费时间,但是能让你对细节更加的了解。



目录
相关文章
|
6月前
|
缓存
node中的优先从缓存中加载模块与模块的加载规则
node中的优先从缓存中加载模块与模块的加载规则
|
6月前
webpack 使用打包报错 ERROR in node_modules\@types\node\ts4.8\assert.d.ts
webpack 使用打包报错 ERROR in node_modules\@types\node\ts4.8\assert.d.ts
407 0
|
3月前
Electron——node_modules\ffi-napi\build\Release\ffi_bindings.node is not a valid Win32 application.
Electron——node_modules\ffi-napi\build\Release\ffi_bindings.node is not a valid Win32 application.
58 0
|
4月前
|
监控 JavaScript 前端开发
Node中的AsyncLocalStorage 使用问题之Node.js内部模块和外部模块的加载的问题如何解决
Node中的AsyncLocalStorage 使用问题之Node.js内部模块和外部模块的加载的问题如何解决
|
5月前
vue.js+node.js+mysql在线聊天室源码
vue.js+node.js+mysql在线聊天室源码 技术栈:vue.js+Element UI+node.js+socket.io+mysql
167 3
|
6月前
|
存储 缓存 资源调度
深入浅出Node.js中的node_modules(二)
深入浅出Node.js中的node_modules
|
4月前
|
JavaScript
TS,编写TS文件,编写hello.ts文件,cmd下打开终端,输入tsc hello.ts会生成一个hello.js文件,简化命令,npm i -g ts-node,ts-node hello.ts
TS,编写TS文件,编写hello.ts文件,cmd下打开终端,输入tsc hello.ts会生成一个hello.js文件,简化命令,npm i -g ts-node,ts-node hello.ts
|
4月前
|
开发工具 git
vscode设置 git提交代码忽略node_modules,dist,vscode如何设置不提交node_modules,dist
vscode设置 git提交代码忽略node_modules,dist,vscode如何设置不提交node_modules,dist
466 0
|
6月前
|
JavaScript 数据库
使用 Webpack 打包 node 程序,node_modules 真的被干掉啦
使用 Webpack 打包 node 程序,node_modules 真的被干掉啦
342 0
|
6月前
Angular启动/node_modules/@types/node/index.d.ts (20,1): Invalid ‘reference‘ directive syntax.
Angular启动/node_modules/@types/node/index.d.ts (20,1): Invalid ‘reference‘ directive syntax.
76 2