DEV Community

Jess
Jess

Posted on • Updated on

How I set up Webpack and Babel with vanilla JS

(Note: I'm moving my posts from my time at Flatiron School from my Github to this platform. This blog entry was first posted on April 29, 2020)

Webpack and Babel are extremely helpful, but they can be pretty overwhelming and confusing to set up. To be honest, every time I need to set them up in a new project I just reference an old one and adapt it to my current needs. I figured it might be good to explain my set up and hopefully it can help others get their projects set up as well.

What is Webpack?

Webpack is a module bundler. It allows you to write your code in as many separate files as you need and creates a single output file for you to import into your html file.

You can view the getting started guide [here]((https://webpack.js.org/guides/getting-started/).

What is Babel?

Babel enables you to write code using all the latest and greatest features of ECMAScript and converts it to backwards compatible code for older environments that may not support all of the newest features.

You can view the usage guide here.

How I set up my projects

Step 1: File structure

Create a dist folder for your distribution code. Keep your index.html in this folder and write your code in the src folder. Later when Webpack creates a bundle file, it will end up in the dist folder.

project-folder
|_ /dist
    |_ index.html
|_/src
    |_ index.js
Enter fullscreen mode Exit fullscreen mode

Step 2: Initialize your project

// set up your package.json

// using yarn:
yarn init

// using npm:
npm init

Enter fullscreen mode Exit fullscreen mode
project-folder
|_ /dist
|_ /src
|_ package.json
Enter fullscreen mode Exit fullscreen mode

Step 3: add Webpack dependencies:

// using yarn
yarn add webpack webpack-cli webpack-dev-server --dev

// using npm 
npm install  webpack webpack-cli --save-dev 
Enter fullscreen mode Exit fullscreen mode

webpack-dev-server allows you to serve the webpack bundle. Every time you save it will re-bundle and show you your changes live.

Step 4: open package.json and add “private”: true to prevent accidentally publishing your code.

Step 5: create a file webpack.config.js in your root project-folder

const path = require('path');
module.exports = {
 "mode": "none",
 "entry": "./src/index.js",
 "output": {
   "path": __dirname + '/dist',
   "filename": "bundle.js"
 },
devServer: {
   contentBase: path.join(__dirname, 'dist')
 }
}
Enter fullscreen mode Exit fullscreen mode

The ‘entry’ is your main JS code file, ‘path’ is where your index.html file is and you want your js bundle to go, and ‘filename’ is the name of your bundled js file. devServer allows the webpack dev server to find your dist folder.

See more about configuring here.

Step 6: Create index.html and index.js

Create index.html in your dist folder and add <script src="bundle.js"></script> to the bottom of the <body>.

Create index.js in your src folder. Add something like alert(‘connected!’) for test purposes.

|_ /dist
    |_ index.html
|_ /src
    |_ index.js
|_ package.json
|_ webpack.config.js
Enter fullscreen mode Exit fullscreen mode

Step 7: Add scripts to package.json

This is what my package.json looks like so far:

{
 "name": "webpack_demo",
 "version": "1.0.0",
 "private": true,
 "main": "index.js",
 "license": "MIT",
 "devDependencies": {
   "webpack": "^4.43.0",
   "webpack-cli": "^3.3.11",
   "webpack-dev-server": "^3.10.3"
 },
 "scripts": {
   "build": "webpack",
   "dev-server": "webpack-dev-server"
 }
}

Enter fullscreen mode Exit fullscreen mode

The scripts here are what will bundle your code. Running yarn run build or npm run build will bundle your code one time and you can open your index.html in your browser and you should see your JavaScript alert.

Running yarn run dev-server or npm run dev-server will start your local server. Once it’s up and running, visit the localhost it says the project is running on in the terminal (ex. http://localhost:8080/) and you should see your JavaScript test alert. By using the dev-server you can make changes, save, and it will re-bundle automatically. You won’t have to worry about manually building and opening your index.html in the browser each time you make a change.

Step 8: Adding Style Loaders

If you want to be able to import css files you will need to add the appropriate loaders to your webpack.config.js

css-loader is used to interpret and resolve imports and style-loader is used to inject your css into the DOM.

// npm install
npm install --save-dev css-loader style-loader

// yarn install
yarn add --dev css-loader style-loader
Enter fullscreen mode Exit fullscreen mode

Now, add the module rules to use the loaders to your webpack.config file.

const path = require('path');

module.exports = {
 "mode": "none",
 "entry": "./src/index.js",
 "output": {
   "path": __dirname + '/dist',
   "filename": "bundle.js"
 },
 devServer: {
   contentBase: path.join(__dirname, 'dist')
 },
 "module": {
   "rules": [
     {
       "test": /\.css$/,
       "use": [
         "style-loader",
         "css-loader"
       ]
     },
   ]
 }
};

Enter fullscreen mode Exit fullscreen mode

Create a folder called ‘styles’ and add a css file inside.

|_ /dist
    |_ index.html
|_ /src
    |_ index.js
    |_ /styles
        |_ main.css
|_ package.json
|_ webpack.config.js
Enter fullscreen mode Exit fullscreen mode

Add some test code to the css file:

body {
 background: green;
}
Enter fullscreen mode Exit fullscreen mode

Connect your styles to your index.js file:

import './styles/main.css';
Enter fullscreen mode Exit fullscreen mode

Now when you start the dev-server you should see the green background.

Step 9: devtools

When you use webpack to bundle your code, if you try to use the browser’s dev tools you will see all the bundled code and you will have a really hard time debugging your code. You can add devtools to your webpack.config, which controls how source maps are generated, and then you’ll be able to see the code you wrote and debugging will be a lot easier. There are a lot of different settings to choose from in the docs, but I’m using devtool: 'cheap-module-eval-source-map'

Step 10: Install Babel dependencies

// using npm
npm install --save-dev babel-loader @babel/core @babel/preset-env

// using yarn 
yarn add babel-loader @babel/core @babel/preset-env --dev
Enter fullscreen mode Exit fullscreen mode

@babel/preset-env is used so you don’t have to worry about polyfills or which syntax is required by your environment.

Add the babel-loader to your webpack.config

const path = require('path');

module.exports = {
 "mode": "none",
 "entry": "./src/index.js",
 "output": {
   "path": __dirname + '/dist',
   "filename": "bundle.js"
 },
 devtool: 'cheap-module-eval-source-map',
 devServer: {
   contentBase: path.join(__dirname, 'dist')
 },
 "module": {
   "rules": [
     {
       "test": /\.css$/,
       "use": [
         "style-loader",
         "css-loader"
       ]
     },
     {
       "test": /\.js$/,
       "exclude": /node_modules/,
       "use": {
         "loader": "babel-loader",
         "options": {
           "presets": [
             "@babel/preset-env",
           ]
         }
       }
     },
   ]
 }
};
Enter fullscreen mode Exit fullscreen mode

And that’s pretty much my set-up. Check out the docs linked throughout this post to find out about all the different ways you can configure your project.

Oldest comments (8)

Collapse
 
allerby profile image
Michael

Awesome work Jess, this was really well explained and trivial to follow. Thanks for posting.

Collapse
 
robotspacefish profile image
Jess

Thanks Michael, I’m glad it was helpful! :)

Collapse
 
adriantoddross profile image
Adrian Ross

Dead simple and still a great introduction to setting up webpack. Thanks to this, I was able to get the basics up & going then really go wild with my dev config. Thank you so much! I'm in love with webpack atm.

Collapse
 
robotspacefish profile image
Jess

Thank you, Adrian. Glad it helped!

Collapse
 
jzuleta profile image
José Ignacio Zuleta

Really straight forward! Thank you

Collapse
 
rschneider94 profile image
Rodrigo Schneider

Thanks for sharing this, really helpful! Just one tip: I had an error because Webpack is now in version 5 and to serve, it's a bit different, running just webpack-dev-server thrown an error. Now we need to do this instead: webpack serve.

Collapse
 
robotspacefish profile image
Jess

awesome, thanks for the update Rodrigo!

Collapse
 
merrimanxyz profile image
merriman-xyz

FYI for anyone using this guide in 2022:

When configuring the devServer, use static instead of contentBase if using the most recent version of webpack-dev-server:

devServer: {
   contentBase: path.join(__dirname, 'dist')
 }
Enter fullscreen mode Exit fullscreen mode
devServer: {
   static: path.join(__dirname, 'dist')
 }
Enter fullscreen mode Exit fullscreen mode