My high-level vision for the next year of Steal is to keep the benefits of client-side module loaders (while adopting new technologies to improve it) while gaining the no-compromises benefit of Node-based module bundlers by improving our watch mode.
Additionally I want to lay out the road to 1.0.
Improve NPM workflow
The addition of NPM support made life much better for Steal users but there are still some holes in our implementation. Steal should be able to load anything that Browserify/Webpack can bundle so we should add support for:
- folder/index convention of NPM modules. That is if we are unable to load folder.js, try folder/index.js. Additionally we should cache the results of these so that there are no 404s on refresh.
- Progressively load package.jsons so that we don’t load them for modules that will never be used.
- Minimize the amount of information kept (from package.jsons) to reduce production size.
Implement smart caching
We can speed up development with smart caching using Service Workers. We should:
- Cache modules served from node_modules/, only fetch these if their associated package.json changes.
- Cache the results of transpiling ES6 code, Less code, etc. so that we only perform the transpilation when the source has changed.
- Cache the complete dependency tree and use that on page load so that all modules needed are fetched right away. (this is an option Steal supports call depCache).
Smaller production builds
To stay competitive our production builds should be reduced down to only what is needed. This means not bundling extensions that are unused in production.
By default only normalize hooks should be included in production builds. We could use tree-shaking techniques to remove extension code that doesn’t perform normalization.
Additionally if the user’s application isn’t using progressive loading, the AMD shim should be used.
Conditional loading
One problem that comes up often in DoneJS applications is the need to only load fixtures in development. steal-conditional was created to solve this problem, however it doesn’t work with the NPM plugin. There have been some changes to the conditional extension in SystemJS so we should take a look at what has been developed there and possible upgrade and make it work with NPM.
Better extension APIs
We should encourage a rich ecosystem of extensions. These extensions should be able to load their own dependencies. configDependencies
is the current way to add extensions, but these cannot have NPM dependencies so they’re not as useful as they should be. This also means you can’t npm install an extension, unless you list node_modules/extension/extension
as the module name in configDependencies. Gross!
Steal could add a new property: extensions
which is an array of modules that will be loaded after the config and before the main.
Writing extensions should be easier as well. Wrapping is not a great API for extensions in JavaScript. We could switch to class-based extensions so they are as easy as:
export default class ForwardSlash extends System.constructor {
normalize() {
...
}
}
These extensions would need to be executed in order, so that each one replaces the global System object.
Dependency injection for testing
This is being discussed on GitHub, essentially people want to be able to inject a dependency as a substitute for testing purposes. This can be done today manually using the low level APIs provided, but could be made more user-friendly.
Steal development server
One advantage that bundlers have over client-side module loaders is that they don’t have to make compromises based on what browsers support. Steal supports continuous builds (aka watch mode) so that development mimics production.
However this only works for you app’s “main” page, not for demo pages or test pages. It would be nice if you could get the benefits of both. I’m thinking of development server middleware that parses HTML files for steal script tags and automatically includes their mains in the continuous build.
Steal 1.0
Steal is mature so we should be on 1.0 already. Since this will be the last opportunity to make breaking changes for a while there’s a couple of things we should definitely do:
- Upgrade to Babel 6 which is not compatible with old versions.
- Make Babel the default transpiler instead of Traceur.
- Progressively load package.jsons. Some people might be relying on having the complete tree all of the time so this would be a breaking change, technically.