Webpack adding jQuery plugin: Error: jQuery requires a window with a document

2.2k Views Asked by At

I'm using Angular 4 +webpack.I've added a jQuery plugin to nonTreeShakableModules const in webpack.config.vendor.js:

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const merge = require('webpack-merge');

const treeShakableModules = [
    '@angular/animations',
    '@angular/common',
    '@angular/compiler',
    '@angular/core',
    '@angular/forms',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/platform-browser-dynamic',
    '@angular/router',
    'font-awesome/css/font-awesome.css',
    'zone.js',

];
const nonTreeShakableModules = [
    'bootstrap',
    'bootstrap/dist/css/bootstrap.css',
    'es6-promise',
    'es6-shim',
    'event-source-polyfill',
    'jquery',
    'virtual-keyboard'              //HERE
];

When starting the application I got this error:

NodeInvocationException: Prerendering failed because of error: Error: jQuery requires a window with a document

If I refresh the page for 2-3 times,error is gone. Thanks for any help!

1

There are 1 best solutions below

1
Tseng On BEST ANSWER

As said in the comments of your previous question, you can't run javascript code which depends on window and some other cases (like session storage) on the server-side with server-sided pre-rendering.

Templates such as ASP.NET Core Angular Web templates comes with server-sided rendering enabled. This works fine for applications which doesn't require session storage, authentication or access to browser components or dom-tree.

You have to disable server-sided prerendering by removing the asp-prerender-module="ClientApp/dist/app.module.server.ts" tag helper from your Index.cshtml.

Replace

<my-app asp-prerender-module="ClientApp/dist/app.module.server.ts"></my-app>

with

<my-app></my-app>

Of course replace my-app with the selector of your application, typically app in templates.

Alternatively you have to run code conditionally, as pointed in this GitHub issue:

// boot-client.ts file 
import 'ngx-charts';

// some.component.ts
import { isBrowser } from 'angular2-universal';
import * as $ from 'jquery';

// inside ngOnInit 
if (isBrowser) { 
    $('body').hide();  // or whatever call you need to make
}

to avoid running such code on the server-sided pre-rendering.