Choo: Code splitting and Es module dynamic import

Created on 31 Jan 2018  路  8Comments  路  Source: choojs/choo

Is there any plan to support code splitting and Es module dynamic import.

Most helpful comment

split-require also comes with bankai by default, so you can use it today :) you still have to do some manual work like in @marcbachmann's example, but with require('split-require') instead of import() syntax.

(i'm hoping to make import() syntax compile to split-require calls in bankai, but some hairy babel things need to be hashed out first, so it might take a while)

All 8 comments

Thanks for bringing that up. I've also experimented a bit and I'm in interested in that.
Basically code splitting isn't necessary related to choo at all. It already supports the registration of routes after rendering a view, so it will work as soon as you have the dynamic imports working.
You'll just need to decide how you want to structure the application.

Here's some code extracted from my prototype. Sadly I was only able to get it to run using webpack.
I wasn't able to get the imports running in bankai/browserify. Bankai just throws weird errors.

npm init -y
npm install --save-dev babel-core choo-devtools babel-plugin-syntax-dynamic-import
// .babelrc
{
  "plugins": ["syntax-dynamic-import"]
}
// index.js
const choo = require('choo')
const html = require('choo/html')
const app = choo()

if (typeof window !== 'undefined') window.app = app
app.use(require('choo-devtools')())
app.route('/', (state, emit) => html`<body>root</body>`)
app.route('/some-route', (state, emit) => html`<body>some-route</body>`)

subapp(app, {
  path: '/subroute',
  getModule () { return import('./subroute') }
})

app.mount('body')

function subapp (app, {path, getModule}) {
  const subApp = {
    isLoaded: false,
    isLoading: false,
    loadingView: (state, emit) => html`<body>Loading...</body>`,
    indexView: (state, emit) => html`<body>${path} App: Not Found</body>`,
    fallbackView: (state, emit) => html`<body>${path} App: Not Found</body>`
  }

  app.route(path, loadSubApp)
  app.route(path + '/*', loadSubApp)

  function loadSubApp (state, emit) {
    if (subApp.isLoaded && state.href === path) return subApp.indexView(state, emit)
    else if (subApp.isLoaded) return subApp.fallbackView(state, emit)
    if (subApp.isLoading) return subApp.loadingView(state, emit)

    subApp.isLoading = true
    getModule().then(function (subAppModule) {
      subApp.isLoading = false
      subApp.isLoaded = true
      subAppModule({
        use: app.use.bind(app),
        state: app.state,
        route (route, handler) {
          if (/^[/]?$/.test(route)) {
            subApp.indexView = handler
            return
          } else if (route === '/*') {
            subApp.fallbackView = handler
            return
          }
          app.route(`${path}${route}`, handler)
        }
      })
      emit('replaceState', state.href)
    })

    return subApp.loadingView(state, emit)
  }
}
// subroute.js
const html = require('choo/html')

module.exports = function (choo) {
  choo.route('/something-else', (state, emit) => html`<body>something else</body>`)
  choo.route('/*', (state, emit) => html`<body>subroute wildcard</body>`)
}

Sorry if this doesn't work right away, I've just extracted it without an additional test.
This could use some iterations and some cleanup/simplification.
It already works in almost all cases; there's only one small glitch with a view sometimes.

Unfortunately Bankai is using browserify. Code splitting is very important specially for PWAs. Bankai must support code splitting/Dynamic Es module import.

There's split-require authored with choo and bankai in mind for just this use case. I haven't tried it out myself but looks to be what you're looking for.

split-require also comes with bankai by default, so you can use it today :) you still have to do some manual work like in @marcbachmann's example, but with require('split-require') instead of import() syntax.

(i'm hoping to make import() syntax compile to split-require calls in bankai, but some hairy babel things need to be hashed out first, so it might take a while)

Why not just use webpack, parceljs or rollupjs for bundling, tree shaking, code splitting and dynamic es module imports like so many other projects.

You can use those if you want! Bankai supports all those things except ES modules, because they are not yet finished in node, and Browserify/bankai aim to match node.js. Tools like webpack and parcel take nonstandard source code, which is fine for them, but not in line with bankai goals.

Yep, what @goto-bus-stop says. A big requirement of Bankai was that it works natively in Node. That said, you're free to use any tool that works for you - Choo works with (almost) all build tools! :sparkles:

I don't think there's anything actionable here鈥攊f you have a feature request or further questions in this area feel free to open a new issue tho.

Was this page helpful?
0 / 5 - 0 ratings