最近公司的一个开发项目,后端用的是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'));

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

ITman彪叔公众号

nodejs的路径问题的更多相关文章

  1. NodeJS require路径

    项目需要用nodejs,感觉nodejs是前端装逼神器了,是通向全栈工程师的必经之路哇,接下来开始踏上学习nodejs的征程.下面是第一个hello,world的程序. 1.server.js文件,这 ...

  2. nodeJS之路径PATH模块

    前面的话 path模块包含一系列处理和转换文件路径的工具集,通过 require('path') 可用来访问这个模块.本文将详细介绍path模块 路径组成 [path.dirname(p)] 返回路径 ...

  3. nodejs fs路径

    引用:https://www.cnblogs.com/guangzhou11/p/7705257.html require()别的js文件的时候,将执行那个js文件. 注意: require()中的路 ...

  4. nodejs 文件路径问题

    fs.stat()  是 获取 本目录下 文件信息 的方法 .如果使用要加上绝对路径.不然会出问题.例: 解决方法

  5. nodeJS文件路径总结

    文件夹目录F:* test1* tes2* test3* test4* a.html*//例句fs.readFile('../../../a.html', function (err, html) { ...

  6. Windows 系统下设置Nodejs NPM全局路径

    Windows下的Nodejs npm路径是appdata,很不爽,想改回来,但是在cmd下执行以下命令也无效 npm config set cache "D:\nodejs\node_ca ...

  7. 设置Nodejs NPM全局路径

    Windows下的Nodejs npm路径是appdata 在nodejs的安装目录中找到node_modules\npm\.npmrc文件 修改如下即可: prefix = E:\nodejs\np ...

  8. [记]Windows 系统下设置Nodejs NPM全局路径

    Windows下的Nodejs npm路径是appdata,担心安装的node_modules越来越多,导致C盘满,所以参考别人的博文,将node_modules安装的默认目录修改一下. 参考Wind ...

  9. windows环境下sublime的nodejs插件详细安装图解

    前面的话   搜索了好多文档后,才成功地安装了sublime text3的nodejs插件.为了存档,也为了方便有同样需求的朋友,将其安装过程详细记录如下 安装nodejs 虽然nodejs官网提供了 ...

随机推荐

  1. disconf实践(一)Ubuntu16.04部署disconf

    在企业中,随着公司业务的扩张,用户量的增大,单一节点应用无法支撑正常的业务逻辑,比较常见的现象是访问速度变慢,甚至超时,严重时可能会造成系统宕机.为了尽量减少宕机的风险,单一节点系统需要进行水平扩展, ...

  2. vue04-动画、组件

    一.vue中使用动画 文档:https://cn.vuejs.org/v2/guide/transitions.html 1. Vue 中的过渡动画 <!DOCTYPE html> < ...

  3. Discuptor入门(二)-实例

    前言:最近在项目中看到有人使用的discuptor框架,因为没有接触过所以网上找了些资料.但最终发现开荒者太少,好像没什么人用那.最后感觉还是官方入门文档靠谱点.所以自己翻译了下(翻译器~),希望能帮 ...

  4. python面试题之基础

    一.基础语法 1. 输入与输出 1.1 代码中要修改不可变数据会出现什么问题? 抛出什么异常? (2018-3-29-lxy) 代码不会正常运行,抛出 TypeError 异常. 1.2a=1,b=2 ...

  5. MYSQL 入门全套

    MySQL简介 1.什么是数据库 ? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不再仅 ...

  6. SpringAOP的自定义注解实践

    springaop属于spring的重要属性,在java中有相当广泛的用途,大家一般都接触过aop实现事务的管理,在xml里配好声明式事务,然后直接在service上直接加上相应注解即可, 今天我们来 ...

  7. php composer 实现类的自动加载

    我们在开发项目中会经常用到第三方的类库插件,但是如果每次需要使用的时候都会在代码的某一处去引入,然后在实例化,这样做感觉很不方便,那么怎么实现自动加载呢,下面简单介绍使用composer实现自动加载: ...

  8. Delphi主线程重入而导致程序卡死的解决方案

    Delphi的线程可以通过调用AThread.Synchronize(AProc),可以将Proc放入主线程中同步运行,此时AThread将挂起,直到主线程执行完AProc. 如果有BThread,调 ...

  9. MIPI调试经验(转载)

    目录 一.D-PHY 1.传输模式 2.Lane States 3.Lane Levels 4.操作模式 5.时序要求 二.DSI 1.线路构成 2.两种接口的 LCD 3.数据包类型 4.从控制器到 ...

  10. QEMU 模拟运行 VxWorks 6.6

    QEMU 模拟运行 VxWorks 6.6 项目简介 本项目是在 Windows 系统编译运行 X86 平台 VxWorks 6.6 系统,使用的模拟软件是 qemu for Windows Host ...