1. 程式人生 > >How to combine Webpack 4 and Babel 7 to create a fantastic React app

How to combine Webpack 4 and Babel 7 to create a fantastic React app

I previously wrote an article called How to conquer Webpack 4 and build a sweet React app.” Soon after I wrote the article, babel swooped in with a major breaking change and many of the packages got deprecated. So I decided to write a new tutorial.

I will focus on setting up webpack with react which will have .scss

support along with code splitting

The purpose for writing this again is simple: I want everyone to feel comfortable. Because setting up webpack can be really daunting. Especially for new developers out there. Follow along, and what seemed difficult and maybe scary will seem like a piece of cake.

Before we start, here is the

source code. I know this has loads of things in it. I plan to use the same code base to talk about webpack, react, SCSS, hot module replacement, testing with jest and enzyme, linting code, and adding a code formatter like prettier in other articles to come, so I will continuously keep on updating this code base. I will not bloat this code base — I promise.

Note: If you feel like making a PR for the repository, you are more than welcome :) So let’s get started.

For simplicity sake, this article is only going to focus on;

  • Setting up Webpack 4 with Babel 7 for React
  • Support for .SCSS
  • Code Splitting
  • Development environment with HMR (Hot Module Replacement)
  • Production configuration
  • Dividing your Webpack configuration into chunks
  • Handling staging, demo, production, test and other environments in code
  • Generating a visualizer in production build to check which chunk of code took how much size and what are the dependencies of the chunks. Super useful.

Prerequisite

You need to have node installed in order to use npm (node package manager).

First things first, create a folder called app then open up your terminal and go into that app folder and type:

npm init -y

This will create a package.json file for you.

Second create a folder called src in your app folder. Inside app/src create a file called index.js and write the following code.

You can write anything above of course. I chose Star Trek.

Change is the essential process of all existence. — Spock

Next we need to install a couple of dependencies. You can just copy the dependencies & devDependencies from the package.json below into your own and do an npm install:

package.json

Yes I know, I know! That’s a lot to create a hello world react app. But wait, this is all you will need. Even if you want to create a enterprise level app. (Maybe one or two more things depending on your requirements, but this is the backbone for it.)

So let’s talk about each and everyone of them before we dive deep into the code.

webpack: We need Webpack to bundle our code.

webpack-cli: We will be using some CLI features of Webpack to make our lives easier while writing some scripts.

webpack-dev-server: I will create a server using the webpack-dev-server package. This is only meant to be used in the development environment, and not for production. This means while developing and working on my code, I don’t need a separate server like NodeJS to setup manually.

webpack-merge: To divide our configuration into chunks, more on this later

webpack-visualizer-plugin: To see a visual representation of each of our bundle size — how much space they are taking and what are their dependencies.

style-loader: This adds CSS to the DOM by injecting a <script /> tag in the header

node-sass: A dependency for sass-loader

css-loader: To convert our .scss files into .css

mini-css-extract-plugin: This plugin extracts CSS into separate files. It creates a CSS file per JS file which contains CSS.

uglifyjs-webpack-plugin: To minify JavaScript code for production

html-webpack-plugin: This does more then generate an HTML file, it supports on demand .css and .js files automatically added to your HTML files on demand

copy-webpack-plugin: Copies files/folders to your build folder.

babel-loader: This is the loader that helps webpack compile .js files

@babel/core: Babel core compiler, this is a dependency that lets you use babel-loader

@babel/preset-env: Babel preset that allows you to use the latest JavaScript

@babel/pollyfill: Babel includes a polyfill that includes a custom regenerator runtime and core-js. This will emulate a full ES2015+ environment. This means support for async/await type of cool syntax sugar.

So what changed?

Well! Babel introduced a breaking change (for the greater good, believe me) which you can read more here: Removing Babel’s Stage Preset. What this meant was that before if you included babel-preset-stage-2 let’s say, it would include all proposals related to stage-2, which would bloat your code. But you just might need one specific feature of stage-2.

So in order to combat this, babel deprecated all those preset plugins and shipped individual features. You now have to set those up manually. Cool right? So let’s talk a bit about those individual packages and what they do.

@babel/plugin-proposal-class-properties: Coverts your class syntax into a function for browsers that don’t support class syntax

@babel/plugin-proposal-throw-expressions New syntax to throw exceptions from within an expression context. I love this feature :D

@babel/plugin-syntax-dynamic-import This is what helps with code splitting. Webpack ships with code splitting by default (Since webpack 1). But when you want to code split in webpack while you are using babel, then you need to use this plugin.

Note: for this tutorial you won’t need@babel/plugin-proposal-export-namsespace-from & @babel/plugin-proposal-throw-exception

Also here is a list of all babel plugins. I mean all of them. Check out the list here.

And now that you know why we need what we need — nothing extra — you’ll feel more confident implementing the webpack configuration.

Let’s start by adding a .babelrc file in the root of out app folder:

We have 2 main presets preset-env & preset-react . The rest are our plugins to add “wings” to our code.

And to quote Captain Kirk from Star Trek (because why not):

Perhaps man wasn’t meant for paradise. Maybe he was meant to claw, to scratch all the way. Captain Kirk

In his defense, Captain Kirk was up against the likes of General Change, Khan, The Borg and so many dangerous foes. All we are up against is the beautiful Webpack and Babel. So perhaps we developers are meant for paradise.

So let’s set our webpack up.

Create a config folder in your app . If you feel lost you can at any time refer to the GitHub repository for this. Now inside our config folder let’s create a file called webpack.base.config.js The reason I call this base is because it is going to be used for our development and for production. Because why write the same thing twice? Again if this isn’t making much sense, just bear with me a few more minutes.

In your config/webpack.base.config.js write this:

Once you have it in place, run this command in your root app directory. (I’ll tell you what this command does a bit later with the code we wrote above, I promise.)

$ node_modules/.bin/webpack-dev-server --mode development --config config/webpack.base.config.js --open --hot --history-api-fallback

Once you run this command, you will see this screen:

Oh! A Fancy Error!

So what happened here? Well when we ran the webpack command, it did find our index.js file that we wrote earlier in app/src/index.js — but it didn’t have a .html to run it in. So let’s create an index.html file in our app/src folder:

<div id=”app></div> is where we will populate our react app.

Let’s update our webpack.base.config.js as well:

Let’s run that command again now:

$ node_modules/.bin/webpack-dev-server --mode development --config config/webpack.base.config.js --open --hot --history-api-fallback

Your browser will open up. If you are using Google Chrome, press ctrl+shift+j and your browser console will open up. You will see something like this: