-
Notifications
You must be signed in to change notification settings - Fork 27k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
exclude a module client side #2069
Comments
In this case, the best way to use dynamic imports which comes with v3. See: https://zeit.co/blog/next3-preview You can do something like this: Comp.getInitialProps = async (ctx) => {
if (isServer) {
const api = await import('./lib/server-api.js')
// do something
} else {
const api = await import('./lib/client-api.js')
// do something
}
} |
Thanks. It does sounds like a workaround though. Dynamic imports is a great feature but I don't feel they fit my use case, it's not like I need them on demand and I'd rather have my imports at the top of my file. Does it means next.js is incompatible with libraries which depends on the webpack/browserify |
related #1091 I just had a look at {
"browser": "fetch-npm-browserify.js",
"main": "fetch-npm-node.js",
} so Next.js does honor the Let me know if you think this is in scope for Next.js and I'll try to send a PR. Cheers |
@arunoda FYI this returns errors: if (false) {
await import('request');
}
So branching in the code is not really possible. |
@fatfisz this a good one. |
There are couple of ways we can fix this. Here's the easy way: Comp.getInitialProps = async (ctx) => {
if (isServer) {
const api = eval(`require('./lib/server-api.js')`)
// do something
} else {
const api = await import('./lib/client-api.js')
// do something
}
} |
I wrote a blog post about this here - https://arunoda.me/blog/ssr-and-server-only-modules Frankly, there's nothing we can do about this in Next.js other than educating everyone. |
Have you used this Using |
@haohcraft you can use solutions like that now, but I wouldn't recommend adding webpack-node-externals 👍 |
@arunoda thanks for your article on the matter. Using the same technique, I was forced to change the require statement like this:
Even if folders The error is:
Like, instead of looking in the current server folder, Is there a way to use a usual require path in those kind of situations? Thanks. |
@timneutkens is |
I found an interesting solution:
const myModule = require('this-only-works-on-the-server');
// ... initialize express + next
server.use((req, res, next) => {
// now I can access this module inside the getInitialProps function
req.myModule = myModule;
return next();
})
server.get('*', (req, res) => {
return handle(req, res);
}) ☝️ this avoids webpack ever trying to include the server side module since the |
hi @codyzu have you found a way to make this work also on |
hello @knitkoder ... no, I haven't used the export functionality. However, my feeling is it would be |
thanks @codyzu I ended up using gatsby to combine data sources from js files, in the end that was what I needed |
@codyzu you made my day!!)) |
Using let getData;
if (process.browser) {
getData = () => fetch('https://....');
} else {
const api = require('lib/api');
getData = () => api.foo();
}
export default class extends React.Component {
static async getInitialProps() {
const { data } = await getData();
return {
data,
};
}
// ...
} The browser-side code then compiles down to something like: var getData;
if (false) { var api; } else {
getData = function getData() {
return fetch('https://...');
};
}
// ... For a real-world example of this pattern, see: https://codesandbox.io/s/n3yj15mk7p |
@arunoda Is the guide on SSR and Server Only Modules still relevant after almost three years? I've been trying to follow instructions there but I'm unsure how they should actually work. If I ignore a module (using Error: Cannot find module 'jsonwebtoken'
at webpackMissingModule (/my-project/.next/server/static/development/pages/index.js:1891:79)
# ...
code: 'MODULE_NOT_FOUND'
} I'm trying to validate a JWT token on the server with // next.config.js
module.exports = {
// Do not show the X-Powered-By header in the responses
poweredByHeader: false,
webpack: (config, { webpack }) => {
// Avoid including jsonwebtoken module in the client side bundle
// See https://arunoda.me/blog/ssr-and-server-only-modules
config.plugins.push(new webpack.IgnorePlugin(/jsonwebtoken/));
return config;
}
}; // auth-token.js (server side only module)
export async function verifyAuthToken(token) {
// Import `jsonwebtoken` here using `require` as this
// is meant to be a server-side only module
// See https://arunoda.me/blog/ssr-and-server-only-modules
const jwt = require('jsonwebtoken');
return new Promise((resolve, reject) => {
jwt.verify(token, JWT_SECRET, (err, decoded) => {
return err ? reject(err) : resolve(decoded);
});
});
} // private-page.js
// ...
PrivatePage.getInitialProps = async ctx => {
// Extract authorization token from cookies
const token = getAuthToken(ctx);
if (ctx.req) {
// Server only
try {
const auth = await verifyAuthToken(token);
return { auth };
} catch (err) {
console.log(err); // <-- this prints the MODULE_NOT_FOUND error server side
// User is either not authenticated or the token verification
// failed: we return `false` as the value for the `auth` prop;
// this should trigger a redirect to the login page
return { auth: false };
}
}
// Client only
return { auth: false };
}; What am I missing? EDIT: Found the solution. I tripped over the fact that I'm excluding the module for both client and server compilations. The const nextConfig = {
// Do not show the X-Powered-By header in the responses
poweredByHeader: false,
webpack: (config, { webpack, isServer }) => {
// Avoid including jsonwebtoken module in the client side bundle
// See https://arunoda.me/blog/ssr-and-server-only-modules
if (!isServer) {
config.plugins.push(new webpack.IgnorePlugin(/jsonwebtoken/));
}
return config;
}
}; @arunoda's 2017 blog post should probably be updated to reflect this - specially since it's linked directly on the official Next.js docs. |
@nfantone's solution of using IgnorePlugin does not work on current Next.js canary. So I've solved this using the following:
module.exports = {
webpack(config, { isServer }) {
if (!isServer) {
// Ensure prisma client is not included in the client bundle
config.module.rules.push({
test: /@prisma\/client/,
use: "null-loader",
})
}
return config
},
} |
Do you - because you've obviously had a working configuration - possibly know, where my mistake could be:
I have to exclude I also tried requiring the null-loader package manual and put it to the config. Same result, not working. @azure/msal-browser still gets included on the server side. The packaged is imported in a wrapper for this library. I need to export a hook from there, so I can't use dynamic() because it only generates LoadableComponents... Help would be highly appreciated! |
@florianmatz I think for that you definitely need to use Probably you need to use |
@flybayer Yes, I have that, getting
and
For the Provider, everything is fine. But with the Consumer it's difficult, because - of some reasons, that are hard to describe here - I actually need to use a useContext Hook, not the Consumer. So out of my auth-Module I need to import
But then again, the SSR breaks due to the @azure-package... So I basically would need something like
But of course, I only get the LoadableComponent... The consumer or the hook are basically provding tokens that I need to call some APIs. I need either to fix next ignoring the package on SSR (prefered) or Microsoft to fix their libraries to support SSR, which is unlikely :( |
This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
Hello,
I'd like to exclude a specific module that uses
fs
from the client side bundle. I've triedin my
package.json
but I getError: Cannot find module '../lib/api'
so it seems to be excluded server side as well somehow.My use case is that I want my
getInitialProps
function to usefetch
client side and an other method from my./lib/api.js
file server side.The text was updated successfully, but these errors were encountered: