React Webpack Production errors - javascript

I'm trying to setup a webpack (1.13.3) config for a React (15.3.2) app, and I want the production version of React in my production build. I'm on Windows.
I'm using this (which is everywhere online when you search):
new webpack.ProvidePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
However, as soon as I add this and run webpack (CLI) I get slapped round the face with many many errors.
I get a whole bunch of these warnings:
WARNING in ./~/fbjs/lib/partitionObject.js.flow
Module parse failed: C:\node\sandbox\react-webpack\node_modules\fbjs\lib[ SOME FILE NAME HERE].flow Unexpected token (18:24)
You may need an appropriate loader to handle this file type.
...and a bunch of these errors:
ERROR in ./~/react/lib/NativeMethodsMixin.js
Module not found: Error: Cannot resolve module 'react-native/lib/TextInputState' in C:\node\sandbox\react-webpack\node_modules\react\lib
# ./~/react/lib/NativeMethodsMixin.js 17:21-63
I'm not using React Native, I wouldn't know how.
I'm also using webpack.optimize.UglifyJsPlugin in my webpack.config.production.js file.
When I remove the webpack.ProvidePlugin bit the build works, but includes the development version of React and I get warnings in the console:
Warning: It looks like you're using a minified copy of the development build of React. When deploying React apps to production, make sure to use the production build which skips development warnings and is faster.
What are these webpack errors all about..? How do I get a production build of React which is also minified..?
UPDATE
Full webpack config requested. I've setup a test app for this, with minimum config and the warnings and errors are still showing:
webpack.config.js
module.exports = process.env.NODE_ENV === 'production' ? require('./webpack.config.production.js') : require('./webpack.config.development.js')
webpack.config.base.js
module.exports = {
entry: {
'bundle': './client/index.js'
},
output: {
path: './public',
filename: 'js/[name].js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: { presets: ['es2015', 'react'] }
}
]
}
}
webpack.config.development.js
var config = require('./webpack.config.base')
module.exports = config
webpack.config.production.js
var webpack = require('webpack')
var config = require('./webpack.config.base')
config.plugins = [
new webpack.ProvidePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
include: /\.js$/,
compress: { warnings: false }
})
]
module.exports = config
The test app I'm using only has the following installed:
"dependencies": {
"express": "^4.14.0",
"react": "^15.3.2",
"react-dom": "^15.3.2"
},
"devDependencies": {
"babel": "^6.5.2",
"babel-core": "^6.18.2",
"babel-loader": "^6.2.7",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"webpack": "^1.13.3"
}
/client/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import Hello from '../components/Hello'
ReactDOM.render(<Hello />, document.getElementById('page'))
/components/Hello.js
import React from 'react'
const Hello = props => <p>Hello world...</p>
export default Hello
Asked again in a separate question, but with the full error list, and from a React Native view, because the errors contain references to React Native, even though I'm not trying to use it:
Webpack in production: Why React Native errors?

Answered here: Webpack in production: Why React Native errors? by Aruna Herath.
I should be using DefinePlugin not ProvidePlugin.

Related

Import ES6 module from npm package

