I went over setting up a basic project with Webpack in this post, so here I'm going to just focus on how to take your React Project and upgrade it to use Webpack and Babel.
In case you forgot, Webpack will help you keep your code compartmentalized into different files, by using import and export statements and a dependency graph.
And Babel will make sure that any browser, no matter how outdated can read and understand your code!
Let's start off with an empty directory again and run npm init -y
to get that package.json up and running. Then, let's install a few packages to get our demo site up and running.
npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader
npm install --save-dev webpack webpack-cli webpack-dev-server
npm install --save react react-dom lodash
We need those Babel presets to parse React code. We need Webpack because that's what this whole article is about, and the Dev Server is just going to let us incorporate a live server with Webpack. We need React and React-DOM to be able to use React, and finally let's grab lodash, a library of utility functions for Javascript.
Before we can get coding let's set up a file structure.
First let's set up the webpack.config.js file to be able to compile the jsx code.
module.exports = {
entry: './src/index.jsx',
output: {
filename: 'app.js',
path: __dirname + 'build',
publicPath: '/'
},
devServer: {
contentBase: './build'
},
devtool: 'eval-source-map',
mode: 'development',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
}
]
}
}
This should look pretty familiar. We're setting the entry and output just as before. However we've added a devServer property, which is just where the devServer is looking for files to host.
We've also added a module property. This is where we set up babel. The test just indicates that any files with those extensions should be compiled. And then we specify a loader, babel-loader, and the presets we want to use to determine how it will transform our code.
Presets load in a bunch of babel plugins automatically and are basically default environments. These two are the most basic, and will definitely get the job done, but there are lots of options out there to explore. If you want to explore individual plugins you can check the babel docs, or if you want to read specifically about what each preset brings to the table, check these docs.
Now set your index.html up exactly as before. It should just have a single script tag with a source of "app.js" and it should only have a div with an id of "app".
We're going to be making an App that gets some placeholder posts off the internet and displays a Post List component that displays a bunch of Posts that represent the placeholder data.
So let's start writing some React code. We'll begin with our entry point index.js.
import ReactDOM from 'react-dom';
import React from 'react';
import App from './App.jsx';
ReactDOM.render(<App />, document.getElementById('app'));
We just import React, ReactDOM, and the App itself and then render it to the Dom. Easy!
Now let's kick it up a notch and look at our App.js.
import React, { Component } from 'react';
import PostList from './PostList.jsx';
class App extends Component {
constructor() {
super();
this.state = {
posts: [],
};
}
componentDidMount () {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => {
res.json()
.then(posts => {
this.setState({posts});
});
});
}
render () {
return (
<div>
<PostList posts={this.state.posts} />
</div>
);
}
}
export default App;
You can see we import React and Component here as well as our next piece of the puzzle, a PostList. Which we call with a list of posts.
We get all our posts from a database of dummy data in our componentDidMount, don't worry about the mechanics of that, let's just focus on hooking all these parts together.
So let's look at our PostList.jsx next. We're going to import lodash here as well, just to see how it's done, but you could easily just use the built in map.
Since we only want map we destructure the object we're importing from lodash and only save the map function out of it. Than we can just call map
instead of _.map
.
import React from 'react';
import { map } from 'lodash';
import Post from './Post.jsx';
const postList = ({posts}) => (
<div>
{map(posts, post => <Post key={post.id} post={post} />)}
</div>
);
export default postList;
Let's follow our chain down to the bottom, Post.jsx. Here we only have to import React and export the post.
import React from 'react';
const post = ({post: {title, body}}) => {
return (
<div>
<p>{title}</p>
<p>{body}</p>
</div >
);
}
export default post;
Alright! We got all of our example React code up! Now let's add a script to start our dev server so we can just make changes to the files and get updates to our locally hosted site live. So add a script to your package.json file.
"start": "webpack-dev-server --config ./webpack.config.js"
So now when you run npm start
in the terminal, you'll have an easy to debug, live updating, local server showing your brand new App!
Once again, this is a very simple app, but hopefully this will help you to see how using import and export statements can be scaled up to larger applications. And learning how to make a compiler work with a bundler is going to be very helpful knowledge to have.
Top comments (4)
Thank you @daniel !
This week I was unsure how to solve the following issue:
I've an existing legacy application in PHP and plain HTML, css and JS served by apache.
Now I wanted to add react into the project. I usually use create-react-app to start a separate react app. But I want to use React inside the apache based application therefor I'm unsure how to set up React to run inside the legacy app.
I was able to build the react code with babel and run a simple hello world react app, but I'm not sure how to setup babel and webpack to be used in dev mode without the webpack dev server because the code should run on the existing apache based code. Any suggestion? Maybe worth a new blog post?
Thank you in advance
Best
Sandor
Ya for sure swapping over to production mode in general would probably be worthy of another post. I'll try to think on it.
But for your current problem, I would say check out Webpack's production documentation. I'm still learning, but my understanding would be that once you get the code working the way you want with the development build, you should be able to swap the mode over to 'production' and generate a minified version that you can just add to your html file.
Best of luck with that!
Daniel
I really don't understand why
create-react-app
is so widespread. It doesn't take that long to configure webpack with the things you're actually going to use.I certainly understand the convenience of
create-react-app
, but I definitely prefer knowing what's going on under the hood. And ya, it really doesn't even take that much longer to set up webpack!