mjswensen
mjswensen

Reputation: 3134

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

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.

Upvotes: 4

Views: 17929

Answers (3)

Jeff McCloud
Jeff McCloud

Reputation: 5927

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>

Upvotes: 5

Paul Stoner
Paul Stoner

Reputation: 1522

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

Upvotes: 1

hanorine
hanorine

Reputation: 7825

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']
};

Upvotes: 0

Related Questions