首頁  >  文章  >  web前端  >  一文詳解Node中的模組化、檔案系統與環境變量

一文詳解Node中的模組化、檔案系統與環境變量

青灯夜游
青灯夜游轉載
2022-12-28 19:59:322165瀏覽

本篇文章帶大家深入了解Node中的模組化、檔案系統與環境變量,有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

一文詳解Node中的模組化、檔案系統與環境變量

一、Node.js模組化

1.0、變數作用域

(1)、在瀏覽器端使用var或不使用關鍵字定義的變數屬於全域作用域,也就是可以使用window物件存取。 【相關教學推薦:nodejs影片教學程式設計教學

#
    <script>
      var a = 100;

      (function () {
        b = 200;
      })();

      console.log(window.a, a);
      console.log(window.b, b);
    </script>

結果:

### ####(2)、在Node.js中沒有window物件################ (3)、在Node.js的互動環境下,定義的變數屬於global, global是類似瀏覽器端的window對象############### (4)、在模組中(檔案中)有global對象,使用關鍵字var,let,const定義的成員不屬於global對象,僅在目前模組中有效,而不使用關鍵字定義的對象屬於global對象。 ######
var a=100;
b=200;
let c=300;
const d=400;
console.log(global);
console.log(global.a);
console.log(global.b);
console.log(global.c);
console.log(global.d);
###

终端输出:

1.1、模块概要

早期的javascript版本没有块级作用域、没有类、没有包、也没有模块,这样会带来一些问题,如复用、依赖、冲突、代码组织混乱等,随着前端的膨胀,模块化显得非常迫切。

前端模块化规范如下:

常见的的JavaScript模块规范有:CommonJS、AMD、CMD、UMD、原生模块化。

虽然我们学习过ES6的模块化但是ES6与NodeJS使用不同的模块化规范,单独学习NodeJS的模块化非常有必要。

模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换 的单元。

JavaScript在早期的设计中就没有模块、包、类的概念,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化。

模块就是一个实现特定功能的文件,有了模块我们就可以更方便的使用别人的代码,要用什么功能就加载什么模块

模块化开发的四点好处:

  (1)、 避免变量污染,命名冲突

  (2)、提高代码复用率

  (3)、提高了可维护性

  (4)、方便依赖关系管理

nodejs中根据模块的来源不同,将模块分为了3大类,分别是:

  • 内置模块(内置模块是由Node.js官方提供的,例如fs、path、http等)
  • 自定义模块 (用户创建的每个 .js文件,都是自定义模块)
  • 第三方模块 (由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)

模块作用域。

和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。

模块作用域的好处:防止了全局变量污染的问题

1.2、CommonJS

CommonJS就是一个JavaScript模块化的规范,该规范最初是用在服务器端NodeJS中,前端的webpack也是对CommonJS原生支持的。

根据这个规范

(1)、每一个文件就是一个模块其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。

(2)、导入自定义的模块时路径需要以./或../开始,同一路径下也不能省略。

(3)、如果反复多次require模块,只加载一次。

(4)、require引入模块时,后缀名.js可以省略

(5)、每个模块文件都是一个独立的函数级作用域,在其它模块中不能直接访问

m1.js:

console.log("这是模块m1");
let a=100;
b=200;

m2.js

var m11=require("./m1");
console.log(a);
console.log(b);

结果:

 从上面的示例可以看出a在模块2中是访问不到的,模块其实就是一个封闭的函数:

m1.js的代码如下:

console.log("这是模块m1");
let a=100;
b=200;
//输出当前函数
console.log(arguments.callee+"");

实际输出结果:

function (exports, require, module, __filename, __dirname) {
console.log("这是模块m1");
let a=100;
b=200;
//输出当前函数
console.log(arguments.callee+"");
}

(6)、每个模块中都包含如下5个对象:

exports:导出对象,默认为{}

require:导入函数,使用该函数可以实现模块的依赖

module:模块信息,用于记录当前模块的所有信息

__filename:当前模块的文件全路径,含文件名

__dirname:当前模块的文件路径不含文件名

(7)、使用exports或module.exports对象可以将当前模块中需要导出的内容暴露出去。

m1.js

let a=100;
let b=()=>{
    return 200;
};

exports.a=a;
exports.b=b;

m2.js

const m1=require("./m1");
console.log(m1);
console.log(m1.a);
console.log(m1.b());

结果:

(8)、导入模块内容可以结合结构语法

m1.js

exports.a=100;
exports.b=function(){
    return 200;
};

m2.js

const {a,b:fun}=require("./m1");
console.log(a);
console.log(fun());

结果:

1.3、NodeJS中使用CommonJS模块管理

CommonJS的核心思想就是通过 require 方法来同步加载所要依赖的其他模块,然后通过 exports 或者 module.exports 来导出需要暴露的接口。

CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的主机环境中。

2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。这标志"Javascript模块化编程"正式诞生。因为老实说,在浏览器环境下,以前没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。NodeJS是CommonJS规范的实现,webpack 也是以CommonJS的形式来书写。

CommonJS定义的模块分为:{模块引用(require)} {模块定义(exports)} {模块标识(module)}
//require()用来引入外部模块;
//exports对象用于导出当前模块的方法或变量,唯一的导出口;
//module对象就代表模块本身。

Nodejs的模块是基于CommonJS规范实现的,通过转换也可以运行在浏览器端。

特点:

1、所有代码都运行在模块作用域,不会污染全局作用域。
2、模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
3、模块加载的顺序,按照其在代码中出现的顺序。

1.3.1、模块定义

根据commonJS规范,一个单独的文件是一个模块每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非为global对象的属性

模块拥有像函数一样的函数级作用域:

  • 每个模块内部,module变量代表当前模块

  • module变量是一个对象,它的exports属性(即module.exports)是对外的接口

  • 加载某个模块,其实是加载该模块的module.exports属性。require()方法用于加载模块。

模块只有一个出口,module.exports对象,我们需要把模块希望输出的内容放入该对象。

mathLib.js模块定义

var message="Hello CommonJS!";

module.exports.message=message;
module.exports.add=(m,n)=>console.log(m+n);

在 Node.js 中,创建一个模块非常简单,如下我们创建一个 'main.js' 文件,代码如下:

var hello = require('./hello');
hello.world();

以上实例中,代码 require('./hello') 引入了当前目录下的hello.js文件(./ 为当前目录,node.js默认后缀为js)。

Node.js 提供了exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

接下来我们就来创建hello.js文件,代码如下:

exports.world = function() {
  console.log('Hello World');
}

在以上示例中,hello.js 通过 exports 对象把 world 作为模块的访 问接口,在 main.js 中通过 require('./hello') 加载这个模块,然后就可以直接访 问main.js 中 exports 对象的成员函数了。

有时候我们只是想把一个对象封装到模块中,格式如下:

