35

Alternative to NextJS: Isomorphic application stack for RiotJS

 5 years ago
source link: https://www.tuicool.com/articles/7JjU7r3
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

zArMRbR.png!web

Riot Isomorphic/SSR Stack

Frontless aims to provide classic web development experience with modern approach.

Classic MVVM approach significantly complicates work with data. In fact, on practice, a frontend developer would end up writing the code that would be better performed by server rather than a client. I believe that the server has to be responsible for things like routing, data requests, user state, and and some cases component's view-model. These are routines that the server does better than browser.

  • It is just an ExpressJS application.
  • It uses FeathersJS on client and server.
  • It is built with :heart: RiotJS.
  • It provides natural routing page.riot -> GET /page
  • It allows to update components' state directly from server response

Getting Started

  1. Clone this repo or use NPX
npx create-frontless <app-name>
  1. Setup a MongoDB Server (optional). Frontless reads MONGODB_URI environment variable.
# config.env
  MONGODB_URI=mongodb://localhost:27017/frontless
  1. Install dependencies and start dev. server
npm run install
  npm start

Оpen http://localhost:6767 in your browser. Navigate to the playground for examples

The Stack

Essential understanding of following technologies is recommended .

Server Client Routing (Express.JS ) Navigation (Turbolinks) View Model (FeathersJS) Data Representation (RiotJS) Layout Rendering (RiotJS SSR) User input (RiotJS) Session / User State (Express.js) JWT, Cookies Realtime (Feathers, SocketIO) FeathersJS Client DB Interface (FeathersJS Client) Rest/IO (FeathersJS Client)

Core concepts

Natural Routing

All files ending with *.riot placed in the pages become site pages, much like php scripts or html pages. [ index.riot -> GET / , page.riot -> GET /page ]

Passing arguments in url

Passing positional argument to the page is possible trough @ modifier. A semicolon-separated string after @ will be parsed as positional arguments. For example consider following request:

GET /page@some_id;data?q=1

This request will fetch page.riot and pass positional arguments into 'request.params.args':

export default {
  async fetch(props){
    const {req} = props;
    const [user_id, data] = req.params.args;
  }
}

Server side rendering

All RiotJS components included in pages will render after all data is fetched. Use method fetch(props) in your components to make db queries and setting components' state on the server. Unlike similar method in next.js , in Frontless you can fetch data in any children component and your page will be rendered after all fetch operations are complete.

export default {
  async fetch(props) {
    const {params, session} = props.req
    const userProfile = await db.users.get(session.user.id)
    this.update({
      username: session.username,
      userProfile
    })
  }
}

Server sent state

Some API requests can return a ready view-model for a specific component. After it happens the target component will update its state from received response. This is convenient whenever you want to update the view after a request is done. Given that, the server should return a ready view-model which eliminates extra steps you would do to handle response.

Normally, you should follow 3 steps to make it work:

  1. Give your component an unique id
export default {
  id: 'uniq-id', // target id
  state: {
    message:''
  }
  ...
}
  1. Use method app.setState() to compose a response
app.use('myservice',{
    async create(data){
      return app.setState('uniq-id', {
        message: 'Hello!'
      })
    }
})
  1. On the client make a call to service method which suppose to return new state
client.service('myservice').create({})

Notice that you don't need to handle API call as the server supposed to return ready view-model for your component. The UI will update automatically. However, you still nedd to handle loading states and errors.

Access control

Access to pages can be controlled trough options set in the access property:

export default ()=> ({
  access: {
    loggedIn: true,
  },
  state:{},
  ...
})

By default two options are awailable: loggedIn and group .

Authentication

Authentication is impemented with @feathersjs/authentication-local module. In order to customize user model you need to modify verifier class and the plugins

Security

  • Under no circumstances, It is NOT recommended to turn off the CORS middlewares .
  • When working with Riot Components, it is NOT recommended to use sensitive variables or use any sentive data as open text
  • When working with Riot Components, is is HIGHLY recommended to use functional approach. Every component should be returned from a function like export default ()=> ({...component}) . This is needed to avoid module caching

Authors

Credits

License

This project is licensed under the MIT License - see the LICENSE.md file for details

Roadmap v1.0


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK