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(二)--- Node.js事件模块
May 21 NodeJs
轻松创建nodejs服务器(4):路由
Dec 18 NodeJs
详解Nodejs基于mongoose模块的增删改查的操作
Dec 21 NodeJs
CentOS 安装NodeJS V8.0.0的方法
Jun 15 NodeJs
NodeJS使用七牛云存储上传文件的方法
Jul 24 NodeJs
NodeJS设计模式总结【单例模式,适配器模式,装饰模式,观察者模式】
Sep 06 NodeJs
nodejs实现套接字服务功能详解
Jun 21 NodeJs
深入理解nodejs搭建静态服务器(实现命令行)
Feb 05 NodeJs
linux 下以二进制的方式安装 nodejs
Feb 12 NodeJs
NodeJS多种创建WebSocket监听的方式(三种)
Jun 04 NodeJs
在NodeJs中使用node-schedule增加定时器任务的方法
Jun 08 NodeJs
Nodejs实现微信分账的示例代码
Jan 19 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之浮点数计算比较以及取整数不准确的解决办法
2015/07/29 PHP
javascript 中对象的继承〔转贴〕
2007/01/22 Javascript
Jquery AutoComplete自动完成 的使用方法实例
2010/03/19 Javascript
用JavaScript对JSON进行模式匹配(Part 1-设计)
2010/07/17 Javascript
js对象之JS入门之Array对象操作小结
2011/01/09 Javascript
jQuery prev ~ siblings选择器使用介绍
2013/08/09 Javascript
js控制页面控件隐藏显示的两种方法介绍
2013/10/09 Javascript
js利用事件的阻止冒泡实现点击空白模态框的隐藏
2014/01/24 Javascript
jQuery 仿百度输入标签插件附效果图
2014/07/04 Javascript
node.js中的fs.writeFileSync方法使用说明
2014/12/14 Javascript
js控制文本框输入的字符类型方法汇总
2015/06/19 Javascript
Jquery中使用show()与hide()方法动画显示和隐藏图片
2015/10/08 Javascript
BootStrap Table对前台页面表格的支持实例讲解
2016/12/22 Javascript
JavaScript函数节流的两种写法
2017/04/07 Javascript
为输入框加入数字js校验代码分享
2017/11/02 Javascript
解决Vue 浏览器后退无法触发beforeRouteLeave的问题
2017/12/24 Javascript
vuejs项目打包之后的首屏加载优化及打包之后出现的问题
2018/04/01 Javascript
如何能分清npm cnpm npx nvm
2019/01/17 Javascript
使用ThinkJs搭建微信中控服务的实现方法
2019/08/08 Javascript
Node.js从字符串生成文件流的实现方法
2019/08/18 Javascript
Vue中多元素过渡特效的解决方案
2020/02/05 Javascript
[05:42]DOTA2英雄梦之声_第10期_蝙蝠骑士
2014/06/21 DOTA
[01:14:34]DOTA2上海特级锦标赛C组资格赛#2 LGD VS Newbee第一局
2016/02/28 DOTA
Python的内存泄漏及gc模块的使用分析
2014/07/16 Python
python实现进程间通信简单实例
2014/07/23 Python
Python3基础之基本数据类型概述
2014/08/13 Python
Python判断中文字符串是否相等的实例
2018/07/06 Python
Python中logging实例讲解
2019/01/17 Python
基于wxPython的GUI实现输入对话框(2)
2019/02/27 Python
Python django框架应用中实现获取访问者ip地址示例
2019/05/17 Python
Python如何执行精确的浮点数运算
2020/07/31 Python
西班牙香水和化妆品购物网站:Arenal Perfumerías
2019/03/01 全球购物
澳大利亚窗帘商店:Curtain Wonderland
2019/12/01 全球购物
电子信息工程专业自荐书
2014/06/24 职场文书
语文教研活动总结
2014/07/02 职场文书
python3实现无权最短路径的方法
2021/05/12 Python