At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it internally builds a dependency graph which maps every module your project needs and generates one or more bundles.
I am trying to provide a kinda step-by-step guide on how to simply setup webpack and get familiar with it. So, let’s get started:
I am using VS code but you can use any other editor. Open up your empty folder with VS code and then open a terminal. Remember you’ve got to have installed node globally.
Now run npm init
, you’ll be asked a couple of questions which you can easily bypass by pressing enter
.
All of webpack modules and loaders would be installed as dev dependency as they are not required for deployment.
1- webpack, you may install the webpack globally but for the time being I am going to set it up as dev dependency.
npm i -D webpack webpack-dev-server
We will need the bellow loaders for the purpose of this guideline. You might be wondering what is a loader. Well to put it simply (from webpack), loaders allow you to pre-process files as you require()
or “load” them.
Loaders are kind of like tasks in other build tools, and provide a powerful way to handle frontend build steps. Loaders can transform files from a different language like, CoffeeScript to JavaScript, or inline images as data URLs. Loaders even allow you to do things like require()
css files right in your JavaScript!
now run this commands:
npm i -D style-loader css-loader sass-loader node-sass file-loader url-loader postcss-loader babel-loader babel-core babel-preset-es2015 eslint eslint-loader eslint-config-airbnb-base eslint-plugin-import extract-text-webpack-plugin
npm i bootstrap --save
Don’t worry, I will go through these one by one:
This package allows transpiling JavaScript files using Babel and webpack.
Here I am assuming, you will be using ES6 and have some idea on babel which is a compiler for writing next generation JavaScript. We will be doing our setup using babel6, which is its latest version and differs a lot from its older versions.
Since babel-loader depends number of modules from babel, we will be installing all of them together. Make sure to read about them.
Following loaders are all used to deal with static resources like css, fonts, images, etc.
<style>
tag.I think you can easily find the use of other loaders on the webpack documentation repository.
package.json
to run webpack-dev-server
with nodeAdd this to scripts section of your package.json
:
"start": "webpack-dev-server --hot --inline"
I am using --inline
and --hot
flags to tell webpack-dev-server
to use hot-reloading for development purposes.
Cool, I think we are now ready to jump to creating necessary files for our project.
We will start by creating a couple of empty folders as the structure of the project.
public
: is used to serve all the files that are accessible to outside world.src
: contains our js files.css
: contains our sass files.For start create a file named app.js
in the src directory
with the bellow code:
import 'bootstrap/dist/css/bootstrap.css'
import '../css/app.scss'
import MyClass from './dependency'
document.write('<h2> This is a demo..! </h2>')
document.write(MyClass.getTemplate())
console.log('app loaded')
Next thing would be to create the MyClass
inside the dependency.js
, I called it dependency to show you it is just a file that is being imported into another and webpack deals with those beautifully.
const MyClass = class Me {
static getClassName() {
return Me.name
}
static getTemplate() {
return `
<div class="row">
<div class="col-xs-6">
<label>Name:</label>
<input class="form-control" type="text" />
</div>
<div class="col-xs-12 link">
<a href="#"><h2>Me</h2></a>
<div>
</div>`
}
}
export default MyClass
console.log('dependency loaded')
Then we add the scss
file inside css
folder:
$body-bg: steelblue;
body {
background-color: $body-bg;
h2 {
font-size: 2em;
color: white;
}
label {
color: white;
}
a {
display: flex;
}
}
Now is time to create the main entry point of the app so called index.html
inside public
folder:
<!DOCTYPE html>
<html>
<head>
<title>Webpack demo</title>
<link rel="stylesheet" type="text/css" src="./public/assets/style.css" />
</head>
<body class="container">
<script type="text/javascript" src="./public/assets/bundle.js"></script>
</body>
</html>
We are pretty much done with the files, so lets create the configuration required by webpack.
Create a file called webpack.config.js
in the root:
var path = require('path')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var autoprefixer = require('autoprefixer')
module.exports = {
context: path.resolve('src'),
entry: './app',
output: {
path: path.resolve('public/'),
publicPath: '/public/assets/',
filename: 'bundle.js',
},
resolve: {
root: __dirname,
extensions: ['', '.js', '.es6'],
},
devServer: {
contentBase: 'public',
},
devtool: 'source-map',
module: {
preLoaders: [
{ test: /\.js?$/, loader: 'eslint-loader', exclude: 'node_modules' },
],
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015'],
},
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract(
'style-loader',
'css-loader!postcss-loader!sass-loader'
),
exclude: /node_modules/,
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader'),
},
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/font-woff',
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=application/octet-stream',
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
loader: 'file',
},
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url?limit=10000&mimetype=image/svg+xml',
},
],
},
postcss: function() {
return [autoprefixer]
},
plugins: [new ExtractTextPlugin('style.css')],
}
I’ll explain the configuration file section by section.
The most important parts are entry points and output of webpack.
context
: this flag defines the root of the source files (for us js files). This is used to prevent repeating the full path while referring to source files.entry
: this can be one or multiple files, depending on which one you use you should alter your output respectively.output
: this is an object containing a couple of key/values. The first one is path which indicates which directory should be used for output. Second is the publicPath
which specifies the public URL address of the output files when referenced in a browser. For loaders that embed <script>
or <link>
tags or reference assets like images, publicPath
is used as the href
or url()
to the file when it’s different then their location on disk (as specified by path).resolve
: options affecting the resolving of modules, extensions is an array of file extensions that should be parsed by webpack.devServer
: these are the configuration of devServer
used for customising how devServer should work. I am usingcontentBase
for pointing the root of public as entry point.devtool
: this one is used to tell webpack it should create source-map
files for debugging purposes.module
: the main configuration flag is module.preloaders
: this section can be used for anything that needs to be done before loading. Linting
is a good example which I’ve setup to use ESList
. This way it webpack gives you error on linting errors.loaders
: I’ve explained this before, generally this is list of loaders used to create the bundle.postcss
: this one is used to tell webpack what should it do after loading css files. Autoprefixer
is used to prefix any css attribute which has browser specific equivalent.plugins
: this is the list of plugins
you might use with webpack. I am using extract-text-webpack-plugin
to force webpack to generate css output outside of js bundle.Long setup nah?
Believe me this is the last one. You can now type npm start
to run the project and see the result.
npm start
You can now open your browser and type localhost:8080
and it will open up the index.html
for you.
Hope you’ve enjoyed the guide.