nodejs的路径问题

最近公司的一个开发项目,后端用的是nodejs。这两天须要打包给客户演示,就让公司一个小伙把以前3D机房的打包工具移植过来。打包以后,发现本来在开发环境下的跑的好好的项目,不能访问了。出现项目的首页不能访问的问题:html

can not get file index.html

express.static

问题出在哪儿?
nodejs后端的用了express,index.html是一个静态文件。咱们知道,经过 Express 内置的 express.static 能够方便地托管静态文件,例如图片、CSS、JavaScript 文件等。
将静态资源文件所在的目录做为参数传递给 express.static 中间件就能够提供静态资源文件的访问了。例如,假设在 public 目录放置了图片、CSS 和 JavaScript 文件,可使用以下代码:node

app.use(express.static('public'));

因此,找到项目中的代码,查看static调用的地方,和上面一行代码很同样:express

app.use(express.static('public'));

到此,我已经发现了问题,我告诉小伙伴,这个地方不用相对路径能够解决这个问题。因为打包时间限制,我让小伙伴先简单处理下,打完包以后,在来整理下思路:后端

app.use(express.static('resource/public'));
固然最重要的是,这个问题其实不难,本身多钻研下,很容易发现问题,也就不会出这个问题,因此小伙伴本身打手心吧。

恩,你没看错,这个地方仍是相对目录。后续产品中会改为比较好的一种状况。api

express.static方法解析

事实上,express.static方法若是传入的是相对路径,express会本身把他转换为绝对路径,咱们能够查看下源代码,在express.js找到以下代码:app

exports.static = require('serve-static');

说明static 调用了serve-static这个包,直接找到这个包,查看index.js, 能够看到代码,下面列出重要的两行工具

...
var resolve = require('path').resolve
...
opts.root = resolve(root)
...

这两行就是,express把相对目录转换成绝对目录的代码,能够看出,最终使用的path这个内置对象的resolve方法,继续往下看。ui

path对象的resolve方法

直接查看这个方法的api文档,以下:
https://nodejs.org/api/path.h...
下面是这个方法的解释:
The path.resolve() method resolves a sequence of paths or path segments into an absolute path.
啥意思呢? 就是这个方法把一系列的paths或者path segments 组织成一个绝对路径,好比this

path.resolve('/foo','bar');
// return /foo/bar

详细的说明请自行参考文档,这个地方有一句话须要特别注意:
If after processing all given path segments an absolute path has not yet been generated, the current working directory is used.
啥意思,就是若是处理完了全部的path segments,也没有生成一个绝对路径, 就要使用 当前工做目录(current working directory)。好比:spa

path.resolve('bar');
// 加上 /Users/terry 是当前工做目录, return /Users/terry/bar

api文档中一个比较复杂的示例(此处注意resolve的时候,从右到左,参考文档了解详情):

path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
// if the current working directory is /home/myself/node,
// this returns '/home/myself/node/wwwroot/static_files/gif/image.gif'

如今的问题是,啥是当前工做目录。

nodejs 当前工做目录 current working directory

nodejs 当前工做目录是启动Node的目录。也就是说,从哪一个目录进去启动node,就返回哪一个目录。

注意,这个目录不是指js文件所在的目录
经过process.cwd()方法能够获取当前工做目录。

下面经过一个示例来介绍这个当前工做目录,假如在/Users/terry/Documents/JSWorkspace目录下写一个js文件,test.js,代码只有一行:

console.log(process.cwd());

此时若是,在目录/Users/terry/Documents/JSWorkspace下面执行命令 :node test.js 输出以下:

/Users/terry/Documents/JSWorkspace

可是若是在在目录/Users/terry/Documents/下面执行命令:node ./JSWorkspace/test.js,输出的结果是:

/Users/terry/Documents

所以能够看出你在那个目录执行node命令,当前目录就是那个目录。

回到以前的打包的问题,因为在开发阶段,通常都是直接在js文件所在目录执行node命令,因此相对目录写的是相对于当前js文件的目录没有问题。
但是打包以后,node的执行放到了js目录的上一层去了。此时相对目录“public”不在是相对于js文件的相对目录,而是相对于上一层的,天然就找不到这个文件夹了,从而也找不到该文件夹下的index.html文件。

如何解决

解决的方法:

  1. 在前面已经说过了,改这个相对目录。但这种方法很蹩脚。由于,启动node命令的目录可能会变;而是若是这应该,开发阶段的node命令执行也须要跟着改。 总之不是兼容性很好的方法。
  2. 直接使用绝对路径。 可是这个绝对路径在不一样的机器上又不同,该如何解决呢?能够考虑使用全局变量__dirname.

全局变量__dirname

查看api文档 https://nodejs.org/api/module...
看到解释以下:
The directory name of the current module. This is the same as the path.dirname() of the __filename
啥意思呢,及时返回nodejs 的js文件的所在目录。
有了这个变量以后,咱们就能够用以下代码解决这个问题。

app.use(express.static(__dirname + '/public'));

更多精彩内容,请关注公众号。
ITman彪叔公众号

相关文章
相关标签/搜索