node.js의 ES6 변수 가져 오기 이름?


108

ES6 가져 오기를 사용하는 동안 변수 이름을 제공하는 모듈로 무언가를 가져올 수 있습니까?

즉, 구성에 제공된 값에 따라 런타임에 일부 모듈을 가져오고 싶습니다.

import something from './utils/' + variableName;

1
@Bigood 네, 컴파일러는 최대 던져 Webstorm는 오류를 보여줍니다
비타 우타 스 버트 커스

답변:


67

import성명서가 아닙니다 . import그리고 export그들은 정적 분석 가능한 것을 그들이 런타임 정보에 의존하지 수 같은 방식으로 정의된다.

loader API (polyfill)를 찾고 있지만 사양 상태에 대해 약간 불분명합니다.

System.import('./utils/' + variableName).then(function(m) {
  console.log(m);
});

3
시스템을 "요구"해야합니까? 그것은 글로벌 범위에 있지 않습니다 .. 추신 나는 babel js를 사용하고 있습니다
Vytautas Butkus

아직 AFAIK 어디에도 구현되지 않았습니다. 링크에서 폴리 필을 사용해야합니다.
Felix Kling 2015 년

1
그냥 (시도는 파일을로드)가 좀 작동 확인하지만 혼잡이 기본적으로 .. 지원되지 않는 너무의 나쁜 ... 다른 모듈에 대한 경로까지
비타 우타 스 버트 커스

3
여전히 문제입니까? ES6 모듈을
다이내믹

26

Felix의 답변 외에도 ECMAScript 6 문법 에서 현재 허용되지 않는다는 점을 분명히 밝힙니다 .

ImportDeclaration :

  • import ImportClause FromClause;

  • import ModuleSpecifier;

FromClause :

  • 에서 ModuleSpecifier

ModuleSpecifier :

  • StringLiteral

ModuleSpecifier은 단지가 될 수 StringLiteral , 같은 표현이 아닌 다른 종류의 AdditiveExpression .


2
이것이 const string literals 를 포함하도록 확장되지 않은 것은 유감 입니다. 정적으로 분석 가능하지 않습니까? 종속성의 위치를 ​​재사용 할 가능성이 있습니다. (예 : 템플릿을 가져오고 템플릿과 템플릿의 위치를 ​​모두 사용할 수 있습니다).
nicodemus13 2013 년

26

이것은 실제로 동적 가져 오기는 아니지만 (예 : 내 상황에서 아래에서 가져 오는 모든 파일은 런타임에 선택되지 않고 웹팩에 의해 가져 와서 번들로 제공됩니다) 일부 상황에서 도움이 될 수있는 패턴은 다음과 같습니다. :

import Template1 from './Template1.js';
import Template2 from './Template2.js';

const templates = {
  Template1,
  Template2
};

export function getTemplate (name) {
  return templates[name];
}

또는 대안으로 :

// index.js
export { default as Template1 } from './Template1';
export { default as Template2 } from './Template2';


// OtherComponent.js
import * as templates from './index.js'
...
// handy to be able to fall back to a default!
return templates[name] || templates.Template1;

require()존재하지 않는 구성된 템플릿 경로를 가져 오려고하면 오류가 발생하는을 사용 하여 쉽게 기본값으로 돌아갈 수 있다고 생각 하지 않습니다.

require와 import 간의 좋은 예와 비교는 여기에서 찾을 수 있습니다 : http://www.2ality.com/2014/09/es6-modules-final.html

@iainastacio에서 다시 내보내기에 대한 우수한 문서 : http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles

이 접근법에 대한 피드백을 듣고 싶습니다. :)


찬성. 나는 "또는 대안적인"접근 방식을 사용했습니다. 내 사용자 지정 현지화 솔루션의 매력처럼 작동했습니다.
groundh0g dec


1
나는 이것을 생각 했어야했다. 가져 오는 방법에 관계없이 (아무것도 가져 오지 않더라도) 훌륭한 솔루션입니다. 나중에 이름을 가져 오거나 이름으로 가져올 항목 목록이 있습니까? 배열 리터럴 대신 개체 리터럴에 넣고 개체 구문이 로컬 상수 / 변수 이름에 따라 이름을 지정하도록합니다. 목록으로 다시 필요하면 Object.values(templates).
Andrew Koster

15

ES 모듈에 대한 동적 가져 오기 라는 새로운 사양이 있습니다. 기본적으로 전화 만하면 import('./path/file.js')됩니다. 함수는 가져 오기가 성공하면 모듈로 해결되는 promise를 반환합니다.

async function importModule() {
   try {
      const module = await import('./path/module.js');
   } catch (error) {
      console.error('import failed');
   }
}

사용 사례

사용 사례에는 React, Vue 등에 대한 경로 기반 구성 요소 가져 오기 및 런타임 중에 필요한 경우 모듈지연로드 하는 기능이 포함 됩니다.

추가 정보

다음은 Google 개발자 에 대한 설명입니다 .

브라우저 호환성 (2020 년 4 월)

MDN 에 따르면 현재 모든 주요 브라우저 (IE 제외)에서 지원되며 caniuse.com 은 전 세계 시장 점유율에서 87 %의 지원을 보여줍니다. IE 또는 non-chromium Edge에서는 다시 지원되지 않습니다.


