Node.js의 기본 ESM w/require() 폴백 및 모든 프런트 엔드 컴파일러 지원!
13294 단어 webpacknodetestingjavascript
제가 걱정했던 한 가지는 프런트 엔드 컴파일러가 ESM을 해석하는 방식과 Node.js가 해석하는 방식 사이의 차이점을 탐색하는 것이었습니다. 브라우저, ESM의 진입점을 분할하려면 모두 동일한 package.json 속성을 이해해야 합니다.
미칼 로저스
컴파일러 전체에서 package.json의 새로운 조건부 `내보내기` 맵이 얼마나 광범위하게 지원됩니까?/ccnodejs.org/dist/latest-v1…
오후 18:24 - 2020년 6월 8일
2
31
그 대답은 "아니오!"였습니다. 컴파일러는 아직 Node.js의 내보내기 맵을 이해하지 못합니다.
라이브러리 소비자가
require()
를 사용하여 라이브러리를 가져올 수 있도록 하려면 내보내기 맵을 사용해야 하며 이 매핑은 Node.js에서 사용되지만 컴파일러에는 표시되지 않습니다.이것은 몇 가지를 의미합니다.
{ “type”: “module” }
를 설정하고 싶을 것입니다. 이렇게 하면 Node.js가 프로젝트의 .js 파일을 ESM으로 해석하고 컴파일러는 이미 소스 파일에서 ESM을 감지할 수 있습니다. 동일한 구현의 별도 소스 파일을 유지하고 싶지 않은 한 .mjs를 사용하는 것은 실제로 이점이 없으며 아마도 그렇지 않을 것입니다. import main from ‘packageName/defaults’
와 같은 것을 허용하는 내보내기 맵을 의도한 대로 사용할 수 없습니다. 미칼 로저스
내가 뭔가를 놓치고 있는 건가요, 아니면 Node.js에서 { type: module } w/{ type: module }로 ESM으로 작성된 모듈/파일을 require()할 수 있는 방법이 *없*나요? cjs에서 구현한 다음 ESM 진입점을 노출합니다.
오후 14:48 - 2020년 6월 19일
0
14
import
를 사용하여 이전 모듈 표준으로 작성된 Node.js 모듈을 로드할 수 있지만 ESM 모듈은 로드할 수 없으므로require()
호환성이 한 방향으로만 흐릅니다.require()
를 지원하려면 문자 그대로 이전 모듈 형식으로 작성되고 내보내기 맵에서 ESM 파일에 대해 오버레이되는 별도의 소스 파일이 있어야 합니다.다음은 내보내기가 많은 js-multiformats의 예입니다.
"exports": {
".": {
"import": "./index.js",
"require": "./dist/index.cjs"
},
"./basics.js": {
"import": "./basics.js",
"require": "./dist/basics.cjs"
},
"./bytes.js": {
"import": "./bytes.js",
"require": "./dist/bytes.cjs"
},
"./cid.js": {
"import": "./cid.js",
"require": "./dist/cid.cjs"
},
...
}
롤업으로 컴파일하는 것은 @mylesborins가 올바른 방향을 알려준 후 매우 간단했지만 조금 더 필요했습니다.
다음은 js-multiformats의 또 다른 예입니다.
import globby from 'globby'
import path from 'path'
let configs = []
const _filter = p => !p.includes('/_') && !p.includes('rollup.config')
const relativeToMain = name => ({
name: 'relative-to-main',
renderChunk: source => {
while (source.includes("require('../index.js')")) {
source = source.replace("require('../index.js')", "require('multiformats')")
}
while (source.includes("require('../")) {
source = source.replace('require(\'../', 'require(\'multiformats/')
}
return source
}
})
const plugins = [relativeToMain('multiformats')]
const add = (pattern) => {
configs = configs.concat(globby.sync(pattern).filter(_filter).map(inputFile => ({
input: inputFile,
output: {
plugins: pattern.startsWith('test') ? plugins : null,
file: path.join('dist', inputFile).replace('.js', '.cjs'),
format: 'cjs'
}
})))
}
add('*.js')
add('bases/*.js')
add('hashes/*.js')
add('codecs/*.js')
add('test/*.js')
add('test/fixtures/*.js')
console.log(configs)
export default configs
모든 .js 파일과 모든 테스트를 컴파일하려고 합니다. 이 번역에는 잘못될 수 있는 부분이 많으므로
require()
를 사용하는 각 테스트 버전을 컴파일하는 것이 매우 유용합니다. 또한 내보낸 인터페이스가 각 진입점에 대해 동일하게 유지되도록 합니다.또한 테스트에서 상대적 가져오기를 컴파일하고 대신 로컬 패키지 이름을 사용해야 합니다. Node.js는 로컬 패키지 이름을 올바르게 해석하지만 상대 가져오기를 사용하는 경우 실제로 내보내기 맵을 완전히 건너뛰고 실패합니다.
상대 가져오기에서 테스트를 마이그레이션하는 것은 유혹적일 수 있지만 컴파일러는 종종 Node.js가 수행하는 방식으로 로컬 패키지 이름에 대한 조회를 지원하지 않으므로 지원하지 않습니다.
Reference
이 문제에 관하여(Node.js의 기본 ESM w/require() 폴백 및 모든 프런트 엔드 컴파일러 지원!), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mikeal_2/native-esm-in-node-js-w-require-fallbacks-and-support-for-all-front-end-compilers-2ded텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)