起因
node 中路径在很多地方都有使用, 基础到不起眼. 但有时候就是不起眼的东西, 会在你不轻易间跳出来给你上一课.
想起来复习一下文件路径的起因, 是因为最近整理了一下项目结构, 调整了目录. 这也是基于对现代 IDE 的信任 (都是 IDE 给惯的病),IDE 会处理好路径问题, 所以我只管拖动, 他负责善后. 可是没想到啊, 我尽然忘了他不会处理 path.join(__dirname, '/../logs/') 这种方式的路径.
于是在代码运行了两天后, 发现怎么 project/logs 的里面的日志停更了两天, 是拖更吗? 这不行啊, 我得催催更.
这才发现 logger 中间件的目录也变了, 但是处理的路径不对, logs 也没有拖更, 只是另寻他处了.
- log4js.configure({
- appenders: {
- console: {
- type: 'console'
- },
- koa: {
- type: 'dateFile',
- filename: path.join(__dirname, '/../logs/'), // 问题出在我身上
- pattern: 'yyyy-MM-dd.log',
- alwaysIncludePattern: true
- }
- },
- categories: { default: { appenders: ['console', 'koa'], level: 'debug' } }
- });
那肛肛好复习一下文件路径吧.
复习
概念
node 中分为相对路径和绝对路径两种, 相对路径表示当前目录层级相对于目标的位置, 而绝对路径表示目标当前所在的位置.
相对路径:
./ 当前目录, ../ 上层目录,...
绝对路径
__dirname 被执行的 JS 所在目录的绝对路径
__filename 被执行的 JS 的绝对路径
process.cwd() 当前 node 命令执行时所在的文件夹的绝对路径
path 路径
path.join([...paths]) 使用平台特定的分隔符把所有 path 片段连接到一起, 并规范化生成的路径
path.resolve([...paths]) 将路径或路径片段的序列处理成绝对路径. 指定的路径序列是从右往左开始处理的, 后面的 path 被依次处理, 直到构造完绝对路径. 例如, 指定的路径片段序列为:/foo,/bar,baz, 则调用 path.resolve('/foo', '/bar', 'baz') 会返回 /bar/baz
- // join
- path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
- // 返回: '/foo/bar/baz/asdf'
- path.join('foo', {
- }, 'bar');
- // 抛出'TypeError: Path must be a string. Received {}'
- // resolve
- path.resolve('/foo/bar', './baz');
- // 返回: '/foo/bar/baz'
- path.resolve('/foo/bar', '/tmp/file/');
- // 返回: '/tmp/file'
- path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif');
- // 如果当前工作目录是 /home/myself/node, 则返回 '/home/myself/node/wwwroot/static_files/gif/image.gif'.
示例
在 logger.JS 的文件里写下如下代码:
- // 所在:/Users/simon/workspace/Inspiration/FitNoteServer/src/util/logger.JS
- console.log(__dirname);
- console.log(process.cwd());
- console.log(__filename);
- console.log('----------------------');
- console.log(path.join(__dirname, '/'));
- console.log(path.join(__dirname, '../logs/'));
- console.log(path.join(__dirname, '../../logs'));
- console.log('----------------------');
- console.log(path.resolve(__dirname, '/'));
- console.log(path.resolve(__dirname, '../logs/'));
- console.log(path.resolve(__dirname, '../../logs'));
然后分别在不同目录下启动项目:
- # workspace/Inspiration/FitNoteServer
- node src/index.JS
- /Users/simon/workspace/Inspiration/FitNoteServer/src/util
- /Users/simon/workspace/Inspiration/FitNoteServer
- /Users/simon/workspace/Inspiration/FitNoteServer/src/util/logger.JS
- ----------------------
- /Users/simon/workspace/Inspiration/FitNoteServer/src/util/
- /Users/simon/workspace/Inspiration/FitNoteServer/src/logs/
- /Users/simon/workspace/Inspiration/FitNoteServer/logs
- ----------------------
- /
- /Users/simon/workspace/Inspiration/FitNoteServer/src/logs
- /Users/simon/workspace/Inspiration/FitNoteServer/logs
- # Inspiration/FitNoteServer/src
- node index.JS
- /Users/simon/workspace/Inspiration/FitNoteServer/src/util
- /Users/simon/workspace/Inspiration/FitNoteServer/src
- /Users/simon/workspace/Inspiration/FitNoteServer/src/util/logger.JS
- ----------------------
- /Users/simon/workspace/Inspiration/FitNoteServer/src/util/
- /Users/simon/workspace/Inspiration/FitNoteServer/src/logs/
- /Users/simon/workspace/Inspiration/FitNoteServer/logs
- ----------------------
- /
- /Users/simon/workspace/Inspiration/FitNoteServer/src/logs
- /Users/simon/workspace/Inspiration/FitNoteServer/logs
重点
上面两个代码片段可以清楚的看到 node 执行目录不同对相对路径的影响, 相对路径 ./ 跟 process.cwd() 相同, 都是当前 node 命令执行时所在的文件夹的绝对路径.
而 node 中, 使用 require 时可以忽略这点, 你可以在 require 中使用相对路径, 但是在其他的地方都需要使用绝对路径. 因为 require 内部的路径始终相对于你调用它的文件, 它与你的工作目录无关.
总结
在项目中要格外注意相对路径与绝对路径, 除了 require()其他地方路径都要使用绝对路径.
而绝对路径要注意 path.join 与 path.resolve 的区别, 同时注意项目启动时 node 执行的位置.
参考
Stack Overflow What is the difference between __dirname and ./ in node.JS?
Node.JS 文档 -- 路径
https://github.com/imsobear/blog/issues/48
来源: https://juejin.im/post/5bf61272e51d4522143b6d4d