loading...

How I set up Webpack and Babel with vanilla JS

robotspacefish profile image Jess Updated on ・5 min read

(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

Step 2: Initialize your project

// set up your package.json

// using yarn:
yarn init

// using npm:
npm init

project-folder
|_ /dist
|_ /src
|_ package.json

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 

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')
 }
}

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

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"
 }
}

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

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"
       ]
     },
   ]
 }
};

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

Add some test code to the css file:

body {
 background: green;
}

Connect your styles to your index.js file:

import './styles/main.css';

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

@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",
           ]
         }
       }
     },
   ]
 }
};

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.

Posted on May 5 by:

robotspacefish profile

Jess

@robotspacefish

Software Engineer / Flatiron School grad

Discussion

markdown guide