nodejs的路径问题的解决


Posted in NodeJs onJune 30, 2018

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

can not get file index.html

express.static

问题出在哪儿?

nodejs后端的用了express,index.html是一个静态文件。我们知道,通过 Express 内置的 express.static 可以方便地托管静态文件,例如图片、CSS、JavaScript 文件等。

将静态资源文件所在的目录作为参数传递给 express.static 中间件就可以提供静态资源文件的访问了。例如,假设在 public 目录放置了图片、CSS 和 JavaScript 文件,可以使用如下代码:

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

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

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

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

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

当然最重要的是,这个问题其实不难,自己多钻研下,很容易发现问题,也就不会出这个问题,所以小伙伴自己打手心吧。

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

express.static方法解析

事实上,express.static方法如果传入的是相对路径,express会自己把他转换为绝对路径,我们可以查看下源代码,在express.js找到如下代码:

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

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

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

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

path对象的resolve方法

直接查看这个方法的api文档,如下:https://nodejs.org/api/path.html#path_path_resolve_paths

下面是这个方法的解释:

The path.resolve() method resolves a sequence of paths or path segments into an absolute path.

啥意思呢? 就是这个方法把一系列的paths或者path segments 组织成一个绝对路径,比如

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)。比如:

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/modules.html#modules_dirname

看到解释如下:

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'));

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
轻松创建nodejs服务器(9):实现非阻塞操作
Dec 18 NodeJs
轻松创建nodejs服务器(10):处理POST请求
Dec 18 NodeJs
NodeJS遍历文件生产文件列表功能示例
Jan 22 NodeJs
详解nodejs微信公众号开发——3.封装消息响应模块
Apr 10 NodeJs
nodejs个人博客开发第七步 后台登陆
Apr 12 NodeJs
详解Windows下安装Nodejs步骤
May 18 NodeJs
让nodeJS支持ES6的词法----babel的安装和使用方法
Jul 31 NodeJs
NodeJS收发GET和POST请求的示例代码
Aug 25 NodeJs
详解使用vscode+es6写nodejs服务端调试配置
Sep 21 NodeJs
nodejs实现连接mongodb数据库的方法示例
Mar 15 NodeJs
nodejs实现的简单web服务器功能示例
Mar 15 NodeJs
nodejs 使用 js 模块的方法实例详解
Dec 04 NodeJs
nodejs用gulp管理前端文件方法
Jun 24 #NodeJs
Nodejs异步回调之异常处理实例分析
Jun 22 #NodeJs
nodejs实现套接字服务功能详解
Jun 21 #NodeJs
详解Nodejs mongoose
Jun 10 #NodeJs
详解NodeJs开发微信公众号
May 25 #NodeJs
nodejs express配置自签名https服务器的方法
May 22 #NodeJs
通过nodejs 服务器读取HTML文件渲染到页面的方法
May 17 #NodeJs
You might like
详解php中反射的应用
2016/03/15 PHP
再谈Yii Framework框架中的事件event原理与应用
2020/04/07 PHP
23个超流行的jQuery相册插件整理分享
2011/04/25 Javascript
JavaScript闭包 懂不懂由你反正我是懂了
2011/10/21 Javascript
form表单中去掉默认的enter键提交并绑定js方法实现代码
2013/04/01 Javascript
JSON中双引号的轮回使用过程中一定要小心
2014/03/05 Javascript
javascript刷新父页面的各种方法汇总
2014/09/03 Javascript
JavaScript数组常用方法
2015/03/02 Javascript
javascript实现五星评价代码(源码下载)
2015/08/11 Javascript
高性能JavaScript DOM编程(1)
2015/08/11 Javascript
JavaScript操作XML/HTML比较常用的对象属性集锦
2015/10/30 Javascript
深入分析jQuery的ready函数是如何工作的(工作原理)
2015/12/17 Javascript
原生javascript实现自动更新的时间日期
2016/02/12 Javascript
全面详细的jQuery常见开发技巧手册
2016/02/21 Javascript
微信小程序网络请求wx.request详解及实例
2017/05/18 Javascript
解决在vue+webpack开发中出现两个或多个菜单公用一个组件问题
2017/11/28 Javascript
微信小程序使用audio组件播放音乐功能示例【附源码下载】
2017/12/08 Javascript
vue富文本框(插入文本、图片、视频)的使用及问题小结
2018/08/17 Javascript
详解Vue前端对axios的封装和使用
2019/04/01 Javascript
从零开始用webpack构建一个vue3.0项目工程的实现
2020/09/24 Javascript
vue 中使用print.js导出pdf操作
2020/11/13 Javascript
python中使用urllib2获取http请求状态码的代码例子
2014/07/07 Python
python实现颜色rgb和hex相互转换的函数
2015/03/19 Python
python获取一组汉字拼音首字母的方法
2015/07/01 Python
python数据结构之链表详解
2017/09/12 Python
ubuntu17.4下为python和python3装上pip的方法
2018/06/12 Python
Python正则表达式匹配和提取IP地址
2019/06/06 Python
搭建python django虚拟环境完整步骤详解
2019/07/08 Python
Django应用程序入口WSGIHandler源码解析
2019/08/05 Python
python list等分并从等分的子集中随机选取一个数
2020/11/16 Python
CSS3动画:5种预载动画效果实例
2017/04/05 HTML / CSS
化学教育专业求职信
2014/07/08 职场文书
部门2015年度工作总结
2015/04/29 职场文书
致我们终将逝去的青春观后感
2015/06/10 职场文书
2015暑假假期总结
2015/07/13 职场文书
python运行脚本文件的三种方法实例
2022/06/25 Python