New context mixin concept for react, redux, graphql, simplified templates
8.0.0 (2017-11-22)
This update changes the previous context implementation and fixes a couple of other issue (read more about those below).
BREAKING CHANGES
-
renderer: createRenderer signature changed to options hash instead of discrete args
Before: The default export ofhops-renderer
(createRenderer
) accepted two options:function createRenderer(webpackConfig, watchOptions) {...}
Now it only accepts one argument, that is an options object with the following shape:
var options = { webpackConfig, watchOptions, hopsConfig };
-
react: new context mixin mechanism using mixinable
-
redux: new context mixin mechanism using mixinable
-
graphql: new context mixin mechanism using mixinable
Before:render
fromhops-react
could be called with either just the App or the App and an options object:import { render } from 'hops-react'; render(<App />)
or
import { render } from 'hops-react'; render(<App />, { mountpoint: '#foo' })
After:
render
always needs to be called with the App (and a hops context):import { render, createContext } from 'hops-react'; render(<App />, createContext({ mountpoint: '#foo' }))
the
createContext
method accepts an options object and can be imported as a named import fromhops-react
.import { render, createContext } from 'hops-react';
Also: There no longer exists a class-based
Context
, but instead the context is composed in a
functional manner, viacreateContext
,contextDefinition
andcombineContexts
(where
createContext
is just a shorthand forcombineContexts(contextDefinition)
).The context methods are now implemented in the
contextDefinition
.
And multiple context definitions (for example:react
,redux
andgraphql
)
can be combined to a context creator function (which will return a combined context, that can be used as second argument torender
).Most packages also export a convenience
createContext
method, which is already a combination of the react context and their owhn context.
For example:hpos-redux
combineshops-react
andhops-redux
:import { render } from 'hops-react'; import { createContext } from 'hops-redux'; render(<App />, createContext({ reducers: {...} }));
And
hops-graphql
combineshops-react
andhops-graphql
:import { render } from 'hops-react'; import { createContext } from 'hops-graphql'; render(<App />, createContext({ graphql: { cache, link } }));
If you want to have a context that combines all three of them, you will need to create it yourself:
import { render, combineContexts, contextDefinition as reactContext } from 'hops-react'; import { contextDefinition as reduxContext } from 'hops-redux'; import { contextDefinition as graphqlContext } from 'hops-graphql'; import App from './app'; const createContext = combineContexts(reactContext, reduxContext, graphqlContext); export default render(<App />, createContext({ mountpoint: '#foo', reducers: {...}, graphql: {...} }));
Additional information for extending / overwriting context definitions:
As the context implementation has changed (instead of using a class based approach
we have switched to mixinable) which favors functional
composition and enables us to use multiple contexts at the same time.
The hops lifecycle definitions are as follows:
DOMexports.combineContexts = mixinable({ bootstrap: mixinable.parallel, enhanceElement: mixinable.pipe, getMountpoint: mixinable.override });
Node
exports.combineContexts = mixinable({ bootstrap: mixinable.parallel, enhanceElement: mixinable.pipe, getTemplateData: mixinable.pipe, renderTemplate: mixinable.override });
This allows us to implement these methods in
contextDefinition
s and combine multiple
contextDefinition
s viacombineContexts(contextDefinition0, contextDefinition1)
.
This means, that allbootstrap
methods in all combined contexts will be executed in parallel
and allenhanceElement
methods will be executed one after another and their return value will be the the input argument to the nextenhanceElement
implementation, allowing you to compose (pipe) them.
mixinable.override
will only execute the respective method of the last implementation passed intocombineContexts
.To get a better understanding of how the context composition works, we suggest, that you take a look at the following files:
-
build-config: remove support for turning flow types to prop types
Hops now no longer has built-in support for converting flow type
annotations into react prop-type definitions.
It still supports flow out of the box, via the babel-react preset,
but now it only removes flow type annotations from the build instead
of converting them to prop-types. -
template-react: The template
hops-template-react
now no longer contains flow type annotations. -
template-react: remove graphql example code
hops-template-react
(default template) now no longer supports graphql
out of the box. You can add the support yourself again or use a
different template (we will provide a newhops-template-graphql
shortly). -
plugin: Constructor signature changed to options hash instead of discrete args.
Before: The webpack pluginhops-plugin
used to be instantiated with three discrete arguments:new HopsPlugin(locations, webpackConfig, watchOptions);
Now it accepts only a single options object:
var options = { locations, webpackConfig, watchOptions, hopsConfig }; new HopsPlugin(options);
Bug Fixes
- build-config: exclude absolute paths from bundled config (4ecc41f)
- build-config: inline core-js polyfills in bundled Node.js code (37e0feb)
- build-config: replace babel-minify with uglify-es (f1be32c)
- local-cli: if _gitignore exists, rename it to .gitignore (520a6da)
- react: make sure to only hydrate on first pass (561cb89)
- template-minimal: keep gitignore after publish by renaming it (d9e7e2d)
- template-react: add missing prop-types dependency (5fb80f2)
- template-react: keep gitignore after publish by renaming it (afb28ae)
Code Refactoring
- build-config: remove propTypes in production builds (50c9d6c)
- graphql: make main export a context mixin (d097d2d)
- graphql: rename mixin definition export (dfd1d4b)
- plugin: switch to options hash (64e0f24)
- redux: make main export a context mixin (f5edae6)
- redux: rename mixin definition export (321e733)
- template-react: remove flow type annotations (4f7bba9)
- template-react: remove graphql from default template (4533445)
Features
- config: allow targeting specific Node version in babel preset (4437c6b)
- graphql: implement simplified mixin support (509c1b5)
- graphql: introduce mixin support (813196f)
- hops-build-config: add source maps to production build output (9cfde51)
- hops-build-config: add webpack-stats-plugin to build (a752635)
- react: add combineContexts, refactor exports (8bd2955)
- react: implement simplified mixin support (6f8bf5c)
- react: introduce mixin support (3a575b1)
- redux: implement simplified mixin support (dfed624)
- redux: introduce mixin support (c0da538)
- renderer: add support for an options hash (8206ad1)
- renderer: make renderer use bootstrapServer config (ce2298d)
Performance Improvements
- graphql: remove fs.existsSync() check from context (1441d20)