Split react code into react library bundle and components bundle - reactjs

I have the following configuration for webpack (integrated with grunt):
var path = require('path');
var webpack = require('webpack');
module.exports = {
run_webpack: {
entry: {
react: "./static/src/jsx/react.jsx",
index: "./static/src/jsx/index.jsx"
},
output:{
path: "./static/js/",
filename: "[name].bundle.js",
},
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
]
},
},
};
My react.jsx and index.jsx:
// react.jsx
var React = require('react');
var ReactDOM = require('react-dom');
// index.jsx
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('app')
);
And then I embed those bundles into html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Kanban app</title>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script type="text/javascript" src="{% static 'js/react.bundle.js' %}"></script>
<script type="text/javascript" src="{% static 'js/index.bundle.js' %}"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
My problem that it doesn't render <h1>Hello, world!</h1>. The error is 'ReactDOM is not defined'. How can I overcome that issue? It works when I merge react.jsx and index.jsx, but still would like to keep them separately to accelerate code compiling.

Your index.jsx simply has to depend on react and react-dom for the code to work. To achieve what you want, you can load them using externals, though. You could set up something like this for the target generating index:
externals: {
'react': {
commonjs: 'react',
commonjs2: 'react',
amd: 'React',
root: 'React'
},
'react-dom': 'react-dom'
},
This way webpack won't bundle react and react-dom to your index bundle.

Related

css file not getting linked in index.html file served from webpack

Hi I have the folder structure like as follows:-
node_modules
src
|____components
|____index.css
|____index.html
|____index.js
|____index.scss
.babelrc
package.json
webpack.config.js
content of my webpack.config.js file is as below:-
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ExtractTextPlugin = require("extract-text-webpack-plugin")
module.exports = {
entry: {
"index": "./src/index.js",
},
output: {
path: path.join(__dirname, "/dist"),
filename: "[name].js",
},
resolve: {
alias: {
components: path.resolve(__dirname, "src/components")
},
extensions: [".js", ".jsx", ".json"],
mainFiles: ["index"]
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(s*)css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "sass-loader"]
})//["style-loader", "css-loader", "sass-loader"]
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new ExtractTextPlugin({
filename: "bundle.css"
})
],
watch: true,
}
content of my index.html file as follows:-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="./index.css">
<title>React Boilerplate</title>
</head>
<body>
<div id="root">
</div>
</body>
</html>
..
<link rel="stylesheet" type="text/css" href="./index.css">
the above line is not loading my index.css into browser while inside src/components level, i do have css files, whichare properly getting bundeled and delivered in bundle.css file.
Any help would be of great help
The link to the css should be:
<link rel="stylesheet" type="text/css" href="/index.css">
This should be like this due to the publicPath. Since it is not set, it is by default /.
The link to the css should be:
<link rel="stylesheet" type="text/css" href="../src/index.css">

Webpack Not Serving React Component

I have created my webpack config file below:
const HtmlWebPackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js',
output: {
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: '/node_modules/',
use: [
{
loader: 'babel-loader'
}
]
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: {minimize: true}
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html',
filename: './index.html'
})
]
};
and added all the necessary packages babel with env and react presets. I have my index.html file and TestComponent like below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React 16 Webpack Setup</title>
</head>
<body>
<script src="bundle.js" type="text/javascript"></script>
<div id="test">
</div>
</body>
</html>
and component code:
import React, { Component } from 'react';
export default class TestComponent extends Component {
render(){
return (
<div>
<h2>React Setup</h2>
</div>
)
}
}
Here's my main.js file where I'm hosting the component:
import React from "react";
import ReactDOM from "react-dom";
import Test from './TestComponent';
ReactDOM.render(<Test/>, document.getElementById("test"));
The problem is that when I run this script from package.json, I don't get any output/dist folder and also the component doesn't render in the browser. On which url do I have to visit to see the output just like with create-react-app?
Import your <script> at the bottom of the <body> tag in the HTML.
In your case, the browser is reading through the DOM and finding the <script> tag before it is finding the <div id="text"> node. What this means is that the browser will read through your script, and then try and render your <Test/> component into an HTML node with the id="test". The browser can't find the HTML node with the id="test" though because it hasn't read it yet, so it fails.
Make sense? See below...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>React 16 Webpack Setup</title>
</head>
<body>
<div id="test"></div>
{* import scripts at the bottom of the body *}
<script src="bundle.js" type="text/javascript"></script>
</body>
</html>
Hope this helps, let me know if you're still running into issues.

Converting an existing HTML to React using Webpack

