Novice, Practiced, Mastered

    @jsenv/importmap-node-module

    5.1.3 • Public • Published

    import map node module npm package github workflow codecov coverage

    Generate import map file with mappings corresponding to node esm resolution algorithm. It can be used to make code dependent on node module resolution executable in a browser.

    Example of code relying on node module resolution:

    import lodash from "lodash"

    Usage

    1 - Install @jsenv/importmap-node-module

    npm install --save-dev @jsenv/importmap-node-module

    2 - Create generate_importmap.mjs

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./project.importmap": {
          mappingsForNodeResolution: true,
        },
      },
    })

    3 - Generate project.importmap

    node ./generate_importmap.mjs

    4 - Add project.importmap to your html

    <!DOCTYPE html>
    <html>
      <head>
        <title>Title</title>
        <meta charset="utf-8" />
        <link rel="icon" href="data:," />
    +   <script type="importmap" src="./project.importmap"></script>
      </head>
    
      <body>
        <script type="module">
          import lodash from "lodash"
        </script>
      </body>
    </html>

    If you use a bundler or an other tool, be sure it's compatible with import maps. As import map are standard the bundler/tool might be compatible by default or with the help of some plugin/configuration. If you don't know what to use, check @jsenv/core.

    At this stage you have generated an importmap file with mappings corresponding to how node resolve imports. You can read the rest of this document to go further.

    writeImportMapFiles

    writeImportMapFiles is an async function generating one or many importmap files.

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./importmap_for_dev.importmap": {
          mappingsForNodeResolution: true,
          mappingsForDevDependencies: true,
        },
        "./importmap_for_prod.importmap": {
          mappingsForNodeResolution: true,
        },
      },
    })

    projectDirectoryUrl

    projectDirectoryUrl is a string/url leading to a folder with a package.json.

    projectDirectoryUrl is required.

    importMapFiles

    importMapFiles is an object where keys are file relative urls and value are objects configuring which mappings will be written in the importmap files.

    importMapFiles is required.

    mappingsForNodeResolution

    mappingsForNodeResolution is a boolean. When enabled mappings required to implement node module resolution are generated.

    mappingsForNodeResolution is optional.

    Be sure node modules are on your filesystem because we'll use the filesystem structure to generate the importmap. For that reason, you must use it after npm install or anything that is responsible to generate the node_modules folder and its content on your filesystem.

    mappingsForDevDependencies

    mappingsForDevDependencies is a boolean. When enabled, "devDependencies" declared in your package.json are included in the generated importMap.

    mappingsForDevDependencies is optional.

    runtime

    runtime is a string used to determine what to pick in package.json conditions.

    runtime is optional and defaults to "browser".

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./browser.importmap": {
          mappingsForNodeResolution: true,
          runtime: "browser",
        },
        "./node.importmap": {
          mappingsForNodeResolution: true,
          runtime: "node",
        },
      },
    })

    packageUserConditions

    packageUserConditions is an array controlling which conditions are favored in package.json conditions.

    packageUserConditions is optional.

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./dev.importmap": {
          mappingsForNodeResolution: true,
          packageUserConditions: ["development"],
        },
        "./prod.importmap": {
          mappingsForNodeResolution: true,
          packageUserConditions: ["production"],
        },
      },
    })

    manualImportMap

    manualImportMap is an object containing mappings that will be added to the importmap. This can be used to provide additional mappings and/or override node mappings.

    manualImportMap is optional.

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./test.importmap": {
          mappingsForNodeResolution: true,
          manualImportMap: {
            imports: {
              "#env": "./env.js",
            },
          },
        },
      },
    })

    entryPointsToCheck

    entryPointsToCheck is an array composed of string representing file relative urls. Each file is considered as an entry point using the import mappings. For each entry point, writeImportMapFiles will check if import can be resolved and repeat this process for every static and dynamic import. You can also pass HTML file(s).

    entryPointsToCheck is optional.

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./project.importmap": {
          mappingsForNodeResolution: true,
          entryPointsToCheck: ["./main.js"],
        },
      },
    })

    It is recommended to use entryPointsToCheck as it gives confidence in the generated importmap. When an import cannot be resolved, a warning is logged.

    magicExtensions

    magicExtensions is an array of strings. Each string represent an extension that will be tried when an import cannot be resolved to a file.

    magicExtensions is optional. It must be used with entryPointsToCheck.

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./test.importmap": {
          mappingsForNodeResolution: true,
          entryPointsToCheck: ["./main.js"],
          magicExtensions: ["inherit", ".js"],
        },
      },
    })

    "inherit" means the extension tried in taken from the importer.

    import "./helper"
    importer path path tried
    /Users/dmail/file.js /Users/dmail/helper.js
    /Users/dmail/file.ts /Users/dmail/helper.ts

    All other values in magicExtensions are file extensions that will be tried one after an other.

    removeUnusedMappings

    removeUnusedMappings is a boolean. When enabled mappings will be treeshaked according to the import found in js files.

    removeUnusedMappings is optional. It must be used with entryPointsToCheck.

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./test.importmap": {
          mappingsForNodeResolution: true,
          entryPointsToCheck: ["./main.js"],
          removeUnusedMappings: true,
        },
      },
    })

    It is recommended to enable removeUnusedMappings so that importmap contains only the mappings actually used by your codebase.

    packagesManualOverrides

    packagesManualOverrides is an object that can be used to override some of your dependencies package.json.

    packagesManualOverrides is optional.

    packagesManualOverrides exists in case some of your dependencies use non standard fields to configure their entry points in their package.json. Ideally they should use "exports" field documented in https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_package_entry_points. But not every one has updated to this new field yet.

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./", import.meta.url),
      importMapFiles: {
        "./test.importmap": {
          mappingsForNodeResolution: true,
        },
      },
      // overrides "react-redux" package because it uses a non-standard "module" field
      // to expose "es/index.js" entry point
      // see https://github.com/reduxjs/react-redux/blob/9021feb9ff573b01b73084f1a7d10b322e6f0201/package.json#L18
      packageManualOverrides: {
        "react-redux": {
          exports: {
            import: "./es/index.js",
          },
        },
      },
    })

    TypeScript

    This repository can generate importmap to make code produced by the TypeScript compiler executable in a browser.

    You need to have your package.json and node_modules into the directory where typescript output js files. You can achieve this with the following "scripts" in your package.json.

    {
      "scripts": {
        "prebuild": "rm -rf dist",
        "build": "tsc",
        "postbuild": "cp package.json dist && ln -sf ../node_modules ./dist/node_modules"
      }
    }

    Then you can use the script below to produce the importmap.

    import { writeImportMapFiles } from "@jsenv/importmap-node-module"
    
    await writeImportMapFiles({
      projectDirectoryUrl: new URL("./dist/", import.meta.url),
      importMapFiles: {
        "./project.importmap": {
          mappingsForNodeResolution: true,
          entryPointsToCheck: ["./index.js"],
          magicExtensions: ["inherit"],
          removeUnusedMappings: true,
        },
      },
    })

    See also

    Keywords

    none

    Install

    npm i @jsenv/importmap-node-module

    DownloadsWeekly Downloads

    8

    Version

    5.1.3

    License

    MIT

    Unpacked Size

    109 kB

    Total Files

    25

    Last publish

    Collaborators

    • jsenv-admin
    • dmail