export values are dynamic today! you can do: let lib = null; export default lib; loadScript("foo").then(o => lib = o);
but what cannot be dynamic, is the set of export names, which shapes the module. /caridy > On Aug 20, 2017, at 8:57 AM, kai zhu <kaizhu...@gmail.com> wrote: > > for the forseeable future, the only practical solution i see to these > frontend performance issues is to avoid using es modules, and revert > to the simple, old-fashioned method of assigning libraries to the > window namespace. > >> On 8/20/17, James Browning <thejameserna...@gmail.com> wrote: >> These are just some ideas I've had for improving es modules based on >> my experiences with them. The syntax and stuff with them isn't too >> important, the main point is the problem I'm trying to solve with each >> of them, feedback and criticism is welcome. >> >> # Dynamic modules >> >> One of the biggest issues I've had with ES modules is not being able >> to load classic scripts as part of the dependency graph, one of the >> solutions I've used but am not particularly happy with is having an >> async loader function e.g.: >> >> ```js >> function loadScript(url) { >> return new Promise(resolve => { >> const scriptElem = document.create('script') >> scriptElem.src = url >> scriptElem.onload = resolve >> }) >> } >> >> // some other file >> >> async function computeSpline() { >> await loadScript('./mathjs.js') >> // use math here >> } >> ``` >> >> And while this approach works somewhat it's a bit of a pain for a >> couple reasons: >> >> - If something gains a `script` dependency it necessarily breaks all >> consumers by becoming asynchronous even if the original operations >> were synchronous >> - It's not generic for other types of resources e.g. I can't load an >> image without creating another loader function or so on >> >> --- >> >> My proposed solution, dynamic (but static) export: >> >> ```js >> // math.mjs >> import loadScript from ".../loadScript.js" >> >> loadScript('./math.js').then(_ => { >> const math = window.math >> delete window.math >> export({ >> math as default >> }) >> }) >> ``` >> >> This solution is also generic so it can be used for loading any type >> of resource: >> >> ``` >> // highPerformanceMath.mjs >> fetch('.../math.wasm').then(response => response.arrayBuffer()) >> .then(buffer => WebAssembly.instantiate(buffer, {})) >> .then(({ instance }) => { >> export({ >> instance.exports as default >> }) >> // or potentially named exports >> export({ >> instance.exports.fastFourierTransform as fastFourierTransform >> ... >> }) >> ``` >> >> Now this solution would be nice because it's generic and allows for >> loading any (even asynchronous) object as part of the module graph and >> doesn't cause explosions where because one part becomes asynchronous >> everything becomes asynchronous. >> >> However there is a deficiency in that it can be quite verbose for >> similar tasks e.g. loading WebAssembly modules which is why I thought >> of idea 2: >> >> # Module Arguments >> >> Effectively module arguments would allow passing data to a module >> (statically) during loading e.g.: >> >> ```js >> // some-file.js >> import dict from "./dictionary.js" where { lang = "en-US" } >> >> // dictionary.js >> fetch(`./dictionaries/${ import.arguments.lang }.txt`) >> .then(response => response.text()) >> .then(text => export({ >> JSON.parse(text) as default >> }) >> ``` >> >> This solves the previous problem of very similar dynamic modules for >> similar types by allowing details like that to be passed in as >> arguments e.g.: >> >> >> ```js >> import math from "./loadScript.mjs" where { >> script = './math.js', >> globalName = 'math' >> } >> ``` >> >> # Lazy Export-From >> >> One of the nice things about named exports is you can minimize the >> amount of mostly similar `import` declarations e.g.: >> >> ```js >> import map from "./lodash/map.js" >> import filter from "./lodash/filter.js" >> import flatMap from "./lodash/flatMap.js" >> ... >> >> // can become >> import { map, filter, flatMap, ... } from "./lodash/lodash.js" >> ``` >> >> However it has a major downside of massively increasing the amount of >> fetch/parse/execute time for all those additional things exported by >> the combined module. >> >> My idea is to allow modules to declare that parts need to not be >> fetched parsed or executed if they're not actually imported e.g.: >> >> ```js >> // my-operators-library.js >> static export { map } from "./map.js" >> static export { filter } from "./filter.js" >> static export { reduce } from "./reduce.js" >> ``` >> >> Effectively all my idea adds is the `static export` (syntax not >> important) form that effectively says these names should only be >> resolved if they're actually imported and can be safely ignored if >> they're not used. This way you get both the benefits of collection >> modules (easier to `import` and reduces duplication) and the benefits >> of individual `import`s (lesser loading sizes). >> >> # Summary >> >> Basically the ideas suggested here are to solve these particular >> problems I've had with ES modules: >> >> - Unable to load classic scripts (and other types of resources >> statically e.g. conditional modules) as part of the module graph >> - Unable to specify more specific behavior for a module to prevent >> duplication >> - Either have to have lots of almost duplicate import declarations or >> have to load unnecessary files >> >> The solutions I proposed aimed to keep the constraint that module >> exports should remain statically parsable which is why `export({ ... >> })` shares the syntactic form. >> >> I refrained from specifying the semantics of the specific operations >> as there's details that'd need to be sorted out for all of them if >> there is any interest whatsoever in implementing them. >> _______________________________________________ >> es-discuss mailing list >> es-discuss@mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > _______________________________________________ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss