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

window is not defined error when used with SSR #1

Open
judocode opened this issue Jan 7, 2017 · 3 comments
Open

window is not defined error when used with SSR #1

judocode opened this issue Jan 7, 2017 · 3 comments

Comments

@judocode
Copy link

judocode commented Jan 7, 2017

I tried to use vue-typer with Vue hackernews 2.0 (which uses SSR), and I get an error from vue-typer when attempting to import it:

    at C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:4714
    at C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:4646
    at t.exports (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:5075)
    at Object.t.__esModule.default (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:18984)
    at e (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:320)
    at Object.t.__esModule.default (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:5506)
    at e (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:320)
    at Object.<anonymous> (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:19176)
    at e (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:320)
    at t.exports.version (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:703)
    at C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:713
    at n.(anonymous function).i (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:81)
    at Object.<anonymous> (C:\Code\justus\node_modules\vue-typer\dist\vue-typer.min.js:6:197)
    at Module._compile (module.js:556:32)
    at Object.Module._extensions..js (module.js:565:10)
    at Module.load (module.js:473:32)```
@cngu
Copy link
Owner

cngu commented Jan 7, 2017

I have 0 experience in SSR, and am quite new to the Vue ecosystem, so I could use some help with this one.

I've spent some time investigating this and the issue is how vue-typer's CSS is being loaded. Here is a summary of what is going on:

  • Normally (using Vue Hackernews 2.0 as an example), you'd use extract-text-webpack-plugin to pull all component CSS out into a generated CSS file, and add a <link> to it in your index.html (using something like html-webpack-plugin to automate that step).
  • vue-typer, being a 3rd party standalone component, can't do this, so it is currently packaging the CSS inside the bundle, and once loaded, uses style-loader to dynamically insert its <style>.
  • During SSR, style-loader executes within Node, not the browser. Unfortunately, style-loader always assumes it's in the browser and accesses window and document, both of which do not exist in Node and throw errors. This is the error that you are seeing.

I can think of some hacky workarounds, none of which are ideal:


Approach 1: Fork style-loader (or vue-style-loader?) to add some error checking before trying to access window and document. This way, style-loader will skip past these code paths on server-side, but still execute on client-side in the browser.

  • Note that I say fork here because this was already sent as a PR to the style-loader repo and it was rejected for another alternative, see Approach 2 below.

Caveat: I don't think anyone wants to keep this fork up-to-date. I know I don't.


Approach 2: Output two vue-typer bundles. One 'server-side-bundle' that uses css-loader/locals, and another 'client-side-bundle' that uses style-loader!css-loader, Read more about it here. The result of this is that the CSS won't be embedded in the 'server-side-bundle', and style-loader won't bomb by trying to embed any <style> tags. The 'client-side-bundle' is what vue-typer is providing currently, no changes there.

Caveat: Essentially doubles the vue-typer package size due to 2 near-duplicate bundles. This is also a huge pain for the isomorphic apps because they'll either have to build 2 separate bundles (one client bundle importing vue-typer's client bundle, and another for the server bundle), or add some detection code to see if they're running in the browser vs server before importing vue-typer. For the latter, I'm pretty sure they can't use the ES6 import either; I think import has to be the first lines (excluding comments) in a file. Finally, doing things this way kind of defeats the purpose of SSR since vue-typer will be rendered client-side.


Approach 3: Use extract-text-webpack-plugin to pull the CSS out of vue-typer into a separate CSS file. Force all users to import the CSS file along with the vue-typer JS bundle.

Caveat: Super ugly and onerous for users. What if users aren't using webpack or browserify? Linking vue-typer's CSS themselves will be annoying. (Note that I tried to prove this out on Vue Hackernews 2.0, but I couldn't get it working. It could be due to some combination of extract-text-webpack-plugin, minified CSS, vue-loader scoped rules, autoprefixer, and/or css-loader/css-nano options, especially when run again on the consuming app's side.)


Again, these are just some workarounds I'm tossing out as someone who has no experience in the area. There must be a better solution, so I look forward to hearing some ideas and PRs.

@rbwilcoxon11
Copy link

I got this working with the Vue SSR framework Nuxt. I bet you can do something similar in Vue's regular SSR but I'm unfamiliar with is...

I wrote a simple plugin file vue-typer.js

import Vue from 'vue'
import VueTyperPlugin from 'vue-typer'

window.onNuxtReady(() => {
  Vue.use(VueTyperPlugin)
})

And then in my nuxt.config.js file

module.exports = {
  ...
  plugins: [
    ...
    { src: 'plugins/vue-typer.js', ssr: false}
  ],
  ...
}

Hope this helps somebody...

@jackiboy
Copy link

jackiboy commented Apr 28, 2018

This is another approach if you only want to load it in a single component in Nuxt.

at the top of your component.vue file

if (process.browser) {
  var VueTyper = require('vue-typer').VueTyper
}

load the component

components: {
   VueTyper
},

in the template

<no-ssr>
    <vue-typer  text='your text' ></vue-typer>
</no-ssr>

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

No branches or pull requests

4 participants