我试图引用自定义模块快捷方式(即使用ts路径映射功能)为我的类型记录应用程序,与以下配置。
项目结构
dist/
src/
lyrics/
... ts files
app/
... ts files完整的项目结构在这里:Github.com/adadgio/npm-歌词-ts,dist文件夹当然是没有完成的)
tsconfig.json
{
"compilerOptions": {
"outDir": "dist",
"module": "commonjs",
"target": "es6",
"sourceMap": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"removeComments": true,
"noImplicitAny": false,
"baseUrl": ".",
"paths": {
"*": ["src/lyrics/*"], // to much here !! but none work
"zutils/*": ["./src/lyrics/*", "src/lyrics/utils/*", "dist/lyrics/utils/*"]
},
"rootDir": "."
},
"exclude": [
"dist",
"node_modules"
],
"include": [
"src/**/*.ts"
]
}当我运行npm启动/编译或查看脚本时,我不会收到任何类型记录错误。以下工作(Atom是我的IDE)
// string-utils.ts does exist, no IDE error, typescript DOES compile
`import { StringUtils } from 'zutils/string-utils';` 但是,我得到了下面的NodeJS错误:
Error: Cannot find module 'zutils/string-utils'
at Function.Module._resolveFilename (module.js:470:15)
at Function.Module._load (module.js:418:25)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/home/adadgio/WebServer/projects/adadgio/npm-lyrics-ts/src/index.ts:7:1)
at Module._compile (module.js:571:32)
at Module.m._compile (/home/adadgio/WebServer/projects/adadgio/npm-lyrics-ts/node_modules/ts-node/src/index.ts:413:23)
at Module._extensions..js (module.js:580:10)
at Object.require.extensions.(anonymous function) [as .ts] (/home/adadgio/WebServer/projects/adadgio/npm-lyrics-ts/node_modules/ts-node/src/index.ts:416:12)
at Module.load (module.js:488:32)看起来该模块正在尝试从node_modules文件夹中解析。我读过关于类型记录路径映射的文档,但是我无法让它工作。
发布于 2018-06-26 13:51:00
我对此做了很多研究。我用的是原子,打字稿和nodejs。
问题是,当您编译类型记录时,它确实搜索路径(要包含的.ts文件的路径)。但是,最终编译的.js文件不会被路径替换。
解决方案:
因此,从本质上讲,tsconfig的部分内容如下所示
"baseUrl": "./app",
"paths" : {
"@GameInstance" : ["model/game/GameInstance"],
"@Map" : ["model/game/map/Map"],
"@MapCreator" : ["model/game/map/creator/MapCreator"],
"@GameLoop" : ["model/game/GameLoop"],
"@Point" : ["model/other/math/geometry/Point"],
"@Rectangle" : ["model/other/math/geometry/Rectangle"],
"@Functions" : ["model/other/Functions"]
}并考虑Rectangle.ts文件
import { Point } from '@Point';
import { Vector } from '@Vector';
/**
* Represents a rectangle.
* You can query it for collisions or whether rectangles are touching
*/
export class Rectangle {
//more codeRectangle.ts在哪里
./src/app/model/other/math/geometry/Rectangle/Rectangle.ts我们跑
tsc它将编译我们设置的所有.ts文件。在那里,路径将在运行时被替换,如果您有错误,请运行
tsc --traceResolution > tmp && gedit tmp并且搜索这里的字段是未定义的路径。您将能够看到替换日志。
然后留给我们的是Rectangle.js (构建)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var _Point_1 = require("@Point");
//more code正如您所看到的,@Point将不存在,并且我们无法像这样运行节点应用程序。
但是,为此,我创建了一个脚本,它递归地搜索js文件,并通过上升到根,然后到目标路径替换令牌。
在requirePaths.data文件中,您可以定义令牌和路径。
'@GameLoop' : "./app/model/game/GameLoop"
'@GameInstance' : "./app/model/game/GameInstance"
"@Map" : "./app/model/game/map/Map"
"@MapCreator" : "./app/model/game/map/creator/MapCreator"
"@Point" : "./app/model/other/math/geometry/Point"
"@Rectangle" : "./app/model/other/math/geometry/Point"现在,这不是普遍的,这只是我的热门剧本。请注意,这个结构是
src
|-app
| |-model
-build
|-src
|-app
|-model
|-test严格地说,应用程序/模型..。结构,只是将其复制到src/build中,tsc从/ src /app获取源代码并对其进行编译。编译结果在/src/build中。
然后是substitutePathsInJS.sh脚本。这个scand用于构建路径,每当它找到token @矩形时,它就会替换它(更详细的解释如下……)代码:
#!/bin/bash
function testreqLevel()
{
local srcPath="$1"
local replacingIn="$2"
local expectedLevel=$3
getPathLevel "$replacingIn"
local res=$?
if [ ! $res -eq $expectedLevel ]; then
echo "[-] test $srcPath , $replacingIn FAILED. ($res != $expectedLevel)"
fi
}
function assertreqPath()
{
local input="$1"
local expected="$2"
if [ ! "$input" = "$expected" ]; then
echo "[-] test $expected FAILED"
echo "computed: $input"
echo "expected: $expected"
fi
}
function testGetPathLevel()
{
testreqLevel "./build/src" "./build/src/app/model/game/GameObject.js" 4
testreqLevel "./build/src" "./build/src/file.js" 1
testreqLevel "./build/src" "./build/src/app/model/game/GameObject.js" 4
}
function testGetPathToRoot()
{
local path=$(getPathToRoot "./build/src" "./build/src/app/model/game/GameObject.js")
assertreqPath "$path" "../../../../../"
path=$(getPathToRoot "./" "./server.js")
assertreqPath "$path" "./"
path=$(getPathToRoot "./" "./app/model/game/GameInstance.js")
assertreqPath "$path" "../../../"
}
function err()
{
echo "[-] $1"
}
function getPathLevel()
{
#get rid of starting ./
local input=$(echo "$1" | sed "s/^\.\///")
local contains=$(echo "$input" | grep '/')
if [ -z "$contains" ]; then
return 0
fi
#echo "$input"
local slashInput=$(echo "$input" | awk -F/ '{print NF-1}')
return $(($slashInput - 1))
}
#given ROOT, and PATH, returns a path P such as being in directory PATH, from there using P we get to root
#example:
#ROOT=./src
#PATH=./src/model/game/objects/a.js
#returns ../../
function getPathToRoot()
{
local root="$1"
local input="$2"
getPathLevel "$input"
local level=$?
if [ $level -eq 0 ]; then
echo "./"
return 0
fi
for ((i=1; i <= level + 1; i++)); do
echo -n '../'
done
#echo "$root" | sed 's/^\.\///'
}
function parseData()
{
echo "**************"
echo "**************"
local data="$1"
let lineNum=1
while read -r line; do
parseLine "$line" $lineNum
if [ $? -eq 1 ]; then
return 1
fi
let lineNum++
done <<< "$data"
echo 'Parsing ok'
echo "**************"
echo "**************"
return 0
}
function parseLine()
{
if [[ "$1" =~ ^\#.*$ ]] || [[ "$1" =~ ^\ *$ ]]; then
#comment line
return 0
fi
local line=$(echo "$1" | sed "s/\"/'/g")
let lineNum=$2
local QUOTE=\'
local WORD_IN_QUOTES=$QUOTE[^:$QUOTE]*$QUOTE
if [[ "$line" =~ ^\ *$WORD_IN_QUOTES\ *:\ *$WORD_IN_QUOTES\ *$ ]]; then
# valid key : value pair
local key=$(echo "$line" | awk -F: '{print $1}' | sed 's/^ *//g' \
| sed 's/ *$//g' | sed 's/\//\\\//g' | sed "s/'//g" | sed "s/\./\\\./g")
local val=$(echo "$line" | awk -F: '{print $2}' | sed 's/^ *//g' \
| sed 's/ *$//g' | sed "s/'//g")
echo "[+] Found substitution from '$key' : '$val'"
if [ -z "$REPLACEMENT_KEY_VAL" ]; then
REPLACEMENT_KEY_VAL="$key|$val"
else
REPLACEMENT_KEY_VAL="$REPLACEMENT_KEY_VAL;$key|$val"
fi
else
err "Parse error on line $lineNum"
echo "Expecting lines 'token' : 'value'"
return 1
fi
return 0
}
function replaceInFiles()
{
cd "$WHERE_SUBSTITUTE"
echo "substitution root $WHERE_SUBSTITUTE"
local fileList=`find . -type f -name "*.js" | grep -v "$EXCLUDE"`
echo "$fileList"| while read fname; do
export IFS=";"
echo "Replacing in file '$WHERE_SUBSTITUTE$fname'"
for line in $REPLACEMENT_KEY_VAL; do
local key=`echo "$line" | awk -F\| '{print $1}'`
local val=`echo "$line" | awk -F\| '{print $2}'`
local finalPath=$(getPathToRoot "./" "$fname")"$val"
if [ $VERBOSE -eq 1 ]; then
echo -e "\tsubstitute '$key' => '$val'"
#echo -e "\t$finalPath"
echo -e "\treplacing $key -> $finalPath"
fi
#escape final path for sed
#slashes, dots
finalPath=$(echo "$finalPath" | sed 's/\//\\\//g'| sed 's/\./\\\./g')
if [ $VERBOSE -eq 1 ]; then
echo -e '\t\tsed -i.bak '"s/require(\(.\)$key/require(\1$finalPath/g"\ "$fname"
fi
sed -i.bak "s/require(\(.\)$key\(.\))/require(\1$finalPath\2)/g" "$fname"
done
done
return 0
}
function quit()
{
echo "*************************************"
echo "*****SUBSTITUTING PATHS EXITING******"
echo "*************************************"
echo
exit $1
}
#######################################
CURRENTDIR=`dirname "$(realpath $0)"`
WHERE_SUBSTITUTE='./build/src'
REPLACEMENT_KEY_VAL="";
VERBOSE=0
FILE="$CURRENTDIR/requirePaths.data"
EXCLUDE='./app/view'
if [ "$1" = "-t" ]; then
testGetPathLevel
testGetPathToRoot
echo "[+] tests done"
exit 0
fi
if [ "$1" = "-v" ]; then
VERBOSE=1
fi
echo "*************************************"
echo "********SUBSTITUTING PATHS***********"
echo "*************************************"
if [ ! -f "$FILE" ]; then
err "File $FILE does not exist"
quit 1
fi
DATA=`cat "$FILE"`
parseData "$DATA"
if [ $? -eq 1 ]; then
quit 1
fi
replaceInFiles
quit $?这似乎令人困惑,但请考虑一下。我们有Rectangle.js文件。
脚本从requirePaths.data文件加载大量输入令牌,在本例中,让我们在线关注
"@Point" : "./app/model/other/math/geometry/Point"脚本运行于./src,并给出根目录./src/build/src。
脚本做cd ./src/build/src
执行查找。在那里,它会收到
./model/other/math/geometry/Rectangle/Rectangle.ts它的绝对路径是
./src/build/src/app/model/other/math/geometry/Rectangle/Rectangle.ts但我们现在不关心绝对的道路。
计算路径,比如他从目录中得到的路径,Whis将得到的结果如下所示
./../../../../他希望从目录中得到
/src/build/app/model/other/math/geometry/Rectangle到目录
/src/build/app然后,在该字符串后面,添加数据文件中提供的路径。
./../../../.././app/model/other/math/geometry/Point因此,文件Rectangle.js的最后替代(在构建文件夹中的某个位置)是
先于
require("@Point")后
require("./../../../.././app/model/other/math/geometry/Point")这很糟糕,但我们并不关心js中的内容。最重要的是它能工作。
缺点
有些人通常只替换@app或一些目录。问题是,每当你移动源文件时,你必须做很多改变.
好的一面
https://stackoverflow.com/questions/42276798
复制相似问题