I created and published my first npm package. This package contains JS in ES6 syntax and is transpiled to ES5 with webpack and babel.
Now I want to use this npm package but it fails with following error:
ERROR in ./node_modules/chokidar/index.js
Module not found: Error: Can't resolve 'fs' in 'C:\dev\git\open-source\test\node_modules\chokidar'
# ./node_modules/chokidar/index.js 3:9-22
# ./node_modules/watchpack/lib/DirectoryWatcher.js
# ./node_modules/watchpack/lib/watcherManager.js
# ./node_modules/watchpack/lib/watchpack.js
# (webpack)/lib/node/NodeWatchFileSystem.js
# (webpack)/lib/node/NodeEnvironmentPlugin.js
# (webpack)/lib/webpack.js
# ./node_modules/technology-radar/webpack.config.js
# ./sample/app.js
For usage I have the following (minimal) set of files
package.json:
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"babel-preset-es2015": "^6.24.1",
"webpack": "^3.5.6",
"webpack-dev-server": "^2.4.5",
"babel-polyfill": "^6.26.0",
"html-webpack-plugin": "^2.28.0"
},
"dependencies": {
"d3": "3.5.17",
"technology-radar": "^1.0.3"
}
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
entry: {
sample: './sample/app.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
loaders: [
{
loader: 'babel-loader',
include: [
path.resolve(__dirname, "sample")
],
test: /\.js$/
}
]
},
plugins: [
new UglifyJSPlugin(),
new HtmlWebpackPlugin({
template: 'sample/index.html',
filename: 'index.html',
inject: 'body'
})
],
devtool: "#source-map"
};
sample/app.js
import Radar from 'technology-radar';
var radar = new Radar("#techradarContainer");
radar.render();
I don't know if there is in the usage or in the npm package itself.
The sourcecode of the package is available on github at https://github.com/raman-nbg/techradar. The npm package is available at https://www.npmjs.com/package/technology-radar.
The class which should be export (as defined as entry point in the webpack.config.js of the package) is defined src/Radar.js with export default class Radar { ... }. The entry point is defined as
module.exports = {
entry: {
"technology-radar": "./src/Radar.js",
...
}
...
}
You seem to be misunderstanding how publishing and using packages works.
Ignoring Webpack entirely, a standard npm module has main set to the JS file that is the root of your package, and generally packages published to npm are compiled with Babel before being published. Usually before publishing technology-radar, you'd use a package like babel-cli with
babel src -d lib
to compile everything in the src directory into ES5 inside lib. Then
your package.json#main value should be
"main": "./lib/index.js"
or whichever package is the conceptual root of your package. That could be Radar.js in your case, but it's hard to tell.
Because your main is set to webpack.config.js, when you run Webpack inside your actual application, you are trying to bundle Webpack itself for use on in a browser, which does not work because it is a Node application.
If you've done the above and have a technology-radar package that is already processed with Babel, the configuration of your sample application is pretty much what you already have.

Error: Uncaught ReferenceError: React is not defined

Overview
I am trying to use Babel and Webpack to build a React app. I know I could use create-react-app but I'd like to learn how these technologies can work together for myself.
When I run yarn run start or yarn run build (see package.json below), Webpack reports to have built the bundle fine. When I run the application in the browser, I get the Uncaught ReferenceError: React is not defined error.
There are a number of questions on SO regarding this same error, but none of the solutions have solved my problem yet.
Question
What piece am I missing to get React, Babel, and Webpack to play together nicely?
Code
package.json
{
"private": true,
"scripts": {
"build": "webpack",
"start": "webpack-dev-server"
},
"dependencies": {
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-redux": "^5.0.1",
"redux": "^3.6.0"
},
"devDependencies": {
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"redux-devtools": "^3.3.1",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2"
}
}
.babelrc
{
"presets": ["react", "es2015"]
}
webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: './dist'
},
devtool: 'source-map',
debug: true,
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<div id="root"></div>
<script src="dist/bundle.js"></script>
</body>
</html>
src/index.js
import ReactDom from 'react-dom';
import React from 'react';
import App from './App';
ReactDom.render(
<App />,
document.getElementById('root'),
);
src/App.js
import React from 'react';
import { Component } from 'react';
export default class App extends Component {
render() {
return (
<h1>hello</h1>
);
}
}
Observations
It seems that Webpack/Babel is expecting React to be available on the global scope, or is ignoring my import React from 'react'; statements.
Also, I have yet to find the proper incantation of devtools and debug properties in my Webpack config to actually get source maps working. I don't yet see them in the compiled output.
EDIT
The broken bundle.js is too large for SO (21,000+ lines), so here is a link: http://chopapp.com/#1a8udqpj — it takes several seconds to load and display.
Since you're trying to learn the in's and out's of webpack et al... Your original problem was that you needed to specify the output.publicPath in your webpack.config.js:
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: './dist',
publicPath: '/dist' // <- was missing
},
devtool: 'source-map',
debug: true,
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
}
}
"path" is the physical path to the folder that contains your bundle.js. "publicPath" is the virtual path (URL) to that folder. So, you don't even have to use "dist". For example, if you used...
output: {
filename: 'bundle.js',
path: './dist',
publicPath: '/assets'
},
Your HTML would then point to:
<script src="assets/bundle.js"></script>
I wish to make the following observations. First to your question regarding devTools and debug. The debug flag for webpack (according to their official documentation) switches the loaders to debug mode. Then, from what I understand, webpack, when running in a dev environment, does not actually compile the code to hard files, but keeps it in memory. Thus the source maps are also kept in memory and linked to the browser. You see their effect when you open the browser dev tools and view source.
Now assuming you have the dev server configured correctly, I also assume your index.html is located in your source directory. If this is the case, then your script reference should simply point to '/bundle.js' and not 'dist/bundle.js' since there may not be a physical "dist" folder.
I would also suggest dropping the ".js" from your entry point in the webpack.config.js
You will need to add a query to your module within the webpack.config.js file:
module: {
loaders: [{
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}]
},
resolve: {
extensions: ['', '.js', '.jsx']
};

How to add a separate CSS file for .scss files using webpack?

I have a pretty simple JavaScript app I'm compiling using Webpack. I have the application splitting into two separate bundles now - App and Vendor. App contains my custom code while the vendor files contains the frameworks.
The app bundle contains all the JavaScript in my app directory, but there are also some Sass files in there as well. I'm trying to get those to compile into a separate CSS bundle file.
Through some research, I figured out I needed to use the extract-text-webpack-plugin with a webpack Sass compiler and style loaders.
Here is my webpack.config file:
var webpack = require('webpack')
var ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
context: __dirname + '/app',
entry: {
app: './app.module.js',
vendor: ['angular','angular-route']
},
output: {
path: __dirname + '/bundle',
filename: 'app.bundle.js'
},
module: {
loaders: [
{ test: /\.scss$/, loader: ExtractTextPlugin.extract("style- loader", "css-loader") }
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.bundle.js'),
new ExtractTextPlugin("styles.css")
]
}
I have the following dependencies installed using npm:
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"node-sass": "^3.8.0",
"sass-loader": "^4.0.0",
"style-loader": "^0.13.1",
"webpack": "^1.13.1"
The problem is when I bundle using webpack, I get the following error:
Module not found: Error: Cannot resolve 'file' or 'directory' ./../node_modules/css-loader/index.js
And
Module not found: Error: Cannot resolve 'file' or 'directory' ./../node_modules/style-loader/addStyles.js
I'm only including one sass file in my main application file at the moment. In my main app.js file, I have: require('./styles.scss') Any ideas why this is happening?
To those of you that may be having the same issue, and you're running Windows, the following solution worked for me:
At the top of our webpack.config add the following:
var path = require('path');
Then change where you define your context to:
context: path.resolve(__dirname, "folder_name")

How to use scss with css modules / postcss inside components

I'm failing to figure out how to setup my webpack in order to be able and use scss modules inside my components like:
import styles from './ComponentStyles.scss'
So far I tried configuring webpack to use sass-loader alongside postcss-loader but had no luck:
{
test: /\.scss$/,
loaders: [
'isomorphic-style-loader',
'css-loader?modules&localIdentName=[name]_[local]_[hash:base64:3]',
'postcss-loader',
'scss-loader'
]
}
Note isomorphic-style-loader is a library I use instead of style-loader due to server rendering requirements, in its github page docs they actually use postcss-loader with .scss extension, but in my case scss is not compiled if I follow their example.
I had to do some tinkering myself, but eventually landed on the following
package.json
"autoprefixer": "^6.3.1",
"css-loader": "^0.23.1",
"extract-text-webpack-plugin": "^1.0.1",
"node-sass": "^3.8.0",
"sass-loader": "^3.1.2",
"style-loader": "^0.13.0"
webpack config
...
const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
...
const config = {
...
postcss: [
autoprefixer({
browsers: ['last 2 versions']
})
],
plugins: [
new ExtractTextPlugin('css/bundle.css'),
],
module: {
loaders: [
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!postcss!sass')
}
]
}
...
};
bootstrap.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './app';
import style from './scss/style.scss';
ReactDOM.render(
<App/>,
document.getElementById('my-app')
);
For those interested: what's happening here is bootstrap.jsx is the webpack entry point, and by importing our raw scss file (via relative path), we tell webpack to include it during the build process.
Also, since we've specified a loader for this file extension in our configuration (.scss), webpack is able to parse style.scss and run it through the defined loaders from right to left: sass --> post-css --> css.
We then use extract-text-webpack-plugin to pull the compiled CSS out from bundle.js, where it would normally reside, and place it in a location (css/bundle.css) relative to our output directory.
Also, using extract-text-webpack-plugin is optional here, as it will simply extract your CSS from bundle.js and plop it in a separate file, which is nice if you utilize server-side rendering, but I also found it helpful during debugging, since I had a specific output location for the scss I was interested in compiling.
If you're looking to see this in action, here's a small boilerplate that uses it: https://github.com/mikechabot/react-boilerplate

Rollup.js: undefined objects in external dependencies

I recently started playing with rollupjs. After configuring everything as per available docs and bundling things up, I got many errors from my external libraries about undefined objects. This sort of errors: Cannot read property 'parse' of undefined coming from crypto-js.
It complains about this line in the code: var ciphertext = Base64.parse(openSSLStr). So Base64 is undefined. I have few errors like this from different external libraries bundled in.
I use a handful of external dependencies:
chart.js,
crypto-js,
mithril,
moment,
pluralize
All of them work perfectly with jspm. I decided to try rollup to speed things up as jspm is soooo slow at the moment. Now half of my external dependencies stopped working. I get "undefined things" and "...not a function" kind of errors coming from external libraries only.
What could possibly be the cause of it?
This is my rollup.config.js
import babel from 'rollup-plugin-babel';
import npm from 'rollup-plugin-npm';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'app/scripts/application/main.js',
format: 'cjs',
plugins: [
npm({
jsnext: true,
main: true,
}),
babel({
exclude: 'node_modules/**',
presets: [ 'es2015-rollup' ],
}),
commonjs(),
uglify(),
],
dest: 'static/js/application.js',
};
Let me know if any other details are needed.
Thanks.
EDIT
I've done a simple tests-reproduction bundling those libraries that generate errors in my application.
package.json
{
"name": "minion",
"private": true,
"babel": {
"presets": [
"es2015-rollup"
]
},
"dependencies": {
"chart.js": "^1.0.2",
"crypto-js": "^3.1.6",
"mithril": "^0.2.2-rc.1",
"moment": "^2.11.1",
"pluralize": "^1.2.1"
},
"devDependencies": {
"babel-preset-es2015-rollup": "^1.1.1",
"rollup-plugin-babel": "^2.3.9",
"rollup-plugin-commonjs": "^2.2.0",
"rollup-plugin-npm": "^1.3.0",
"rollup-plugin-uglify": "^0.1.0"
}
}
rollup.config.js
import babel from 'rollup-plugin-babel';
import npm from 'rollup-plugin-npm';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'app/main.js',
format: 'cjs',
plugins: [
npm({
jsnext: true,
main: true,
}),
babel({
exclude: 'node_modules/**',
presets: [ 'es2015-rollup' ],
}),
commonjs(),
//uglify(),
],
dest: 'static/js/app.js',
}
main.js
import Application from './application'
import pluralize from 'pluralize'
var text = Application.run()
console.log(`Testing encryption: ${text}`)
console.log(`Testing pluralization: ${pluralize('person')}`)
application.js
import crypt from 'crypto-js'
var Application = {
run() {
var ciphertext = crypt.AES.encrypt('Testing encryption...', 'password')
var bytes = crypt.AES.decrypt(ciphertext.toString(), 'password')
return bytes.toString(crypt.enc.Utf8)
}
}
export default Application
Running the above will generate the errors.
Just speculating: Maybe is a bug of the rollup and/or crypto.
I have a similar error when trying to run a js function in Node Red, the js is ok when I run it locally but it throws TypeError: Cannot read property 'split' of undefined when runs remotely.
The only thing that my code have in common with yours is that both uses cryptography, specifically crypto-js 3.1.2 rollup "hmac-sha256.js" and the code is not imported but raw.
Even after deleting the only instance of 'split' yet I can't solve it (but keeps running locally)

Categories