노드를 이야기하다.js의 모듈 시스템

6408 단어 node.js모듈
Node.js의 모듈
JavaScript는 웹 페이지에 상호작용 기능을 추가하는 간단한 스크립트 언어로 출시되었는데 탄생할 때 모듈 시스템을 포함하지 않았다. JavaScript의 해결 문제가 갈수록 복잡해지면서 모든 코드를 한 파일에 쓰고 function으로 기능 단원을 구분하는 것은 복잡한 응용 프로그램 개발을 지탱할 수 없게 되었다. ES6는 대부분의 고급 언어에 있는class와module를 가져와 개발자가 코드를 조직하는 데 편리하게 했다

import _ from 'lodash';

class Fun {}

export default Fun;
위의 세 줄 코드는 모듈 시스템의 가장 중요한 두 가지 요소인import와 export를 보여 준다
1. export 규정된 모듈의 대외 인터페이스
2. import 다른 모듈에서 제공하는 기능 입력
ES6 이전에 커뮤니티에는 CommonJS와 AMD 두 가지, Node 등 많은 모듈 로딩 시나리오가 등장했습니다.js는 ES6보다 먼저 탄생했고 모듈 시스템은 CommonJS와 유사한 실현을 사용했으며 몇 가지 원칙을 따랐다
1. 하나의 파일은 하나의 모듈이고 파일 내의 변수 작용역은 모두 모듈 안에 있다
2. module.exports 객체 내보내기 모듈 외부 인터페이스 사용
3. 사용 require 추가 모듈 도입
circle.js

const { PI } = Math;

module.exports = function area(r) {
 PI * r ** 2;
};
위의 코드는 Node를 실현했다.js의 한 모듈, 모듈은 다른 모듈에 의존하지 않고 방법area 계산원의 면적을 내보냅니다
test.js

const area = require('./circle.js');
console.log(`  4   ${area(4)}`);
모듈은circle에 의존합니다.js, 대외적으로 노출된area방법을 사용하여 원의 면적을 계산한다
module.exports
모듈 대외 노출 인터페이스는 모듈을 사용합니다.exports, 흔히 볼 수 있는 두 가지 용법은 속성을 추가하거나 새 대상에 값을 부여하는 것이다
test.js

//  
module.exports.prop1 = xxx;
module.exports.funA = xxx;
module.exports.funB = xxx;

//  
module.exports = {
 prop1,
 funA,
 funB,
};
두 가지 작법은 등가이므로 사용할 때 차이가 없다

const mod = require('./test.js');

console.log(mod.prop1);
console.log(mod.funA());
exports 대상을 직접 사용하는 또 다른 방법도 있지만 속성만 추가할 수 있고 새로운 대상에 값을 부여할 수 없습니다. 다음에 원인을 소개합니다.

//  : 
exports.prop1 = xxx;
exports.funA = xxx;
exports.funB = xxx;

//  
module.exports = {
 prop1,
	funA,
 funB,
};
require('id')
모듈 유형
require 사용법은 비교적 간단합니다. id 지원 모듈 이름과 파일 경로 두 가지 유형
모듈 이름

const fs = require('fs');
const _ = require('lodash');
예시의 fs, lodash는 모두 모듈 이름이고 fs는 Node입니다.js에 내장된 핵심 모듈, lodash는 npm를 통해 node_에 설치됨모듈의 제3자 모듈, 중명이 발생하면 시스템 내장 모듈을 우선적으로 사용합니다
한 항목에 여러 노드가 포함될 수 있기 때문에_modules 폴더(Node.js가 실패한 디자인), 제3자 모듈 검색 과정은 가까운 원칙에 따라 층층이 거슬러 올라간다(프로그램에서 module.paths를 인쇄하여 구체적인 검색 경로를 볼 수 있음). NODE_PATH 환경 변수에서 파일 시스템 루트 디렉토리를 찾을 수 있습니다. 구체적인 절차는 참조할 수 있습니다공식 문서
그리고 Node.js에서는 다음 글로벌 디렉토리 목록도 검색합니다.
  • $HOME/.node_modules
  • $HOME/.node_libraries
  • $PREFIX/lib/node
  • 여기서 $HOME은 사용자의 홈 디렉토리이고 $PREFIX는 Node입니다.js에 설정된 node_prefix.모든 의존도를 로컬의 node_modules 디렉터리, 이렇게 하면 더 빨리 불러오고 더 믿을 수 있습니다
    파일 경로
    모듈은 파일 경로를 사용하여 불러올 수 있습니다. 이것은 프로젝트 내 사용자 정의 모듈의 일반적인 불러오는 방식입니다. 경로는 확장명을 생략할 수 있습니다.js、.json、.node 순서 시도
  • '/'를 접두사로 하는 모듈은 파일의 절대 경로이며, 시스템 경로에 따라 모듈을 찾습니다
  • .'/'접두사를 위한 모듈은 현재 리퀘스트 방법을 호출하는 파일에 비해 후속 모듈이 어디에서 사용되는지 영향을 받지 않습니다
  • 단일 로드 & 순환 의존
    모듈은 첫 번째 불러온 후 Module._cache 캐시되며, 호출할 때마다 require('foo') 같은 파일로 해석되면 같은 대상을 되돌려주고, 여러 번 호출할 때마다 require(foo) 모듈의 코드가 여러 번 실행되지 않습니다.Node.js는 실제 파일 이름 캐시 모듈에 따라 등급별 디렉터리에서 같은 모듈을 인용하면 중복 불러오지 않습니다.
    이해된 모듈 단일 부하 메커니즘은 모듈 순환 의존 후의 현상을 이해하기 편리하다
    a.js
    
    console.log('a  ');
    exports.done = false;
    const b = require('./b.js');
    console.log('  a  ,b.done = %j', b.done);
    exports.done = true;
    console.log('a  ');
    b.js
    
    console.log('b  ');
    exports.done = false;
    const a = require('./a.js');
    console.log('  b  ,a.done = %j', a.done);
    exports.done = true;
    console.log('b  ');
    main.js
    
    console.log('main  ');
    const a = require('./a.js');
    const b = require('./b.js');
    console.log('  main  ,a.done=%j,b.done=%j', a.done, b.done);
    메인js가 a.js를 불러올 때 a.js가 b.js를 불러옵니다. 이때 b.js는 a.js를 불러오려고 시도합니다.
    무한한 순환이 a.js의 exports 대상의 미완성 복사본을 b.js 모듈에 되돌려 주는 것을 방지하기 위해 b.js가 불러오기를 완료하고 exports 대상을 a.js 모듈에 제공합니다.
    따라서 예시된 출력은
    main 시작
    시작하다
    시작하다
    b에서, a.done =false
    끝내다
    a에서, b.done =true
    끝내다
    main에서 a.done=true, b.done=true
    위의 과정을 이해하지 못해도 괜찮아요. 일상적인 업무는 전혀 사용할 수 없어요. 알아봐도 프로젝트에서 순환 의존을 사용하지 마세요!
    작업 원리
    Node.js는 모든 파일이 하나의 모듈이고 모듈 내의 변수는 국부 변수이며 전체 변수를 오염시키지 않습니다. 모듈 코드를 실행하기 전에 Node.js는 다음과 같은 함수 봉인기로 모듈을 봉인합니다
    
    (function(exports, require, module, __filename, __dirname) {
    	//  
    });
  • __filename: 현재 모듈 파일의 절대 경로
  • __dirname: 현재 모듈 파일이 있는 디렉터리의 절대 경로
  • module: 현재 모듈 실례
  • require: 다른 모듈을 불러오는 방법,module.require 바로 가기
  • exports: 모듈 인터페이스를 내보내는 대상,module.exports의 바로 가기
  • 처음에 문제를 돌이켜보면, 왜 exports 대상은 다른 대상으로 값을 부여하는 것을 지원하지 않습니까?위 함수를 exports 대상의 출처에 추가하면 간단합니다.
    
    const exports = module.exports;
    (function(exports, require, module, __filename, __dirname) {
    	//  
    });
    다른 모듈require가 도착한 것은 틀림없이 모듈의module이다.exports 대상, 만약에 exports 대상이 다른 대상에게 값을 부여한다면,module.exports 대상이 연결을 끊으면 자연히 쓸모가 없습니다
    노드에서.js에서 ES Module 사용
    ES6의 사용이 갈수록 광범위해짐에 따라 Node.js도 ES6 Module을 지원합니다. 몇 가지 방법이 있습니다.
    babel 구축
    babel 구축을 사용하는 것은 v12 이전 버전에서 가장 간단하고 통용되는 방식이며 구체적인 설정 참조@babel/preset-env
    .babelrc
    
    {
     "presets": [
      ["@babel/preset-env", {
       "targets": {
        "node": "8.9.0",
        "esmodules": true
       }   
      }]
     ]
    }
    네이티브 지원
    v12 이후 ES Module 지원
  • 오픈--experimental-modules
  • 모듈 이름은 .mjs (강력 추천하지 않음) 또는 패키지로 수정되었습니다.json에서 설정 "type": module
  • 이렇게 노드.js는 js 파일을 모두 ES Module로 처리합니다. 자세한 내용은 참조공식 문서
    이상은 노드를 이야기하는 것입니다.js의 모듈 시스템에 대한 상세한 내용, 더 많은 node.js 모듈의 자료는 우리 기타 관련 문장을 주목하세요!

    좋은 웹페이지 즐겨찾기