next.js
next.js copied to clipboard
On demand ISR works fine in local machine but fails when deployed to iisnode running in azure windows webaps
Verify canary release
- [X] I verified that the issue exists in Next.js canary release
Provide environment information
Operating System: Platform: win32 Arch: x64 Version: Windows 10 Enterprise Binaries: Node: 16.13.1 npm: N/A Yarn: N/A pnpm: N/A Relevant packages: next: 12.1.7-canary.23 react: 17.0.2 react-dom: 17.0.2
What browser are you using? (if relevant)
chrome
How are you deploying your application? (if relevant)
next start
Describe the Bug
On demand ISR works on Local machine . But when deployed to windows webapp iisnode revalidate fails with Error revalidating
Expected Behavior
Revalidate should work fine
To Reproduce
// pages/api/revalidate.js export default async function handler(req, res) { // Check for secret to confirm this is a valid request if (req.query.secret !== process.env.MY_SECRET_TOKEN) { return res.status(401).json({ message: "Invalid token" }) }
try {
await res.unstable_revalidate("/en-us/gentiane-valiquette")
return res.json({ revalidated: true })
} catch (err) {
// If there was an error, Next.js will continue
// to show the last successfully generated page
return res.status(500).send("Error revalidating")
}
}
//package.json
"scripts": { "start": "node server.js", "dev": "next dev", "build": "next build", "postbuild": "node -e "require('./config/generators').generateSSRWebConfig()"", "export": "npm run check-quality && next build && next export", "postexport": "babel-node -e 'require("./config/generators").generateSitemap()' && babel-node -e 'require("./config/generators").generateSSGWebConfig()'", "preview": "npm --production=false install && next build", "setup-preview": "npm --production=false install && next build", "dev:debug": "cross-env NODE_OPTIONS='--inspect' next dev", "lint": "npm run lint:js && npm run lint:styles && next lint", "lint:fix": "npm run lint:js-fix && npm run lint:styles-fix && next lint", "lint:js": "eslint "./src/pages/.js" "./src/components/**/.js" "./src/adapters//.js"", "lint:js-fix": "eslint "./src/pages/.js" "./src/components//.js" "./src/adapters/**/.js" "./src/store/.js" --fix", "lint:styles": "stylelint "src/components/**/.styles.js" "src/styles//*.css"", "lint:styles-fix": "stylelint "src/components//.styles.js" "src/styles/**/.css" --fix", "eslint-report": "eslint --ext .jsx,.js "./src/components/**" -o report.json -f json",
Server.js
--------------------
// server.js
const { createServer } = require('http') const { parse } = require('url') const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = process.env.PORT || "3000"
// when using middleware hostname
and port
must be provided below
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer(async (req, res) => {
try {
// Be sure to pass true
as the second argument to url.parse
.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true)
const { pathname, query } = parsedUrl
if (pathname === '/a') {
await app.render(req, res, '/a', query)
} else if (pathname === '/b') {
await app.render(req, res, '/b', query)
} else {
await handle(req, res, parsedUrl)
}
} catch (err) {
console.error('Error occurred handling', req.url, err)
res.statusCode = 500
res.end('internal server error')
}
}).listen(port, (err) => {
if (err) throw err
console.log(> Ready on http://${hostname}:${port}
)
})
})
Hi all,
I've experienced this same issue -- and have also identified a cause, and implemented a temporary patch (which I'm hopeful I won't have to rely on for too long!)
First, the bug appears if you are running Next:
- using a Windows virtual folder that is
- mounted to a network fileshare.
So to reproduce:
-
PS> npx create-next-app@latest testapp
- Share the testapp folder
-
PS> New-PSDrive -Name K -PSProvider FileSystem -Root "\\[computerName | IP]\testapp" -Persist
-
PS> cd K:
-
PS> npm run build
You'll get this:
> [email protected] build
> next build
info - Checking validity of types
info - Creating an optimized production build
Failed to compile.
K:\node_modules\next\dist\build\webpack\loaders\next-client-pages-loader.js?absolutePagePath=private-next-pages%2F_app.js&page=%2F_app!
Module not found: Can't resolve 'private-next-pages/_app.js' in '\\[computerName | IP]\testappt'
K:\node_modules\next\dist\build\webpack\loaders\next-client-pages-loader.js?absolutePagePath=private-next-pages%2Findex.js&page=%2F!
Module not found: Can't resolve 'private-next-pages/index.js' in '\\[computerName/IP]\testapp'
Module not found: Error: Can't resolve './K:/node_modules/next/dist/client/next.js' in '\\[computerName | IP]\testapp'
> webpack config.resolve.alias was incorrectly overridden. https://nextjs.org/docs/messages/invalid-resolve-alias
You can get all kinds of messy additional error messages by running in dev and/or actually installing some additional modules. The key bit of info is already in the simpler messages above, though: Webpack is using a UNC path to look for these files. We never gave it a UNC path; that UNC path should be hidden behind the abstraction of the virtual folder, and yet here it is. And Webpack doesn't seem to like UNC paths, for whatever reason. As a result, the app breaks.
The reason this is happening appears to be the use of the fs.realpathSync.native function in next/lib/get-project-dir.ts:
const resolvedDir = path.resolve(dir || '.')
const realDir = fs.realpathSync.native(resolvedDir)
Though I only had limited time to research the difference between realpathSync and realpathSync.native, it looks like the latter is supposed to work better with Windows paths (though I'm not sure in what way). Unfortunately, this case, it exposes the underlying UNC origin of the virtual directory. For instance, assuming your context is the root of the testApp example above, running with a working directory of K:, here's what you get:
input | fs.realpathSync | fs.realpathSync.native |
---|---|---|
path.resolve('.') | K:\ | \[computerName or IP]\testApp |
So my temporary patch is just adding to my pipeline a step to modify /node_modules/next/dist/lib/get-project-dir.js such that the above line uses fs.realpathSync instead of fs.realpathSync.native. That allows builds to work properly, including enabling ISR.
I'm sure realpathSync.native was chosen for a reason, so I'm not sure that swapping to realpathSync is a workable permanent fix, but perhaps at the very least it could be used in cases where the underlying path exposed by realpathSync.native is a UNC path, so that whatever the downsides of using realpathSync are would at least be limited only to virtual directory scenarios.
Turns out this bug was documented earlier as well here:
https://github.com/vercel/next.js/issues/36707
There hasn't been any action on this ticket, so I may recreate it with my above comment, since it provides more complete diagnostic info than the initial issue contains. I may also submit a PR, although because of the compatibility issues and the fundamental nature of the code involved, I'd rather assist somebody with more experience than propose a fix myself. But I'd rather not have to keep monkeypatching my deployment, and I don't really want to have to maintain a separate branch just for this tiny subtractive fix. :)
@timfitzzz This issue is also related to: https://github.com/vercel/next.js/issues/35542. At least the same part of the code is causing both of these problems. For more context, the issue was introduced in https://github.com/vercel/next.js/pull/29205. No idea how to fix it properly though, so I've been patching it in my own deployments too.
Hi All,
Patching might not be right solution for production. So is there any latest fix available for this issue ?
any updates on this issue?