Skip to content

Releases: lore/lore

v0.12.7

14 Jul 17:29

Choose a tag to compare

[559ccf1] Fixes an issue preventing the package.json file in new projects from being generated correctly.

v0.12.6

04 Jul 05:52

Choose a tag to compare

I'm not sure if the v0.12.5 release was published correctly, so this is forced publish of all packages to make sure it ended up on npm properly.

v0.12.5

04 Jul 05:51

Choose a tag to compare

This releases makes sure all lore packages use the same version of lodash at ^v4.0.0. Using the absolutely fantastic webpack-visualizer tool it became clear that lodash was being included in the project multiple times, which was causing massive bloat.

New lore projects were ~4.4MB in size (unminified), which didn't make much sense. After syncronizing the lodash version across projects, the size of new projects is reduced by 55%, from ~4.4 MB to 2.4 MB.

When minified, new projects are ~480k (what you would serve in production).

Here's a breakdown of the largest libraries in a new project

webpack_visualizer

Lodash is a clear target for further reducing the size of new projects. If necessary, I'll replace it with the individual packages, like lodash.defaults or lodash.find, but I'm going to tackle it first by converting lore packages to use ES6 imports and exports, and then set up new projects to use tree shaking.

In a test, configuring a lore project for tree-shaking in this way dropped the package size of lodash down to under 100k, which should place the development build for new projects at ~1.75MB and the minified build at ~350k.

v0.12.4

04 Jul 05:32

Choose a tag to compare

This release changes lore's behavior to load the initializers after the hooks.

This is useful if you need to access data created by the hooks in one of your initializers.

v0.12.3

04 Jul 05:30

Choose a tag to compare

This release refactors lore-hook-connect and introduces two new queries:

model.all

This query provides a way to search through the data in the store and return exactly what you want. It will never invoke an action.

The motivation for creating this query was to display new data on top of paginated data, such as in an infinitely scrolled list, which is useful such as when displaying a list of tweets that have been received since the user started using the application (tweets the user might have created themselves, or tweets that may have arrived via a websocket connection).

@lore.connect(function(getState, props) {
  return {
    tweets: getState('tweet.all', {
      where: function(tweet) {
        return !tweet.id || (tweet.data.createdAt - timestamp) > 0
      },
      sortBy: function(tweet) {
        return -tweet.data.createdAt;
      }
    })
  }
})

The where field is optional, and allows you to provide a function to filter the data. In the example above, we are returning all tweets that either a) don't have an id, which means they're optimistically created the the user, or b) where they showed up in the application after some timestamp, such as the timestamp the first page of data was fetched, or the timestamp the application was loaded.

if you don't provide a where field, it will simply return all of the tweet models.

The sortBy argument is also optional, and allows you to order the results, such as "most recent tweets first".

model.cyCid

This query lets you return a specific model with a matching cid. Admittedly this query isn't as useful...but it might be more useful in a websocket app (doubtful). It's mostly here for "completion", so there's a connect query that maps to anything the reducer keep track of.

@lore.connect(function(getState, props) {
  return {
    tweets: getState('tweet.byCid', {
      cid: 'c1'
    })
  }
})

v0.12.2

12 May 07:21

Choose a tag to compare

There were small differences in the versions of packages used across the ES5, ES6 and ESNext project templates created using the lore new command. This release makes sure all project templates use the same versions of each packages, with the same semantic identifier for the version number (patch, minor or major).

The relevant commit is e362846.

v0.12.1

08 May 05:49

Choose a tag to compare

This patch release fixes an issue in the v0.12.0 release where the lore new generator was producing a package.json for new projects that referenced the ~0.12.0-beta versions of the lore packages instead of the official ~0.12 versions.

v0.12.0

08 May 05:47

Choose a tag to compare

Please see the upgrade guide if you are migrating from v0.11 to v0.12.

Big thanks to @timcase for all the great discussion, ideas and feedback during the course of this release.

This release upgrades Webpack to v2, simplifies the Webpack config, and also includes an official build configuration for production along with built-in favicon generation. It also includes support for normalization of API responses, the inclusion of Redux DevTools in development (disabled by default), and breaks the React and Redux build process out of Lore core and into their own hooks (lore-hook-react and lore-hook-redux respectively).