module.exports = function() {  // ...}

例如:

//hello.js 
function Hello() { 
    varname; 
    this.setName = function(thyName) { 
        name = thyName; 
    }; 
    this.sayHello = function() { 
        console.log('Hello ' + name); 
    }; 
}; 
module.exports = Hello;

这样就可以直接获得这个对象了:

//main.js 
var Hello = require('./hello'); 
hello = new Hello(); 
hello.setName('BYVoid'); 
hello.sayHello();

模块接口的唯一变化是使用 module.exports = Hello 代替了exports.world = function(){}。 在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的 exports。

1.3.2、模块依赖

加载模块用require方法,该方法读取一个文件并且执行,返回文件内部的module.exports对象。

在用require加载自定义模块期间,可以省略.js这个后缀名。

myApp.js 模块依赖

var math=require('./mathLib');
console.log(math.message);
math.add(333,888);

3、测试运行

安装好node.JS

打开控制台,可以使用cmd命令,也可以直接在开发工具中访问

运行

1.3.3、内置模块加载

也许你已经注意到,我们已经在代码中使用了模块了。像这样:

var http = require("http");

...

http.createServer(...);

Node.js中自带了一个叫做"http"的模块,我们在我们的代码中请求它并把返回值赋给一个本地变量。

这把我们的本地变量变成了一个拥有所有 http 模块所提供的公共方法的对象。

Node.js 的 require方法中的文件查找策略如下:

由于Node.js中存在4类模块(原生模块和3种文件模块),尽管require方法极其简单,但是内部的加载却是十分复杂的,其加载优先级也各自不同。如下图所示:

从文件模块缓存中加载

尽管原生模块与文件模块的优先级不同,但是都不会优先于从文件模块的缓存中加载已经存在的模块。

从原生模块加载

原生模块的优先级仅次于文件模块缓存的优先级。require方法在解析文件名之后,优先检查模块是否在原生模块列表中。以http模块为例,尽管在目录下存在一个http/http.js/http.node/http.json文件,require("http")都不会从这些文件中加载,而是从原生模块中加载。

原生模块也有一个缓存区,同样也是优先从缓存区加载。如果缓存区没有被加载过,则调用原生模块的加载方式进行加载和执行。

从文件加载

当文件模块缓存中不存在,而且不是原生模块的时候,Node.js会解析require方法传入的参数,并从文件系统中加载实际的文件,加载过程中的包装和编译细节在前一节中已经介绍过,这里我们将详细描述查找文件模块的过程,其中,也有一些细节值得知晓。

require方法接受以下几种参数的传递:

  • http、fs、path等,原生模块。
  • ./mod或../mod,相对路径的文件模块。
  • /pathtomodule/mod,绝对路径的文件模块。
  • mod,非原生模块的文件模块。

node_modules文件夹用来存放所有已安装到项目中的包。require()导入第三方包时,就是从这个目录中查找并加载包。

package-lock.json配置文件用来记录node_modules目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等。

注意:不要手动修改node_modules或package-lock.json文件中的任何代码,npm包管理工具会自动维护它们。

1.3.4、module对象

在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息

每个模块内部,module变量代表当前模块
module变量是一个对象,它的exports属性(即module.exports)是对外的接口
加载某个模块,其实是加载该模块的module.exports属性。require()方法用于加载模块。

二、Node.js 文件系统

Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示:

var fs = require("fs")

2.1、异步和同步

Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。

异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。

建议大家是用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。

实例

创建 input.txt 文件,内容如下:

foo

创建 filereaddemo.js 文件, 代码如下:

const fs=require("fs");  //依赖内置模块fs,用于文件管理

//异步读取文件students.txt,设置读取成功时的回调函数,err表示错误信息,data表示数据
fs.readFile("students.txt",function(err,data){
    if(err) throw err;
    console.log("异步:"+data+"");
});

console.log("---------------");

//同步读取
let data=fs.readFileSync("students.txt");
console.log("同步:"+data+"");

以上代码执行结果如下:

接下来,让我们来具体了解下 Node.js 文件系统的方法。

2.2、获取文件信息

以下为通过异步模式获取文件信息的语法格式:

fs.stat(path, callback)

参数使用说明如下:

  • path - 文件路径。

  • callback - 回调函数,带有两个参数如:(err, stats), stats 是 fs.Stats 对象。

fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:

const fs=require("fs");

fs.stat("students.txt",(err,stats)=>{
    console.log("是文件吗?"+stats.isFile());
    console.log("是目录吗?"+stats.isDirectory());
    console.log(stats);
});

結果:

stats類別中的方法有:

方法 描述
stats.isFile() 如果是檔案回傳true,否則回傳false。
stats.isDirectory() 如果是目錄回傳 true,否則回傳 false。
stats.isBlockDevice() 如果是區塊裝置回傳 true,否則回傳 false。
stats.isCharacterDevice() 如果字元裝置傳回 true,否則傳回 false。
stats.isSymbolicLink() 如果是軟連結回傳 true,否則回傳 false。
stats.isFIFO() 如果是FIFO,回傳true,否則回傳 false。 FIFO是UNIX中的一種特殊類型的命令管道。
stats.isSocket() 如果是 Socket 回傳 true,否則回傳 false。

接下来我们创建 file.js 文件,代码如下所示:

var fs = require("fs");

console.log("准备打开文件!");
fs.stat('input.txt', function (err, stats) {
   if (err) {
       return console.error(err);
   }
   console.log(stats);
   console.log("读取文件信息成功!");

   // 检测文件类型
   console.log("是否为文件(isFile) ? " + stats.isFile());
   console.log("是否为目录(isDirectory) ? " + stats.isDirectory());    
});

以上代码执行结果如下:

$ node file.js
准备打开文件!
{ dev: 16777220,
  mode: 33188,
  nlink: 1,
  uid: 501,
  gid: 20,
  rdev: 0,
  blksize: 4096,
  ino: 40333161,
  size: 61,
  blocks: 8,
  atime: Mon Sep 07 2015 17:43:55 GMT+0800 (CST),
  mtime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST),
  ctime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST) }
读取文件信息成功!
是否为文件(isFile) ? true
是否为目录(isDirectory) ? false

2.3、写入文件

以下为异步模式下写入文件的语法格式:

fs.writeFile(filename, data[, options], callback)

如果文件存在,该方法写入的内容会覆盖旧的文件内容。

参数使用说明如下:

  • path - 文件路径。

  • data - 要写入文件的数据,可以是 String(字符串) 或 Buffer(流) 对象。

  • options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 'w'

  • callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。

接下来我们创建 file.js 文件,代码如下所示:

const fs=require("fs");

fs.writeFile("output1.txt","异步hello","utf-8",function(err){
    if(!err){
        console.log("异步文件写入成功!");
    }
    else{
        throw err;
    }
});
console.log("---------------");
fs.writeFileSync("output2.txt","同步hello","utf-8");
console.log("同步文件写入成功");

以上代码执行结果如下:

2.4、删除文件

以下为删除文件的语法格式:

fs.unlink(path, callback)

参数使用说明如下:

  • path - 文件路径。

  • callback - 回调函数,没有参数。

接下来我们创建 file.js 文件,代码如下所示:

const fs=require("fs");

fs.unlink("output1.txt",function(err){
    if(err){
        throw err;
    }
    else{
        console.log("异步删除文件成功!");
    }
});
console.log("--------------------");
fs.unlinkSync("output2.txt");
console.log("同步删除文件成功!");

以上代码执行结果如下:

2.5、创建目录

以下为创建目录的语法格式:

fs.mkdir(path[, mode], callback)

参数使用说明如下:

  • path - 文件路径。

  • mode - 设置目录权限,默认为 0777。

  • callback - 回调函数,没有参数。

接下来我们创建mkdirfile.js 文件,代码如下所示:

const fs=require("fs");

fs.mkdir("dir1",function(err){
    if(err){
        throw err;
    }
    else{
        console.log("异步创建目录成功!");
    }
});
console.log("---------------------");
fs.mkdirSync("dir2");
console.log("同步创建目录成功!");

以上代码执行结果如下:

2.6、读取目录

以下为读取目录的语法格式:

fs.readdir(path, callback)

参数使用说明如下:

  • path - 文件路径。

  • callback - 回调函数,回调函数带有两个参数err, files,err 为错误信息,files 为 目录下的文件数组列表。

接下来我们创建 file.js 文件,代码如下所示:

const fs=require("fs");

fs.readdir("dir1",(err,files)=>{
    if(err) 
    {throw err;}
    else{
        console.log("异步获取目录下的文件成功!");
        files.forEach(file=>console.log(file));
    }
});
console.log("-----------------------");
let files=fs.readdirSync("dir2");
console.log("同步获取目录下的文件成功!");
files.forEach(file=>console.log(file));

以上代码执行结果如下:

2.7、删除目录

以下为删除目录的语法格式:

fs.rmdir(path, callback)

参数使用说明如下:

  • path - 文件路径。

  • callback - 回调函数,没有参数。

接下来我们创建 file.js 文件,代码如下所示:

var fs = require("fs");