당신의 편집에 대해 확신합니까? 제안은 변수 경로가있는 예제를 보여줍니다 : github.com/tc39/proposal-dynamic-import#example
phil294

@Blauhirn 나는 그랬지만 귀하의 링크는 가능성이 있음을 분명히 보여줍니다. 예를 들어 웹팩이 이러한 가져 오기를 어떻게 해결할지 모르겠지만
Nicolai Schmid

내가 틀렸다면 수정하지만 webpack은 이것을 처리하지 않습니까? 브라우저에서 "있는 그대로"실행되는 것이 동적 가져 오기의 포인트라고 생각했습니다.
phil294

예, 브라우저에서 그대로 실행할 수 있습니다. 그러나 webpack은 자동으로 가져 오기를 사용하여 앱의 여러 부분 (예 : 경로)에 대해 앱을 여러 번들로 분할합니다. 나는 그것들을 항상 사용하며 정말 도움이됩니다. 그리고 "처리"가 진행되는 한; webpack은 이전 브라우저의 기능을 폴리 필하는 babel 가져 오기를 전달합니다.
Nicolai Schmid

명확하게 말하면 dynamic import () 변수와 함께 작동하며 정적으로 분석 할 필요가 없습니다 (그것이 '동적'의 전체 요점입니까?). 내 대답을 참조하십시오.
Velojet

6

importNode.js의 ES6 에 대해 구체적으로 묻는 질문을 이해 하지만 다음은 더 일반적인 솔루션을 찾는 다른 사람들에게 도움이 될 수 있습니다.

let variableName = "es5.js";
const something = require(`./utils/${variableName}`);

ES6 모듈을 가져 오는 중이고default 내보내기 에 액세스 해야하는 경우 다음 중 하나를 사용해야합니다.

let variableName = "es6.js";

// Assigning
const defaultMethod = require(`./utils/${variableName}`).default;

// Accessing
const something = require(`./utils/${variableName}`);
something.default();

다른 가져 오기에 더 많은 구문 친숙성을 추가 할 수있는이 접근 방식으로 구조 해제를 사용할 수도 있습니다.

// Destructuring 
const { someMethod } = require(`./utils/${variableName}`);    
someMethod();

안타깝게도 액세스 default및 구조 해제를 원할 경우 여러 단계로이 작업을 수행해야합니다.

// ES6 Syntax
Import defaultMethod, { someMethod } from "const-path.js";

// Destructuring + default assignment
const something = require(`./utils/${variableName}`);

const defaultMethod = something.default;    
const { someMethod, someOtherMethod } = something;

4

비 ES6 표기법을 사용하면됩니다. 이것은 나를 위해 일한 것입니다.

let myModule = null;
if (needsToLoadModule) {
  myModule = require('my-module').default;
}

3

덜이 같은 문법 I,하지만 작동 :
대신 작성

import memberName from "path" + "fileName"; 
// this will not work!, since "path" + "fileName" need to be string literal

다음 구문을 사용하십시오.

let memberName = require("path" + "fileName");

1
@UlysseBN 나쁜 방식으로 다른가요? 아니면 정말 중요하지 않은 방법?
Sam

@Jacob 그들은 정말 완전히 다르기 때문에 당신이하는 일에 따라 중요 할 수 있습니다. 첫 번째 구문은 정적으로 평가되고 두 ​​번째 구문은 동적으로 평가됩니다. 예를 들어 웹팩을 사용하는 경우 두 번째로 트리 쉐이킹을 올바르게 수행하는 것은 아닙니다. 다른 많은 차이점이 있습니다. 문서를 읽고 어느 것이 더 적합한 지 확인하는 것이 좋습니다!
Ulysse BN

@Jacob-정말 중요하지 않습니다 (대부분의 경우). require()초기 버전 인 파일을로드하는 Node.JS 메소드입니다. importstatement는 이제 공식 언어 구문의 일부인 최신 버전입니다. 그러나 대부분의 경우 브라우저는 이전 브라우저를 사용합니다 (과학 뒤에). require 문은 또한 파일을 현금화하므로 파일이 두 번째로로드되면 메모리에서로드됩니다 (성능 향상). WebPack을 사용하는 경우 가져 오기 방식에는 고유 한 이점이 있습니다. 그러면 웹팩이 죽은 참조를 제거 할 수 있습니다 (이 스크립트는 클라이언트에 다운로드되지 않습니다).
Gil Epshtain 19

1

동적 import () (Chrome 63 이상에서 사용 가능)가 작업을 수행합니다. 방법은 다음과 같습니다.

let variableName = 'test.js';
let utilsPath = './utils/' + variableName;
import(utilsPath).then((module) => { module.something(); });

0

나는 이렇게 할 것이다

function load(filePath) {
     return () => System.import(`${filePath}.js`); 
     // Note: Change .js to your file extension
}

let A = load('./utils/' + variableName)

// Now you can use A in your module

0

./utils/test.js

export default () => {
  doSomething...
}

파일에서 호출

const variableName = 'test';
const package = require(`./utils/${variableName}`);
package.default();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.