Webpack (#166, #167)

This release upgrades Webpack to v2 and simplifies the webpack configuration. There is no longer a /webpack folder. Instead, thanks to a video series by Kent Dodds and his helpful webpack-config-utils, there is now an elegant way to manage multiple build environments in a single file.

This release also includes:

  • a much improved build configuration that includes support for common CSS preprocessors (LESS, SASS), font file types, and image types
  • automatic addition of browser vendor prefixes to CSS output
  • automatic generation of a set of favicons from an image file located at assets/images/favicon.png
  • an official production build includes minification, cache busting, and the extraction of CSS includes into text files
  • an example project demonstrating features of the webpack config

For a walkthrough of the build process, please see the publishing section of the Quickstart.

React and Redux broken out of Lore core and into their own hooks (#164, #161)

In v0.11, all of Lore's core functionality had been broken out into hooks with the exception of two behaviors: the creation of the Redux store, and the mounting of the React project to the DOM.

As of this release, that functionality has been broken out into the lore-hook-react and lore-hook-redux hooks. This means you now have full control of the build and mounting process of the application, and Lore core is not officially nothing more than a plugin engine to load hooks in the proper order.

Here are a couple reasons why this is useful:

  • you can build the project differently in different environments, and this release demonstrates that by integrating the Redux DevTools into the development config, but excluding them from the production config
  • having control over the build and mounting process means you can use any version of React, Redux or React Router you want, without worrying about whether those libraries have breaking changes - if they do, just update the build steps in the respective hook

Redux DevTools now included by default (#166)

The Redux DevTools are nifty, fun and sometimes quite useful. And now they're included in new Lore projects by default : )

To enable them, just open up the development config in config/env/development.js and toggle the devToolsEnabled property to true:

// config/env/development.js
redux: {
  devToolsEnabled: true
}

Normalization (#162)

This release includes the ability to automatically normalize API responses that contain nested data. This can be incredibly helpful for reducing the number of network requests and improving the load time and responsiveness of applications.

If you're not familiar with the concept of normalizing API responses see the normalization section in the Quickstart for some discussion about what normalization is and how to take advantage of it.

The behavior is turned on by default, but in order to use it you have to tell the framework what to look for (what models might have nested data and what model that data is associated with). You do this by defining an attribute in the model, declaring the type as a model, and providing the name of the associated model.

export default {
  attributes: {
    user: {
      type: 'model',
      model: 'user'
    }
  }
}

Debouncing Batch Actions (c3bb82a)

Redux has no concept of batch actions by default, which was problematic when implementing normalization. The way Lore handles normalization is by examining the API response in the Action Creators (like lore.actions.tweet.find() and breaking the response up into multiple actions (if nested data exists) which it then dispatches to the Store.

This is a very simple way to support normalization, but because Redux doesn't understand the concept of "batch actions", dispatching 20 actions to the Store will cause the application to attempt to re-render 20 times back-to-back-to-back, which is a huge waste and can noticeably and negatively impact the responsiveness of the application (it can feel like it "locks up" for a second).

To fix this, the build process for the Redux store now includes the redux-batched-subscribe store enhancer, which will prevent React from being notified until after the Store is finished updating all requests. It looks like this:

// config/redux.js

  /**
   * Length of time (in milliseconds) that needs to exist between updates
   * to the Redux store before React is notified the store has changed.
   * A value of zero corresponds to "one tick".
   *
   * https://lodash.com/docs/4.17.4#debounce
   */

  debounceWait: 0,

  /**
   * Enhance the store with third-party capabilities such as middleware,
   * time travel, persistence, etc.
   *
   * http://redux.js.org/docs/api/compose.html
   */

  enhancer: function(middleware, config) {
    return Redux.compose(
      Redux.applyMiddleware.apply(null, middleware),
      batchedSubscribe(_.debounce(function(notify) {
        notify();
      }, config.redux.debounceWait))
    );
  },

By default, debouncing is set to a delayed wait that will only cause notification delay's for batch requests, but you can also adjust this setting higher to improve performance if you know there are periods when your application will be slammed with network requests, and want to slow down how often the application attempts to re-render based on Store changes (like limiting it to 20 times/minute or something).

Break mutable reference between Store data and Components (cc9c1f7 )

The default behavior in Redux is to provide components with a reference to the store state returned from the reducers. This poses a problem when a component tries to change that data, because it will modify the state of the store through that reference.

To address this issue, the top-level reducer will invoke this method right before returning the next state, which gives you the ability to experiment with different solutions for this problem.

The default behavior is to return a copy of the store state, which will prevent any component from being able to modify the "truth" kept in the reducers.

Others solutions could be invoking Object.freeze(nextState) (which will throw an error if a component tries to modify the store state) or converting the store state to an Immutable object using Immutable.map(nextState) from Immutable.js.

This method is intended ONLY as a way to explore different solutions for addressing immutability concerns that arise when components have a direct reference to the data kept in the reducers. You should never use this function to modify the data itself.

v0.11.4

26 Feb 21:56

Choose a tag to compare

This release fixes a bug that was preventing the environment specific configuration from being loaded and merged into the common configuration.

Fix pushed in this commit: b2783e4

v0.11.3

25 Feb 06:44

Choose a tag to compare

Tutorial: Creating Custom Hooks

This release includes a new tutorial for creating custom hooks.

To support that, the lore-generate-hook generator has been updated to output code in the same language as your project (ES5, ES6 or ESNext). Previously it only output code in ES5.