Skip to content

Latest commit

 

History

History
81 lines (63 loc) · 3.13 KB

0.43.md

File metadata and controls

81 lines (63 loc) · 3.13 KB

Upgrade 0.42 to 0.43

Change startupjs and all @startupjs/* dependencies in your package.json to ^0.43.

RELEASE NOTES

No breaking changes

Added automatic caching for styles and creation of scoped models during react render.

This is considered to be an experimental feature. By default it's turned OFF so nothing should break whatsoever.

To turn in ON, pass observerCache: true to the startupjs preset in babel.config.js:

    ['startupjs/babel.cjs', {
      ...,
      observerCache: true
    }]

To make sure caching is enabled, check the value of window.__startupjs__.DEBUG.cacheEnabled in browser console.

Cache will be enabled for all components. You can explicitly prohibit a specific component from using cache by passing { cache: false } to its observer():

export default observer(function Test ({ frequentlyChangedRandomColor }) {
  return pug`
    Div(style={ backgroundColor: frequentlyChangedRandomColor })
  `
}, { cache: false })

After enabling caching you must carefully test your whole application because some components might have been relying on excessive renderings to function properly. So you might have to fix some things in your codebase to account for optimized rerenders.

Examples:

  1. cache pure style. This will only work if you have observer imported in the current file, this way we don't screw up the 3rd-party libraries which don't use startupjs.

    export default observer(function Test () {
      return pug`
        Div(style={ backgroundColor: 'red' })
      `
    })
  2. cache pure styleName or any combination of part, style, *Style, *StyleName

    export default observer(function Test () {
      return pug`
        Div.div
      `
      styl`
        .div
          background-color red
      `
    })
  3. cache scoped model created with .at() and .scope()

    export default observer(function Games () {
      const [games, $games] = useQuery('games', { active: true })
      return pug`
        each game in games
          Game($game=$games.at(game.id))
      `
    })
    const Game = observer(({ $game }) => {
      const game = $game.get()
      return pug`
        Span= game.title
      `
    })

The last example is especially important since writing code in this way simplifies code a lot in many places. Now you can (and should) pass models whenever possible to child components as arguments, instead of passing an id and using useDoc or useLocalDoc.

Earlier in situations when you run useQuery in the parent component and then render each item as a separate component the only way to do it easily and properly was to pass an item id and then do a useLocalDoc. And you had to use useLocalDoc, otherwise useDoc will create an additional doc-only subscription and wait for it. Now this usecase is handled for you automatically, you just create a scoped model for the item inline using $items.at(item.id) and pass it as $item into the child component.

So this change alone will save you from making extra queries in many situations and will make the code easier to follow and more performant overall.