Alternative to NextJS: Isomorphic application stack for RiotJS
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.
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
- Clone this repo or use NPX
npx create-frontless <app-name>
- Setup a MongoDB Server (optional). Frontless reads
MONGODB_URI
environment variable.
# config.env MONGODB_URI=mongodb://localhost:27017/frontless
- 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:
- Give your component an unique id
export default { id: 'uniq-id', // target id state: { message:'' } ... }
- Use method app.setState() to compose a response
app.use('myservice',{ async create(data){ return app.setState('uniq-id', { message: 'Hello!' }) } })
- 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
- Anton Nesterov - @nesterow
Credits
- Gianluca Guarini - @GianlucaGuarini - riot/hydrate , Riot.js
License
This project is licensed under the MIT License - see the LICENSE.md file for details
Roadmap v1.0
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK