npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

import-remap

v0.6.0

Published

Rewrite ES module import specifiers using an import-map

Downloads

17

Readme

Import-Remap

npm Module Modules License

Rewrite ES module import specifiers using an import-map.

Overview

ES modules with bare import specifiers (like import foo from "foo") work fine in Node, but don't work in the browser; the browser expects URLs (like "/path/to/foo.js").

Import-maps are an ideal solution to that problem, because they instruct the engine/browser to map a bare import specifier like "foo" to a URL like "/path/to/foo.js". However, import-maps are not yet an available and reliable cross-environment feature.

Import-remap "solves" this problem by applying your import-map mappings to your ES module file(s), typically as part of a build process. This replaces any matching bare import specifier strings (in import, dynamic import(..), and export .. from ".." statements) with their corresponding URLs from the import-map. These remapped files are suitable for use in browsers regardless of the support for import-maps.

Note: While this tool can remap dynamic import(..) calls, it will only do so if there if the first argument is a static string literal (ie, "in-double-quotes" or 'in-single-quotes') or a simple (non-tagged) template literal with no expressions (ie, `in-back-ticks`). Any other expression as an argument to dynamic import(..) will be ignored.

Any processed file(s) that aren't recognized/parsed as ES modules will simply be copied as-is without being touched.

Example

Consider this ES module:

// import statement/call forms
import { addFriend } from "friends";
import render from "friends/render";
import("friends/list").then(function(list){
    // ..
});

// supported export statement forms
export * from "friends/events";
export { subscribe } from "friends/subscriptions";
// also supports proposed export-default form
// (currently stage-1!)
export messenger from "friends/messenger";

// NOTE: this specifier isn't listed in the
// import-map, so it won't be remapped and will
// likely still not work in the browser
import manager from "friends/manager";

And consider an import-map (JSON) is provided as such:

{
    "friends": "./packages/friends.mjs",
    "friends/render": "./packages/friends/render.mjs",
    "friends/list": "./packages/contrib/friends-list.mjs",
    "friends/events": "https://some-cdn/friends-events/index.mjs",
    "friends/subscriptions": "./packages/subscriptions/index.mjs",
    "friends/messenger": "./messenger.mjs"
}

The remapped output file will look like this:

// import statement/call forms
import { addFriend } from "./packages/friends.mjs";
import render from "./packages/friends/render.mjs";
import("./packages/contrib/friends-list.mjs").then(function(list){
    // ..
});

// supported export statement forms
export * from "https://some-cdn/friends-events/index.mjs";
export { subscribe } from "./packages/subscriptions/index.mjs";
// also supports proposed export-default form
// (currently stage-1!)
export messenger from "./messenger.mjs";

// NOTE: this specifier isn't listed in the
// import-map, so it won't be remapped and will
// likely still not work in the browser
import manager from "friends/manager";

As you can see, there's no fancy matching logic in the string values. Only exact matches (case-sensitive!) are replaced.

Note: This strict matching doesn't exactly follow the current proposed (and fluctuating) import-map behaviors; behavior adherence is expected in the future when the specification for import-map is finalized.

CLI

npm Module

To use the CLI:

import-remap --from="./src" --to="./src.remapped"
--map="./path/to/import-map.json" [--ignore={GLOB-PATTERN}] [--recursive] [--minify]

See import-remap --help for a list of available parameter flags.

CLI Flags

  • --from=PATH: specifies the path to a directory (or a single file) containing the files to duplicate (and remap, if applicable) into the --to-sepcified target location; defaults to ./ in the current working directory

  • --to=PATH: specifies the path to a directory to write the remapped ES module file(s); defaults to a directory called ./.remapped in the same location as the --from-specified path

  • --map=PATH: specifies the path to the JSON import-map file to use for remapping; defaults to "./import-map.json"

  • --keep (alias -k): specify a glob pattern for ignoring remap processing on an input file path -- keeps/copies the file from the input path untouched if matched; multiple keep-patterns can be specified by using --keep / -k multiple times in the command

  • --ignore (alias -i): deprecated (as of v0.6.0) (due to semantic confusion); renamed to --keep / -k

  • --skip (alias -s): specify a glob pattern for skipping a file entirely; multiple skip-patterns can be specified by using --skip / -s multiple times in the command

  • --recursive (alias -r): traverse the --from-specified path recursively

  • --minify (alias -n): minify the output (using terser), while preserving any code comments; otherwise, the output is the default serialization from the babel parser/generator

The CLI tool will also read the following settings from the current process environment (or source them from a .env file in the current working directory):

  • FROMPATH: corresponds to the --from parameter (see above)
  • TOPATH: corresponds to the --to parameter (see above)
  • MAPPATH: corresponds to the --map parameter (see above)

Library

npm Module Modules

The typical use of Import-remap is through the CLI, but it can also be used in your application code. The package provides a single function called remap(..), which expects the following arguments:

  • codePath: a string representing the current path of the file; not currently used, but reserved for potential future use

  • contents: a string holding the code from the file to be remapped

  • importMap: an object holding the contents of the JSON import-map

The return value from remap(..) is a string with the remapped code. If the contents weren't parsed properly as an ES module, or if no matching specifiers were found to replace, this return value will identical to the passed in contents argument.

npm Package

npm Module Modules

To install this package from npm:

npm install import-remap

And to require it in a node script:

var remap = require("import-remap");

Or in an ES module (in Node):

import remap from "import-remap";

Note: As of v0.6.0, the previously deprecated ESM import specifier segment /esm in Import-Remap import paths have been removed, in favor of unified import specifier paths via Node Conditional Exports. For ESM import statements, always use the specifier style "import-remap", as "import-remap/esm" style will now break.

Running this tool in a non-Node environment is not supported.

License

License

All code and documentation are (c) 2023 Kyle Simpson and released under the MIT License. A copy of the MIT License is also included.