choo-bundles
Version:
Bundle splitting with HTTP2 push support for Choo with choo-ssr
265 lines (187 loc) • 6.62 kB
Markdown
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.
[](
[](
[](
[](
[](
[![stability][stability-image]][stability-url]
[![standard][standard-image]][standard-url]
[]: https://img.shields.io/badge/stability-experimental-orange.svg?style=flat-square
[]: https://nodejs.org/api/documentation.html#documentation_stability_index
[]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square
[]: http://npm.im/standard
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
```
npm install choo-bundles
```
Works with Browserify v16 and newer
```bash
browserify ./app.js -p [ choo-bundles/browserify --output ./bundles/ --manifest ./bundles/manifest.json ]
> ./bundles/common.js
```
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.
Set the output path for manifest file.
The default is `./bundles.manifest.json`, outputting in the current working directory.
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
URL prefix for the dynamic bundles.
Defaults to `/`, so the URL of dynamic bundle
```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'))
```
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 `.`.
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 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'
})
```
URL prefix for the dynamic bundles.
Defaults to `/`, so dynamic bundle
`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')}`))
})
```
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.md)