How should we handle import.meta

Hey, @sokra @ooflorent, @Kovensky @ljharb:

It looks like import.meta has landed in Stage 3 and Babel has just landed it also. It looks like there is already an acorn plugin that allows for the syntax support.

First piece is: Should we add this or wait?

Second piece is: Are there webpack specific things we should consider for this syntax. I feel like platforms (Electron, etc.) are going to start shoving a bunch of crap (which use to be globals) in these objects that we would automatically use to treat as Externals. Is there specific handlings that we need to be concerned here.

Author: Fantashit

10 thoughts on “How should we handle import.meta

  1. I actually don’t think import.meta will be that abused; at least I hope not.

    It is mostly useful for things that are actually not global but still need to exist in every module anyway; for example their own filename, or even the require function as it needs to be bound to the module’s dirname.

    In webpack’s use case, it’d be useful to put import.meta.hot in it. AFAIK it’s our only extension to the module object, which we could then remove from scope entirely. We could also put import.meta.moduleId there if that would be useful.

    __dirname and __filename will not be available, instead there will be a per-module import.meta.url.

    The problem is how to deal with them — they have to be absolute URLs that are parseable by using the WHATWG URL constructor (new URL(import.meta.url) will throw if it’s not absolute, with protocol scheme and all).

    This could mean that, if import.meta.url is used by a bundled module, that we would be forced to always enable the NamedModulesPlugin, or maybe something even more drastic such as supporting import()s using a pseudo webpack: protocol.

    We don’t necessarily have to put url there, though; it’s not part of the JS spec. We could just say it’s something that’s only available when the file is not bundled, and instead use some other key if modules really need to know their dirname.

  2. Hi, if you want to use acorn-import-meta, you can choose under which license you want to use it. It is released under AGPLv3 and Apache2, so you can choose the one or the other 🙂

  3. @Kovensky Is there any progress on this? As of now, Webpack is still failing to parse import.meta:

    Module parse failed: Unexpected token (145:21)
    You may need an appropriate loader to handle this file type.
    |       key: "importMeta",
    |       get: function get() {
    >         return import.meta;
    |       }
    |     }, {
    

    This makes import.meta totally unusable and it seems rather strange for the spec draft moved to Stage 3 already last September. Apparently not much people tried to use it so far, but it is important at least for Polymer developers, as Polymer 3 actively promotes this feature.

  4. @web-padawan Only stage 4 features are currently supported (except dynamic imports). We are waiting for import.meta to stabilize in node and in browsers before implementing it.

  5. Webpack does not generate ES6 modules, Webpack generates raw ES5 code.

    We are working on it 😄 Hope it will be in near future

  6. We recently added this syntax: new URL("bundle/x.js", import.meta.url) to reference assets. x.js will be copied into the output directory and webpack will generate code that will create an valid URL to that asset at runtime (using public path and the base URL).
    Maybe this is something useful for your case.

    Using import.meta.url on its own isn’t that useful as it’s unclear what the meaning should be: URL of the bundle or URL of the module. Since the individual modules doesn’t exist anymore at runtime and there are usually multiple bundles we decided to go with the module URL.

  7. @sokra
    Using import.meta.url on its own isn’t that useful as it’s unclear what the meaning should be: URL of the bundle or URL of the module.

    There’s nothing unclear there. Read the spec. It’s supposed to be the runtime base URL from which the module was obtained, i.e. loaded, for external script files; or the document’s URL for modules defined inline in an HTML page.

    https://html.spec.whatwg.org/multipage/webappapis.html#hostgetimportmetaproperties
    https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url

    Anything else is wrong.

    As I mentioned further back in this issue thread, the correct solution would’ve been to put Webpack-specific properties onto import.meta (which the spec allows !!) and then offer an import.meta.urlthat uses a hash fragment to separate the bundle URL and the module identifier, the last part retreading the path of how fragments work for e.g. pointing to subparts of SVG files.

    import.meta.url // -> "my/bundle/url.js#relative/path/to/file.js"
    import.meta.webpack.bundle // -> "my/bundle/url.js"
    import.meta.webpack.resource // -> "relative/path/to/file.js"

    This is completely in keeping with the spec and still has all necessary information to support every use-case, whether that is based on bundle URL or compile-time module path.

  8. import.meta.webpack

    Where is it in the specification? 😄

    @rjgotten What is the your problem, please stop arguing and show your problem

    Incorrect. The spec literally states that import.meta.url is the module script’s base URL and clearly defines the base URL as “the URL from which the script was obtained.” That means if you have a transcoded representation of a module woven into a bundle, then the bundle URL is where the script was obtained…

    Do you understand what it is bunder? Where should we store this? How? In runtime? Do you want a huge overhead? And why?

    That difference is already there considering @kaleidawave showing that Webpack emits a file:// protocol url for import.meta.url which makes even less sense. Might as well emit the custom webpack:// protocol used for source maps at that point, which at least offers some modicum of ‘closed environment’ internal consistency.

    What?

  9. The spec says

    the URL from which the script was obtained

    And thats exactly what we return. The module was obtained from the filesystem. That’s where it’s located.

    The bundle is a kind of transport format.

    Webpack also supports import("file://..."), so this is consistent with import.meta.url, e.g. you can do import(import.meta.url + "/../other.js") (please don’t do that).

    It also makes sense for console.error("error in " + import.meta.url). For other scenarios it doesn’t make sense. I don’t think there is a solution that makes everybody happy. We had similar discussions with __filename.

    Webpack tries it’s best to map urls to there public counterpart if some exist. E.g. assets have a public URL and we use it. JS modules are bundled so they don’t have a public counterpart.

Comments are closed.