ノード内のネイティブESM.js w/require ()すべてのフロントエンドコンパイラのフォールバックとサポート!


ネイティブESMのサポートは、ノードのフラグが解除されました.数ヶ月前のJS現在とLTS.私がダイビングを始めたならば、それは私が予想したより少し難しいと判明しました.
私が心配したことは、フロントエンドコンパイラがESMとウェイノードを解釈する方法の違いをナビゲートすることでした.ジェイ.私はブラウザ、ESMのためのエントリポイントを分割したい場合は、すべての同じパッケージを理解する必要があります.JSONプロパティー.

ミケラルロジャーズ

どのように広くサポートされてパッケージ内の新しい条件付きの`輸出`マップです.アクロスコンパイラ?CCnodejs.org/dist/latest-v1…
午後20時24分
2
31
その答えは「いいえ!」コンパイラはまだノードを理解していません.輸出地図.
あなたのライブラリの消費者がそれをインポートすることができる場合require() エクスポートマップを使用する必要があります.しかし、コンパイラには見えない.
これはいくつかのことを意味します.
  • おそらく設定します{ “type”: “module” } あなたのパッケージで.JSONをデフォルトでESMを使用するために.これによりノードが作成されます.JSが解釈する.ESMとコンパイラとしてプロジェクト内のJSファイルは、ソースファイル内のESMを検出できます.本当に使用する利点はありません.あなたが同じ実装の別々のソースファイルを維持したいならば、MJSはそうしないでしょう.
  • あなたは彼らが意図された方法をエクスポートマップを使用することができませんimport main from ‘packageName/defaults’ それが有効なファイル経路でないので、このマッピングはコンパイラに見えません.

  • ミケラルロジャーズ

    私は何かを欠落しているか、またはノードにESM W/{ TYPE : module }で書かれたモジュール/ファイルを指定する必要はありません.JS ?私が見つけることができるすべては別々のエントリポイントの例です.そして、それはあなたがCJSで実行していて、それからちょうどESMエントリーポイントを公開することを意味します.
    午後14時48分
    0
    14
    使えますimport ノードを読み込む.古いモジュール標準に書かれたJSモジュールですが、できませんrequire() ESMモジュールなので、互換性は一方向にのみ流れます.
    あなたは全く文字通りの別のソースファイルを持っていなければなりません、古いモジュール形式で書かれて、あなたがサポートしたいならば、輸出マップでESMファイルに対してオーバーレイしてくださいrequire() .
    以下に例を示します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"
        },
        ...
    }
    
    rollupでこれらをコンパイルすることはかつて単純でした@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() はとても便利です.また、エクスポートされたインターフェイスは、各エントリポイントに同じまま残っていることを確認します.
    また、テストの相対的なインポートをコンパイルし、その代わりにローカルパッケージ名を使用する必要があります.ノード.JSはローカルパッケージ名を正しく解決しますが、相対的なインポートを使用する場合は、実際にエクスポートマップをスキップして失敗するでしょう.
    テストを相対的な輸入から離れて移動させることを誘惑するでしょうが、コンパイラはしばしばウェイノードに対してルックアップをサポートしていません.JSはそうしません.