jQuery requires a window with a document in webpack - reactjs

I'm using ReactJS.net (server-side render) and when I use jquery in Webpack then I got error
here is my error
Error while rendering "Components.ToDoListSkeleton" to
"react_0LmYYfSk30qdrKJQe4McUQ": Error: jQuery requires a window with a
document
at module.exports (Script Document [5]:51:87) -> module.exports=global.document?factory(global,true):function(w){if(!w.document){throw
new Error("jQuery requires a window with a document");}return
factory(w);};}else {factory(global);} // Pass this if window is not
defined yet
at new ToDoListSkeleton (Script Document [5]:26:903)
at ReactCompositeComponentMixin._constructComponentWithoutOwner (Script Document [2]:8271:28)
at ReactCompositeComponentMixin._constructComponent (Script Document [2]:8253:22)
at ReactCompositeComponentMixin.mountComponent (Script Document [2]:8172:22)
at ReactReconciler.mountComponent (Script Document [2]:1977:36)
at Script Document [2]:19549:37
at Mixin.perform (Script Document [2]:3788:21)
at renderToStringImpl (Script Document [2]:19544:25)
at renderToString (Script Document [2]:19574:11)
at Script Document [7] [temp]:1:16 Line: 19549 Column:37
here is my webpack config
"use strict";
var path = require('path');
var WebpackNotifierPlugin = require('webpack-notifier');
var webpack = require("webpack");
module.exports = {
context: path.join(__dirname, 'Content'),
entry: {
server: './server'
},
output: {
path: path.join(__dirname, 'build'),
filename: '[name].bundle.js'
},
module: {
loaders: [
// Transform JSX in .jsx files
{ test: /\.jsx$/, loader: 'jsx-loader?harmony' },
{ test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" }
]
},
resolve: {
// Allow require('./blah') to require blah.jsx
extensions: ['', '.js', '.jsx']
},
externals: {
//// Use external version of React (from CDN for client-side, or
//// bundled with ReactJS.NET for server-side)
react: "React"
},
plugins: [
new WebpackNotifierPlugin(),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
})
]
};
Any help or suggestions would be appreciated, Thanks.

jQuery is only designed for use in a browser, and does not support server-side rendering. You'll need to remove jQuery from any of your code that you want to use server-side.

Related

Webpack: Can I get a source map for after babel, before minification?

I have a fairly basic webpack setup that runs babel and out comes my minified js with a source map.
Now when I run my source map in chrome I get the js before babel and before minification. However I would often like to have my source map after babel but before minification. Is this possible?
TL;DR I want source map to post-babel pre-minifcation. Possible?
For completeness
I run babel-loader 8 with webpack 4
Here is a screenshot from chrome showing the problem. As you can see the Dropzone tag indicates this is jsx (and so before babel)
Secondly here is my webpack config (not that it actually matters for my question).
const path = require('path');
module.exports = {
context: path.join(__dirname, 'Scripts', 'react'),
entry: {
client: './client'
},
output: {
path: path.join(__dirname, 'Scripts', 'app'),
filename: '[name].bundle.min.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
plugins: [require('#babel/plugin-proposal-object-rest-spread')],
presets: ["#babel/es2015", "#babel/react", "#babel/stage-0"]
}
}
}
]
},
resolve: {
extensions: ['.js', '.jsx']
},
externals: {
// Use external version of React (from CDN for client-side, or
// bundled with ReactJS.NET for server-side)
react: 'React'
},
devtool: 'source-map'
};
Running webpack with -d gives a second set of source maps in chrome that does the trick.

Webpack : config npm modules load

I'm new with webpack and I didn't find a way to load my vendor libs from node_modules with their dependencies (order and main files [js, css]) into a separate bundle file.
I used to work with bower_components but according to this documentation I moved to npm.
Example
I have angular material in my system that depends on angular and his own css file (angular-material.css).
What did I try already
I used the webpack.optimize.CommonsChunkPlugin which did load the venodors js files, but in the order that I entered in the configuration file (see config file attached below) so if I would have put angular material before angular the run would fail.
I tried configuring the resolve object to read from the "bower.json" which has a main files description and dependencies configured in it but that didn't work as well.
My config file
let webpack = require("webpack");
let path = require("path");
// define preprocessor variables
const envOptions = {
NODE_ENV: "development",
DEBUG: true,
isProduction: false
};
// pass as JSON object into query string ?json=...
const envJson = require('querystring').encode({json:JSON.stringify(envOptions)});
module.exports = {
context: __dirname + "/app",
entry: {
app: "./app.ts",
vendor: [
"jquery",
"angular-animate",
"angular-aria",
"angular-messages",
"angular-resource",
"angular-sanitize",
"angular-ui-router",
"angular-cache",
"angularjs-toaster",
"angular-translate",
"angular-translate-handler-log",
"angular-translate-loader-static-files",
"angular-material",
"angular",
"angular-dynamic-locale",
"ng-file-upload",
"angular-permission",
"moment",
"angular-moment",
"angular-hotkeys",
"angular-scroll",
"jquery.scrollbar",
"lodash",
"ag-grid",
"angular-ui-tree"],
},
output: {
filename: "bundle.js"
},
module: {
loaders: [
{ test: /\.ts/, loader: ['ts-loader?transpileOnly=true', `ifdef-loader?${envJson}`], exclude: [nodeModulesDir], }
]
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery" : "jquery",
"moment": "moment",
"agGrid": "ag-grid"
}),
new webpack.optimize.CommonsChunkPlugin(
{ name: 'vendor', filename: 'vendor.bundle.js' , test: 'node_modules/'}
)
],
resolve:{
modules: ['node_modules'],
extensions: ['.ts','.js', '.css', '.scss'],
},
devtool: "#source-map"
};
What do I want to achieve
Webpack will generate 2 bundles:
vendor.bundle.js - a file that contains all the vendor main js
files in the correct loading order.
app.bundle.js - a file that contains all of my app's inner files.
vendor.bundle.css - a file with all the vender main css files
both vendor bundles should be as defined as in the bower.json dependencies.
My Webpack version is 2.1.0-beta.25

webpack with angular 1 and bower

