UNPKG

choo-bundles

Version:

Bundle splitting with HTTP2 push support for Choo with choo-ssr

265 lines (187 loc) 6.62 kB
# choo-bundles Bundle splitting with HTTP2 push support for [`choo-ssr`](https://github.com/nearform/choo-ssr) (server-side rendering with Choo). Requires [choo-async](https://github.com/nearform/choo-async). Lazy load the parts of your app that are not immediately used, to make the initial load faster. This module works without a compile step on the server, and in the browser with the browserify plugin. [Usage](#usage) - [Install](#install) - [Plugin CLI](#browserify-plugin-cli-usage) - [Plugin API](#browserify-plugin-api-usage) - [License: MIT](#license) [![stability][stability-image]][stability-url] [![standard][standard-image]][standard-url] [stability-image]: https://img.shields.io/badge/stability-experimental-orange.svg?style=flat-square [stability-url]: https://nodejs.org/api/documentation.html#documentation_stability_index [standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square [standard-url]: http://npm.im/standard ## Usage This plugin exposes a `load` function on a `bundles` object in the Choo instance: ```js // app.js const choo = require('choo') const ssr = require('choo-ssr') const async = require('choo-async') const bundles = require('choo-bundles') const home = require('./views/home') const notfound = require('./views/notfound') function main () { const app = async(choo()) const page = view => ( ssr.html( ssr.head( ssr.state(), bundles.assets() ), ssr.body(view) ) ) app.use(ssr()) app.use(bundles()) app.route('/', page(home)) app.route('/lazy', page(lazy)) app.route('*', page(notfound)) app.mount('html') async function lazy (state, emit) { const view = await app.bundles.load('./views/lazy') return view(state, emit) } return app } if (typeof window !== 'undefined') { main() } module.exports = main ``` ```js // server.js const path = require('path') const fastify = require('fastify')() fastify.register(require('fastify-static'), { root: path.join(__dirname, 'build'), prefix: '/build' }) fastify.register(require('choo-ssr/fastify'), { app: require('./app'), plugins: [[ require('choo-bundles/ssr'), { manifest: path.resolve(__dirname, 'build/manifest.json'), bundles: [{ name: 'common', js: '/build/bundle.js' }] } ]] }) fastify.listen(8080, function () { console.log('listening on 8080') }) ``` ```js // build.js const fs = require('fs') const path = require('path') const browserify = require('browserify') browserify('app.js') .plugin(require('choo-bundles/browserify'), { output: path.resolve(__dirname, 'build'), manifest: path.resolve(__dirname, 'build/manifest.json'), prefix: '/build' }) .bundle() .pipe(fs.createWriteStream('./build/bundle.js')) ``` This will split the `load`ed files into their own bundles so they can be dynamically loaded at runtime. In this case, a common bundle would be created including `choo`, `choo/html`, `choo-bundles` and the file above. A second bundle will be created for the `lazyView.js` file and its dependencies. See [examples](https://github.com/nearform/choo-bundles/tree/master/examples) for more ## Install ``` npm install choo-bundles ``` ## Browserify Plugin Works with Browserify v16 and newer ### CLI Usage ```bash browserify ./app.js -p [ choo-bundles/browserify --output ./bundles/ --manifest ./bundles/manifest.json ] > ./bundles/common.js ``` #### Options ##### `--output` Set the output directory for dynamic bundles. Use a folder path to place dynamic bundles in that folder. The default is `.`, outputting in the current working directory. ##### `--manifest` Set the output path for manifest file. The default is `./bundles.manifest.json`, outputting in the current working directory. ##### `--filename` Filename for the dynamic bundles. You must use %f in place of the bundle id ``` -p [ choo-bundles/browserify --filename bundle.%f.js ] ``` Defaults to `bundle.%f.js`, so the filename of dynamic bundle #1 is `bundle.1.js`. ##### `--prefix` URL prefix for the dynamic bundles. Defaults to `/`, so the URL of dynamic bundle #1 is `/bundle.1.js`. ### API Usage ```js var bundles = require('choo-bundles/browserify') browserify('./entry') .plugin(bundles, { output: '/output/bundles', manifest: '/output/manifest.json', }) .pipe(fs.createWriteStream('/output/bundles/common.js')) ``` #### Options ##### `output` Set the output directory for dynamic bundles, if a string is passed. Also accepts a function that returns a stream and takes `filename` as argument. The dynamic bundle will be written to the stream: ```js b.plugin(bundles, { output: filename => fs.createWriteStream(`/output/bundles/${filename}`) }) ``` Defaults to `.`. ##### `manifest` Set the output path for manifest file, if a string is passed. Also accepts a function that takes `manifest` object as argument: ```js b.plugin(bundles, { manifest: manifest => fs.writeFileSync('/output/manifest.json', JSON.stringify(manifest)) }) ``` Defaults to `./bundles.manifest.json` ##### `filename` Filename for the dynamic bundles. If string is passed you must use %f in place of the bundle id. Also accepts a function that takes the entry point `entry` as argument: ```js b.plugin(bundles, { filename: entry => 'bundle.' + entry.index + '.js' }) ``` ##### `prefix` URL prefix for the dynamic bundles. Defaults to `/`, so dynamic bundle #1 will have `/bundle.1.js` as URL. ### Events #### `b.on('choo-bunldes.pipeline', function (pipeline, entry, filename, manifest) {})` `choo-bunlde` emits an event on the browserify instance for each pipeline it creates. `pipeline` is a [labeled-stream-splicer](https://github.com/browserify/labeled-stream-splicer) with labels: - `'pack'` - [browser-pack](https://github.com/browserify/browser-pack) - `'wrap'` - apply final wrapping `entry` is the browserify row object for the entry point of the dynamic bundle. `filename` is the name of the dynamic bundle file. `manifest` is an object with an `add` function to add entries to the manifest ```js b.on('choo-bundles.pipeline', function (pipeline, entry, filename, manifest) { manifest.add('css', '/' + filename.replace('.js', '.css')) // URL of the CSS file pipeline.get('pack').unshift(extractcss(`/output/bundles/${filename.replace('.js', '.css')}`)) }) ``` ## Notes Browserify plugin heavily inspired on [`@goto-bus-stop`](https://github.com/goto-bus-stop)'s [`split-require`](https://github.com/goto-bus-stop/split-require) ## License [MIT](LICENSE.md)