Skip to content
This repository has been archived by the owner on Jul 13, 2020. It is now read-only.

Added ability to name anonymous modules #343

Merged
merged 1 commit into from Apr 2, 2015
Merged

Added ability to name anonymous modules #343

merged 1 commit into from Apr 2, 2015

Conversation

ghost
Copy link

@ghost ghost commented Apr 2, 2015

When using <script type="module"> it would be nice to give it a name using something like <script type="module" name="init-page"> so that it shows up as something other than <Anonymous Module 1> in dev tools sources panel. Plus it would make dynamic scripts specific to the page easily importable and reusable.

@guybedford
Copy link
Member

Thanks! This is on the right track, but unfortunately not the exact spec behaviour. As such we can't take this.

The spec behaviour will be <script type="module" src="module.js">. We can only implement this when we've updated to the new URL-based module system.

I'm making it my top priority to do this transition at the moment.

@guybedford
Copy link
Member

If there aren't other options for your use case, we could take this though assuming its going to be a breaking API change. I'd rather keep it undocumented as well.

What do you mean it would make dynamic scripts specific to the page easily importable and reusable?

@ghost
Copy link
Author

ghost commented Apr 2, 2015

How would <script type="module" src="module.js"> work exactly?

I'm assuming that if we have something like:

<script type="module" src="init-page.js">
export var foo = 'bar specific to page';
</script>

We could do this elsewhere?

import initPage from 'init-page';
console.log(initPage.foo);

And of course:

System.import('init-page').then(function (initPage) {
    console.log(initPage.foo);
});

@ghost
Copy link
Author

ghost commented Apr 2, 2015

In my case, I'm wanting the above functionality but assumed the name attribute makes more sense than src since it's an inline script.

@ghost
Copy link
Author

ghost commented Apr 2, 2015

Also, the script would show up in the dev tools sources panel as init-page instead of <Anonymous Module 1>.

@guybedford
Copy link
Member

The module system was changed a few months back to use URLs instead of special names. This was done to align with the rest of URLs instead of inventing all normalization operations.

There's still the ability to perform pre-normalization steps like mapping init-page into init-page.js before hitting normal URL normalization, but the js extension adding is being removed and the module table will store everything keyed entirely by URLs.

Do you not have production issues with using inline modules?

@ghost
Copy link
Author

ghost commented Apr 2, 2015

I might be doing something fundamentally wrong here, but suppose I have some pretty dynamic pages that initialize differently depending on the user, and I want to include these initialization parameters and methods immediately as inline script(s) rather than adding an unnecessary request.

In the following (relatively simple) example, this HTML might be generated based on something the user created. SomethingDynamic would be whatever the user had associated with that particular page.

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv='Content-type' content='text/html; charset=utf-8'>
    <title>Example</title>
  </head>
  <body>

    <div id="container"></div>

    <script src="/js/system/system.js"></script>
    <script src="/js/system/config.js"></script>

    <script type="module" name="main">

        import React from 'react';
        import 'components/SomethingDynamic.css!css';
        import App from 'components/SomethingDynamic.jsx!jsx';

        var UserProps = {some: "json blob", generated: "by server"};

        React.render(
            React.createElement(App),
            document.getElementById('container')
        );

        export { App, UserProps };

    </script>

  </body>
</html>

And then suppose we had some other static module that could take a look at what exactly was created for the page via main:
SomeStaticModule.js:

import main from 'main';
console.log(main.App);
console.log(main.UserProps);

@guybedford
Copy link
Member

Unfortunately loading an ES6 transpiler in production is worse than an extra request here.

The options are:

  • Have some kind of HTML build process automatically compile this inline ES6 into the System.register format
  • Just reference a single main entry point
  • Just write in AMD or CommonJS for this inline code

For production optimization you need to bundle though anyway, so I'm not sure that that extra request costs you anything at all.

I'd strongly suggest the single main entry point bootstrapper approach.

@ghost
Copy link
Author

ghost commented Apr 2, 2015

This page is actually generated in a development environment which is why I find it acceptable (and necessary). The production flow will definitely be different, minimal everything.

@ghost
Copy link
Author

ghost commented Apr 2, 2015

I'll elaborate a little more. The idea here is that developers can collaboratively build apps in real-time, which is where this development page and all my other recent issues are coming from. :)

@probins
Copy link
Contributor

probins commented Apr 2, 2015

don't forget that the script type="module" thing is just temporary until <module> is implemented. But AFAIK no-one has even started on a spec for <module>. <script>, like other tags, has id, and probably <module> will too, but I don't think we can rely on that at the moment. There's no point including something in the polyfill that won't be available in browsers' implementations, and the way to do that is to adhere to the spec. If you want this implemented, ISTM this is something to discuss at the spec level.

@guybedford
Copy link
Member

This is conceptually happening at the spec level, and is consistent with our current spec model, so I'm happy to take it for now.

guybedford added a commit that referenced this pull request Apr 2, 2015
Added ability to name anonymous modules
@guybedford guybedford merged commit 7ca571c into ModuleLoader:master Apr 2, 2015
@ghost
Copy link
Author

ghost commented Apr 2, 2015

Sweet!

@probins What's the best place to discuss the spec for this?

@guybedford
Copy link
Member

Note the spec we're matching here is what was described in jorendorff/js-loaders#83 (comment). So we are being consistent with the previous intentions.

There are NO guarantees though that this same behaviour will still even be possible in the updated spec though, so note that this is still at your own risk. If you want more certainty, I'd advise posting an issue at https://github.com/whatwg/loader as @probins mentions.

@ghost
Copy link
Author

ghost commented Apr 2, 2015

Understandable. To me, the concept makes sense, plus the usage of a name attribute matches the current convention (at least within this code-base) where name is used internally to describe loaded modules. Hopefully it sticks!

@ghost ghost mentioned this pull request Apr 2, 2015
@matthewp
Copy link
Contributor

matthewp commented Apr 2, 2015

@probins There is a module tag spec, though not active at the moment: https://github.com/dherman/module-tag

@probins
Copy link
Contributor

probins commented Apr 2, 2015

yeah, thanks. I was actually aware of that (even have it in my bookmarks), but had forgotten :-)

@guybedford
Copy link
Member

@timbur my apologies, but after the discussion on the loader project I've decided to remove this.

Since it is now clear that this is not a feature that will be available, offering it now makes no sense.

@ghost
Copy link
Author

ghost commented Apr 3, 2015

What makes no sense is excluding the feature. It's a one-liner that makes things flexible and hurts absolutely nothing. It will be ridiculous to have to include something resembling the following hack on every page where I want a common reference to a dynamic module imported during initialization:

var modules = document.getElementsByTagName('module');

for (var i = 0; i < modules.length; i++) {

    var module = modules[i];

    if (module.hasAttribute('name')) {
        var name = module.getAttribute('name');
        var source = module.innerHTML.substr(1);
        System.define(name, source);
    }

}

I'll wait patiently for someone to explain an alternative, equally elegant solution to the scenario I outlined here: whatwg/loader#42 (comment)

@probins
Copy link
Contributor

probins commented Apr 3, 2015

if it's not in the spec, it probably won't be in browser implementations either, so you would have to come up with such a solution whenever that happens. Having it in the polyfill doesn't help you

@ghost
Copy link
Author

ghost commented Apr 3, 2015

That's why I'm trying to get it in the spec. :)

Check this nice little perk with named inline modules within dev tools (couple of screen caps to compare): whatwg/loader#42 (comment)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants