Evaluate AMD replacement of F2's internal loader #129

Open
markhealey opened this Issue Sep 4, 2013 · 8 comments

Comments

Projects
None yet
3 participants
@markhealey
Member

markhealey commented Sep 4, 2013

Based on the discussion in #125 let's use this Issue as a place to discuss requirements for replacing F2's internal loader with an AMD solution (such as requirejs). The discussion should also cover dependency management at a high level. (I realize there is overlap between AMD and "dependency management".)

Note: the internal loader was recently upgraded, see #120.

The floor is open...

@ilinkuo

This comment has been minimized.

Show comment
Hide comment
@ilinkuo

ilinkuo Sep 4, 2013

Please look at e2dfa28#commitcomment-4013708 as a safer approach than an in-place rewrite of the F2 loader engine.

ilinkuo commented Sep 4, 2013

Please look at e2dfa28#commitcomment-4013708 as a safer approach than an in-place rewrite of the F2 loader engine.

@brianbaker

This comment has been minimized.

Show comment
Hide comment
@brianbaker

brianbaker Sep 4, 2013

Member

Few questions for discussion:

  • What would replacing the internals of F2 with AMD require of containers?
    • Is it up to a container to provide require via RequireJS, Dojo, etc. or does is it bundled with F2?
  • Does this type of update force all containers to adopt AMD?
  • Would it be necessary to have separate builds of F2 for AMD and non-AMD sites?
Member

brianbaker commented Sep 4, 2013

Few questions for discussion:

  • What would replacing the internals of F2 with AMD require of containers?
    • Is it up to a container to provide require via RequireJS, Dojo, etc. or does is it bundled with F2?
  • Does this type of update force all containers to adopt AMD?
  • Would it be necessary to have separate builds of F2 for AMD and non-AMD sites?
@ilinkuo

This comment has been minimized.

Show comment
Hide comment
@ilinkuo

ilinkuo Sep 5, 2013

From @montlebalm 's comment in #125 (comment)

To do a proper port of F2, every AppClass needs to be wrapped in a define() block with dependencies that are also wrapped in define(). These dependencies will need to be referenced by path, which likely can't be hard-coded because of your build system (i.e., for cache busting). Dependencies need to be named explicitly by version, because apps may depend on different 3rd party libraries. If path aliases are defined, containers and app developers need to agree on a naming convention or else every app needs to return every lib it needs, thereby inflating the size of every app request.

I'd like to add and clarify:

  • Apps, Container, F2 core, F2 App manifest, F2 plugins should all have versions. Currently, AFAIK, only F2 core has version numbers.
  • Apps, Container, and F2 should have manifests? Currently, only the App has a plugin. The Container manifest should contain the list of Container plugins and versions, and maybe the services it provides (perhaps in the form of the keys of the RequireJS alias/paths in the RequireJS config). F2 manifest should contain list of F2 plugins and versions. Maybe a list of plugins isn't necessary if has() functionality is built into the framework.

ilinkuo commented Sep 5, 2013

From @montlebalm 's comment in #125 (comment)

To do a proper port of F2, every AppClass needs to be wrapped in a define() block with dependencies that are also wrapped in define(). These dependencies will need to be referenced by path, which likely can't be hard-coded because of your build system (i.e., for cache busting). Dependencies need to be named explicitly by version, because apps may depend on different 3rd party libraries. If path aliases are defined, containers and app developers need to agree on a naming convention or else every app needs to return every lib it needs, thereby inflating the size of every app request.

I'd like to add and clarify:

  • Apps, Container, F2 core, F2 App manifest, F2 plugins should all have versions. Currently, AFAIK, only F2 core has version numbers.
  • Apps, Container, and F2 should have manifests? Currently, only the App has a plugin. The Container manifest should contain the list of Container plugins and versions, and maybe the services it provides (perhaps in the form of the keys of the RequireJS alias/paths in the RequireJS config). F2 manifest should contain list of F2 plugins and versions. Maybe a list of plugins isn't necessary if has() functionality is built into the framework.
@ilinkuo

This comment has been minimized.

Show comment
Hide comment
@ilinkuo

ilinkuo Sep 5, 2013

@brianbaker I'll take a shot, but the answer depends on which strategy below is chosen

First, I think three strategies are possible:

  1. Rewrite the internals of the F2 engine to use AMD, keeping the existing API
  2. Switch F2 over completely to AMD
  3. Keep both legacy API and new AMD API, both using the same underlying AMD engine.

Option 1 is the cheapest and most backwards compatible. The AMD engine can load both define()- wrapped and unwrapped scripts, though you might need some small adjustments to the unwrapped scripts because the execution order of unwrapped scripts is not well-defined. There might also have to be some cross-domain loading tweaks. You'll get ~50% of the AMD benefits -- cached resources, elimination of duplicate resource loading, but no r.js optimization.

Option 2 requires Containers, Apps, and F2 itself to make big changes, but it also has the biggest benefits.

Option 3 is a blend of the options 1 and 2. It makes switching to AMD optional for users and has roughly the same development cost as Option 2, but the long term maintenance costs to F2 are quite high (consider that most estimate maintenance costs to be 3-4x development costs).

ilinkuo commented Sep 5, 2013

@brianbaker I'll take a shot, but the answer depends on which strategy below is chosen

First, I think three strategies are possible:

  1. Rewrite the internals of the F2 engine to use AMD, keeping the existing API
  2. Switch F2 over completely to AMD
  3. Keep both legacy API and new AMD API, both using the same underlying AMD engine.

Option 1 is the cheapest and most backwards compatible. The AMD engine can load both define()- wrapped and unwrapped scripts, though you might need some small adjustments to the unwrapped scripts because the execution order of unwrapped scripts is not well-defined. There might also have to be some cross-domain loading tweaks. You'll get ~50% of the AMD benefits -- cached resources, elimination of duplicate resource loading, but no r.js optimization.

Option 2 requires Containers, Apps, and F2 itself to make big changes, but it also has the biggest benefits.

Option 3 is a blend of the options 1 and 2. It makes switching to AMD optional for users and has roughly the same development cost as Option 2, but the long term maintenance costs to F2 are quite high (consider that most estimate maintenance costs to be 3-4x development costs).

@ilinkuo

This comment has been minimized.

Show comment
Hide comment
@ilinkuo

ilinkuo Sep 5, 2013

My thoughts on @brianbaker's discussion questions

What would replacing the internals of F2 with AMD require of containers?

If done via Option 1, probably nothing would be required of Containers. It may or may not be necessary to label an appManifest or appConfig as being AMD-friendly.

If done via Option 2, then the Container itself should be an AMD module, though it is possible to call AMD code from non-AMD code, but you'll need to combine that with Promises.

Is it up to a container to provide require via RequireJS, Dojo, etc. or does is it bundled with F2?

The point of the AMD specification is to allow different AMD implementation to be interchangeable, so I would vote for unbundling.

require() and define(), ironically, are globals.

Does this type of update force all containers to adopt AMD?

Depends on which option is chosen, see #129 (comment)

Would it be necessary to have separate builds of F2 for AMD and non-AMD sites?

That depends on how much you care about JS minification -- you only need separate builds if there is a significant difference in the size of the library. Without AMD, there have to be separate grunt tasks for each configuration. With AMD correctly structured, r.js will build only the modules you actually use, without any work/decisions from the user.

ilinkuo commented Sep 5, 2013

My thoughts on @brianbaker's discussion questions

What would replacing the internals of F2 with AMD require of containers?

If done via Option 1, probably nothing would be required of Containers. It may or may not be necessary to label an appManifest or appConfig as being AMD-friendly.

If done via Option 2, then the Container itself should be an AMD module, though it is possible to call AMD code from non-AMD code, but you'll need to combine that with Promises.

Is it up to a container to provide require via RequireJS, Dojo, etc. or does is it bundled with F2?

The point of the AMD specification is to allow different AMD implementation to be interchangeable, so I would vote for unbundling.

require() and define(), ironically, are globals.

Does this type of update force all containers to adopt AMD?

Depends on which option is chosen, see #129 (comment)

Would it be necessary to have separate builds of F2 for AMD and non-AMD sites?

That depends on how much you care about JS minification -- you only need separate builds if there is a significant difference in the size of the library. Without AMD, there have to be separate grunt tasks for each configuration. With AMD correctly structured, r.js will build only the modules you actually use, without any work/decisions from the user.

@ilinkuo

This comment has been minimized.

Show comment
Hide comment

ilinkuo commented Sep 9, 2013

FYI, jQuery just finally switched their internals over to AMD

@markhealey

This comment has been minimized.

Show comment
Hide comment
@markhealey

markhealey Oct 2, 2013

Member

Just to keep a heartbeat going and to inform watchers, we have been meeting internally to get a more formal proposal—which we'll post here—drafted on updating F2's internals to use AMD. We're striving to keep the current API the same as it is today but it's looking like we'll have some minor changes. More soon, stay tuned.

Member

markhealey commented Oct 2, 2013

Just to keep a heartbeat going and to inform watchers, we have been meeting internally to get a more formal proposal—which we'll post here—drafted on updating F2's internals to use AMD. We're striving to keep the current API the same as it is today but it's looking like we'll have some minor changes. More soon, stay tuned.

@ilinkuo

This comment has been minimized.

Show comment
Hide comment
@ilinkuo

ilinkuo Oct 17, 2013

If the API changes become major enough to also change the manifest, do please consider revising to extend package.json instead of extending the current F2 manifest format.

ilinkuo commented Oct 17, 2013

If the API changes become major enough to also change the manifest, do please consider revising to extend package.json instead of extending the current F2 manifest format.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment