-
Notifications
You must be signed in to change notification settings - Fork 27.2k
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
Server-side only method to ensure server-only code is never sent to the browser #5354
Comments
Did you try? if (!process.browser) {
console.log('this code will only run on the server')
} or let myLib
if (process.browser) {
myLib = require('library-browser')
} else {
myLib = require('library-node')
} |
|
@HaNdTriX being able to check if I'm in the server or the browser is not really a problem. As you mention we can use process.browser or as sergiodxa mentions check for window. My issue is that if I do something like What I'm offering here is a way to mark code to be loaded/ran during server side rendering, but then maybe purged before it is sent to the browser. The more I try to explain this is less it seems plausible tho 🤔 |
can't you move your server logic to the server.js file instead of your component? |
@sergiodxa As far as I know the behaviour of So Here is the code thats related to my theory: Another approach could be to use of dynamic imports (see |
when window === 'undefined' casuing ReferenceError: window is not defined |
|
thx. |
@HaNdTriX really knows what he's talking about. #5159 added code elimination on webpack-level when |
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 |
Is there a way to use a folder (for example |
That's a great idea!! |
The idea in #5354 (comment) might be ok within a project, but is not particularly viable for published packages as consumers might not have a custom server setup. For I also use the undocumented, but handy, This used to be inferior to |
Yes. Create a folder
|
For anyone else like me that comes across this thread wondering what they should use, according to this PR #7651 typeof window === "undefined" |
👆 the above actually results in the code being removed from your client-side bundles. We have a test to ensure server-only code does not appear in the client bundle: #8361! |
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
Next.js has changed the recommended way to detect whether we're on the client or not to check for the presence of `window`. See vercel/next.js#5354 (comment).
@Timer Will the following check work as well? const hasWindow = () => {
return typeof window === 'object'
}
if (!hasWindow()) {
// server-side code
} Or does the built-in Next optimization search specifically for when |
It specifically replaces |
I really hate this answer... no offense! It shouldn't evaluate a function at build time like that without an explicit plugin. If this is in fact what's happening, then we should look into removing webpack all together in favor of pure es6 modules. Is it possible to prevent this or do somewhat of the reverse: use a plugin to swap a placeholder with hasWindow() to be evaluated at runtime? |
Not sure what your problem is with the answer... I've explained the behavior that has been there since Next.js 9.1 or so. Hate is a pretty strong word 😅
It's not evaluating a function, it's converting a statement that is known to always be a certain value because we take care of the full environment.
This is a bundle size / performance optimizations that so far has had no issues reported by issuers. It only runs against first-party code so not against node_modules (would have even bigger size wins if we did run it against node_modules however that gave issues with some packages in the ecosystem).
Why do you want to do that? There is no benefit to it as we know it's always going to be defined client-side. This is no different than We do tons of optimizations against first-party code that make sure the bundle output is as optimized as possible. E.g. |
Sorry, the "hate" was due to a looming deadline. 😉
According to This code block is what I tested:
This is the result:
I take it all back... this makes me very happy! |
@y0n3r |
@timneutkens thank you for the info and that link!!! |
next-code-elimination only shows how the elimination of getServerSideProps/getStaticProps works and doesn't include the other Babel plugin optimizations we run including the one that optimizes |
useEffect only runs on client, i think you do not need to check for process.browser. Also, `process.browser` is deprecated in favor of `typeof window === 'undefined'` (vercel/next.js#5354 (comment))
useEffect only runs on client, i think you do not need to check for process.browser. Also, `process.browser` is deprecated in favor of `typeof window === 'undefined'` (vercel/next.js#5354 (comment))
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. |
Feature request
Is your feature request related to a problem? Please describe.
Let's say I have a hypothetical
Analytics.js
module which works differently depending on whether we are on the server or in the browser. It dynamically loads alibrary-node
orlibrary-browser
package with an eval for example.Since it's an analytics module we need it inside most of our components to send events.
I tried to initialise it in getInitialProps like this:
This allows to correctly load Analytics with server or client side setup, but when loaded on the server side, the code will then be sent to the browser, which will error on unknown code (such as
fs
etc).Describe the solution you'd like
It would be nice to have a way to say "here is some code I want ran only on the server because it will break in the browser".
We can already do this with browser code, because we have
componentDidMount
which is only called in the browser, so we know it will never get evaluated on the server. Something similar for server-side would be helpful.Describe alternatives you've considered
Right now I'm just loader my module inside component in
componentDidMount
(only in the browser) and abstracted the analytics logic in other non-components modules that are ran in the server, but it's not as flexible and mixes concerns.Additional context
n/a
Thanks!
The text was updated successfully, but these errors were encountered: