从别人那里拷了份前端项目的代码,对方确定代码是可以正常运行的,不管是开发模式下serve还是生成模式下build都没问题。我拷过来,没做任何修改该,开发模式下serve还是正常的,build prod 就会出错(我用的win7, 他用的linux)。
错误信息比较明显,是systemJS builder buildStatic() 的时候找不到某些模块,实际上只要import的格式是 import(‘./someModule‘) , 对应的模块都找不到。 根据打印出的信息,发现systemJS对于这种格式的模块解析出的完整路径都是错的。具体错误形式如下:
parentModule.js这个文件的完整路径如下: f:\project\dist\tmp\app\someModule\parentModule.js
parentModule.js 中
import(‘./childModule‘)
显然,childModule.js的完整路径应该是
f:\project\dist\tmp\app\someModule\childModule.js
但是systemJS builder
解析出来的路径都是 f:\project\dist\tmp\app\childModule.js ,
结果就是找不到这个模块。
看起来,应该是builder的路径相关的配置有问题, 也就是说可能是 map,
path或者package的配置不对。最终发现,是path中的这么一条配置导致的: [join(this.TMP_DIR, app, ‘*‘)]:
。
${this.TMP_DIR}/app/*
github的issue上还真有个人碰到了类似的问题: https://github.com/systemjs/systemjs/issues/157
systemJS的作者的解释是:
The point is that you can never "step below" the path specified in
paths.
就是说path里面配置的路径,是没法使用 ./, 那么上面那条path配置的行为就导致:一个模块如果路径是
...\tmp\app\**\*.js
,会被systemJS builder解析成
...\tmp\app\*.js
。也就是说,只要该模块的路径匹配到 ...\tmp\app, 就直接提出模块名,添加到
...\tmp\app后面。
我觉得这真的是反直觉的行为:
首先,‘./‘这种相对路径的格式,真的需要按照path里面的配置来解析吗?真的会有人希望
‘./someModule.js‘ 不和当前目录的模块对应,而是对应某个其他的稀奇古怪的地方的模块吗?
第二,
[f:\project\dist\tmp\app\*]:‘f:\project\dist\tmp\app\*‘
这种配置,正常人都会觉得,冒号左边和右边的两个*的内容应该是一致的,
因为这种配置看起来就像是两个目录之间的映射关系,但是现在的情况是,左边的*表示路径上在f:\project\dist\tmp\app\
之后的剩余的路径,而右边的*仅仅是模块名,不包含任何目录名称。
第三,为啥同样的配置,linux下运行正常,win7下就有这个问题。