Next.js:_next/webpack-hmr request 404 - javascript

This issue's demo repo is https://github.com/hh54188/happy-server/tree/issue-demo
I try to integrate Next.js with Hapi.js as a plugin. Here is my next.js plugin project folder main structure:
--plugins
|--app
|--pages
|--app
|--a.js
|--handlers
|--public
|--dist
|--index.js
|--next.config.js
And here is index.js main content, most for route register
const nextRenderService = next({
dir: path.join(__dirname)
});
module.exports = {
name: "AppService",
version: "0.0.1",
register: async function(server, options) {
await nextRenderService.prepare();
server.route({
method: "GET",
path: `/app/${assetPrefix}/_next/webpack-hmr`,
handler: nextHandlerWrapper(nextRenderService)
});
server.route({
method: "GET",
path: "/app/{param*}",
handler: defaultHandler(nextRenderService)
});
server.route({
method: "GET",
path: `/app/${assetPrefix}/_next/on-demand-entries-ping`,
handler: nextHandlerWrapper(nextRenderService)
});
server.route({
method: "GET",
path: `/app/${assetPrefix}/_next/-/page/{param*}`,
handler: {
directory: {
path: path.join(__dirname, pagesPath),
listing: true
}
}
});
server.route({
method: "GET",
path: `/app/${assetPrefix}/_next/{param*}`,
handler: {
directory: {
path: path.join(__dirname, distPath),
listing: true
}
}
});
}
};
However, when I run the server, and visit http://127.0.0.1:4000/app/a, the page could render success, and most script file could load successful. But the _next/webpack-hmr and the _next/on-demand-entries-ping requests status is 404. And I notice the 404 status is from Next.js, not Hapi.js
So what's wrong with my code ? How can I solve this problem ?

The issue has arisen right after upgrading nextjs 11 > 12.
This helped me:
npm install webpack-dev-server -g
source: https://stackoverflow.com/a/31627310/

The assetPrefix configuration is for using a CDN only and is global to NextJs (documentation). You don't want to set that for something else, like modifying the NextJs router paths. If you don't plan on using a CDN, just ignore this setting.
// in constants/index.js
const assetPrefix = process.env.NODE_ENV === "production"
? "https://cdn.mydomain.com"
: "";
You also do not want to list all NextJs internal routes and use the NextJs request handler to handle all calls:
// index.js
const next = require("next");
const path = require("path");
const nextRenderService = next({
dir: path.join(__dirname),
dev: process.env.NODE_ENV !== "production"
});
const { defaultHandler, nextHandlerWrapper } = require("./hanlders");
module.exports = {
name: "AppService",
version: "0.0.1",
register: async function(server, options) {
// https://github.com/zeit/next.js/blob/master/examples/custom-server-hapi/server.js
await nextRenderService.prepare();
// handle NextJs application requests
const handler = nextRenderService.getRequestHandler();
server.route({
method: "GET",
path: "/app/{p*}",
handler: async ({ raw, url }, h) => {
await handler(raw.req, raw.res, url);
return h.close;
}
});
// handle NextJs private routes
server.route({
method: "GET",
path: "/_next/{p*}" /* next specific routes */,
handler: nextHandlerWrapper(nextRenderService)
});
// Other routes
server.route({
method: "GET",
path: "/{p*}" /* catch all route */,
handler: defaultHandler(nextRenderService)
});
}
};

Related

How to do 301 redirect Next.js using fridays / next-routes

According to the Nextjs documentation I can make 301 redirect adding the following code to next.config.js
But the problem is that I am using next-routes and the solution is not working.
module.exports = {
async redirects() {
return [
{
source: '/about',
destination: '/',
permanent: true,
},
]
},
}
But the problem that it's not working with next-routes.
I need to redirect users from 'contact-us' to '/new/contact-us' page
My file with routing:
routes
.add('index', '/', 'index')
.add('contact-us', '/new/contact-us')
and next.config.js file
const withImages = require('next-images');
module.exports = withImages({
webpack: config => {
if (config.resolve.alias) {
const aliases = {
app: 'src',
};
for (const [alias, value] of Object.entries(aliases)) {
config.resolve.alias[alias] = path.resolve(__dirname, value);
}
}
if (process.env.NODE_ENV !== 'production') {
}
return config;
},
});
Please help how can I make 301 redirect?

How to fix CORS policy issue with get request?

please help me to solve CORS policy issue, it happens when I'm trying to make a get request to applications endpoint, and issue is only reproducible from http://localhost:8080/ on prod request works fine.
vue.config.js file
module.exports = {
devServer: {
proxy: 'https://spinstatus.zenoss.io/'
}
}
request method
const grabApps = async () => {
const res = await axios({
method: 'get',
url: `${spinnakerURL}/gate/applications`,
withCredentials: false,
crossdomain: true,
headers: {
'Access-Control-Allow-Origin': '*',
}
});
return res.data || []
}
error
headers from localhost request
headers from prod request
Change the devServer configuration in vue.config.js like this:
module.exports = {
devServer:
{
proxy:
{
'/gate':
{
target: 'https://spinstatus.zenoss.io',
changeOrigin: true,
onProxyReq: (proxyReq, req, res, options) =>
{
proxyReq.setHeader('Origin', 'https://spinstatus.zenoss.io');
}
}
}
}
};

Next.js Express Custom Server { dev: true } loads forever (empty response) but production { dev: false } works

I am using a express custom server with next.js. Custom Server
I added the next app to my router under the path /custom/uibackend/next
const next = require('next')
const app = next({ dev: true, dir: './', conf: { } })
const handle = app.getRequestHandler()
module.exports = router => {
router.all('*', (req, res) => handle(req, res))
}
If i run my app and access the route in the browser it loads for a while and gives a empty response back.
There is just this one log i the console:
info - Using webpack 5. Reason: Enabled by default https://nextjs.org/docs/messages/webpack5
If i build the app and set dev to false it works as expected and i can access the route and the pages.
const app = next({ dev: false, dir: './', conf: { } })
I used the following next.config.js file:
module.exports = {
basePath: '/custom/uibackend/next'
}
My /pages folder is in the root.
Thank you.
I have found the error.
I forgot to call app.prepare()
app.prepare().then(() => {
// add handle to router/app after app.prepare has finished
})

get List of routes via axios in Vue Webpack Cli

I'm using prerender-spa-plugin in my Vue Webpack Cli project. Like from the documentation i'm registering the Plugin in webpack.prod.conf.js like this
...
plugins: [
...
new PrerenderSpaPlugin(
path.join(__dirname, '../dist'),
['/', '/about', '/contact'],
{
captureAfterTime: 5000
}
)
]
I'm wondering if it would be possible to get the list of routes array via an axios call.
I tried the following without success:
var routes = axios.get('http://myapi.com/api').then(function (response) {
return response.map(function (response) {
return '/base/' + response.slug
})
})
plugins: [
...
new PrerenderSpaPlugin(
path.join(__dirname, '../dist'),
routes,
{
captureAfterTime: 5000
}
)
]
Since my Javascript knowledge is poor I'm not able to solve this. Thankfull for any hints.
Best regards
This currently won't work (or at least work reliably) because Webpack assumes your configuration is synchronous by default. To get around this is to use Webpack's support for asynchronous configuration and return a promise that is resolved after your route request.
If you are in an environment that supports async/await (node 8+) then it's as simple as exporting an async function. Otherwise, return a new Promise:
// webpack.conf.js
module.exports = async function () {
const response = await axios.get('http://myapi.com/api')
const routes = response.map((response) => {
return '/base/' + response.slug
})
return {
plugins: [
// ...
new PrerenderSpaPlugin(
path.join(__dirname, '../dist'),
routes,
{
captureAfterTime: 5000
}
)
]
}
}
If that isn't an option, you can always have a task that makes this request, writes it to a json file, and then require('./route-response.json') in your config.
I had a similar requirement - to get the list of routes from my API. I ended up creating a prebuild script - prebuild.js
const fs = require('fs')
const axios = require('axios')
// Fetch data from API
axios.get('http://myapi.com/api.php')
.then(function(response) {
const data = response.data
try {
// Save the route list to local file
fs.writeFileSync('./route-response.js', data)
} catch(err) {
console.log(err)
}
})
.catch(function(err) {
console.log(err)
})
My API sends the data of the route-response.js file, ready to be directly saved and consumed by npm. You could handle this formatting in Node instead. Sample format:
module.exports = {
theList: [
'/',
'/about',
'/contact',
'/login',
'/register'
]
}
The above file is fetched in webpack.prod.conf.js as below:
...
const routeList = require('./route-response.js')
...
const webpackConfig = merge(baseWebpackConfig, {
...
plugins: [
...
new PrerenderSPAPlugin({
staticDir: path.resolve(__dirname, '../dist'),
routes: routeList.theList,
renderer: new PuppeteerRenderer()
})
...
]
...
})
and finally, add the prebuild script to the package.json
prebuild: runs before the build step.
postbuild: runs after the build step.
Here's a sample
...
"scripts": {
"dev": "node build/dev-server.js",
"prebuild": "node build/prebuild.js",
"build": "node build/build.js"
},
"dependencies": {
...
This way, I only have to run npm run build

How to mock a server error in hapi

I have set up a hapi server as follows:
'use strict'
// node modules
const Hapi = require('hapi')
const Inert = require('inert')
const Path = require('path')
// server config
const server = new Hapi.Server()
const port = 4000
server.connection({
port: port
})
// Hapi plugins
const plugins = [
Inert
]
server.register(plugins, (err) => {
if (err) {
throw err
}
server.route([
{
method: 'GET',
path: '/',
handler: (request, reply) => {
reply.file(Path.join(__dirname, '../front/production/index.html'))
}
},
{
method: 'GET',
path: '/{param*}',
handler: {
directory: {
path: 'front/production'
}
}
}
])
})
module.exports = server
I have written tests for it, but have a problem being able to cover this line:
if (err) {
throw err <----
}
how can I mock a server error in server.register, so far I have tried:
server.inject({method: 'GET', url: '/notanendpoint'}...
server.inject({method: 'NOTMETHOD', url: '/'}...
server.inject({method: 'GET', url: '/', simulate: {error: true}}...
I've been looking through the hapi api docs and cant work out how to cover this line, any help would be greatly appreciated.
Let me know if I can add more description to my question or include what I have tried in my tests (let me know if you want to see more of my test file)

Categories