Skip to content

node

在 ES Modules 模块中如何使用 import.meta.url 和 __dirname

import.meta.url 属于 ES Modules 模块化中的 API;import.meta 包含当前模块的一些信息,其中 import.meta.url 表示当前模块的 file: 协议绝对路径,拿到这个绝对路径我们就可以配合其他 API 来实现 __filename 和 __dirname。(ESM 模块中没有 __dirname API)

js
console.log(import.meta.url);
// 运行会得到一个基于 file 协议的 URL:file:///Users/lukecheng/Desktop/vite/vite-project2/1.ts。

fileURLToPath

如果需要把 file 协议转换成路径,我们需要借助 Node.js 内部 url 模块的 fileURLToPath API。

js
import path from "node:path";
import { fileURLToPath } from "node:url";

console.log(path.dirname(fileURLToPath(import.meta.url)));
// 将会得到 /Users/lukecheng/Desktop/vite/vite-project2

__dirname

js
import path from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = path.dirname(fileURLToPath(import.meta.url))

或者

js
import { fileURLToPath } from 'node:url'
// 当前目录名
// URL 是一个全局变量
const __dirname = fileURLToPath(new URL('.', import.meta.url))

在 node 中使用 ESM 模块时,需要同步加载其它模块或使用 require 加载其它 commonjs 模块时该怎么办?

js
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);

const pkg = require(`${pkgDir}/package.json`)

引入模块时模块名前加 node: 前缀的作用

  • 使用 node: 前缀来识别核心模块(内置模块),不会模块缓存,也更加规范。

参考:

求路径指向的文件的扩展名

const url = 'xxx.com'
const dotIndex = url.lastIndexOf('.')
const extendName = url.substring(dotIndex + 1)

已知一个文件或文件夹的路径,求该文件或文件夹的名字(不包括扩展名)

js
import path from 'node:path'
// 不包含扩展名的文件名
const filename = path.parse(path).name;

获取某个文件的内容

js
// node: 表示引入的是 node 原生模块
import path from 'node:path';

const content = fs.readFileSync('./code-compiled.js', {
  encoding: 'utf-8'
})
console.log(content)

往一个文件中写入内容

js
const fs = require('fs')
fs.writeFileSync('./code-compiled.js', code)

#!/usr/bin/env node 的含义

在一个 js 文件最顶部添加 #!/usr/bin/env node 有什么含义?

用来告诉操作系统用哪个解析器执行该文件。node 可以省略,这样系统会自动寻找解释器来执行该文件。

删除某个文件或文件夹

js
const buildProjectPath = path.join('C:/Users/lukecheng/Desktop/code/my-test-build-project/test')

fs.rmSync(buildProjectPath, { recursive: true, force: true })

删除一个目录下的所有文件及文件夹

js
const files = fs.readdirSync(buildSourcePlacePath)
files.forEach((file) => {
  const filePath = `${buildSourcePlacePath}/${file}`;
  fs.rmSync(filePath, { recursive: true, force: true })
});

判断某个文件或文件夹是否存在

js
if (fs.existsSync(realDistPath)) {
  // 存在
}

判断一个路径是文件还是目录

js
fs.statSync(filePath).isFile()

fs.statSync(filePath).isDirectory()

获取一个文件或目录的最后一次的修改时间

js
const statOption = fs.statSync(tianData.logPath)

statOption.mtimeMs

移动某个文件或文件夹

如果是文件,不仅会移动,而且可以更改文件名。

如果是文件夹,不仅会移动,而且还可以更改文件名,并且目录下的所有文件也会跟着移动到对应的目录下。

js
fs.renameSync(distPath, realDistPath)

一个目录下的所有文件(夹)移动到另一个目录下

js
const sourceFiles = fs.readdirSync(sourceDir)
sourceFiles.forEach((file) => {
  const sourcePath = path.join(sourceDir, file)
  const destinationPath = path.join(buildSourcePlacePath, file)
  fs.renameSync(sourcePath, destinationPath)
})

Released under the MIT License.