React - Best practice for application with different entry points/sections - reactjs

I'm working on a larger React Application right now and have some questions about if I set everything up correct (Best Practice). The application has two different "sections". I'm trying to give an easier example (school scenario) how the structure is set up:
The first section of the application is used by principal to set up school classes, teachers, students, rooms, etc...
The section section is used by all the users (teachers, students) that the principal defined. The teachers can set up timetables, etc...
Now what I trying to is: The principal can access his section of the application with the url: admin.school.com - The teachers and students can access the application with the url: school.com
I've put everything in a single react application right now, so I can use the same design, components, etc. During development I switch between the two applications by comment out the application I don't want to access in the index.js file:
// ReactDOM.render(<AppAdmin />, document.getElementById('root'));
ReactDOM.render(<App />, document.getElementById('root'));
My question now is: (How) is it possible that I can get a Build of the application with two "index.html" files so "admin.school.com" points to "admin.html" and "school.com" points to "index.html". My main goal is (like I said) - to have one code basis on my server and just two different html files. Is this possible or do I need to build the application twice? The principal should be able to access the normal section without new login.
I hope that my explanation was easy to understand. Thank you for your help!

You can use process.env to pass environment variables (see https://create-react-app.dev/docs/adding-custom-environment-variables/ if using create-react-app), e.g. in index.js:
const Component = process.env.REACT_APP_ADMIN ? AppAdmin : App
ReactDOM.render(<Component />, ...)
and in package.json:
"scripts": {
...
"build-admin": "REACT_APP_ADMIN=1 npm run build"
}

You can split React application into several Single Page Applications (SPAs). Crisp React boilerplate supports this functionality. Although it uses TypeScript.
My question now is: (How) is it possible that I can get a Build of the application with two "index.html" files.
The two .html files can be called differently.
You can have one SPA called admin with the entry point (also called landing page) admin.html. And another SPA called school with entry point school.html. All you need for that is to modify the SPA Configuration block:
var SPAs = [
new SPA({
name: "admin",
entryPoint: "./src/entrypoints/first.tsx",
redirect: false
}),
new SPA({
name: "school",
entryPoint: "./src/entrypoints/second.tsx",
redirect: true
})
];
SPAs.appTitle = "SchoolApp";
and execute yarn build. Both SPAs are created for you with .html files. Of course you can write admin.tsx, school.tsx and use it instead of first.tsx, second.tsx.
so "admin.school.com" points to "admin.html" and "school.com" points to "index.html".
This is a non-React part.
You create two DNS entries for "admin.school.com" and "school.com", both pointing to the same IP address of your webserver. Let's assume you use NodeJS/Express. In its route handler for / e.g. app.get("/", (req, res, next) => { ... } examine req.hostname and depending on it being either "admin.school.com" or "school.com" make the handler serve admin.html or school.html.

Related

NextJS custom URLs

I want to transfer my blog from Jekyll to NextJS and looking how to specify custom URLs.
I followed the official NextJS guide on their website, but the routing part was relatively simple. From docs, I got that URLs are based on folders/files structure, but I want to have a subfolder per site topic in the pages folder but keep URLs flat. Something like that:
pages (top-level folder)
investing (subfolder)
how-to-start-investing.js (https://example.com/how-to-start-investing <- no investing folder in URL)
devops (subfolder)
how-to-upgrade-ubuntu.js ([https://example.com/how-to-upgrade-ubuntu <- no devops folder in URL)
In Jekyll, I used Front Matter to specify a custom URL per page. In NextJS looks like I have to use rewrites, but is there any other option?
Also Link component has an attribute to change the link URL, but this is just to display links with URLs.
In NextJS, routes are defined by the structure of the pages directory. If you don't want that, you're going to have to work around that feature. Some options you have:
Use rewrites to map incoming request from /how-to-start-investing/ to /investing/... — note that unlike redirects, rewrites don't expose the destination path, so the user will stay on /how-to-start-investing/ url.
Create files in the root directory called how you want your routes to be exposed (e.g. how-to-start-investing.js). Inside the file, export another component, for example:
// how-to-start-investing.js
import { HowToStartInvesting } from "../components/investing/HowToStartInvesting";
export default HowToStartInvesting;
If you use this approach, I suggest you put your components somewhere outside the pages directory, so you don't have two urls for the same component.
Finally got it to work, so in order to use custom URLs, I have to combine rewrites with redirects, the latter needed for SEO.
Without redirects, I can just use the canonical tag to tell Google my preferred URL, but technically the same article keeps on being available using two URLs, in my case:
sypalo.com/how-to-start-investing
sypalo.com/investing/how-to-start-investing
So the final next.config.js is:
module.exports = {
async rewrites() {
return [
{
source: '/how-to-start-investing',
destination: '/investing/how-to-start-investing'
}
]
},
async redirects() {
return [
{
source: '/investing/how-to-start-investing',
destination: '/how-to-start-investing',
permanent: true
}
]
}
}
And this is to be repeated for all URLs.

Add Gatsby blog to specific URL in a React app

I have two separate apps. One is a react app that is deployed at www.example.com, the other is a completely separate blog app built with Gatsby.
I would like users to be able to visit www.example.com/blog and see the blog app without using a redirect that would change the URL.
Both apps are hosted as separate firebase projects, is this achievable?
There's a feature called pathPrefix which purpose is what you are looking for.
You just need to set it in the main Gatsby configuration file (gatsby-config.js):
module.exports = {
pathPrefix: `/blog`,
}
Following the previous example, a link to /test-1 will be rewritten as /blog/test-1 automatically.
Another important consideration is to understand that all your building commands (build and serve) will need to be respectively flagged as:
gatsby build --prefix-paths
gatsby serve --prefix-paths
During development paths don't need to be prefixed.
In-app linking is handled automatically by Gatsby's Link component.
For pathnames you construct manually, there’s a helper function, withPrefix that prepends your path prefix in production.
Additional resources:
https://www.gatsbyjs.com/docs/how-to/previews-deploys-hosting/asset-prefix/
https://www.gatsbyjs.com/docs/deploying-to-gitlab-pages/#add-path-prefix-to-gatsby

Serve react project on dev througth proxy

I've split my react application in 3 different projects, using CRA for all of them, auth, X and Y. User is first sent to auth, then I redirect him to either X or Y based on some info.
It works perfectly on PRODUCTION environment (because they run on the same domain), but on dev, X and Y failed to authenticate the user, because they run on different ports (different domains) the data in local storage is not shared between auth, X and Y.
I've tried to find a way to use a reverse proxy (http-proxy) to host the React dev servers on the same domain, but failed too, because the services could not find the assets/static folder, resulting in 404. Also tried http-proxy-middleware, as it is recommended on the CRA docs page, but failed to do so. Is there an easier way that I'm not seeing?
Edit: Found something new, but also failed. Used react-rewired to override CRA scripts, to use PUBLIC_PATH on DEV, but now my bundle.js returns an index.html file.
The following code does redirect to the accordingly react project, but the assets are requested to the wrong path.
const apiProxy = httpProxy.createProxyServer();
app.all("/login/*", function(req, res) {
console.log('redirecting to Login');
apiProxy.web(req, res, {target: servers.login});
});
app.all("/implementacao/*", function(req, res) {
console.log('redirecting to Implementation');
apiProxy.web(req, res, {target: servers.implementation});
});
So I used react-rewired to change the public path
const {
override,
} = require('customize-cra');
module.exports = {
webpack: override(
(config) => {
config.output.publicPath = '/login/';
return config;
},
),
jest: config => {
return config;
},
devServer: configFunction => (proxy, allowedHost) => {
return configFunction(proxy, allowedHost);
},
paths: (paths, env) => {
return paths;
}
};
Now, the assets requests are made correctly to /login/, but nothing the dev server always return an index.html file.
Even with react-app-rewired, to override config, and use publicPath on dev, the assets will not be served from the publicPath.
There is already a pull request on CRA to use PUBLIC_URL in dev mode.
Is there an easier way that I'm not seeing?
Another approach would be to use multiple React Single Page Applications (SPAs) inside one application, see crisp-react. E.g. instead of 3 CRAs in 3 applications/projects have 3 SPAs in one application/project. The backend surely can get data from other backend servers transparently for each SPA.
how do I migrate from a set of existing CRA projects to using crisp-react ?
Background
crisp-react comes with two stock SPAs called ‘First’ and ‘Second’. Both render some explanatory/sample UI.
Migration overview
1.Pick one CRA project and migrate it to the ‘First’ SPA. When finished, you have two CRAs left and two crisp-react SPAs: ‘First’ (renders your UI) and ‘Second’ (still renders the sample UI). Rename the ‘First’ SPA to give it more meaningful name.
2. Pick another CRA and migrate it. When finished, you have one CRA left and two crisp-react SPAs both rendering your UI.
3.Modify crisp-react to add the third SPA and then migrate the remaining CRA to the third SPA.
Migration steps (sketch)
1.1 Follow crisp-react Getting Started.
1.2 The landing page of the First SPA is rendered by crisp-react/client/src/entrypoints/first.tsx
The landing page of the CRA is rendered by src/index.tsx
Replace the content of the former with the latter.
1.3 The first CRA consists of React components: src/App.tsx and others you added. Copy the components to crisp-react/client/src/components/from-first-cra/
1.4 Ensure crisp-react client app compiles: From crisp-react/client/ execute: yarn compile
1.5 Ensure crisp-react client app builds: From crisp-react/client/ execute: yarn build
1.6 Ensure crisp-react client looks ok without backend data: see client Usage Scenarios.
1.7 Get the backend (e.g. Express) involved: see backend Usage Scenarios.
1.8 Milestone reached: browser can be pointed to backend (Express) and get from it html files and bundles - which results in the first SPA rendering initial UI (to the extent possible without data supplied via API enpoints).
1.9 Decide how the the first SPA will get data from API. 3 basic choices here:
- the API endpoints are implemented in Express so you can retire your backend servers
- Express does expose API endpoints but acts as a reverse proxy getting data from your backend servers
- Express knows nothing about API and data supplied by backend servers that are queried directly by the components inside the first SPA.
2.1 Second SRA
as above
...

create-react-app with multiple entries

I have a create-react-app project where I am creating a front side for users and an admin side, and want this two sides to use the same code base and run on one time instead of building two separate apps and each will use a different theme and files.
As suggested in some places I have ejected my create-react-app App and then tried adding a different entry point as suggested in this tutorial:
http://imshuai.com/create-react-app-multiple-entry-points/
but when i navigate to /admin nothing happens...any suggestions?
I am using react-router-dom as well.
When you navigate to /foo Webpack dev server has a little convenience feature to consider /foo/index.html as well if /foo does not exist. This is probably meant to be compatible with the user's expectations of other HTTP servers (i.e. Apache, Nginx). This means that /admin resolves to either something actually called /admin or /admin/index.html if the former is unavailable.
If you did follow the linked tutorial, the path you are looking for is clearly not supposed to be /admin but /admin.html. And your normal 'user' front end remains at /index.html, which is why you can still navigate to it the same way you were used to before ejecting.
Note: I don't speak Japanese, but I do read Webpack, so I just looked at the sample Webpack config and layout of the build/ folder as described in the tutorial.

Running an Backbone app as an independent JS application - Routes not working

currently, I run backbone as the front-end of my rails 3.2 application. I need to migrate it into an independent JS application, as part of my putting it as part of Trigger.io.
It now exists as its own index.html file, referencing the assets folder.
When I open the file, it loads the Backbone modules, but the page remains empty. And when I run fetch() commands, it
So, I got a couple of qns:
1) How do I trigger the routes such that it goes to a designated page by default?
I know it gets triggered in Backbone.History.Start, but I am not sure what to do before that.
2) The url is "file://localhost/Users/mingyeow/Desktop/index.html"
How do I set the root url manually to use localhost:3000/my web address?
// define router
var Router = Backbone.Router.extend({
routes : {
'index' : 'indexAction',
'*default' : '_defaultAction'
},
indexAction : function() {
// this will be executed when user navigate to #index
},
_defaultAction : function() {
// this will be executed when user navigate anywhere else (#XXX)
}
});
// on document ready
$(function() {
// initialize router
new Router();
// and start history
Backbone.history.start();
});
You can navigate this way.
Or by clicking the link : Index route
You can use python server. To start it type in the Terminal:
$ python -m SimpleHTTPServer
And check http://localhost:8000
1) To trigger a route change you just need to navigate to a page via a href or JavaScript like window.location. Read up on Backbone Routes but essentially you need to write a function for every 'page'. Each function should take care of rendering the page.
2) This should be very simple. You need a local web server. What I started doing recently is just having a simple Node server. Node is very easy to install and its worth experimenting with. Download a static web server such as this one I made. To use it just put your backbone application in a directory named 'public' and run server.js in node.
If you don't want to do this you can run a simple LAMP/WAMP/MAMP installation and set the root of the Apache web server.

Resources