-
-
Notifications
You must be signed in to change notification settings - Fork 474
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
Module build failed: Error: The style-loader cannot be used in a non-browser environment #109
Comments
It would be helpful to post your webpack config. |
@wzup you are using
You're probably executing your bundle code with nodejs, and i'm not sure why do you want css for server-side code. |
Building a site compiler that embeds webpack. The build process generates many of the files consumed by webpack and my intention is to include bootstrap CSS and glyphicons. I've actually got both server-side and client-side bundles being produced, and the final build step loads the webpacked entry scripts for each generated page in the site and pre-renders at build time (on Node.js). But that fails when my webpacked server-side render code hits the style-loader code injected by webpack into the bundle.
In a little more detail, the failing 'node' build of this page's entry bundle is leveraging ReactDOMServer to affect the server-side rendering. And, of course this loader knows/cares nothing about that. Wondering if anyone has figured out how to get inlined CSS working server side? Thanks. |
@ChrisRus - I am getting something really similar, at however I am not compiling for a server. - /msie [6-9]\b/.test(({}).navigator.userAgent.toLowerCase()); Can not imagine under what circumstances this would work. Somebody would have to have modified in a file that looks like function(module, exports, __webpack_require__) {
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/ |
I've actually created a PR that I think it solves this, at least if you're using local scopes. Check out #115 |
@magalhas thanks, been thinking that should be there for a while, i've run into this a few times. -To the universe- This would be extremely server dependent, perhaps an option that outputs a json file with an array of css files to include. So a server could do what the wanted by requiring said file. I know a bit magical, but would allow for styles to be included in sync with the client.... |
Sounds reasonable. I do have React server rendering. I don't want |
@wzup, you can add your style-including code into bundle conditionally - omit it for server-side bundle. One way of doing that is using Then you can write conditions like:
If block will not appear in bundle unless in your
Because of dead code elimination ADD: I mised the part about I guess something like this may work:
|
I'm using webpack to compile my server code with React rendering and have this problem as well. The PR of @magalhas looks good. Can someone please test and merge it? In the mean time, my workaround is using https://github.com/kriasoft/isomorphic-style-loader in webpack server config. |
@wzup @BaoDelta - What works best for me is shoving the style loading bit of my libraries into the componentDidMount hook of the react component. This lifecycle hook will not get called until client rendering occurs. See https://github.com/cchamberlain/react-hatch/blob/master/src/lib/index.js#L77 for a working example. |
Suggestions made by @cchamberlain and @Xazzzi seem reasonable to me and require nothing more than clear separation of concerns so that code paths that are not required server-side do not get executed in that context. @cchamberlain suggests an approach that would work in my specific scenario that leverages React's lifecycle callbacks to ensure that the style loader doesn't get required in unless the component(s) that require the stylesheet actually mount (on the DOM). It's likely not significant but worth mentioning that the loader and the stylesheets would still however be included in the server-side bundle. @Xazzzi suggestion is more generally applicable as he simply suggests excluding the superfluous modules from the bundle using Certainly this approach would work for my scenario where all the React components I'm working with are custom (i.e. I control the source so can punch in conditional logic around require of the style loader). But this isn't really practical for react-toolbox as was mentioned. Maybe the right approach is to hijack the loader regex |
@ChrisRus that also sounds like a good approach to me although I would think it would be more apt to attract the react dev errors telling you your server and client markup differ. I'd be interested to see if that is more or less performant with the styles not delivered with the initial bundle. TBH I think the best approach would be if the style-loader didn't attempt to run window / document oriented code when they don't exist. This seems like it should be a simple change to me but I have done no research there. I've recently moved over to postcss loader with css modules and extract text plugin and have not noticed the issue occurring even with the style loading outside of componentDidMount. |
I just ran into this problem, and I observe that the react-bootstrap (for example) code does this: /* 82 */
/***/ function(module, exports) {
'use strict';
is_document_defined = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
module.exports = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
/***/ }, then var canUseDOM = __webpack_require__(82); to prevent issues. Could something similar be done here? |
Kinda disappointed that style-loader is client-only. How come no one ever noticed this when writing isomorphic React app? |
So I took the multiple entry point approach, and that worked well: I just made an entry point called client_only, and loaded up anything related strictly to client there, and then that gets included only on the client side. Problem solved. |
@catmando could u please post a snippet of how to do this multiple entry point approach to solve this problem? |
@mmajko You have to use something like jss, react-look or isomporhic-stlye-loader. Would be nice if the style-loader checked if it was in a browser environment before adding styles to the document. So that it wouldn't cause runtime errors server side. |
I'm also running into this problem in development mode with an app that renders on both the server and the client. In production mode it's no problem, since I'm using the extract text plugin for styles, but in development mode style loader breaks my app. My expected behaviour is that styles are just ignored on the server side. The only workaround I can think of is compiling the app separately for the server with style loader removed, but I'd like to avoid that because I'd have to compile twice on every file change. I think PR #115 would have solved my problem. If you don't want it, Is there an easy fix for this? |
@amannn Yes, the easiest way to avoid in a React app is to move your style loading into requires within componentDidMount component lifecycle hook since they are not executed server side. I am working on a universal-style-loader drop-in replacement for style loader but the docs are not exactly pristine and I'd label it experimental at this stage. I am using it successfully in a few projects at this time so feel free to use and let me know if you experience issues. |
|
Stumbled upon this issue too and I found an every simple solution. You just need to use ExtractTextPlugin on the server side for css-loader to extract CSSs without going through style-loader. Then, we could just ignore that duplicated css file without any harm. This is the config for css loader: |
I forked |
@creeperyang Thanks, that solves it :) |
@creeperyang your changes solve this issue. You should open a PR with your changes and hopefully they'll get merged in! |
What error is this? How to resolve?
The text was updated successfully, but these errors were encountered: