Node.js 모듈 로딩에 대한 자세한 설명
JavaScript는 세계에서 가장 많이 사용되는 프로그래밍 언어 중 하나이며 웹 세계의 보편적 언어이며 모든 브라우저에서 사용됩니다. 자바스크립트의 탄생은 넷스케이프 시대로 거슬러 올라간다. 그 핵심 콘텐츠는 당시 마이크로소프트와 경쟁하고 치열한 브라우저 전쟁에 참여하기 위해 급하게 개발됐다. 조기 출시로 인해 필연적으로 좋지 않은 기능이 발생했습니다.
짧은 개발 시간에도 불구하고 JavaScript에는 각 스크립트가 전역 네임스페이스를 공유한다는 점을 제외하면 여전히 많은 강력한 기능이 있습니다.
웹 페이지가 JavaScript 코드를 로드하면 전역 네임스페이스에 삽입되고 로드된 다른 모든 스크립트와 동일한 주소 공간을 공유하게 됩니다. 이로 인해 많은 보안 문제, 충돌 및 몇 가지 일반적인 문제가 발생합니다. 버그를 추적하기 어렵고 해결하기도 어렵게 만듭니다.
그러나 고맙게도 Node는 서버 측 JavaScript에 대한 일부 사양을 설정하고 CommonJS 모듈 표준도 구현했습니다. 이 표준에서 각 모듈은 고유한 컨텍스트를 가지며 다른 모듈과 구별됩니다. 이는 전역 범위와 같은 것이 없고 모듈이 서로 간섭하지 않기 때문에 모듈이 전역 범위를 오염시키지 않는다는 것을 의미합니다.
이 장에서는 다양한 모듈과 이를 로드하는 방법에 대해 알아봅니다.
코드를 잘 정의된 일련의 모듈로 분할하면 애플리케이션을 제어하는 데 도움이 될 수 있습니다. 아래에서는 자신만의 모듈을 만들고 사용하는 방법을 알아봅니다.
Node가 모듈을 로드하는 방법 이해
Node에서는 파일 경로나 모듈 이름을 통해 모듈을 참조할 수 있습니다. 비핵심 모듈을 이름으로 참조하면 Node는 결국 모듈 이름을 암시합니다. . 해당 모듈 파일 경로로 이동합니다. 핵심 기능을 포함하는 핵심 모듈은 Node가 시작될 때 미리 로드됩니다.
비핵심 모듈에는 NPM(노드 패키지 관리자)을 사용하여 설치된 타사 모듈과 귀하 또는 동료가 만든 로컬 모듈이 포함됩니다.
현재 스크립트로 가져온 각 모듈은 프로그래머에게 공개 API 세트를 노출합니다. 모듈을 사용하기 전에 다음과 같이 require 함수를 사용하여 가져와야 합니다.
var module = require(‘module_name')
위 코드는 핵심 모듈이거나 NPM을 사용하여 설치된 모듈일 수 있는 module_name이라는 모듈을 가져옵니다. require 함수는 모듈의 모든 공개 API를 포함하는 객체를 반환합니다. 모듈에 따라 반환되는 개체는 JavaScript 값, 함수 또는 일련의 속성을 포함하는 개체(함수, 배열 또는 JavaScript 개체)일 수 있습니다.
모듈 내보내기
CommonJS 모듈 시스템은 Node.js 아래 파일 간에 객체와 기능을 공유할 수 있는 유일한 방법입니다. 매우 복잡한 프로그램의 경우 일부 클래스, 개체 또는 함수를 잘 정의된 재사용 가능한 일련의 모듈로 재구성해야 합니다. 모듈 사용자에게 모듈은 지정한 코드만 노출합니다.
다음 예에서는 Node에서 파일과 모듈 사이에 일대일 대응이 있음을 알 수 있습니다. Circle 생성자만 내보내는 Circle.js라는 파일을 만들었습니다.
function Circle(x, y, r) { function r_squared() { return Math.pow(r, 2); } function area() { return Math.PI * r_squared(); } return {area: area}; } module.exports = Circle;
코드에서 가장 중요한 줄은 모듈이 내보내는 내용을 정의하는 마지막 줄입니다. module은 현재 모듈 자체를 나타내는 특수 변수이며, module.exports는 모듈에서 내보낸 객체입니다. 이 예에서는 모듈 사용자가 사용할 수 있도록 Circle의 생성자를 내보냈습니다. 서클 인스턴스.
일부 복잡한 개체를 내보낼 수도 있습니다. module.exports는 빈 개체로 초기화되며 외부에 노출하려는 모든 콘텐츠를 module.exports 개체의 속성으로 내보낼 수 있습니다. 예를 들어, 함수 세트를 노출하는 모듈을 설계합니다.
function printA() { console.log('A'); } function printB() { console.log('B'); } function printC() { console.log('C'); } module.exports.printA = printA; module.exports.printB = printB; module.exports.pi = Math.PI;
이 모듈은 두 개의 함수(printA 및 printB)와 숫자(pi)를 내보냅니다. 호출 코드는 다음과 같습니다.
var myModule2 = require('./myModule2'); myModule2.printA(); // -> A myModule2.printB(); // -> B console.log(myModule2.pi); // -> 3.141592653589793
모듈 로드
앞서 언급했듯이 require 함수를 사용하여 모듈을 로드할 수 있습니다. 코드에서 require를 호출하면 전역 네임스페이스에 영향을 미칠까 걱정할 필요가 없습니다. Node.js에는 전역 네임스페이스라는 개념이 없습니다. 모듈이 존재하고 구문이나 초기화 오류가 없으면 require 함수는 모듈 개체를 반환하며 이 개체를 모든 지역 변수에 할당할 수 있습니다.
모듈에는 여러 가지 유형이 있으며 크게 코어 모듈, 로컬 모듈, NPM을 통해 설치된 타사 모듈로 나눌 수 있습니다. 모듈 유형에 따라 모듈을 참조하는 방법이 여러 가지 있습니다. 아래에서 이 지식을 다운로드해 보겠습니다.
코어 모듈 로드
노드에는 코어 모듈이라는 바이너리 파일로 컴파일되는 일부 모듈이 있습니다. 이러한 모듈은 경로로 참조할 수 없으며 모듈 이름으로만 참조할 수 있습니다. 코어 모듈은 동일한 이름을 가진 타사 모듈이 있더라도 가장 높은 로딩 우선순위를 갖습니다.
예를 들어 http 핵심 모듈을 로드하고 사용하려는 경우 다음과 같이 할 수 있습니다.
var http = require('http');
이렇게 하면 다음에 정의된 http 모듈이 포함된 http 모듈 개체가 반환됩니다. 해당 htpp 모듈에 대한 노드 API 문서.
파일에서 모듈 로드
절대 경로를 사용하여 파일 시스템에서 모듈을 로드할 수도 있습니다.
var myModule = require('/home/pedro/my_modules/my_module');
다음을 기반으로 하는 상대 경로를 사용할 수도 있습니다. 현재 파일:
var myModule = require('../my_modules/my_module'); var myModule2 = require('./lib/my_module_2');
注意上面的代码,你可以省略文件名的扩展名,如果Node找不到这个文件,会尝试在文件名后加上js后缀再次查找(译者注:其实除了js,还会查找json和node,具体可以看官网文档),因此,如果在当前目录下存在一个叫my_module.js的文件,会有下面两种加载方式:
var myModule = require('./my_module'); var myModule = require('./my_module.js');
加载目录模块
你还可以使用目录的路径来加载模块:
var myModule = require('./myModuleDir');
Node会假定这个目录是个模块包,并尝试在这个目录下搜索包定义文件package.json。
如果没找到,Node会假设包的入口点是index.js文件(译者注:除了index.js还会查找index.node,.node文件是Node的二进制扩展包,具体见官方文档),以上面代码为例,Node会尝试查找./myModuleDir/index.js文件。
反之,如果找到了package.json文件,Node会尝试解析它,并查找包定义里的main属性,然后把main属性的值当作入口点的相对路径。以本例来说,如果package.json定义如下:
{ "name" : "myModule", "main" : "./lib/myModule.js" }
Node就会尝试加载./myModuleDir/lib/myModule.js文件
从node_modules目录加载
如果require函数的参数不是相对路径,也不是核心模块名,Node会在当前目录的node_modules子目录下查找,比如下面的代码,Node会尝试查找文件./node_modules/myModule.js:
var myModule = require('myModule.js');
如果没找到,Node会继续在上级目录的node_modules文件夹下查找,如果还没找到就继续向上层目录查找,直到找到对应的模块或者到达根目录。
你可以使用这个特性来管理node_modules目录的内容或模块,不过最好还是把模块的管理任务交给NPM(见第一章),本地node_modules目录是NPM安装模块的默认位置,这个设计把Node和NPM关联在了一起。通常,作为开发人员不必太关心这个特性,你可以简单的使用NPM安装,更新和删除包,它会帮你维护node_modules目录
缓存模块
模块在第一次成功加载后会被缓存起来,就是说,如果模块名被解析到同一个文件路径,那么每次调用require(‘myModule')都确切地会返回同一个模块。
比如,有一个叫my_module.js的模块,包含下面的内容:
console.log('module my_module initializing...'); module.exports = function() { console.log('Hi!'); }; console.log('my_module initialized.');
然后用下面的代码加载这个模块:
var myModuleInstance1 = require('./my_module');
它会产生下面的输出:
module my_module initializing... my_module initialized
如果我们两次导入它:
var myModuleInstance1 = require('./my_module'); var myModuleInstance2 = require('./my_module');
如果我们两次导入它:
var myModuleInstance1 = require('./my_module'); var myModuleInstance2 = require('./my_module');
输出依然是:
module my_module initializing... my_module initialized
也就是说,模块的初始化代码仅执行了一次。当你构建自己的模块时,如果模块的初始化代码里含有可能产生副作用的代码,一定要特别注意这个特性。
小结
Node取消了JavaScript的默认全局作用域,转而采用CommonJS模块系统,这样你可以更好的组织你的代码,也因此避免了很多安全问题和bug。可以使用require函数来加载核心模块,第三方模块,或从文件及目录加载你自己的模块
还可以用相对路径或者绝对路径来加载非核心模块,如果把模块放到了node_modules目录下或者对于用NPM安装的模块,你还可以直接使用模块名来加载。
译者注:
建议读者把官方文档的模块章节阅读一遍,个人感觉比作者讲得更清晰明了,而且还附加了一个非常具有代表性的例子,对理解Node模块加载会很有很大帮助。下面把那个例子也引用过来:
用require(X) 加载路径Y下的模块 1. 如果X是核心模块, a. 加载并返回核心模块 b. 结束 2. 如果X以 './' or '/' or '../ 开始' a. LOAD_AS_FILE(Y + X) b. LOAD_AS_DIRECTORY(Y + X) 3. LOAD_NODE_MODULES(X, dirname(Y)) 4. 抛出异常:"not found" LOAD_AS_FILE(X) 1. 如果X是个文件,把 X作为JavaScript 脚本加载,加载完毕后结束 2. 如果X.js是个文件,把X.js 作为JavaScript 脚本加载,加载完毕后结束 3. 如果X.node是个文件,把X.node 作为Node二进制插件加载,加载完毕后结束 LOAD_AS_DIRECTORY(X) 1. 如果 X/package.json文件存在, a. 解析X/package.json, 并查找 "main"字段. b. 另M = X + (main字段的值) c. LOAD_AS_FILE(M) 2. 如果X/index.js文件存在,把 X/index.js作为JavaScript 脚本加载,加载完毕后结束 3. 如果X/index.node文件存在,把load X/index.node作为Node二进制插件加载,加载完毕后结束 LOAD_NODE_MODULES(X, START) 1. 另DIRS=NODE_MODULES_PATHS(START) 2. 对DIRS下的每个目录DIR做如下操作: a. LOAD_AS_FILE(DIR/X) b. LOAD_AS_DIRECTORY(DIR/X) NODE_MODULES_PATHS(START) 1. 另PARTS = path split(START) 2. 另ROOT = index of first instance of "node_modules" in PARTS, or 0 3. 另I = count of PARTS - 1 4. 另DIRS = [] 5. while I > ROOT, a. 如果 PARTS[I] = "node_modules" 则继续后续操作,否则下次循环 c. DIR = path join(PARTS[0 .. I] + "node_modules") b. DIRS = DIRS + DIR c. 另I = I - 1 6. 返回DIRS
更多Node.js模块加载详解相关文章请关注PHP中文网!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











프론트 엔드 개발시 프론트 엔드 열지대 티켓 인쇄를위한 자주 묻는 질문과 솔루션, 티켓 인쇄는 일반적인 요구 사항입니다. 그러나 많은 개발자들이 구현하고 있습니다 ...

기술 및 산업 요구에 따라 Python 및 JavaScript 개발자에 대한 절대 급여는 없습니다. 1. 파이썬은 데이터 과학 및 기계 학습에서 더 많은 비용을 지불 할 수 있습니다. 2. JavaScript는 프론트 엔드 및 풀 스택 개발에 큰 수요가 있으며 급여도 상당합니다. 3. 영향 요인에는 경험, 지리적 위치, 회사 규모 및 특정 기술이 포함됩니다.

JavaScript는 현대 웹 개발의 초석이며 주요 기능에는 이벤트 중심 프로그래밍, 동적 컨텐츠 생성 및 비동기 프로그래밍이 포함됩니다. 1) 이벤트 중심 프로그래밍을 사용하면 사용자 작업에 따라 웹 페이지가 동적으로 변경 될 수 있습니다. 2) 동적 컨텐츠 생성을 사용하면 조건에 따라 페이지 컨텐츠를 조정할 수 있습니다. 3) 비동기 프로그래밍은 사용자 인터페이스가 차단되지 않도록합니다. JavaScript는 웹 상호 작용, 단일 페이지 응용 프로그램 및 서버 측 개발에 널리 사용되며 사용자 경험 및 크로스 플랫폼 개발의 유연성을 크게 향상시킵니다.

동일한 ID로 배열 요소를 JavaScript의 하나의 객체로 병합하는 방법은 무엇입니까? 데이터를 처리 할 때 종종 동일한 ID를 가질 필요가 있습니다 ...

이 기사에서 시차 스크롤 및 요소 애니메이션 효과 실현에 대한 토론은 Shiseido 공식 웹 사이트 (https://www.shiseido.co.jp/sb/wonderland/)와 유사하게 달성하는 방법을 살펴볼 것입니다.

JavaScript를 배우는 것은 어렵지 않지만 어려운 일입니다. 1) 변수, 데이터 유형, 기능 등과 같은 기본 개념을 이해합니다. 2) 마스터 비동기 프로그래밍 및 이벤트 루프를 통해이를 구현하십시오. 3) DOM 운영을 사용하고 비동기 요청을 처리합니다. 4) 일반적인 실수를 피하고 디버깅 기술을 사용하십시오. 5) 성능을 최적화하고 모범 사례를 따르십시오.

Console.log 출력의 차이의 근본 원인에 대한 심층적 인 논의. 이 기사에서는 Console.log 함수의 출력 결과의 차이점을 코드에서 분석하고 그에 따른 이유를 설명합니다. � ...

프론트 엔드에서 VSCODE와 같은 패널 드래그 앤 드롭 조정 기능의 구현을 탐색하십시오. 프론트 엔드 개발에서 VSCODE와 같은 구현 방법 ...
