Step by step guide for creating your first App.
Before anything, you need to initialize a new npm package for your App:
$ npm init
Fill in the details, like your App's name, in the CLI prompts.
Install the minimum dependencies required to get your App up and running, :
$ npm install --save frint frint-react react react-dom prop-types
And also the the build tools:
$ npm install --save-dev babel-core babel-preset-travix webpack babel-loader
We use Babel for transpiling ES6/JSX code to browser compatible ES5. Since we already ship our own Babel preset, all you need to do is create a new .babelrc
file in your root directory with this content:
{
"presets": [
"travix"
]
}
We try to follow a convention for our file structure in Apps. A simple App's directory tree would look like this:
├── app/
│ ├── index.js
├── components/
│ ├── Root.js
├── .babelrc
├── index.js
├── webpack.config.js
└── package.json
Creating a new App class is pretty straightforward. You would be required to create a new file at app/index.js
with the following content:
// app/index.js
import { createApp } from 'frint';
import RootComponent from '../components/Root'; // we still need to write this file
export default createApp({
name: 'MyAppName',
providers: [
{
name: 'component',
useValue: RootComponent
}
]
});
Previously, we saw that App requires a Component for rendering. We will write our entry-level Component in components/Root.js
:
// components/Root.js
import React from 'react';
export default function Root() {
return (
<p>Hello World!</p>
);
}
Basically, you import the createApp
function from our frint
package, and define your App by giving it a name, and also the Component that it needs to render.
You can also use our higher-order component observe
coming from frint-react
to access the app
instance, and generate the props for your component (which can live anywhere in the components tree):
// components/Root.js
import React from 'react';
import { observe } from 'frint-react';
function Root(props) {
// `props.appName`: name of your App (`MyAppName`)
// return JSX
}
export default observe(function (app) {
// `app` is your Root App's instance here
// the object you return from here,
// is going to be the props of your Root component
return {
appName: app.getName(),
};
})(Root);
You can also stream the props expressed as an Observable, that will keep passing new updated props to your Component:
import React from 'react';
import { observe } from 'frint-react';
import { Observable } from 'rxjs';
function Root(props) {
// JSX
}
export default observe(function (app) {
const interval$ = Observable.interval(1000);
// return an Observable,
// that emits a props-compatible object over time
return interval$
.map(x => ({ interval: x }));
})(Root);
Now your base component will be receiving an interval
prop that keeps incrementing every second.
Now that we have our App
defined, we can import and instantiate it, and then render it to the DOM:
// index.js
import { render } from 'frint-react';
import App from './app';
const app = new App();
render(app, document.getElementById('root'));
The code above assumes, you have an element in your webpage with ID root
:
<!-- ./build/index.html -->
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>
We use Webpack for bundling Apps, and to do that, we require a webpack.config.js
file in root directory:
module.exports = {
entry: __dirname + '/index.js',
output: {
path: __dirname + '/build',
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.(js)$/,
loader: 'babel-loader',
query: {
presets: [
'travix'
]
}
}
]
},
};
The build can now be performed with this command:
$ ./node_modules/.bin/webpack --config ./webpack.config.js
Doing so would generate a new bundle at ./build/bundle.js
.
Open your index.html
file in the browser, and you would see Hello World
.