WICG / import-maps

How to control the behavior of JavaScript imports
https://html.spec.whatwg.org/multipage/webappapis.html#import-maps
Other
2.68k stars 69 forks source link

Support single entry-file for trailing slash import keys #145

Closed alber70g closed 5 years ago

alber70g commented 5 years ago

In the subsection ""Packages" via trailing slashes" we support mapping from a "wildcard-import" to a "wildcard-path".

{
  "imports": {
    "lodash": "/node_modules/lodash-es/lodash.js",
    "lodash/": "/node_modules/lodash-es/"
  }
}

It would be nice to support "wildcard-import" to "file":

{
  "imports": {
    "lodash/": "https://unpkg.com/lodash-es@4.17.11/lodash.js"
  }
}

This allows to use import isArray from "lodash/isArray"; while not having a massive import-map.

This file can then be a bundled file for everything below package/* or "deferres" it's "import-map" through the export statement.

E.g.: https://unpkg.com/lodash-es@4.17.11/lodash.js

chase-moskal commented 5 years ago

i don't understand

given this import map

{
  "imports": {
    "lodash/": "/node_modules/lodash-es/"
  }
}

we actually can do this

import isArray from "lodash/isArray.js"

i think this is what you're looking for, no?

you had mentioned that you want to

[...] use import isArray from "lodash/isArray"; while not having a massive import-map.

i think my example is not massive, and also gives you what you're looking for

as for using a bundle, i wouldn't recommend using the bundles that some libraries provide, because once you are interested in those optimizations, you are better off using a bundler like rollup (plus a minifier) on your whole application, instead of using import maps to resolve modules in-browser (you might be interested to use import maps during development, and then use a bundler for production -- you get better results with whole-app optimizations when you are using individual es modules instead of bundles, read: tree shaking)

cheers friend, let me know if you're trying to accomplish something different

:wave: Chase

daKmoR commented 5 years ago

deriving a file and path import from a single string would only work we can assume that the main entry point is always in the root of the package.

from

    "lodash-es/": "/node_modules/lodash-es/lodash.js",

you could safely construct the following imports

import 'lodash-es' =>  /node_modules/lodash-es/lodash.js
import 'lodash-es/package.json' =>  /node_modules/lodash-es/package.json

however, if the path is different then it can result in strange results

    "lodash": "/node_modules/lodash-es/dist/lodash.js",
import 'lodash-es' =>  /node_modules/lodash-es/dist/lodash.js
import 'lodash-es/package.json' =>  /node_modules/lodash-es/dist/package.json
import 'lodash-es/dist/lodash.js' =>  /node_modules/lodash-es/dist/dist/lodash.js

I am afraid a single path does not have enough information to define the package path + main entry point file... 🙈

domenic commented 5 years ago

I don't really understand this issue. What is wrong with the OP's example of

{
  "imports": {
    "lodash": "/node_modules/lodash-es/lodash.js",
    "lodash/": "/node_modules/lodash-es/"
  }
}

is two entries being considered "massive"?

Could you give a concrete example of an import map you are using, a package you want to configure the import map for, a set of import statements, and the way in which your import map is not working? Then maybe we can help come up with a better import map or set of import statements.

domenic commented 5 years ago

Closing due to lack of follow-up, but happy to continue discussing, and reopen if there's something here.

alber70g commented 5 years ago

I don't really understand this issue. What is wrong with the OP's example of

{
  "imports": {
    "lodash": "/node_modules/lodash-es/lodash.js",
    "lodash/": "/node_modules/lodash-es/"
  }
}

is two entries being considered "massive"?

Could you give a concrete example of an import map you are using, a package you want to configure the import map for, a set of import statements, and the way in which your import map is not working? Then maybe we can help come up with a better import map or set of import statements.

@domenic The concrete example would be the following (massive):

{
  "imports": {
                 "lodash/add.js": "./path/lodash-es.min.js",
        "lodash/after.js": "./path/lodash-es.min.js",
        "lodash/at.js": "./path/lodash-es.min.js",
        "lodash/attempt.js": "./path/lodash-es.min.js",
        "lodash/before.js": "./path/lodash-es.min.js",
        "lodash/camelCase.js": "./path/lodash-es.min.js",
        "lodash/capitalize.js": "./path/lodash-es.min.js",
        "lodash/castArray.js": "./path/lodash-es.min.js",
        "lodash/ceil.js": "./path/lodash-es.min.js",
        "lodash/chunk.js": "./path/lodash-es.min.js",
        "lodash/clamp.js": "./path/lodash-es.min.js",
        "lodash/clone.js": "./path/lodash-es.min.js",
        "lodash/cloneDeep.js": "./path/lodash-es.min.js",
        "lodash/cloneDeepWith.js": "./path/lodash-es.min.js",
        "lodash/cloneWith.js": "./path/lodash-es.min.js",
        "lodash/compact.js": "./path/lodash-es.min.js",
        "lodash/cond.js": "./path/lodash-es.min.js",
        "lodash/conforms.js": "./path/lodash-es.min.js",
        "lodash/conformsTo.js": "./path/lodash-es.min.js",
        "lodash/countBy.js": "./path/lodash-es.min.js",
        "lodash/create.js": "./path/lodash-es.min.js",
        "lodash/debounce.js": "./path/lodash-es.min.js",
        "lodash/deburr.js": "./path/lodash-es.min.js",
        "lodash/defaultTo.js": "./path/lodash-es.min.js",
        "lodash/defaultToAny.js": "./path/lodash-es.min.js",
        "lodash/defaults.js": "./path/lodash-es.min.js",
        "lodash/defaultsDeep.js": "./path/lodash-es.min.js",
        "lodash/defer.js": "./path/lodash-es.min.js",
        "lodash/delay.js": "./path/lodash-es.min.js",
        "lodash/difference.js": "./path/lodash-es.min.js",
        "lodash/differenceBy.js": "./path/lodash-es.min.js",
        "lodash/differenceWith.js": "./path/lodash-es.min.js",
        "lodash/divide.js": "./path/lodash-es.min.js",
        "lodash/drop.js": "./path/lodash-es.min.js",
        "lodash/dropRight.js": "./path/lodash-es.min.js",
        "lodash/dropRightWhile.js": "./path/lodash-es.min.js",
        "lodash/dropWhile.js": "./path/lodash-es.min.js",
        "lodash/each.js": "./path/lodash-es.min.js",
        "lodash/eachRight.js": "./path/lodash-es.min.js",
        "lodash/endsWith.js": "./path/lodash-es.min.js",
        "lodash/eq.js": "./path/lodash-es.min.js",
        "lodash/eqDeep.js": "./path/lodash-es.min.js",
        "lodash/escape.js": "./path/lodash-es.min.js",
        "lodash/escapeRegExp.js": "./path/lodash-es.min.js",
        "lodash/every.js": "./path/lodash-es.min.js",
        "lodash/everyValue.js": "./path/lodash-es.min.js",
        "lodash/filter.js": "./path/lodash-es.min.js",
        "lodash/filterObject.js": "./path/lodash-es.min.js",
        "lodash/findKey.js": "./path/lodash-es.min.js",
        "lodash/findLast.js": "./path/lodash-es.min.js",
        "lodash/findLastIndex.js": "./path/lodash-es.min.js",
        "lodash/findLastKey.js": "./path/lodash-es.min.js",
        "lodash/first.js": "./path/lodash-es.min.js",
        "lodash/flatMap.js": "./path/lodash-es.min.js",
        "lodash/flatMapDeep.js": "./path/lodash-es.min.js",
        "lodash/flatMapDepth.js": "./path/lodash-es.min.js",
        "lodash/flatten.js": "./path/lodash-es.min.js",
        "lodash/flattenDeep.js": "./path/lodash-es.min.js",
        "lodash/flattenDepth.js": "./path/lodash-es.min.js",
        "lodash/flip.js": "./path/lodash-es.min.js",
        "lodash/floor.js": "./path/lodash-es.min.js",
        "lodash/flow.js": "./path/lodash-es.min.js",
        "lodash/flowRight.js": "./path/lodash-es.min.js",
        "lodash/forEach.js": "./path/lodash-es.min.js",
        "lodash/forEachRight.js": "./path/lodash-es.min.js",
        "lodash/forOwn.js": "./path/lodash-es.min.js",
        "lodash/forOwnRight.js": "./path/lodash-es.min.js",
        "lodash/fromEntries.js": "./path/lodash-es.min.js",
        "lodash/functions.js": "./path/lodash-es.min.js",
        "lodash/get.js": "./path/lodash-es.min.js",
        "lodash/groupBy.js": "./path/lodash-es.min.js",
        "lodash/gt.js": "./path/lodash-es.min.js",
        "lodash/gte.js": "./path/lodash-es.min.js",
        "lodash/has.js": "./path/lodash-es.min.js",
        "lodash/hasIn.js": "./path/lodash-es.min.js",
        "lodash/hasPath.js": "./path/lodash-es.min.js",
        "lodash/hasPathIn.js": "./path/lodash-es.min.js",
        "lodash/head.js": "./path/lodash-es.min.js",
        "lodash/inRange.js": "./path/lodash-es.min.js",
        "lodash/indexOf.js": "./path/lodash-es.min.js",
        "lodash/initial.js": "./path/lodash-es.min.js",
        "lodash/intersection.js": "./path/lodash-es.min.js",
        "lodash/intersectionBy.js": "./path/lodash-es.min.js",
        "lodash/intersectionWith.js": "./path/lodash-es.min.js",
        "lodash/invert.js": "./path/lodash-es.min.js",
        "lodash/invertBy.js": "./path/lodash-es.min.js",
        "lodash/invoke.js": "./path/lodash-es.min.js",
        "lodash/invokeMap.js": "./path/lodash-es.min.js",
        "lodash/isArguments.js": "./path/lodash-es.min.js",
        "lodash/isArrayBuffer.js": "./path/lodash-es.min.js",
        "lodash/isArrayLike.js": "./path/lodash-es.min.js",
        "lodash/isArrayLikeObject.js": "./path/lodash-es.min.js",
        "lodash/isBoolean.js": "./path/lodash-es.min.js",
        "lodash/isBuffer.js": "./path/lodash-es.min.js",
        "lodash/isDate.js": "./path/lodash-es.min.js",
        "lodash/isElement.js": "./path/lodash-es.min.js",
        "lodash/isEmpty.js": "./path/lodash-es.min.js",
        "lodash/isEqualWith.js": "./path/lodash-es.min.js",
        "lodash/isError.js": "./path/lodash-es.min.js",
        "lodash/isFunction.js": "./path/lodash-es.min.js",
        "lodash/isLength.js": "./path/lodash-es.min.js",
        "lodash/isMap.js": "./path/lodash-es.min.js",
        "lodash/isMatch.js": "./path/lodash-es.min.js",
        "lodash/isMatchWith.js": "./path/lodash-es.min.js",
        "lodash/isNative.js": "./path/lodash-es.min.js",
        "lodash/isNil.js": "./path/lodash-es.min.js",
        "lodash/isNull.js": "./path/lodash-es.min.js",
        "lodash/isNumber.js": "./path/lodash-es.min.js",
        "lodash/isObject.js": "./path/lodash-es.min.js",
        "lodash/isObjectLike.js": "./path/lodash-es.min.js",
        "lodash/isPlainObject.js": "./path/lodash-es.min.js",
        "lodash/isRegExp.js": "./path/lodash-es.min.js",
        "lodash/isSet.js": "./path/lodash-es.min.js",
        "lodash/isString.js": "./path/lodash-es.min.js",
        "lodash/isSymbol.js": "./path/lodash-es.min.js",
        "lodash/isTypedArray.js": "./path/lodash-es.min.js",
        "lodash/isUndefined.js": "./path/lodash-es.min.js",
        "lodash/isWeakMap.js": "./path/lodash-es.min.js",
        "lodash/isWeakSet.js": "./path/lodash-es.min.js",
        "lodash/kebabCase.js": "./path/lodash-es.min.js",
        "lodash/keyBy.js": "./path/lodash-es.min.js",
        "lodash/keys.js": "./path/lodash-es.min.js",
        "lodash/keysIn.js": "./path/lodash-es.min.js",
        "lodash/last.js": "./path/lodash-es.min.js",
        "lodash/lastIndexOf.js": "./path/lodash-es.min.js",
        "lodash/lowerCase.js": "./path/lodash-es.min.js",
        "lodash/lowerFirst.js": "./path/lodash-es.min.js",
        "lodash/lt.js": "./path/lodash-es.min.js",
        "lodash/lte.js": "./path/lodash-es.min.js",
        "lodash/map.js": "./path/lodash-es.min.js",
        "lodash/mapKey.js": "./path/lodash-es.min.js",
        "lodash/mapObject.js": "./path/lodash-es.min.js",
        "lodash/mapValue.js": "./path/lodash-es.min.js",
        "lodash/matches.js": "./path/lodash-es.min.js",
        "lodash/matchesProperty.js": "./path/lodash-es.min.js",
        "lodash/maxBy.js": "./path/lodash-es.min.js",
        "lodash/mean.js": "./path/lodash-es.min.js",
        "lodash/meanBy.js": "./path/lodash-es.min.js",
        "lodash/memoize.js": "./path/lodash-es.min.js",
        "lodash/merge.js": "./path/lodash-es.min.js",
        "lodash/mergeWith.js": "./path/lodash-es.min.js",
        "lodash/method.js": "./path/lodash-es.min.js",
        "lodash/methodOf.js": "./path/lodash-es.min.js",
        "lodash/minBy.js": "./path/lodash-es.min.js",
        "lodash/multiply.js": "./path/lodash-es.min.js",
        "lodash/negate.js": "./path/lodash-es.min.js",
        "lodash/nth.js": "./path/lodash-es.min.js",
        "lodash/nthArg.js": "./path/lodash-es.min.js",
        "lodash/once.js": "./path/lodash-es.min.js",
        "lodash/orderBy.js": "./path/lodash-es.min.js",
        "lodash/over.js": "./path/lodash-es.min.js",
        "lodash/overArgs.js": "./path/lodash-es.min.js",
        "lodash/overEvery.js": "./path/lodash-es.min.js",
        "lodash/overSome.js": "./path/lodash-es.min.js",
        "lodash/package.js": "./path/lodash-es.min.js",
        "lodash/package.js": "./path/lodash-es.min.js",
        "lodash/pad.js": "./path/lodash-es.min.js",
        "lodash/padEnd.js": "./path/lodash-es.min.js",
        "lodash/padStart.js": "./path/lodash-es.min.js",
        "lodash/parseInt.js": "./path/lodash-es.min.js",
        "lodash/partition.js": "./path/lodash-es.min.js",
        "lodash/pick.js": "./path/lodash-es.min.js",
        "lodash/pickBy.js": "./path/lodash-es.min.js",
        "lodash/property.js": "./path/lodash-es.min.js",
        "lodash/propertyOf.js": "./path/lodash-es.min.js",
        "lodash/pull.js": "./path/lodash-es.min.js",
        "lodash/pullAll.js": "./path/lodash-es.min.js",
        "lodash/pullAllBy.js": "./path/lodash-es.min.js",
        "lodash/pullAllWith.js": "./path/lodash-es.min.js",
        "lodash/pullAt.js": "./path/lodash-es.min.js",
        "lodash/random.js": "./path/lodash-es.min.js",
        "lodash/range.js": "./path/lodash-es.min.js",
        "lodash/rangeRight.js": "./path/lodash-es.min.js",
        "lodash/reduce.js": "./path/lodash-es.min.js",
        "lodash/reduceRight.js": "./path/lodash-es.min.js",
        "lodash/reject.js": "./path/lodash-es.min.js",
        "lodash/remove.js": "./path/lodash-es.min.js",
        "lodash/repeat.js": "./path/lodash-es.min.js",
        "lodash/replace.js": "./path/lodash-es.min.js",
        "lodash/result.js": "./path/lodash-es.min.js",
        "lodash/round.js": "./path/lodash-es.min.js",
        "lodash/sample.js": "./path/lodash-es.min.js",
        "lodash/sampleSize.js": "./path/lodash-es.min.js",
        "lodash/set.js": "./path/lodash-es.min.js",
        "lodash/setWith.js": "./path/lodash-es.min.js",
        "lodash/shuffle.js": "./path/lodash-es.min.js",
        "lodash/size.js": "./path/lodash-es.min.js",
        "lodash/slice.js": "./path/lodash-es.min.js",
        "lodash/snakeCase.js": "./path/lodash-es.min.js",
        "lodash/some.js": "./path/lodash-es.min.js",
        "lodash/someValue.js": "./path/lodash-es.min.js",
        "lodash/sortedIndex.js": "./path/lodash-es.min.js",
        "lodash/sortedIndexBy.js": "./path/lodash-es.min.js",
        "lodash/sortedIndexOf.js": "./path/lodash-es.min.js",
        "lodash/sortedLastIndex.js": "./path/lodash-es.min.js",
        "lodash/sortedLastIndexBy.js": "./path/lodash-es.min.js",
        "lodash/sortedLastIndexOf.js": "./path/lodash-es.min.js",
        "lodash/sortedUniq.js": "./path/lodash-es.min.js",
        "lodash/sortedUniqBy.js": "./path/lodash-es.min.js",
        "lodash/split.js": "./path/lodash-es.min.js",
        "lodash/startCase.js": "./path/lodash-es.min.js",
        "lodash/startsWith.js": "./path/lodash-es.min.js",
        "lodash/subtract.js": "./path/lodash-es.min.js",
        "lodash/sum.js": "./path/lodash-es.min.js",
        "lodash/sumBy.js": "./path/lodash-es.min.js",
        "lodash/tail.js": "./path/lodash-es.min.js",
        "lodash/take.js": "./path/lodash-es.min.js",
        "lodash/takeRight.js": "./path/lodash-es.min.js",
        "lodash/takeRightWhile.js": "./path/lodash-es.min.js",
        "lodash/takeWhile.js": "./path/lodash-es.min.js",
        "lodash/throttle.js": "./path/lodash-es.min.js",
        "lodash/times.js": "./path/lodash-es.min.js",
        "lodash/toArray.js": "./path/lodash-es.min.js",
        "lodash/toFinite.js": "./path/lodash-es.min.js",
        "lodash/toInteger.js": "./path/lodash-es.min.js",
        "lodash/toLength.js": "./path/lodash-es.min.js",
        "lodash/toNumber.js": "./path/lodash-es.min.js",
        "lodash/toPath.js": "./path/lodash-es.min.js",
        "lodash/toPlainObject.js": "./path/lodash-es.min.js",
        "lodash/toSafeInteger.js": "./path/lodash-es.min.js",
        "lodash/toString.js": "./path/lodash-es.min.js",
        "lodash/transform.js": "./path/lodash-es.min.js",
        "lodash/trim.js": "./path/lodash-es.min.js",
        "lodash/trimEnd.js": "./path/lodash-es.min.js",
        "lodash/trimStart.js": "./path/lodash-es.min.js",
        "lodash/truncate.js": "./path/lodash-es.min.js",
        "lodash/unescape.js": "./path/lodash-es.min.js",
        "lodash/union.js": "./path/lodash-es.min.js",
        "lodash/unionBy.js": "./path/lodash-es.min.js",
        "lodash/unionWith.js": "./path/lodash-es.min.js",
        "lodash/uniq.js": "./path/lodash-es.min.js",
        "lodash/uniqBy.js": "./path/lodash-es.min.js",
        "lodash/uniqWith.js": "./path/lodash-es.min.js",
        "lodash/uniqueId.js": "./path/lodash-es.min.js",
        "lodash/unset.js": "./path/lodash-es.min.js",
        "lodash/unzip.js": "./path/lodash-es.min.js",
        "lodash/unzipWith.js": "./path/lodash-es.min.js",
        "lodash/update.js": "./path/lodash-es.min.js",
        "lodash/updateWith.js": "./path/lodash-es.min.js",
        "lodash/upperCase.js": "./path/lodash-es.min.js",
        "lodash/upperFirst.js": "./path/lodash-es.min.js",
        "lodash/values.js": "./path/lodash-es.min.js",
        "lodash/without.js": "./path/lodash-es.min.js",
        "lodash/words.js": "./path/lodash-es.min.js",
        "lodash/xor.js": "./path/lodash-es.min.js",
        "lodash/xorBy.js": "./path/lodash-es.min.js",
        "lodash/xorWith.js": "./path/lodash-es.min.js",
        "lodash/zip.js": "./path/lodash-es.min.js",
        "lodash/zipObject.js": "./path/lodash-es.min.js",
        "lodash/zipObjectDeep.js": "./path/lodash-es.min.js",
        "lodash/zipWith.js": "./path/lodash-es.min.js",
  }
}

The alternative I'm looking for to accomplish this behavior with only one line, is:

{
  "imports": {
    "lodash/": "./path/lodash-es.min.js"
  }
}

Closing due to lack of follow-up, but happy to continue discussing, and reopen if there's something here.

I'm sorry for my slow reply. Please reopen as well, thank you!

domenic commented 5 years ago

Ah, well, no, that's not a supported use case. Remapping multiple specifiers to a single file is not useful; just remap them to a single specifier.

Note that with the current version of lodash your massive import map wouldn't work because the exports of lodash-es.min.js and lodash/zipObject.js are different.

justinfagnani commented 5 years ago

@alber70g I think you'd really want to import individual modules, with:

{
  "imports": {
    "lodash/": "/node_modules/lodash-es/"
  }
}

rather than a pre-build bundle, then when the application is bundled it can include only the modules that are actually referenced in the module graph, rather than the whole lodash bundle.

alber70g commented 5 years ago

Ah, well, no, that's not a supported use case

Yes that's why I put it here ;)

Note that with the current version of lodash your massive import map wouldn't work because the exports of lodash-es.min.js and lodash/zipObject.js are different

Yes, this is more of an example. I'd build something else which has it bundled like that.

rather than a pre-build bundle

I do want a pre-build bundle for several reasons. The bundle in my case would be rebuild every time there's a new version. This way we can't leverage the cache for individual files. Also, files that aren't bundled are less optimal gzipped.