├── .eslintignore
├── .gitignore
├── .travis.yml
├── .editorconfig
├── examples
├── remount
│ ├── components
│ │ ├── app.jsx
│ │ └── html.jsx
│ ├── client.js
│ ├── webpack.js
│ └── server.js
├── layout
│ ├── views
│ │ ├── about.jsx
│ │ ├── home.jsx
│ │ └── layout.jsx
│ └── server.js
└── simple
│ ├── views
│ └── home.jsx
│ └── server.js
├── test
├── fixtures
│ ├── view.jsx
│ └── view-precompiled.jsx
└── index.js
├── LICENSE
├── package.json
├── index.js
└── README.md
/.eslintignore:
--------------------------------------------------------------------------------
1 | examples/remount/assets
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | examples/remount/assets
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | node_js:
4 | - "0.10"
5 | - "0.11"
6 | - "0.12"
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # 4 space indentation
2 | [*.js]
3 | indent_style = space
4 | indent_size = 4
5 | [*.jsx]
6 | indent_style = space
7 | indent_size = 4
8 |
--------------------------------------------------------------------------------
/examples/remount/components/app.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 |
4 | var Component = React.createClass({
5 | render: function () {
6 |
7 | return (
8 |
Foo: {this.props.foo}
9 | );
10 | }
11 | });
12 |
13 |
14 | module.exports = Component;
15 |
--------------------------------------------------------------------------------
/examples/remount/client.js:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var AppComponent = require('./components/app.jsx');
3 |
4 |
5 | var App = React.createFactory(AppComponent);
6 | var mountNode = document.getElementById('app-mount');
7 | var serverState = window.state;
8 |
9 |
10 | React.render(App(serverState), mountNode);
11 |
--------------------------------------------------------------------------------
/examples/layout/views/about.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Layout = require('./layout.jsx');
3 |
4 |
5 | var Component = React.createClass({
6 | render: function () {
7 |
8 | return (
9 |
10 | About the plot device.
11 |
12 | );
13 | }
14 | });
15 |
16 |
17 | module.exports = Component;
18 |
--------------------------------------------------------------------------------
/examples/layout/views/home.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 | var Layout = require('./layout.jsx');
3 |
4 |
5 | var Component = React.createClass({
6 | render: function () {
7 |
8 | return (
9 |
10 | Welcome to the plot device.
11 |
12 | );
13 | }
14 | });
15 |
16 |
17 | module.exports = Component;
18 |
--------------------------------------------------------------------------------
/examples/remount/webpack.js:
--------------------------------------------------------------------------------
1 | var Path = require('path');
2 |
3 |
4 | module.exports = {
5 | entry: Path.join(__dirname, './client.js'),
6 | resolve: {
7 | extensions: ['', '.js', '.jsx']
8 | },
9 | output: {
10 | filename: Path.join(__dirname, './assets/client.js')
11 | },
12 | module: {
13 | loaders: [
14 | { test: /\.jsx$/, loader: 'jsx-loader' }
15 | ]
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/test/fixtures/view.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 |
4 | var Component = React.createClass({
5 | render: function () {
6 |
7 | return (
8 |
9 |
10 | {this.props.title}
11 |
12 |
13 | Activate the plot device.
14 |
15 |
16 | );
17 | }
18 | });
19 |
20 |
21 | module.exports = Component;
22 |
--------------------------------------------------------------------------------
/examples/simple/views/home.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 |
4 | var Component = React.createClass({
5 | render: function () {
6 |
7 | return (
8 |
9 |
10 | {this.props.title}
11 |
12 |
13 | Activate the plot device.
14 |
15 |
16 | );
17 | }
18 | });
19 |
20 |
21 | module.exports = Component;
22 |
--------------------------------------------------------------------------------
/examples/layout/views/layout.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 |
4 | var Component = React.createClass({
5 | render: function () {
6 |
7 | return (
8 |
9 |
10 | {this.props.title}
11 |
12 |
13 | {this.props.children}
14 |
15 |
16 | Home | About Us
17 |
18 |
19 |
20 | );
21 | }
22 | });
23 |
24 |
25 | module.exports = Component;
26 |
--------------------------------------------------------------------------------
/examples/remount/components/html.jsx:
--------------------------------------------------------------------------------
1 | var React = require('react');
2 |
3 |
4 | var Component = React.createClass({
5 | render: function () {
6 |
7 | return (
8 |
9 |
10 | Remount Example
11 |
12 |
13 |
15 |
16 |
19 |
20 |
21 |
22 | );
23 | }
24 | });
25 |
26 |
27 | module.exports = Component;
28 |
--------------------------------------------------------------------------------
/examples/simple/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi');
2 | var Vision = require('vision');
3 | var HapiReactViews = require('../..');
4 |
5 |
6 | var server = new Hapi.Server();
7 | server.connection();
8 | server.register(Vision, function (err) {
9 |
10 | if (err) {
11 | console.log('Failed to load vision.');
12 | }
13 |
14 | server.views({
15 | engines: {
16 | jsx: HapiReactViews
17 | },
18 | relativeTo: __dirname,
19 | path: 'views'
20 | });
21 |
22 | server.route({
23 | method: 'GET',
24 | path: '/',
25 | handler: function (request, reply) {
26 |
27 | reply.view('home');
28 | }
29 | });
30 |
31 | server.start(function (err) {
32 |
33 | if (err) {
34 | throw err;
35 | }
36 |
37 | console.log('Server is listening at ' + server.info.uri);
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/test/fixtures/view-precompiled.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | // precompiled with Babel (like when using the require hook for Babel)
3 |
4 | var React = require('react');
5 |
6 | var Component = React.createClass({
7 | displayName: 'Component',
8 |
9 | render: function render() {
10 |
11 | return React.createElement(
12 | 'html',
13 | null,
14 | React.createElement(
15 | 'head',
16 | null,
17 | React.createElement(
18 | 'title',
19 | null,
20 | this.props.title
21 | )
22 | ),
23 | React.createElement(
24 | 'body',
25 | null,
26 | React.createElement(
27 | 'p',
28 | null,
29 | 'This is precompiled.'
30 | )
31 | )
32 | );
33 | }
34 | });
35 |
36 | module.exports = Component;
--------------------------------------------------------------------------------
/examples/layout/server.js:
--------------------------------------------------------------------------------
1 | var Hapi = require('hapi');
2 | var Vision = require('vision');
3 | var HapiReactViews = require('../..');
4 |
5 |
6 | var server = new Hapi.Server();
7 | server.connection();
8 | server.register(Vision, function (err) {
9 |
10 | if (err) {
11 | console.log('Failed to load vision.');
12 | }
13 |
14 | server.views({
15 | engines: {
16 | jsx: HapiReactViews
17 | },
18 | relativeTo: __dirname,
19 | path: 'views'
20 | });
21 |
22 | server.route({
23 | method: 'GET',
24 | path: '/',
25 | handler: function (request, reply) {
26 |
27 | reply.view('home');
28 | }
29 | });
30 |
31 | server.route({
32 | method: 'GET',
33 | path: '/about',
34 | handler: function (request, reply) {
35 |
36 | reply.view('about');
37 | }
38 | });
39 |
40 | server.start(function (err) {
41 |
42 | if (err) {
43 | throw err;
44 | }
45 |
46 | console.log('Server is listening at ' + server.info.uri);
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | (The MIT License)
2 |
3 | Copyright (c) 2014 Reza Akhavan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | 'Software'), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hapi-react-views",
3 | "version": "3.1.2",
4 | "description": "A hapi view engine for React components.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "./node_modules/lab/bin/lab -c -L",
8 | "test-cover": "./node_modules/lab/bin/lab -c -r html -o ./test/artifacts/coverage.html && open ./test/artifacts/coverage.html",
9 | "simple-example": "node ./examples/simple/server",
10 | "layout-example": "node ./examples/layout/server",
11 | "remount-example": "webpack --config ./examples/remount/webpack.js && node ./examples/remount/server"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "https://github.com/jedireza/hapi-react-views"
16 | },
17 | "keywords": [
18 | "hapi",
19 | "react",
20 | "views"
21 | ],
22 | "author": "Reza Akhavan (http://reza.akhavan.me/)",
23 | "license": "MIT",
24 | "bugs": {
25 | "url": "https://github.com/jedireza/hapi-react-views/issues"
26 | },
27 | "homepage": "https://github.com/jedireza/hapi-react-views",
28 | "dependencies": {
29 | "hoek": "^2.x.x",
30 | "node-jsx": "^0.13.x"
31 | },
32 | "peerDependencies": {
33 | "react": "^0.14.x ",
34 | "react-dom": "^0.14.x "
35 | },
36 | "devDependencies": {
37 | "code": "^1.x.x",
38 | "hapi": "^9.x.x",
39 | "inert": "^3.x.x",
40 | "jsx-loader": "^0.13.x",
41 | "lab": "^5.x.x",
42 | "react": "^0.14.x ",
43 | "react-dom": "^0.14.x ",
44 | "vision": "^3.x.x",
45 | "webpack": "^1.x.x"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var Hoek = require('hoek');
2 | var React = require('react');
3 | var ReactDOMServer = require('react-dom/server');
4 |
5 |
6 | var EXT_REGEX = new RegExp('\\.jsx$');
7 | var DEFAULTS = {
8 | doctype: '',
9 | renderMethod: 'renderToStaticMarkup',
10 | removeCache: process.env.NODE_ENV !== 'production',
11 | useNodeJsx: true,
12 | 'node-jsx': undefined
13 | };
14 |
15 |
16 | var compile = function compile (template, compileOpts) {
17 |
18 | compileOpts = Hoek.applyToDefaults(DEFAULTS, compileOpts);
19 | var Component, Element;
20 |
21 | return function runtime (context, renderOpts) {
22 |
23 | renderOpts = Hoek.applyToDefaults(compileOpts, renderOpts);
24 | if (renderOpts.useNodeJsx === true) {
25 | require('node-jsx').install(compileOpts['node-jsx']);
26 | }
27 | var output = renderOpts.doctype;
28 | Component = Component || require(compileOpts.filename);
29 | Element = Element || React.createFactory(Component);
30 | output += ReactDOMServer[renderOpts.renderMethod](Element(context));
31 |
32 | // node-jsx takes a long time to start up, so we delete
33 | // react modules from the cache so we don't need to restart
34 | // to see view changes (unless we're in production silly)
35 | if (renderOpts.removeCache) {
36 | Component = undefined;
37 | Element = undefined;
38 |
39 | Object.keys(require.cache).forEach(function (module) {
40 |
41 | if (EXT_REGEX.test(module)) {
42 | delete require.cache[module];
43 | }
44 | });
45 | }
46 |
47 | return output;
48 | };
49 | };
50 |
51 |
52 | module.exports = {
53 | compile: compile
54 | };
55 |
--------------------------------------------------------------------------------
/examples/remount/server.js:
--------------------------------------------------------------------------------
1 | var Path = require('path');
2 | var Hapi = require('hapi');
3 | var Inert = require('inert');
4 | var Vision = require('vision');
5 | var HapiReactViews = require('../..');
6 |
7 |
8 | var server = new Hapi.Server();
9 | server.connection();
10 | server.register([Inert, Vision], function (err) {
11 |
12 | if (err) {
13 | console.log('Failed to load plugins.');
14 | }
15 |
16 | server.views({
17 | engines: {
18 | jsx: HapiReactViews
19 | },
20 | relativeTo: __dirname,
21 | path: 'components'
22 | });
23 |
24 | server.route({
25 | method: 'GET',
26 | path: '/assets/client.js',
27 | handler: {
28 | file: Path.join(__dirname, './assets/client.js')
29 | }
30 | });
31 |
32 | server.route({
33 | method: 'GET',
34 | path: '/',
35 | handler: function (request, reply) {
36 |
37 | var appContext = {
38 | foo: 'bar'
39 | };
40 | var renderOpts = {
41 | runtimeOptions: {
42 | renderMethod: 'renderToString'
43 | }
44 | };
45 |
46 | server.render('app', appContext, renderOpts, function (err, appOutput) {
47 |
48 | var htmlContext = {
49 | remount: appOutput,
50 | state: 'window.state = ' + JSON.stringify(appContext) + ';'
51 | };
52 |
53 | server.render('html', htmlContext, function (err, htmlOutput) {
54 |
55 | reply(htmlOutput);
56 | });
57 | });
58 | }
59 | });
60 |
61 | server.start(function (err) {
62 |
63 | if (err) {
64 | throw err;
65 | }
66 |
67 | console.log('Server is listening at ' + server.info.uri);
68 | });
69 | });
70 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | var Lab = require('lab');
2 | var Code = require('code');
3 | var Hapi = require('hapi');
4 | var Vision = require('vision');
5 | var HapiReactViews = require('../index');
6 |
7 |
8 | var lab = exports.lab = Lab.script();
9 |
10 |
11 | lab.experiment('Engine', function () {
12 |
13 | lab.test('it is an object with a compile method', function (done) {
14 |
15 | Code.expect(HapiReactViews).to.be.an.object();
16 | Code.expect(HapiReactViews.compile).to.be.a.function();
17 | done();
18 | });
19 | });
20 |
21 |
22 | lab.experiment('Rendering', function () {
23 |
24 | var server;
25 |
26 | lab.beforeEach(function (done) {
27 |
28 | server = new Hapi.Server(0);
29 |
30 | server.register(Vision, function (err) {
31 |
32 | if (err) {
33 | return done(err);
34 | }
35 |
36 | server.views({
37 | engines: {
38 | jsx: HapiReactViews
39 | },
40 | relativeTo: __dirname,
41 | path: 'fixtures'
42 | });
43 |
44 | done();
45 | });
46 | });
47 |
48 |
49 | lab.test('it successfully renders with jsx compilation turned off', function (done) {
50 |
51 | var context = { title: 'Woot, with no jsx options.' };
52 | var renderOpts = {
53 | runtimeOptions: {
54 | useNodeJsx: false
55 | }
56 | };
57 |
58 | server.render('view-precompiled', context, renderOpts, function (err, output) {
59 |
60 | Code.expect(err).to.not.exist();
61 | done();
62 | });
63 | });
64 |
65 |
66 | lab.test('it fails if rendering jsx with jsx compilation turned off', function (done) {
67 |
68 | var context = { title: 'Ooops, node-jsx is disabled.' };
69 | var renderOpts = {
70 | runtimeOptions: {
71 | useNodeJsx: false
72 | }
73 | };
74 |
75 | server.render('view', context, renderOpts, function (err, output) {
76 |
77 | Code.expect(err).to.exist();
78 | done();
79 | });
80 | });
81 |
82 |
83 |
84 | lab.test('it returns an error when the path misses', function (done) {
85 |
86 | var context = { title: 'Woops.' };
87 |
88 | server.render('viewz', context, function (err, output) {
89 |
90 | Code.expect(err).to.be.an.object();
91 | done();
92 | });
93 | });
94 |
95 |
96 | lab.test('it successfully renders', function (done) {
97 |
98 | var context = { title: 'Woot, it rendered.' };
99 |
100 | server.render('view', context, function (err, output) {
101 |
102 | Code.expect(err).to.not.exist();
103 | done();
104 | });
105 | });
106 |
107 |
108 | lab.test('it successfully renders with runtime options', function (done) {
109 |
110 | var context = { title: 'Woot, with runtime options.' };
111 | var renderOpts = {
112 | runtimeOptions: {
113 | doctype: '',
114 | renderMethod: 'renderToString'
115 | }
116 | };
117 |
118 | server.render('view', context, renderOpts, function (err, output) {
119 |
120 | Code.expect(err).to.not.exist();
121 | done();
122 | });
123 | });
124 |
125 |
126 | lab.test('it demonstrates caching', function (done) {
127 |
128 | var context = { title: 'Woot, it rendered.' };
129 | var renderOpts = {
130 | runtimeOptions: {
131 | removeCache: false
132 | }
133 | };
134 |
135 | server.render('view', context, renderOpts, function (err, output) {
136 |
137 | Code.expect(err).to.not.exist();
138 |
139 | server.render('view', context, renderOpts, function (err, out) {
140 |
141 | Code.expect(err).to.not.exist();
142 | done();
143 | });
144 | });
145 | });
146 | });
147 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hapi-react-views
2 |
3 | A hapi view engine for React components.
4 |
5 | [](https://travis-ci.org/jedireza/hapi-react-views)
6 | [](https://david-dm.org/jedireza/hapi-react-views)
7 | [](https://david-dm.org/jedireza/hapi-react-views#info=peerDependencies)
8 | [](https://david-dm.org/jedireza/hapi-react-views#info=devDependencies)
9 |
10 | By default, we render static markup. We can also choose to use
11 | `React.renderToString`, preserving the `data-react-id` attributes so
12 | re-mounting client side is possible.
13 |
14 |
15 | ## Install
16 |
17 | ```bash
18 | $ npm install hapi-react-views
19 | ```
20 |
21 | Note: Your project should have it's own `react` dependency installed. We depend
22 | on `react` via `peerDependencies`.
23 |
24 |
25 | ## Usage
26 |
27 | Note: As of hapi v9.x, your project must register the
28 | [`vision`](https://github.com/hapijs/vision) plugin in order for the
29 | `server.views()` method to be available.
30 |
31 | Configuring the server manually:
32 |
33 | ```js
34 | var Hapi = require('hapi');
35 | var Vision = require('vision');
36 | var HapiReactViews = require('hapi-react-views');
37 |
38 | var server = new Hapi.Server();
39 |
40 | server.register(Vision, function (err) {
41 |
42 | if (err) {
43 | console.log("Failed to load vision.");
44 | }
45 |
46 | server.views({
47 | engines: {
48 | jsx: HapiReactViews
49 | },
50 | compileOptions: {}, // optional
51 | relativeTo: __dirname,
52 | path: 'views'
53 | });
54 | });
55 | ```
56 |
57 | Configuring with a CLI manifest using
58 | [`visionary`](https://github.com/hapijs/visionary):
59 |
60 | ```json
61 | {
62 | "servers": [{
63 | "port": 8080
64 | }],
65 | "plugins": {
66 | "vision": {},
67 | "visionary": {
68 | "engines": {
69 | "jsx": "hapi-react-views"
70 | },
71 | "compileOptions": {},
72 | "path": "./views"
73 | }
74 | }
75 | }
76 | ```
77 |
78 |
79 | ## API
80 |
81 | ### `server.views(options)`
82 |
83 | [Please refer to the `vision` docs on
84 | `server.views(options)` for complete details.](https://github.com/hapijs/vision/blob/master/API.md#serverviewsoptions)
85 |
86 | We'll be focusing on the `compileOptions` property that you can include when
87 | passing `options` to `server.views`.
88 |
89 | The following `compileOptions` will customize how `hapi-react-views` works.
90 |
91 | - `compileOptions` - options object passed to the engine's compile function.
92 | Defaults to `{}`.
93 | - `doctype` - a simple string prepended to the response. Defaults to
94 | ``
95 | - `renderMethod` - the method to invoke on `React` to generate our output.
96 | Available options are `renderToStaticMarkup` and `renderToString`.
97 | Defaults to `renderToStaticMarkup`.
98 | - `removeCache` - since `node-jsx` takes a while to startup, we can remove
99 | templates from the cache so we don't need to restart the server to see
100 | changes. Defaults to `'production' !== process.env.NODE_ENV`.
101 | - `useNodeJsx` - a boolean that controls if `node-jsx` is used. Defaults to
102 | `true`. Set to `false` if you're using another transformer (ex:
103 | `babel/require`) or don't need `jsx` transformations.
104 | - `node-jsx` - options object passed to
105 | [`node-jsx`](https://github.com/petehunt/node-jsx)'s `install` method.
106 | Defaults to `undefined`.
107 |
108 | You're able to override all these `compileOptions` at runtime except `node-jsx`
109 | which only happens once.
110 |
111 | ```js
112 | var context = { name: 'Steve' };
113 | var renderOpts = {
114 | runtimeOptions: {
115 | doctype: '',
116 | renderMethod: 'renderToString'
117 | }
118 | };
119 |
120 | server.render('template', context, renderOpts, function (err, output) {
121 |
122 | // ...
123 | });
124 | ```
125 |
126 | [Please refer to `vision`'s docs on
127 | `server.render(template, context, [options], callback)` for complete details.](https://github.com/hapijs/vision/blob/master/API.md#serverrendertemplate-context-options-callback)
128 |
129 |
130 | ## Examples
131 |
132 | Before you can run the examples, you need to clone this repo and install the dependencies.
133 |
134 | ```bash
135 | $ git clone git@github.com:jedireza/hapi-react-views.git
136 | $ cd hapi-react-views
137 | $ npm install
138 | ```
139 |
140 | ### Rendering a simple page
141 |
142 | This example renders a simple component as HTML output. [View the
143 | code.](https://github.com/jedireza/hapi-react-views/tree/master/examples/simple)
144 |
145 | ```bash
146 | $ npm run simple-example
147 | ```
148 |
149 | ### Rendering with layouts
150 |
151 | This example is renders simple components as HTML but adds the idea of using
152 | layouts. [View the
153 | code.](https://github.com/jedireza/hapi-react-views/tree/master/examples/layout)
154 |
155 | ```bash
156 | $ npm run layout-example
157 | ```
158 |
159 | ### Remounting on the client (universal/isomorphic)
160 |
161 | This example demonstrates the idea of remounting client side in order to create
162 | universal/isomorphic applications. [View the
163 | code.](https://github.com/jedireza/hapi-react-views/tree/master/examples/remount)
164 |
165 | ```bash
166 | $ npm run remount-example
167 | ```
168 |
169 |
170 | ## License
171 |
172 | MIT
173 |
174 |
175 | ## Don't forget
176 |
177 | What you create with `hapi-react-views` is more important than `hapi-react-views`.
178 |
--------------------------------------------------------------------------------