Skip to content
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

Webpack 2 compatibility : ERROR in ReferenceError: self is not defined #79

Open
dbrrt opened this issue Mar 3, 2017 · 17 comments
Open

Comments

@dbrrt
Copy link

dbrrt commented Mar 3, 2017

I can't having it working with Webpack 2, because it runs on server and returns :

ERROR in ReferenceError: self is not defined

Does one have been able solving it?
Would it be possible to run it on client only ?

@dbrrt dbrrt changed the title Webpack 2 compatibility Webpack 2 compatibility : ERROR in ReferenceError: self is not defined Mar 3, 2017
@bpevs
Copy link

bpevs commented Mar 8, 2017

I noticed this error as well. I'm currently working on two personal projects; it works in one, and in the other, I get the same error as you. The only difference in the surrounding code is mostly that one of them extracts the css and the other does not (sorry it's not the cleanest code, these are little in-progress personal projects).

This repo is working with 3.1, but and webpack 2 (I checked and it also works with 3.3, however):
https://github.com/ivebencrazy/React-Starter/tree/basic-web

This one is broke with 3.3 and webpack 2:
https://github.com/Blanket-Warriors/Zuck.js/tree/postcss-refactor

Currently not sure whether it's the plugin, or just misuse. I'll be looking into it a bit more the next day or two as I get the time. But I figured maybe linking them could help solve your problem in itself.

ERROR in ReferenceError: self is not defined
    at evalmachine.<anonymous>:4005:30
    at evalmachine.<anonymous>:4000:47
    at module.exports (evalmachine.<anonymous>:4022:68)
    at Object.<anonymous> (evalmachine.<anonymous>:64292:37)
    at __webpack_require__ (evalmachine.<anonymous>:30:30)
    at Object.defineProperty.value (evalmachine.<anonymous>:31917:15)
    at __webpack_require__ (evalmachine.<anonymous>:30:30)
    at Object.hasOwnProperty (evalmachine.<anonymous>:6452:15)
    at __webpack_require__ (evalmachine.<anonymous>:30:30)
    at Object.defineProperty.value (evalmachine.<anonymous>:31773:13)

edit: btw keep note of the deps while you're looking around. Since I started using Webpack 2 a bit early and I haven't updated everything, some of the dependencies are non-standard versions.

@dbrrt
Copy link
Author

dbrrt commented Mar 8, 2017

Thanks for having shared that code, it'll certainly help me. I also thought I might misused the plugin but it failed on other projects too.

@alexleventer
Copy link

alexleventer commented Mar 10, 2017

Having the same issue w/ webpack 2.2.0-rc.3

@bpevs
Copy link

bpevs commented Mar 10, 2017

