require.ensure error in React Code Splitting - reactjs

I'm using react-router's code splitting(Dynamic Routing). When building app from webpack it doesn't give error, but when running it, it is giving me error of require.ensure is not a function. I'm using server-side rendering also.
Following is my getComponent code
module.exports = {
path: "/",
getComponent(nextState, cb) {
require.ensure([], (require) => {
cb(null, require('./component/Home'));
})
}
};

I think server side render doesn't support require.ensure, because node has its own require, and when you use server side render, it will use node require, not webpack require.
I think you should try to user different routes for server and client. the server routes don't use dynamic route

Related

Link tag in React is not working with devserver-proxy

I'm following this tutorial to make my React app (localhost:3000) communicate with Node server (localhost:5000) .. so instead of typing <Link to='localhost:5000/auth/google'>Login with Google</Link> I only want it to be just '/auth/google', but when I click on the button with Link tag it sends this error "No routes matched location "/auth/google"
I'm using React v17.0.2
this is what's inside my setupProxy.js file
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use(
["/auth/google", /api/*],
createProxyMiddleware({
target: "http://localhost:5000",
changeOrigin: true,
})
);
};
the weird thing though is that I got no error when I type the route directly in the browser (both ports work just fine) and it redirect me to the page I want (handled by Express)
If there's no solution for this problem for now, is there any other way to use a proxy in a MERN application because from what I know adding "proxy" in package.json is not working anymore

ngrok does not work with react-router when deep links are explicitly defined

Context: I'm opening up my React dev environment to external hits using a paid version of the tool ngrok -- I am running WebPack 4.0 with a devServer.
I go to my app's main page:
https://my-example-domain.ngrok.io
Loads fine.
I click one of the links on my app's main page, The router works well and I see the content for:
https://my-example-domain.ngrok.io/my-sub-page
However, if I refresh at this point, ngrok gives out a 404:
Cannot GET /my-sub-page
The reason I suspect is that in a SPA, the internal app's URLs are processed by the front end in React-Router and externally, there is no resource called /my-sub-page
Is there a way to force this to work?
The problem is that the local server doesn't know about your spa routes(react-router). To fix this, you have to create a simple server that will serve your static build and have a fallback route that will enable spa-routing.
Example in express.js:
import express from 'express';
import path from 'path';
// ... other imports
const app = express();
app.use(express.static('build'));
/*
... some route handlers
*/
// * Unknown endpoint
app.use("/*", (_req, res) => {
res.sendFile(path.join(__dirname, "../build/index.html"), (err) => {
if (err) {
res.status(500).send(err);
}
});
});
app.listen(process.env.PORT || 3000 , ()=>{
console.log('server running')
})
This resolved it -- in webpack.config.js
devServer: {
...
...
historyApiFallback: true, // <- inserting this resolved the issue.
}

Shallow routing using withRouter and custom server not working

Using withRouter as a wrapper with custom server, shallow routing doesn't seem to be working.
I currently use this method to change the route:
this.props.router.push({
pathname: currentPath,
query: currentQuery,
});
router prop comes from using withRouter to wrap my class component.
And couldn't figure where to put the shallow flag. So I switched to the method mentioned in the docs:
this.props.router.push('/post/[pid]?hello=123', '/post/abc?hello=123', { shallow: true })
So I did that manually, but I started getting 404s.
http://localhost:3000/_next/static/development/pages/search/%5Btype%5D/%5Bcat%5D/%5Barea%5D.js net::ERR_ABORTED 404 (Not Found)
decoded:
"http://localhost:3000/_next/static/development/pages/search/[type]/[cat]/[area].js"
I tried using :type instead of [type] but it also didn't work.
This is how it's configured on the server:
if ('/search/:type/:cat/:area' === route.path) {
return app.render(req, res, route.page);
}
Folder Structure:
/pages/search/index.js
I think this structure has something to do with the problem, since it's in the index.js and not just a plain file in the pages folder.
It should not reload the page while changing the route, that's the main thing I'm trying to accomplish.
I'm implementing SSR pagination, and I'm planning to use shallow routing to make page changes happen on the client instead of the server. Meaning achieve SSR on first load only, keep user in without refreshing.
I also tried this:
server.get('/search/:type/:cat/:area', (req, res) => {
console.log("reached here..."); // this gets logged
return app.render(
req,
res,
'/search/[type]/[cat]/[area]',
req.params
);
});
But I'm getting 404s, the page is not there now!
This also didn't work:
this.props.router.push(
`/search/[type]/[cat]/[area]?${stringifyQs(currentQuery)}`,
{
pathname: currentPath,
query: currentQuery,
},
{ shallow: true }
);
This should work:
server.js
server.get('/search/:type/:cat/:area', (req, res) => {
return app.render(req, res, '/search', {
...req.params,
...req.query,
});
});
pages/search/index.js
props.router.push(
'/search?type=foo&cat=bar&area=baz&counter=10',
'/search/foo/bar/baz?counter=10',
{ shallow: true }
);
Linked issue from GitHub

How do I rewrite all urls to index.html in Heroku?

My Heroku app is using React with React Router. I use Switch to navigate through different components, so the URL changes as well (e.g. /room/4141). However, if I reload the page, it doesn't act like if it was a React app, but instead it searches for the mentioned .html file.
I used this Buildpack: https://github.com/mars/create-react-app-buildpack.git but it seems to do nothing in regards with pages being rewritten to index.html.
Is there a way to prevent this behaviour and rewrite all URLs to index.html?
**EDIT:
I'm not familiar enough with express, but here's how the index.html is served.
const express = require("../../node_modules/express");
const app = express();
const server = require("http").Server(app);
const io = module.exports.io = require('../../node_modules/socket.io/lib')(server)
const path = require("path")
app.use(express.static(path.join(__dirname, '../../build')));
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../../build')));
console.log("DEBUG HERE", __dirname, path.join(__dirname+'../../build'));
//
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname+'../../build/index.html'));
})
}
//build mode
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname+'../../public/index.html'));
})
That buildpack can be configured via a JSON file:
You can configure different options for your static application by writing a static.json in the root folder of your application.
One of the sample routing configurations looks like it does exactly what you want:
When serving a single page app, it's useful to support wildcard URLs that serves the index.html file, while also continuing to serve JS and CSS files correctly. Route ordering allows you to do both:
{
"routes": {
"/assets/*": "/assets/",
"/**": "index.html"
}
}

Client side routing with react-router and expressJS only works one level deep

I'm trying to use react-router to enable client side routing, but I can only get the routing to behave as expected at one level deep past "/". (i.e. localhost:8080/ works, localhost:8080/{id} works, but localhost:8080/vote/{id} does not)
Additionally, I am trying to develop locally using webpack-dev-server, and deploy to heroku using webpack -p and an expressjs server. My express server is set to have all routes default to index.html.
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, './dist/index.html'));
});
When using npm start (express server) and I try to navigate to localhost:8080/vote/{id} the console says: SyntaxError: expected expression, got '<' meaning I have a situation like this issue. However, when using webpack-dev-server, I get a different error in the console that says: Loading failed for the with source “http://localhost:8080/vote/bundle.js”. I believe what I'm seeing is two different outputs for the same core problem, the difference being my environment or differences in how express/webpack-dev-server are serving up the content.
Here is my full expressJS server:
const express = require('express');
const path = require('path');
const port = process.env.PORT || 8080;
app = express();
// the __dirname is the current directory from where the script is running
app.use('/', express.static(path.resolve(__dirname, 'dist')));
// send the user to index html page inspite of the url
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, './dist/index.html'));
});
app.listen(port);
console.log("server started on port " + port);
Here are the relevant parts of my webpack.config.js:
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: "/"
},
devServer: {
contentBase: path.resolve(__dirname, "dist"),
historyApiFallback: true
}
And here is my App.js with relevant routes (Home, RealtimeView, PollVote being custom React components):
export default class App extends Component {
render() {
return (
<BrowserRouter history={browserHistory}>
<div>
<Route exact path="/" component={Home} />
<Route exact path="/:id" component={RealtimeView} />
<Route exact path="/vote/:id" component={PollVote}/>
</div>
</BrowserRouter>
);
}
}
With this configuration, I can reliably get localhost:8080/ to work and localhost:8080/{whatever} to work but localhost:8080/vote/{id} or any route more complicated than localhost:8080/{something} fails with the errors I mentioned earlier depending on if I'm using webpack-dev-server or my expressjs server.
FWIW I'm relatively new to webdev (my experience so far is that it's a cluster-fck) and I can't go with a totally isomorphic app because my back-end is in java/spring and I'm not re-writing my whole back-end. I found this post to be helpful but it doesnt solve my problem. Please help this is making me crazy.
Try setting fallback file explicitly:
historyApiFallback:{
index: 'index.html'
}

Resources