I'm building an app that uses webpack to bundle all of my javascript, node modules, and bower components. I was able to get angular and node modules working on their own, but when I tried to include my bower components I get the following error
app.bundle.js:9 Uncaught TypeError: angular.module is not a function
what my webpack build looks like
var webpack = require('webpack');
var BowerWebpackPlugin = require("bower-webpack-plugin");
module.exports = {
loaders: [
{test: /\.css$/, loader: "style!css"},
{test: /\.(woff|svg|ttf|eot)([\?]?.*)$/, loader: "file-loader?name=[name].[ext]"}
],
context: __dirname + '/web',
entry: {
app: './app.js',
vendor: ['angular']
},
resolve: {
modulesDirectories: ["web_modules", "node_modules", "bower_components"]
},
output: {
path: __dirname + '/dist/js',
filename: 'app.bundle.js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin( /* chunkName= */ "vendor", /* filename= */ "vendor.bundle.js"),
new BowerWebpackPlugin({
excludes: /.*\.less/
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
],
extensions: ['', '.json', '.js']
};
inside of my app.js (angular app declaration file) I have this
var angular = require('angular');
require("jquery");
require("bootstrap");
angular.module('App', []);
require('./services');
require('./controllers');
require('./directives');
How can I resolve this issue?
EDIT** I'm starting to think it has something to do with using the same entry point for the commonschunkplugin and the bowerwebpackplugin
In my npm-based project that uses Browserify, I had a similar issue. Then I noticed either on another discussion or in the docs it was said (paraphrasing):
do not store angular in a var as it creates issues with the global reference to angular
So instead of
var angular = require('angular');
try
require('angular');
and still call angular.module( name, []) as you normally would. My guess is that whatever returns from require('angular') is undefined or doesn't provide the angular APIs.

The following modules couldn't be hot updated: (Full reload needed)

I'm trying to setup hot module reloading in a react/typescript (with TSX) environment. I have used the react/redux real-world example as a model in getting things going, and this is what I have so far:
server.js
var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var webpackHotMiddleware = require('webpack-hot-middleware')
var config = require('./webpack.config')
var app = new (require('express'))()
var port = 3000
var compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
app.use(webpackHotMiddleware(compiler))
app.use(function(req, res) {
res.sendFile(__dirname + '/index.html')
})
app.listen(port, function(error) {
if (error) {
console.error(error)
} else {
console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
}
})
webpack.config.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
path.resolve('./src/index.tsx'),
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({ template: './index.html' })
],
module: {
loaders: [
{ test: /\.tsx?$/, loader: 'ts-loader' }
]
},
resolve: {
extensions: ['', '.ts', '.tsx', '.js', '.json']
},
}
index.tsx
import * as React from 'react';
import { render } from 'react-dom';
import Root from './containers/root';
render(
<Root />,
document.getElementById('root')
);
containers/root.tsx
import * as React from 'react';
export default class Root extends React.Component<void, void> {
render(): JSX.Element {
return (
<p>boom pow</p>
);
}
}
Changing <p>boom pow</p> to <p>boom boom pow</p> in the root element kicks off this in the javascript console in the browser:
[HMR] bundle rebuilding
client.js?3ac5:126 [HMR] bundle rebuilt in 557ms
process-update.js?e13e:27 [HMR] Checking for updates on the server...
process-update.js?e13e:81 [HMR] The following modules couldn't be hot updated: (Full reload needed)
This is usually because the modules which have changed (and their parents) do not know how to hot reload themselves. See http://webpack.github.io/docs/hot-module-replacement-with-webpack.html for more details.
process-update.js?e13e:89 [HMR] - ./src/containers/root.tsx
process-update.js?e13e:89 [HMR] - ./src/index.tsx
I've stepped through these steps as best I can tell, but am still having no luck.
What am I missing?
The problem, as mentioned by commenters, was missing in my loader - I'm not sure if this had anything to do with it, but I also switched to using babel after typescript - and having typescript compile to ES6. New config below:
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
path.resolve('./src/index.ts'),
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({ template: path.resolve('./src/index.html') })
],
module: {
loaders: [
{ test: /\.tsx?$/,
loaders: [
'react-hot',
'babel?presets[]=es2015',
'ts-loader'
]
},
{ test: /\.json$/,
loader: 'json'
}
]
},
resolve: {
extensions: ['', '.ts', '.tsx', '.js', '.json']
},
}
if someone still struggles with this see the readme: https://github.com/webpack-contrib/webpack-hot-middleware/blob/master/README.md
This module is only concerned with the mechanisms to connect a browser client to a webpack server & receive updates. It will subscribe to changes from the server and execute those changes using webpack's HMR API. Actually making your application capable of using hot reloading to make seamless changes is out of scope, and usually handled by another library.
webpack-hot-middleware doesn't handle hot reload, you'd need to use react-hot-loader for example

React webpack create bundle with separated react

is possible to configure webpack to not compile react inside bundle file? I would like to have more react applications in one page and I would like to load react library only once to get smallest size. How to achieve this?
In same situation I created final bundle with all small "applications" + React bundled once.
// components/index.js (webpacks entry point)
require("expose?React!react");
require("expose?MarketProductListing!./MarketProductListing");
require("expose?ProductDetail!./ProductDetail");
require("expose?MarketSearch!./MarketSearch");
Then, I include bundled JS via <script/> tag.
<script src="js/components.bundle.js"></script>
Now, I can access React, MarketProductListing, ... components in JS and render them where needed.
As you see, I use expose-loader for Webpack.
Webpack config
var path = require('path');
var webpack = require('webpack');
const js_dir = path.join(__dirname, 'src');
module.exports = {
devtool: 'eval',
entry: {
components: path.join(js_dir, 'components'),
},
output: {
path: js_dir,
filename: '[name].bundle.js'
},
plugins: [
new webpack.ProvidePlugin({
'es6-promise': 'es6-promise',
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
})
],
module: {
loaders: [
{ test: /\.js$/, loaders: ['babel'] }
]
},
resolve: {
extensions: ['', '.js', '.json']
}
};

Resources