console.log("准备删除目录 /tmp/test");
fs.rmdir("/tmp/test",function(err){
   if (err) {
       return console.error(err);
   }
   console.log("读取 /tmp 目录");
   fs.readdir("/tmp/",function(err, files){
      if (err) {
          return console.error(err);
      }
      files.forEach( function (file){
          console.log( file );
      });
   });
});

以上代码执行结果如下:

$ node file.js
准备删除目录 /tmp/test
input.out
output.out
test
test.txt
读取 /tmp 目录
……

2.8、文件模块方法参考手册

以下为 Node.js 文件模块相同的方法列表:

##fs.truncate(path, len, callback)非同步truncate().回呼函數沒有參數,但可能拋出例外。 fs.truncateSync(path, len)#同步truncate()fs.chown(path, uid, gid, callback)非同步chown().回呼函數沒有參數,但可能拋出例外。 fs.chownSync(path, uid, gid)#同步chown()##fs.fchown(fd, uid, gid, callback)fs.fchownSync(fd, uid, gid)fs.lchown(path, uid, gid, callback)fs.lchownSync(path, uid, gid)##fs.chmod(path, mode, callback)非同步chmod().回呼函數沒有參數,但可能拋出例外。 fs.chmodSync(path, mode)#同步chmod().fs.fchmod(fd, mode , callback)非同步fchmod().回呼函數沒有參數,但可能拋出例外。 fs.fchmodSync(fd, mode)#同步fchmod().fs.lchmod(path, mode , callback)非同步lchmod().回呼函數沒有參數,但可能拋出例外。 Only available on Mac OS X.fs.lchmodSync(path, mode)同步lchmod().# fs.stat(path, callback)非同步stat(). 回呼函數有兩個參數err, stats,stats 是fs.Stats 物件。 fs.lstat(path, callback)非同步 lstat(). 回呼函數有兩個參數 err, stats,stats 是 fs.Stats 物件。 fs.fstat(fd, callback)非同步 fstat(). 回呼函數有兩個參數 err, stats,stats 是 fs.Stats 物件。 fs.statSync(path)同步 stat(). 傳回 fs.Stats 的實例。 fs.lstatSync(path)同步 lstat(). 傳回 fs.Stats 的實例。 fs.fstatSync(fd)同步 fstat(). 傳回 fs.Stats 的實例。 fs.link(srcpath, dstpath, callback)異步 link().回呼函數沒有參數,但可能拋出例外。 fs.linkSync(srcpath, dstpath)#同步link().非同步symlink().回呼函數沒有參數,但可能拋出例外。 type 參數可以設定為 'dir', 'file', 或 'junction' (預設為 'file') 。 同步symlink().非同步readlink(). 回呼函數有兩個參數err, linkString。 非同步 realpath(). 回呼函數有兩個參數 err, resolvedPath。 #同步 realpath()。返回絕對路徑。 非同步 unlink().回呼函數沒有參數,但可能拋出例外。 同步unlink().非同步rmdir().回呼函數沒有參數,但可能拋出例外。 同步rmdir().S非同步mkdir(2).回呼函數沒有參數,但可能拋出例外。 mode defaults to 0777.同步mkdir().非同步readdir(3). 讀取目錄的內容。 同步 readdir().傳回檔案陣列清單。 非同步 close().回呼函數沒有參數,但可能會拋出例外。 同步close().非同步開啟檔案。 同步version of fs.open().?#修改文件時間戳,檔案通過指定的檔案路徑。 ?修改檔案時間戳,透過檔案描述符指定。 異步 fsync.回呼函數沒有參數,但可能拋出例外。
方法 描述
#fs.rename(oldPath, newPath, callback) 非同步rename().回呼函數沒有參數,但可能拋出例外。
fs.ftruncate(fd, len, callback) 非同步 ftruncate().回呼函數沒有參數,但可能拋出例外。
fs.ftruncateSync(fd, len) 同步ftruncate()
非同步fchown().回呼函數沒有參數,但可能拋出例外。
同步fchown()
非同步lchown().回呼函數沒有參數,但可能拋出例外。
同步lchown()
##fs.symlink(srcpath, dstpath [, type], callback)
fs.symlinkSync(srcpath, dstpath[, type])
fs.readlink (path, callback)
fs.realpath(path[, cache], callback)
fs.realpathSync(path[, cache])
fs.unlink(path, callback)
fs.unlinkSync(path)
fs.rmdir(path, callback)
fs.rmdirSync(path)
fs.mkdir(path[, mode] , callback)
fs.mkdirSync(path[, mode])
fs.readdir(path, callback)
fs.readdirSync(path)
fs.close(fd, callback)
fs.closeSync(fd)
fs.open(path, flags[, mode], callback)
fs.openSync(path, flags[, mode])
fs.utimes(path, atime, mtime, callback)
#fs.utimesSync(path, atime, mtime)
fs.futimes(fd, atime, mtime, callback)
fs.futimesSync(fd, atime , mtime)
fs.fsync(fd, callback)
fs.fsyncSync(fd) 同步fsync.
fs.write(fd, buffer, offset, length [, position], callback) 將緩衝區內容寫入到透過檔案描述符指定的檔案。
fs.write(fd, data[, position[, encoding]], callback) 透過檔案描述子 fd 寫入檔案內容。
fs.writeSync(fd, buffer, offset, length[, position]) 同步版的 fs.write()。
fs.writeSync(fd, data[, position[, encoding]]) 同步版的fs.write().
fs.read(fd, buffer, offset, length, position, callback) 透過檔案描述子fd 讀取檔案內容。
fs.readSync(fd, buffer, offset, length, position) 同步版的fs.read.
#fs.readFile(filename[, options], callback) 非同步讀取檔案內容。
fs.readFileSync(filename[, options])  
fs.writeFile(filename, data[, options ], callback) 非同步寫入檔案內容。
fs.writeFileSync(filename, data[, options]) 同步版的 fs.writeFile。
fs.appendFile(filename, data[, options], callback) #非同步追加檔案內容。
fs.appendFileSync(filename, data[, options]) The 同步version of fs.appendFile.
# fs.watchFile(filename[, options], listener) 檢視檔案的修改。
fs.unwatchFile(filename[, listener]) #停止檢視 filename 的修改。
fs.watch(filename[, options][, listener]) 查看 filename 的修改,filename 可以是檔案或目錄。傳回 fs.FSWatcher 物件。
fs.exists(path, callback) 偵測給定的路徑是否存在。
fs.existsSync(path) 同步版的fs.exists.
fs.access(path[, mode], callback) 測試指定路徑使用者權限。
fs.accessSync(path[, mode]) #同步版的 fs.access。
fs.createReadStream(path[, options]) 傳回ReadStream 物件。
fs.createWriteStream(path[, options]) 傳回 WriteStream 物件。
fs.symlink(srcpath, dstpath[, type], callback) 異步 symlink().回呼函數沒有參數,但可能拋出例外。

更多内容,请查看官网文件模块描述:File System

三、参数与环境变量

3.0、读取自定义配置文件数据

创立一个 config 目录并向其中增加一个 config/default.json 文件。这将是默认配置文件,并将蕴含所有默认环境变量。

在咱们的示例应用程序中它应该是这样的:

config/default.json

{
    "student":{
        "name":"tom",
        "age":19
    }
}

先依赖模块config,

npm i config

咱们将在咱们的应用程序中通过导入 config 和应用 get 办法拜访变量来访问它。

const config=require("config");
console.log(config.get("student.name"));
console.log(config.get("student.age"));

运行结果:

3.1、读取package.json配置参数

用于添加命令行的环境变量

package.json 可以配置config
脚本中 (see npm-scripts) package.json “config” 字段会被环境变量覆盖
8a11bc632ea32a57b3e3693c7987c420[@3d689bd3819ead35ed794427bd12f459]:42538adbdb6240b2b083a000a615d5bd
例如,下面的package.json:
代码中使用 process.env['npm_package_config_xxxxxx'] 获取配置的内容

package.json

{
  "name": "demo06",
  "config": {
    "foo": "123456"
  },
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"node configtest.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "config": "^3.3.7"
  }
}

configtest.js

console.log(process.env.npm_package_config_foo);

直接运行(node configtest.js)结果:

直接在命令行执行 node configtest,会输出undefined

使用 npm run start,会输出 123456

npm 设置包的config

npm config set foo = 3000 就可以修改默认的配置内容

然后再执行 npm test 会输出 3000

3.2、环境变量的设置与读取

文件.env

USER_ID="239482"
USER_KEY="foobar"
NODE_ENV="development"

m3.js

 npm i dotenv  //依赖模块

require("dotenv").config();
console.log(process.env.USER_ID);

输出结果:

239482

3.3、取得系統中的環境變數

#命令列下操作環境變數

3.3.1、查看目前所有可用的環境變數

輸入set 即可查看。

一文詳解Node中的模組化、檔案系統與環境變量

3.3.2、查看某個環境變數

輸入 「set 變數名稱」即可。例如想查看path變數的值,即輸入set path

一文詳解Node中的模組化、檔案系統與環境變量

#3.3.3、修改環境變數

注意:所有的在cmd命令列下環境變數的修改只對目前視窗有效,不是永久性的修改。也就是說關閉此cmd命令列視窗後,將不再起作用。

永久性修改環境變數的方法有兩種:一種是直接修改登錄檔,另一種是透過我的電腦-〉屬性-〉高級,來設定係統的環境變數(查看詳細) 。

1、修改環境變數

輸入 「set 變數名稱=變數內容」即可。例如將path設定為“d:\nmake.exe”,只要輸入set path="d:\nmake.exe"。

注意,此修改環境變數是指用現在的內容去覆寫先前的內容,並不是追加。例如當我設定了上面的path路徑之後,如果我再重新輸入set path="c",再次查看path路徑的時候,其值為“c:”,而不是“d:\nmake.exe”;“ c」。

2、設定為空:

如果想將某一變數設為空,輸入「set 變數名稱=」即可。

如「set path=」 那麼查看path的時候就為空。注意,上面已經說了,只在當前命令列視窗起作用。因此查看path的時候不要去右鍵「我的電腦」—「屬性」........

3、給變數追加內容

輸入「set 變數名=%變數名%;變數內容」。 (不同於3,那個是覆蓋)。如,為path新增一個新的路徑,輸入「 set path=%path%;d:\nmake.exe」即可將d:\nmake.exe加入path中,再次執行」set path=%path%; c:",那麼,使用set path語句來查看的時候,將會有:d:\nmake.exe;c:,而不是像第3步驟中的只有c:。

3.3.4、一些常用的环境变量

  • %AllUsersProfile%: 局部 返回所有“用户配置文件”的位置。 {所有用户文件目录 – C:\Documents and Settings\All Users}
  • %AppData%: 局部 返回默认情况下应用程序存储数据的位置。 {当前用户数据文件夹 – C:\Documents and Settings\wy\Application Data}
  • %Cd%: 局部 返回当前目录字符串。
  • %CmdCmdLine%: 局部 返回用来启动当前的 Cmd.exe 的准确命令行。
  • %CmdExtVersion%: 系统 返回当前的“命令处理程序扩展”的版本号。
  • %CommonProgramFiles%: {文件通用目录 – C:\Program Files\Common Files}
  • %ComputerName%: 系统 返回计算机的名称。 {计算机名 – IBM-B63851E95C9}
  • %ComSpec%: 系统 返回命令行解释器可执行程序的准确路径。 C:\WINDOWS\system32\cmd.exe
  • %Date%: 系统 返回当前日期。使用与 date /t 命令相同的格式。由 Cmd.exe 生成。有关 date 命令的详细信息,请参阅 Date。
  • %ErrorLevel%: 系统 返回最近使用过的命令的错误代码。通常用非零值表示错误。
  • %HomeDrive%: 系统 返回连接到用户主目录的本地工作站驱动器号。基于主目录值的设置。用户主目录是在“本地用户和组”中指定的。 {当前用户根目录 – C:}
  • %HomePath%: 系统 返回用户主目录的完整路径。基于主目录值的设置。用户主目录是在“本地用户和组”中指定的。 {当前用户路径 – \Documents and Settings\wy}
  • %HomeShare%: 系统 返回用户的共享主目录的网络路径。基于主目录值的设置。用户主目录是在“本地用户和组”中指定的。
  • %LogonSever%: 局部 返回验证当前登录会话的域控制器的名称。
  • %Number_Of_Processors%: 系统 指定安装在计算机上的处理器的数目。 {处理器个数 – 1}
  • %Os%: 系统 返回操作系统的名称。Windows 2000 将操作系统显示为 Windows_NT。 {操作系统名 – Windows_NT}
  • %Path%: 系统 指定可执行文件的搜索路径。
  • %PathExt%: 系统 返回操作系统认为可执行的文件扩展名的列表。
  • %Processor_Architecture%: 系统 返回处理器的芯片体系结构。值: x86,IA64。 {处理器芯片架构 – x86}
  • %Processor_Identfier%: 系统 返回处理器说明。
  • %Processor_Level%: 系统 返回计算机上安装的处理器的型号。 {处理器型号 – 6}
  • %Processor_Revision%: 系统 返回处理器修订号的系统变量。 {处理器修订号 – 0905}
  • %ProgramFiles%: {程序默认安装目录 – C:\Program Files}
  • %Prompt%: 局部 返回当前解释程序的命令提示符设置。由 Cmd.exe 生成。 $P$G
  • %Random%: 系统 返回 0 到 32767 之间的任意十进制数字。由 Cmd.exe 生成。
  • %SystemDrive%: 系统 返回包含 Windows XP 根目录(即系统根目录)的驱动器。 {系统根目录 – C:}
  • %SystemRoot%: 系统 返回 Windows XP 根目录的位置。 {系统目录 – C:\WINDOWS}
  • %Temp%: 系统和用户 返回对当前登录用户可用的应用程序所使用的默认临时目录。有些应用程序需要 TEMP,而其它应用程序则需要 TMP。 {当前用户临时文件夹 – C:\DOCUME~1\wy\LOCALS~1\Temp}
  • %Time%: 系统 返回当前时间。使用与 time /t 命令相同的格式。由 Cmd.exe 生成。9:16:25.05
  • %UserDomain%: 局部 返回包含用户帐户的域的名称。 {包含用户帐号的域 – IBM-B63851E95C9}
  • %UserName%: 局部 返回当前登录的用户的名称。 {当前用户名 – wy}
  • %UserProfile%: 局部 返回当前用户的配置文件的位置。 {当前用户目录 – C:\Documents and Settings\wy}
  • %WinDir%: 系统 返回操作系统目录的位置。 {系统目录 – C:\WINDOWS}

假定当前的系统环境变量定义如下,注意JAVA_HOME:

 m3.js

console.log(process.env.JAVA_HOME);

輸出:

 

a,b在系統中已定義好

注意目前的終端是cmd,不是powershell

 

 這裡a輸出123的原因是修改成888後沒有重新啟動電腦。

四、作業

4.1、根據影片完成每一個上課範例。

4.2、定義一個模組circle.js,中模組中定義兩個方法一個用於計算圓的周長,一個用於計算圓的面積,再定義一個模組main.js依賴模組circle. js,並呼叫模組中的兩個方法用於計算。

4.3、在設定檔package.json中定義好連接埠port與主機位址host,建立一個web伺服器,引用設定訊息,實現連接埠與主機位址的切換功能。

4.4、使用config的方式完成4.3

4.5、使用.env,dotenv的方式完成4.3

4.6、使用系統環境變數完成4.3

 五、影片

https://www.bilibili.com/video/BV1WW411B78S

更多node相關知識,請造訪: nodejs 教學

以上是一文詳解Node中的模組化、檔案系統與環境變量的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除