I just finished learning ReactJS and was trying to go start learning webpack. I was curious if I could turn my existing website (server-side) structure into react type website (SPA). But my only issue is that I am using a lot of vendor js and css files.
<!doctype html>
<html lang="en">
<head>
<!-- Fonts Online -->
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,800,300' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Montserrat:400,700' rel='stylesheet' type='text/css'>
<!-- Style Sheet -->
<link rel="stylesheet" href="css/owl.carousel.css">
<link rel="stylesheet" href="css/main-style.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<!-- Scripts -->
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="js/jquery-2.1.3.min.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/plugins/superfish.min.js"></script>
<script src="js/jquery.ui.min.js"></script>
<script src="js/plugins/rangeslider.min.js"></script>
<script src="js/plugins/jquery.flexslider-min.js"></script>
<script src="js/uou-accordions.js"></script>
<script src="js/uou-tabs.js"></script>
<script src="js/plugins/select2.min.js"></script>
<script src="js/owl.carousel.min.js"></script>
<script src="js/gmap3.min.js"></script>
<script src="js/scripts.js"></script>
<script>
</script>
</body>
</html>
Now I want to make it like this:
<!doctype html>
<html lang="en">
<head>
<!-- Fonts Online -->
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,800,300' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Montserrat:400,700' rel='stylesheet' type='text/css'>
</head>
<body>
<div id="#root"></div>
</body>
</html>
This is my current webpack config:
const path = require('path');
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
chunkFilename: '[id].js',
publicPath: ''
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query:
{
presets:['react']
}
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]'
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer({
browsers: [
"> 1%",
"last 2 versions"
]
})
]
}
}
]
},
{
test: /\.(png|jpe?g|gif|svg)$/,
loader: 'url-loader?limit=8000&name=images/[name].[ext]'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + '/src/index.html',
filename: 'index.html',
inject: 'body'
})
]
};
The online tutorials kind of confuse me as a beginner in Webpack. So if someone could help me out in this particular use-case, it will help me better understand webpack in general.

Webpack/React app setup failing - "React is not defined"

I am using webpack to set up a React app.
When I serve my app locally using webpack-dev-server I get VM1086 bundle.js:9812 Uncaught ReferenceError: React is not defined in the console.
I have know idea what is going on as there aren't any other errors or information to go on, as webpack seems to compile ok.
index.html
<html>
<head>
<script src="./dist/bundle.js" ></script>
</head>
<body>
<div id="mount"></div>
</body>
</html>
webpack config
var path = require('path');
module.exports = {
entry: [
'./src/App.js',
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: ['node_modules'],
loader: 'babel-loader',
query: {
babelrc: true,
},
}
]
}
}
app.js
import React from 'react';
import ReactDOM from 'react-dom';
console.log('Hello World!');
class App extends React.Component {
render() {
return (<div>314159263</div>);
}
}
ReactDOM.render(<App />, document.getElementById('mount'))
try to define bundle.js after <div id="mount"></div> because may be your bundle compiles your code and it does not find where to render the code
</head>
<body>
<div id="mount"></div>
<script src="./dist/bundle.js" ></script>
</body>
</html>
and also in your webpack add this
query: {
presets: ['es2015', 'react']
}

React + Webpack: React.createElement: type should not be null, undefined, boolean, or number

Why am I getting that error in the console of the chrome ?
My code:
index.html
<!DOCTYPE html>
<html>
<head>
<title>hello React</title>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div id="root">
<!-- my app renders here -->
</div>
<script src="../react-15.3.1/build/react.js"></script>
<script src="../react-15.3.1/build/react-dom.js"></script>
<script src="./dist/bundle.js"></script>
</body>
</html>
main.js
import SalutaMondo from './salutamondo';
var UnaProva = React.createClass({
render: function(){
return (
<div>
<SalutaMondo/>
<div>Ciao Emiliano</div>
</div>
);
},
});
ReactDOM.render(<UnaProva />, document.getElementById("root"));
salutamondo.js
var SalutaMondo = React.createClass({
render: function(){
return (
<h1>Hello World</h1>
);
}
});
module.export = SalutaMondo;
webpack.config.js
const webpack = require('webpack')
const path = require('path')
module.exports = {
entry: [ './src/salutamondo.js', './src/main.js' ],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.js?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015']
}
}
]
}
}
In your webpack config, you're using the babel-loader. This implies that you're using ES6 style modules. In salutamondo.js, you're using CommonJS style modules. As a result, the babel-loader isn't picking up the module. Can you try:
export default SalutaMondo;
instead of:
module.export = SalutaMondo;
This is likely due to salutamondo.js using CommonJS module format, while main.js is using ECMAScript module. I recommend keeping everything in ECMAScript modules:
var SalutaMondo = React.createClass({
render: function(){
return (
<h1>Hello World</h1>
);
}
});
export default SalutaMondo;

Resources