[javascript] ES6 : 조건부 및 동적 가져 오기 문

가정 어구

아래와 같은 조건부 import 문을 가질 수 있습니까?

if (foo === bar) {
    import Baz from './Baz';
}

위의 방법을 시도했지만 컴파일 할 때 Babel에서 다음과 같은 오류가 발생합니다.

'import' and 'export' may only appear at the top level

동적

아래와 같은 동적 import 문을 가질 수 있습니까?

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        import Baz from `./${foo}`;
    }
}

위의 내용은 컴파일하는 동안 Babel에서 동일한 오류를 수신합니다.

이것이 가능합니까 아니면 내가 놓친 것이 있습니까?

추리

내가 이것을 시도하는 이유는 여러 “페이지”에 대해 많은 가져 오기를 가지고 있고 유사한 패턴을 따르기 때문입니다. 동적 for 루프를 사용하여 이러한 파일을 가져 와서 코드베이스를 정리하고 싶습니다.

이것이 가능하지 않다면 ES6에서 많은 수의 가져 오기를 처리하는 더 좋은 방법이 있습니까?



답변

우리는 이제 ECMA와 함께 동적 수입 제안을 가지고 있습니다. 이것은 2 단계에 있습니다. 이것은 babel-preset 으로도 사용할 수 있습니다 .

다음은 귀하의 경우에 따라 조건부 렌더링을 수행하는 방법입니다.

if (foo === bar) {
    import('./Baz')
    .then((Baz) => {
       console.log(Baz.Baz);
    });
}

이것은 기본적으로 약속을 반환합니다. 약속의 해결에는 모듈이있을 것으로 예상됩니다. 제안에는 여러 동적 가져 오기, 기본 가져 오기, js 파일 가져 오기 등과 같은 항목도 있습니다 . 여기에서 동적 가져 오기 에 대한 자세한 정보를 찾을 수 있습니다 .


답변

imports정적 분석을위한 것처럼 종속성을 동적으로 해결할 수 없습니다 . 그러나 require다음과 같이 여기에서 사용할 수 있습니다 .

for (let foo in bar) {
    if (bar.hasOwnProperty(foo)) {
        const Baz = require(foo).Baz;
    }
}


답변

이 질문은 Google에서 높은 순위를 차지하기 때문에 이전 답변이 게시 된 후 상황이 변경되었음을 지적 할 가치가 있습니다.

MDN은 동적 가져 오기 아래에 다음 항목이 있습니다 .

import 키워드는 모듈을 동적으로 가져 오는 함수로 호출 될 수 있습니다. 이런 식으로 사용하면 promise를 반환합니다.

import('/modules/my-module.js')
  .then((module) => {
    // Do something with the module.
  });

// This form also supports the await keyword.
let module = await import('/modules/my-module.js');

주제에 대한 유용한 기사는 Medium 에서 찾을 수 있습니다 .


답변

Require는 동기 호출이므로 문제를 해결하지 못합니다. 몇 가지 옵션이 있으며 모두 포함됩니다.

  1. 필요한 모듈 요청
  2. 모듈 반환 약속을 기다리는 중

ECMA 스크립트에는 SystemJS를 사용하는 지연로드 모듈에 대한 지원이 있습니다. 물론 이것은 모든 브라우저에서 지원되는 것은 아니므로 그 동안 JSPM 또는 SystemJS shim을 사용할 수 있습니다.

https://github.com/ModuleLoader/es6-module-loader


답변

2016 년 이후 자바 스크립트 세계에서 많은 것이 통과되었으므로이 주제에 대한 최신 정보를 제공 할 때라고 생각합니다. 현재 동적 가져 오기노드브라우저 모두 에서 현실입니다 (기본적으로 IE에 관심이 없다면 @ babel / plugin-syntax-dynamic-import를 사용하세요).

따라서 something.js두 개의 이름이 지정된 내보내기와 하나의 기본 내보내기가 있는 샘플 모듈 을 고려하십시오 .

export const hi = (name) => console.log(`Hi, ${name}!`)
export const bye = (name) => console.log(`Bye, ${name}!`)
export default () => console.log('Hello World!')

import()구문을 사용 하여 쉽고 깔끔하게 조건부로로드 할 수 있습니다.

if (somethingIsTrue) {
  import('./something.js').then((module) => {
    // Use the module the way you want, as:
    module.hi('Erick') // Named export
    module.bye('Erick') // Named export
    module.default() // Default export
  })
}

그러나 반환 값이 Promise이므로 async/ await구문 설탕도 가능합니다.

async imAsyncFunction () {
  if (somethingIsTrue) {
    const module = await import('./something.js')
    module.hi('Erick')
  }
}

이제 Object Destructuring Assignment 와 함께 가능성에 대해 생각해보십시오 ! 예를 들어, 사후 사용을 위해 이름이 지정된 내보내기 중 하나만 메모리에 쉽게 넣을 수 있습니다.

const { bye } = await import('./something.js')
bye('Erick')

또는 이름이 지정된 내보내기 중 하나를 잡고 원하는 다른 이름으로 이름을 바꿀 수도 있습니다.

const { hi: hello } = await import('./something.js')
hello('Erick')

또는 기본 내 보낸 함수의 이름을 더 이해하기 쉬운 이름으로 바꿉니다.

const { default: helloWorld } = await import('./something.js')
helloWorld()

마지막 (적어도) 참고 : import() 함수 호출처럼 보일 수 있지만 Function. 괄호를 사용하는 특수 구문입니다 (에서 발생하는 것과 유사 함 super()). 따라서 import변수 에 할당 하거나 / Function와 같은 프로토 타입을 사용할 수 없습니다 .callapply


답변