Unchained takes advantage from browsers support for ES6 modules and Service Workers in order to load a full web application without using a bundler like Webpack or Rollup.
☢️ This project is just a research about web technologies.
DO NOT use it in production.
-
Since Safari, Firefox and Chrome started to support ES6 modules syntax, I started to look for a good practise to load my applications.
-
Bundlers are great, and I will continue to use them for working/production environments, but I felt nostalgic about the times where I used to build application without installing ~1000 node modules just to start.
Read more on Medium: https://medium.com/@edoardo.cavazza/a-study-about-how-to-improve-frontend-dev-experience-without-a-bundler-1b4c3a461a35
Native ES6 modules syntax accepts relative paths only (so, support for dependencies installed by NPM/Yarn is missing). Also, it doesn't work with other source formats rather than javascript (JSON, texts, styles...) or syntaxes (like JSX).
Today, those issues are resolved on dev environment side by bundlers (Webpack, Rollup, Browserify) and transpilers (Babel, Traceur).
The idea is to intercept import calls and transform the source in a ServiceWorker context, using the magninificent Babel standalone distribution to manipulate sources and resolve NPM dependencies.
Install from NPM:
$ npm install unchained-js
# OR
$ yarn add unchained-js
Use the Unchained client helper to register a ServiceWorker and to import the main application file.
index.html
<script src="node_modules/unchained-js/dist/unchained.client.js"></script>
<script>
UnchainedClient
.register('./sw.js', { scope: '/' })
.then(() => UnchainedClient.import('index.js'))
.then(() => console.log('🚀'));
</script>
sw.js
// import Unchained core and plugins
self.importScripts('node_modules/unchained-js/dist/unchained.sw.js');
index.js
import { Component, h, render } from 'preact';
class App extends Component {
render() {
return <h1>Hello world!</h1>;
}
}
render(document.body, <App />);
The Unchained object can be configured with a set of plugins, through the Unchained.resolve
method.
An array of Plugin constructors or Plugin instances or Plugin names.
{
plugins: [
// constrcutor
Unchained.TextPlugin,
// instance
new Unchained.ResolvePlugin(),
// name
'env',
// constructor|instance|name with options
['jsx', { pragram: 'h' }]
]
}
The Plugin name may be registered via the
Unchained.registerPlugin(name, constructor)
method.
A list of available plugins can be found here.
You may also configure Unchained via querystring in the service worker registration url:
navigator.serviceWorker.register(`sw.js?unchained={"plugins":["env", "text"]}`);
The equivalent can be written using the third parameter of the Unchained.register
helper method:
Unchained.register('sw.js', { scope: '/' }, {
plugins: ['env', 'text'],
});
Support for Service Workers, ES6 syntax and ES6 modules is required.
Manually tested on Chrome v63.0.3239.84.
ES6 modules
Service Workers
Babel Standalone
See the wiki.
MIT