Hey, update; After looking around a tad, it looks like for me, this error is coming from isomorphic-fetch dependency (https://github.com/matthew-andrews/iso…). Seems similar to document is not defined kind of issues people get, since this pre rendering doesn't happen in a browser context. I don't have any more time to look at it today for why that's the case or for solutions, but that's my hunch. Check your polyfills and dependencies.

@vectorsize
Copy link

In my case this happened when with running StaticSiteGeneratorPlugin with webpack-de-server.

adding this conditional in the config fixed it:

if (!development) {
  config.plugins = config.plugins.concat([
    new StaticSiteGeneratorPlugin('bundle.js', routes)
  ])
}

@jota
Copy link

jota commented Mar 21, 2017

In case it helps someone, for me it was caused by "style-loader".
Before i had it configured like so:
loaders: ["style-loader", "css-loader", "postcss-loader"]

and solved it by using the ExtractTextPlugin instead and including the generated css file in my html:
loader: ExtractTextPlugin.extract( { fallback: "style-loader", use: "css-loader!postcss-loader", publicPath: "/dist" })

I also had to use the webpack -p option to generate a production build

@azat-io
Copy link

azat-io commented Apr 6, 2017

I have the same error. Look here please:
https://github.com/azat-io/static-site-generator-webpack2-example

@jota
Copy link

jota commented Apr 6, 2017

@azat-io seems like you are just missing the first param to the callback is null in your case.

Your index.js

callback('<!doctype html><html><head></head><body>It works!</body></html>')

Change to what the docs say and you should be good to go:

callback(null, '<!doctype html><html><head></head><body>It works!</body></html>')

@azat-io
Copy link

azat-io commented Apr 6, 2017

@jota My repository was updated. No difference:

ERROR in ReferenceError: self is not defined
    at Object.<anonymous> (evalmachine.<anonymous>:1:73734)
    at Object.<anonymous> (evalmachine.<anonymous>:1:74028)
    at e (evalmachine.<anonymous>:1:346)
    at Object.<anonymous> (evalmachine.<anonymous>:1:127841)
    at e (evalmachine.<anonymous>:1:346)
    at r.function.Object.create.t.exports.t.super_ (evalmachine.<anonymous>:1:729)
    at evalmachine.<anonymous>:1:739
    at evalmachine.<anonymous>:1:84
    at evalmachine.<anonymous>:1:223
    at ContextifyScript.Script.runInContext (vm.js:32:29)

@sillero
Copy link

sillero commented Apr 17, 2017

The issue here is that, with this plugin, the entry point is loaded in node's context, and that's why you can use a globals property when initializing the plugin to avoid these kind of errors. When using webpack-dev-server, your entry point becomes the dev-server client JS, which is supposed to load in the browser's context, so it's filled with self, window, WebSocket and other stuff.

The best way to deal with this is to just run the plugin on a normal build process as mentioned earlier, when not using webpack-dev-server (usually production).

If for some reason this is really what you want to do, the quick/easy way out is to load globals with something like jsdom, which will add everything a browser context has, like this:

new StaticSiteGeneratorPlugin({
    paths: ....,
    globals: require('jsdom').jsdom().defaultView
})

@tharnach
Copy link

@ivebencrazy I'm having the same problem with isomorphic-fetch. Did you have any success resolving this before I dig in?

@bpevs
Copy link

bpevs commented Apr 27, 2017

@tharnach
So I figured it out. The problem is actually caused by Webpack target:
https://webpack.js.org/configuration/target/#target

Basically, packages that are supposed to be able to run in node AND web environments (like isomorphic-fetch), have to deal with these environments separately, and many times have separate builds for both. The thing is that when you're building with Webpack for a web application, you probably have the target set to "web", so the package will act like there's a browser there, when there isn't. So our application is telling all of our dependencies that we're running in a browser, but static-site-generator-webpack-plugin is actually running in node!

There are two ways to solve this for real:

1. Change the Target

Webpack Config adjustments for static site creation:

{
  target: "node", // <- NOT "web"
  plugins: [
    new StaticSiteGeneratorPlugin({
      paths: prerenderedPaths
    })
  ]
}

1.5 For Universal/Isomorphic Sites, use Two Builds

For universal/isomorphic sites and applications, you should probably use two builds, one for the static site, and one for the client code. Use a node target for building the html files with static-site-generator-plugin, and then use a web target WITHOUT the static-site-generator-plugin for your client javascript. This kind of makes sense anyway, since in general, bundling a normal universal app requires building the node stuff and the web stuff separately...

Webpack Config adjustments for client code:

{
  target: "web",
  plugins: [] // <- NO StaticSiteGeneratorPlugin
}

2. Run static-site-generator-webpack-plugin as if target is node

If we want to update this plugin to prevent this from happening, it would probably be a sane default for static-site-generator-webpack-plugin to assume a node target while building html. This seems like something that a bored/motivated person could look into (I don't know a ton about building webpack plugins, and I'm too lazy to learn this right now) 😆

This way, the plugins that are meant to be isomorphic/universal, and tell that they're in a node environment, and adjust accordingly.

Hacky Way

There is, of course, always a hacky way as well.... 😛

if (typeof document !== "undefined") {
	require("isomorphic-fetch");
}

if (typeof fetch == "undefined") {
	global.fetch = function() { return Promise.resolve() };
}

fetch("https://www.somethingsomethingurl.com")
	.then(function(response) {
		console.log(response);
	});

@Birowsky
Copy link

Birowsky commented Sep 2, 2017

Unfortunately, target: 'web' didn't fix it for me. Is there anywhere a working webpack example project with this plugin?

Adding inline: false to devServer fixed it for me.

https://stackoverflow.com/a/41492420/592641

@bpevs
Copy link

bpevs commented Sep 3, 2017

@Birowsky I'm not sure what you mean? It sounds like you got your client-only build working, if you got it working with devServer. For the static site generation, target needs to NOT be web, as I explained in my last comment.

@Birowsky
Copy link

Birowsky commented Sep 3, 2017

@ivebencrazy sorry i wasn't clear. I needed both for it to work. target: web and devServer.inline: false

@bpevs
Copy link

bpevs commented Sep 4, 2017

Ah! I didn't notice that you had edited it is all. Glad you found a solution!

@dbrrt
Copy link
Author

dbrrt commented Sep 4, 2017

Maybe it'd be nice now to have an up-to-date working example available under the plugin repository?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants