What is Webpack 5 and Module Bundling
What is an Webpack?
- Webpack lets you code using the different filetypes and dependencies that your compfortable with and converts them to into the static assets that your browser prefers.
- When building an APP we typically will see two folders
- SRC
- This folder has all the working files that we will edit during the development process
- DIST
- This folder holds all the static assets after the BUILD process has been ran
- SRC
Other Types of Module Bundlers
- Snowpack
- Rollup
- Parcel
Webpack Installation
- When NOT using a tool, such a Create React App, we can manually install webpack into our workspace by add these two commands.
- Initialize npm
1npm init -y
- Install webpack developer dependency
1npm i -D webpack
- Install webpack-cli developer dependency
1npm i -D webpack-cli
- [optional] Verify installation went well, check package.json devDependencies
- Initialize npm
How to setup the run script
- Inside our our package.json we can setup our scripts next to run our app
- Add "build": "webpack --mode production"
- Now this will generate a new file main.js that takes our application and MINIFYS it and makes it CROSS-BROWSER-COMPATIBLE
- Confirm your index.html is referencing our new file, main.js
- We can now view the page and our app should be running
- Production will generate less code than development
Webpack Config
Webpack Config Setup
- Create webpack.config.js in your root folder
- Use standard JS code only
- If we add mode development to our config file, we can remove that flag from our build script in our package.json
- Add const path = require('path') to allow us to use __dirname
1const path = require('path')
- Add src/index.js as our entry
1src/index.js
- Add bundle.js as our filename
Rebuild AFTER new Webpack Config
- Now we can delete our main.js file from our dist folder, our old build file
1npm run build
- Now bundle.js will be generated now in the dist folder
- Lastly update index.html to have bundle.js instead of main
- Sometimes you will see the entry as an OBJECT
- You can see multiple entries and this is called code splitting
- In this instance it is best to change the output file name to by dynamic so instead of
you might see1bundle.js
1[name].js
- In this instance it is best to change the output file name to by dynamic so instead of
- You can see multiple entries and this is called code splitting
Webpack Config Example
1const path = require('path') 2 3module.exports = { 4 mode: "development", 5 entry: path.resolve(__dirname, 'src/index.js') 6 output: { 7 path: path.resolve(__dirname, 'dist'), 8 filename: 'bundle.js', 9 }, 10} 11
Adding Sass to be compiled by Webpack
- Sass can be easily added to Webpack by adding loaders.
Installation and Setup of Loaders
- First we want to import Sass and our 3 loader packages, I prefer NPM.
1npm i -D sass style-loader css-loader sass-loader
- In src folder lets create a styles folder
- Add main.scss file and some css to test
- Now we can import to our index.js file by adding import './styles/main.scss'
- We CANNOT run the build yet as we don't have loaders setup
- Inside our webpack config file, after our output we can add a modules object
- Inside we will add a rules array
- Inside that array we will add an object with test: /.scss$/,
- add ``use:['style-loader', 'css-loader', 'sass-loader',]
Updated module Exports
1module.exports = { 2 mode: "development", 3 entry: path.resolve(__dirname, 'src/index.js') 4 output: { 5 path: path.resolve(__dirname, 'dist'), 6 filename: 'bundle.js', 7 }, 8 modules: { 9 rules: [ 10 { 11 test: /\.scss$/, 12 use:['style-loader', 'css-loader', 'sass-loader' 13 } 14 ] 15 } 16} 17
Plugins are great
- Plugins are great in that they allow us to just delete our dist folder and npm run build without having to go in and modify our index.html file manually
HTML Webpack Plug-in Setup
- Install the devDependency first
1npm i -D html-webpack-plugin
- Import to your webpack config file
1const HtmlWebpackPlugin = require('html-webpack-plugin')
- Add underneath the module object next a plugins array
- add newHtmlWebpackPlugin()
- title: 'webpack a filename'
- filename: 'index.html'
- add newHtmlWebpackPlugin()
1plugins: [ 2 new HtmlWebpackPlugin({ 3 title: 'Webpack A Title', 4 filename: 'index.html' 5 }) 6
- Now we can DELETE our dist folder completely
- Whenever we run npm run build we will generate a new dist folder
- This mean we can never modify the DIST files directly moving forward as they will be overridden,
Updated Example with Plug-Ins
1const path = require('path') 2const HtmlWebpackPlugin = require('html-webpack-plugin') 3 4module.exports = { 5 mode: "development", 6 entry: path.resolve(__dirname, 'src/index.js') 7 output: { 8 path: path.resolve(__dirname, 'dist'), 9 filename: '[name].js', 10 }, 11 modules: { 12 rules: [ 13 { 14 test: /\.scss$/, 15 use:['style-loader', 'css-loader', 'sass-loader' 16 } 17 ] 18 } 19 plugins: [ 20 new HtmlWebpackPlugin({ 21 title: 'Webpack A Title', 22 filename: 'index.html' 23 }) 24 ] 25} 26
What are Templates?
- Templates allow us to have a base index.html file that our build file will process each time its ran so you can have code that isn't removed
- Normally we copy our index.html file and paste into our template.html file inside our root
- Add templates underneat our filename inside our 'html-webpack-plugin' plugin in our config
1template: template.html
- Now we can add <%= htmlWebpackPlugin.options.title %>
- Now this file dynamic data is being imported form our config file and generated on build!
Generating Hashes and Caching
- If we want to utilizing caching or add hash IDs to our generated filename so our browsers no when the content is update its quite easy.
- Simply add contenthash to your output filename in the config file
- Delete dist folder again:
1npm run build
- Now we will see our bundle with an appended hash
Hash/Caching Example
1module.exports = { 2mode: "development", 3 entry: { 4 bundle: path.resolve(__dirname, 'src/index.js') 5 }, 6 output: { 7 path: path.resolve(__dirname, 'dist'), 8 filename: '[name][contenthash].js', 9}, 10
Adding Development Script
- Lets add different flags for our development or production builds
- Development allows you to build after each change and is quicker for development
- Inside our scripts object in our package.json, lets add:
1'dev': 'webpack serve'
- Now if we go to terminal:
1npm run dev
- We may get a prompt to install webpack-dev-server, install it
- go to localhost:8080 to see our dev server running
Adding devServer to config and options
- After output add devServer
- port specifies port
- open auto opens browser upon run of script
- hot will auto reload upon save
- compress will use g-zip compression
- historyApiFallback allows history from previous runs for testing
- localhost:3000 is the new address
Updated with devServer
1 module.exports = { 2 mode: "development", 3 entry: { 4 bundle: path.resolve(__dirname, 'src/index.js') 5 }, 6 output: { 7 path: path.resolve(__dirname, 'dist'), 8 filename: '[name][contenthash].js', 9 clean: 'true', 10 }, 11 devServer: { 12 static: { 13 directory: path.resolve(__dirname, 'dist') 14 }, 15 port: 3000, 16 open: true, 17 hot: true, 18 compress: true, 19 historyApiFallback: true, 20 }, 21 modules: { 22 rules: [ 23 { 24 test: /\.scss$/, 25 use:['style-loader', 'css-loader', 'sass-loader' 26 } 27 ] 28 } 29 plugins: [ 30 new HtmlWebpackPlugin({ 31 title: 'Webpack A Title', 32 filename: 'index.html' 33 }) 34 ] 35 } 36
Removing old builds
- With each new build a new bundle file is generated and can easily make your app bloated in filesize
- We can add clean: true to our output in the webpack config file
- Now when we npm run build our bundle file is replaced now instead of creating another each time and keeping the old.
Adding Babbel loader to make your code backwards compatible with older browsers
- Installation:
1npm i -D babel-laoder @babel/core @babel/preset-env
- Verify success in our package.json
- Add to webpack config next
- inside module, inside rules after the first object with our .scss entry
- Add the code below and exclude our node modules folder
Add babel to webpack
1test: /\.js$/, 2exclude: /node_modules/, 3use: { 4 loader: 'babel-loader', 5 options: { 6 presets: ['@babel/preset-env'] 7 } 8} 9
Adding Assets Loader
- First put an asset in our assets folder inside src folder
- Add to webpack config next
- Inside module, inside rule normally after the babel loader
- Add assetModuleFilename: '[name][ext]' inside our output of our webpack config
- now if we add npm run build our asset will be generated inside our dist folder!
Asset Loader Example
1test: /\.(png|svg|jpeg|jpg|gif)$/i, 2type: 'asset/resource' 3
Notable Information
- Any NPM module can be installed and used with Webpack bundling
- Add devtool: source-map to generate source bundle for debugging
- install npm i -D webpack-bundle-analyzer and add to config file to get a complete overview if the WHOLE bundle if your app
- Add to webpack config file
Information Sourced from: Webpack-5-Crash-Course