Webpack - A Detailed Introduction - Smashing Magazine
Basic setup:
Go to directory
npm init → Initialise npm
create src
folder and put script.js
, index.html
and style.css
in it.
in index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document Name</title>
</head>
<body>
</body>
</html>
in script.js
add:
import ./style.css
in style.css
add:
* {
margin: 0;
padding: 0;
PS: We adding just the basic boiler plate.
Webpack Setup
yarn add webpack webpack-cli
in CLI to add webpack dependencies: webpack and webpack-clibundler
folder at the same level as srcwebpack.common.js
in it.Webpack Configuration:
Creating entry and output -> in webpack.common.js
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, '../src/script.js'),
output:
{
filename: 'bundle.[contenthash].js',
path: path.resolve(__dirname, '../dist')
},
devtool: 'source-map',
}
For testing in package.json add the following scripts:
"scripts": {
"test": "webpack --config ./bundler/webpack.common.js",
},
here we are specifing that instead of having a webpack.config.js file in our e=root folder we have seperated it on to a bundler folder.
You can run npm run test
any time in between to see the output in the dist
folder
Installing loaders, plugins and writing corresponding rules for webpack configuration:
Learn Webpack Pt. 8: Html-loader, File-loader, & Clean-webpack
Adding file-loader
other loaders for handeling fonts and images
yarn add file-loader
Add the following rules for working with images and fonts being used in the app.
// Images
{
test: /\\.(jpg|png|gif|svg)$/,
use:
[
{
loader: 'file-loader',
options: {
outputPath: 'assets/images/'
}
}
]
},
// Fonts
{
test: /\\.(ttf|eot|woff|woff2)$/,
use:
[
{
loader: 'file-loader',
options: {
outputPath: 'assets/fonts/'
}
}
]
},
In options we are specifying that after building the app, put images, fonts in the assets folder.
When we run a npm run build
to create a production ready distribution folder, webpack will browse through your code and as soon as it finds something like image or fonts, it will automatically create an asset folder inside which there will be an image folder to store that imported image and there will be an font folder in assets created to store its corresponding font.
Adding copy-webpack-plugin
:
Copies individual files or entire directories, which already exist, to the build directory.
The idea here is you will have a static folder in dev where you will store all your fonts, images, etc, and in prod build you want this to be all copied in the build folder.
Without this plugin, in the final production folder that is created, only those images will be bundles that are imported in the javascript.
Also make sure from now on you have atleast one image inside the static folder, else it will trown an error.
The structure inside the static folder will be replicated in the dist (production build) folder.
Make sure you create a static folder first.
yarn add copy-webpack-plugin
Require/import it:
const CopyWebpackPlugin = require('copy-webpack-plugin')
Declare it:
plugins:[
new CopyWebpackPlugin({
patterns: [
{ from: path.resolve(__dirname, '../static') }
]
}),
....
],
Here, From now on make sure that there is a test image in your static folder else building it (npm run test) will result in an error.
Creating Dev Configuration: to start a live server.
We will use webpack.common.js a commn configuration that will be used by for the dev and prod configurations:
In Dev server, files get build in memory and are destroyed as soon as the server id destroyed.
Create a webpack.dev.js
file in bundler folder
Importing commonConfiguration
from webpack.common.js
To import we will need webpack-merge
module
yarn add webpack-merge
Adding basic things to webpack.dev.js
const { merge } = require('webpack-merge')
const commonConfiguration = require('./webpack.common.js')
module.exports = merge(
commonConfiguration,
{
mode: 'development'
}
)
Adding dev script in package.json
"scripts": {
"test": "webpack --config ./bundler/webpack.common.js",
"dev": "webpack serve --config ./bundler/webpack.dev.js",
},
here the serve flag will make it live reload, but before running it, there are still a few things we need to add to serve this app.
Adding Server Dependencies.
yarn add portfinder-sync
Find an open port synchronously.
yarn add D webpack-dev-server
Dev Server for web applications, ideal for buildless es module workflows. Optionally supports simple code transformations.
This is added so now the webpack 'serve'
command is recognised
Updating wepack dev:
Importing required modules:
const ip = require('internal-ip')
const portFinderSync = require('portfinder-sync')
Function that prints local domain (where server is running) names distinctly:
const infoColor = (_message) => {
return `\\u001b[1m\\u001b[34m${_message}\\u001b[39m\\u001b[22m`
}
Adding devServer key to module exports:
devServer: {
host: '0.0.0.0',
port: portFinderSync.getPort(8080),
contentBase: './dist',
watchContentBase: true,
open: true,
https: false,
useLocalIp: true,
disableHostCheck: true,
overlay: true,
noInfo: true,
after: function(app, server, compiler)
{
const port = server.options.port
const https = server.options.https ? 's' : ''
const localIp = ip.v4.sync()
const domain1 = `http${https}://${localIp}:${port}`
const domain2 = `http${https}://localhost:${port}`
console.log(`Project running at:\\n - ${infoColor(domain1)}\\n - ${infoColor(domain2)}`)
}
}
Try running npm run dev
and you should see a live server being sprung up! and this is now live updating with all the changes you make!
Creating build Configuration: to creat a production ready dist folder.
Creating a production configuration file in bundlers folder:
bundlers → webpack.prod.js
Adding basic configurations to webpack.prod.js:
const { merge } = require('webpack-merge')
const commonConfiguration = require('./webpack.common.js')
module.exports = merge(
commonConfiguration,
{
mode: 'production',
}
)
It will use the same merge and commonConfiguration as dev configuration. We will just change the mode.
Adding Plugin:
yarn add clean-webpack-plugin
A webpack plugin to remove/clean your build folder(s).
It makes sure that there is no dist folder.
If there is already existing one it deletes it.
Importing and Declating Plugin in the webpack production configuration:
const { merge } = require('webpack-merge')
const commonConfiguration = require('./webpack.common.js')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = merge(
commonConfiguration,
{
mode: 'production',
plugins:
[
new CleanWebpackPlugin()
]
}
)
Add scripts to package.json
for a build command.
"scripts": {
"test": "webpack --config ./bundler/webpack.common.js",
"dev": "webpack serve --config ./bundler/webpack.dev.js",
"build": "webpack --config ./bundler/webpack.prod.js"
},
And that should be it, try running npm run build
and check the dist folder that would have been created.
Adding raw-loader for loading shaders:
yarn add raw-loader
Webapack rules:
// Shaders
{
test: /\\.(glsl|vs|fs|vert|frag)$/,
exclude: /node_modules/,
use: [
'raw-loader'
]
}