Using react router and iron router together


#1

Hi all we’re switching our Blaze app to React, and want to use react router in lieu of Iron Router. The issue is that the site depends on iron router for server requests, and the two do not play nice. Iron Router hijacks the client routes away from React Router, even though none are configured for Iron Router. We need Iron Router to live on the server, and React Router to live on the client, how do we keep them there?

Thanks


#2

Hi @jdmswong,

Did you find a solution to use both Iron Router (Server Side) and React Router (Client Side) together?

I also need to use Iron Router only server side especially to deal with file uploads.

Thanks,

Thomas.


#3

You can get around this if you’re using S3, in which case, check out https://github.com/CulturalMe/meteor-slingshot


#4

Thanks for your help @energistic.

I already tried Slingshot, but it looks like they do not manage server side upload (https://github.com/CulturalMe/meteor-slingshot/issues/164).

I built my entire REST API with Iron Router and use CollectionFS combined with Busboy to manage server side file upload.

Now I’m trying to use react-router on client side, but I don’t know how to use Iron router on server only.


#5

I know you are using React. But no matter what front end you are using, the Meteor server side is actually same.

The demo Angular2-Universal-Meteor is not for React specific, but it may help you.
It uses Angular router on client side, and FlowRouter on the server side.


#6

Hi @Hongbo_Miao, thanks for your help.

If I’m not wrong, Flow Router doesn’t support server side routing: https://github.com/kadirahq/flow-router#server-side-routing. The only router I found to make server side routing and handle file upload is Iron Router.

Iron Router can do server side routing and this is why I decided to develop my rest API with it. I could also make the client side routing with Iron Router, but this is not possible when using React (it only supports Blaze)…

I’m sure there is a way to disable Iron Router on client side to use another router such as Flow Router or React Router. I tried this, but it doesn’t work.

I’m gonna try to use both Iron Router and Flow Router together.


#7

That sounds complicated. Have you looked at nimble:restivus, simple:rest or centiq:crud for server-side endpoints?


#8

Thanks @robfallows.
Yes I did try restivus, and I was not able to upload and parse files with busboy.
If I’m not wrong, simple:rest doesn’t handle server side file upload.
I will try centiq:crud


#9

@thomaskn thanks for investigating. I came across the same issue. Did you figure it out?
Yea, Flow and React routes are both client side only so no way to use FlowRoute on server.
Thanks


#10

Unless I’m missing something, why don’t you just use https://github.com/peerlibrary/meteor-aws-sdk

I do server-side uploads with this all the time and it works great. I’ve only had good experiences with AWS’s sdk. I wouldn’t recommend using more than one router at the same time.


#11

@wikioops I found a solution to avoid the iron:router splash screen to show up.

Note that this solution is temporary (and pretty disgusting):

I added a template in main.html:

<head>
  <meta charset="utf-8">
  <title>My App</title>
</head>

<body>
  <div id="react-root"></div>
</body>

<template name="pageNotFound">
  <div id="notFound"></div>
</template>

Then I configured the notFoundTemplate in route.js:

if (Meteor.isClient) {
  Router.configure({
    notFoundTemplate: 'pageNotFound',
  });
}

So each time a page is loaded the iron:router splash screen is empty: <div id="notFound"></div>

But this is just a way to hide the splash screen, I didn’t find a solution to deactivate iron:router on client side.

@streemo thanks for your help! I decided to use iron:router to build a REST API. It works amazingly well but I just want it to work on server side. Using the meteor-aws-sdk will not help me building the REST API. Do you know a meteor package to build a REST API that can handle server side file upload?

#12

You can take a look at nimble:restivus: https://atmospherejs.com/nimble/restivus and centiq:crud: https://atmospherejs.com/centiq/crud


#13

Thanks @robfallows!
If I’m not wrong, nimble:restivus doesn’t handle server side file upload: https://github.com/kahmali/meteor-restivus/issues/25

CRUD isn’t REST, I need to build a REST API

I tried a lot of packages but iron:router is the only solution I found to deal with server side file upload via REST.


#14

CRUD lets you expose REST endpoints (the HTTP interface is used for those).


#15

Why don’t you just have the AWS SDK upload calls in your rest endpoint handler? Picker or Iron:router can provide such a handler.


#16

I use cfs:standard-packages to deal with file upload and iron:router to build the REST API.
Which package do you use for your REST endpoints? I’ll give meteor hacks:picker a try.


#17

In case anyone is still interested, I ended up using React Router mixed with https://github.com/meteorhacks/picker and it works flawlessly.


#18

@Siyfion I’m doing the same.

I used Iron Router before for both Client and Server side routing. After migrating off of IR and onto FlowRouter (and I’m soon going to move onto my version of FlowRouter named FineRouter after seeing 9 PRs on FlowRouter unanswered), I needed a server side router to fill in as FlowRouter is client side only. Picker worked great. I also made a version of Picker called FinePicker by the way. Anyone that wants to add PRs or contribute to FineRouter or FinePicker is more than welcomed.


#19

Might not be that relevant or overly complex, but I implement these kinda things by just starting an express server in parallel. You just install express and get-ports (to find a free port) with npm.

You start the express server on a free port and store that port in a global variable. On the client you can call a method that gets the url for the express server from the meteor server. Works very well for my specific needs, so might be an option for others.


#20

IIRC Collection FS has been deprecated and is no longer maintained. I highly recommend using picker and then doing this:

//approximately
import AWS from "peer-library:aws-sdk"
let S3 = new AWS.S3()
Picker.route('/api/v1/upload/',(req,par,res,next)=>{
  if (!passSecurityTest(req)){
    return res.end(403)
  }
  const opts = getOptsFromParams(par);
  S3.uploadFileSync(opts); //uploads to your s3 bucket.
}

It’s very straightforward. There are also known problems with uploading large files over ddp, where the socket interrupts after a few megabytes of piped data. I’m not sure if that’s still a problem or was fixed. None of what I am saying is useful for you if you absolutely must store objects in your own database. S3 is a great external storage for files, and is pretty easy to use.