React is a Javascript library that's typically used to build client-side web applications. It provides a convenient way of organizing your front-end code into reusable components. It also provides some "syntactial sugar" (i.e. JSX) that makes it far easier to comingle HTML and Javascript. Please note that client-side web applications do not provide server side application logic, and rely on a server to handle requests from the web application. This server could be an external system (e.g. headless system), or it could be a server that's been developed specifically to work with your client-side application.
This tutorial focuses on creating a React client-side web application (from scratch). It will not cover creating a backend for your web application.
When building a React client-side web application you'll need the following things:
-
Transpiler: a transpiler can convert source code from one format to another. It's recommended to use "modern" Javascript when writing React applications. The problem is that browsers can't interpret modern Javascript. This is where the transpiler comes in, it transpiles modern Javascript to a form that browsers can understand. Babel is typically used as the transpiler for React applications.
-
Module Bundler: a module bundler takes a bunch of files of different types and bundles them into a smaller group of files. It also helps ensure that modules are loaded in the correct order. Webpack is typically used as the module bundler for React applications.
create-react-app
is an incredible tool, but it abstracts many important details from developers. I've always been of the mindset that one first needs to understand the fundamentals before using heavy abstraction. Hopefully, after going through this tutorial you'll come away with a new understanding of how create-react-app
works behind the scenes!
The first step is to initialize a new project. By using the -y
flag npm will setup some sane defaults.
~/Projects/react-webpack-tutorial> npm init -y
At this point your package.json
will look like:
{
"name": "react-webpack-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Install the neccessary React packages:
~/Projects/react-webpack-tutorial> npm install react react-dom
react
: the core React library.react-dom
: provides binding between React and the DOM.
Install the Webpack module bundler, along with the CLI tools, and development server. The Webpack development server supports "hot" reload.
Note: we are installing Webpack as a development dependency. This is an important distinction, as it is not required as part of a production deployment. To install packages as development dependencies, use the --save-dev
switch. Alternatively you can use the -D
switch.
~/Projects/react-webpack-tutorial> npm install --save-dev webpack webpack-cli webpack-dev-server
Install the Babel transpiler, presets, and loader as development dependencies:
Note: any packages that start with @ are used to indicate a node group/namespace. For example @babel/core will install the core
package from the babel
node group.
~/Projects/react-webpack-tutorial> npm install --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader
A Babel preset is a collection of plugins that support lanuage features.
@babel/preset-env
: allows us to use modern ECMA Script syntax (lambas, imports, etc.), without needing to manage which syntax transforms are needed for a target environent (e.g. browser).@babel/preset-react
: includes plugins to support React language features (e.g. jsx files).
Loaders allow Webpack to handle and process different file types. In this case babel-loader
transpiles and processes Javascript for Webpack.
Specific loaders and libraries will need to be installed in order for Webpack to correctly process your styling code.
When defining your styling you can choose to use plain old CSS, or a CSS extension language which is converted into CSS during the build process. What's nice about using a CSS extension language is that it makes writing your styling code easier and supports more advanced features (e.g. variables, mixins, nesting, etc.). A very common CSS extension language is Sass (Syntactically Awesome Style Sheets) https://sass-lang.com/. Sass can be written in two syntaxes:
- Sassy CSS (
.scss
file extension): This syntax uses brackets to denote different styling rules and is compliant with CSS syntax. - Indented (
.sass
file extension): This syntax uses indentation to denote different styling rules and is more concise. It is not, however, compliant with CSS syntax.
For this example we will be using .scss
files. Regardless of what syntax you choose to use, webpack will compile your .scss
and/or .sass
files into plain old CSS.
If you're just using plain CSS, you'll need to install the following packages as development dependencies:
~/Projects/react-webpack-tutorial> npm install --save-dev css-loader style-loader
css-loader
: handles processing of CSS files for Webpack.style-loader
: handles processing of style definitions in the<head><style>
tag.
If you're using Sass, you'll need the install the following packages as development dependencies:
~/Projects/react-webpack-tutorial> npm install --save-dev sass sass-loader css-loader style-loader
sass
: the core Sass librarysass-loader
: handles processing of .scss/.sass files for Webpack.css-loader
: handles processing of .css files for Webpack.style-loader
: handles processing of style definitions in the<head><style>
tag
The HTML Webpack Plugin simplifies the process of adding bundled files to our HTML files. In our case it will automatically inject our bundled JS and bundled style code. Because this is only used by Webpack, it will also be installed as a development dependency.
~/Projects/react-webpack-tutorial> npm install --save-dev html-webpack-plugin
At this point your package.json
should look something like (version numbers might be different):
Note: in our example we are using Sass, so we've installed the sass
and sass-loader
packages.
{
"name": "react-webpack-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.19.3",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"sass": "^1.55.0",
"sass-loader": "^13.0.2",
"style-loader": "^3.3.1",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1"
}
}
For this tutorial we'll be using fairly standard code organization:
~/Projects/react-webpack-tutorial
│
├── dist -- location for production builds
│ ├── index.html -- Webpack generated HTML file (production)
│ ├── main.css -- Webpack generated CSS file (production when using mini-css-extract-plugin)
│ └── main.js -- Webpack bundled JS file (production)
│
├── node_modules -- (auto gen) location for installed npm packages
│
├── src -- main source folder
│ │
│ ├── components -- location for React components (other than main React component)
│ │ ├── myComponent1
│ │ └── myComponent2
│ │
│ ├── styles -- locations for styling code
│ │ ├── App.scss
│ │ ├── index.scss -- global styles
│ │ ├── myComponent1.scss
│ │ └── myComponent2.scss
│ │
│ ├── App.js -- main React component
│ ├── index.html -- main HTML file to bootstrap JS application
│ └── index.js -- main JS file, serves as entry point for Webpack
│
├── package-lock.json -- records installed npm packages
├── package.json -- defines required npm packages and npm scripts
├── webpack.config.js -- Webpack configuration file
└── .babelrc -- Babel configuration file
Webpack uses webpack.config.js
for configuration. This file is standard JS code that is processed by Node.js. It ultimately returns an object that defines the configuration for Webpack. It's also important to note that because it's processed by Node.js, you might be limited in the JS language features and syntax you are able to use (e.g. require vs. import).
Note: At this point it's still recommended to use the older require syntax as opposed to the newer import syntax.
Below is good example of a "simple" Webpack configuration:
// webpack.config.js is run via node.js therefore you might be limited
// on the JS language features and syntax you use (e.g. require vs. import)
// use built in node path module
const path = require('path');
// use HTML Webpack plugin
const HTMLWebpackPlugin = require('html-webpack-plugin');
// define default exported object (webpack configuration)
module.exports = {
// entry point of the app (used to create a dependency graph)
entry: './src/index.js',
// bundled .js file will be created as ./dist/main.js
output: {
path: path.join(__dirname, '/dist'),
filename: 'main.js'
},
// inject bundled files into HTML file
plugins: [
new HTMLWebpackPlugin({
template: './src/index.html'
})
],
// define how to process different file types
module: {
rules: [
// JS and JSX files
{
test: /.(js|jsx)$/,
// exclude any .js and .jsx files in node_modules
exclude: /node_modules/,
// process using babel-loader
use: {
loader: 'babel-loader'
// note: presets should be configured in .babelrc, but here is
// how you can explicitly provide them to webpack if you prefer:
/*
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react'
]
}
*/
}
},
// SCSS files
{
test: /\.scss$/,
// exclude any .scss files in node_modules
exclude: /node_modules/,
// process using: (note reverse order)
// 1. sass-loader
// 2. css-loader
// 3. style-loader
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'sass-loader' }
]
},
//enable if using CSS and disable SCSS rule
/*
{
test: /\.css$/,
// exclude any .css files in node_modules
exclude: /node_modules/,
// process using: (note reverse order)
// 1. css-loader
// 2. style-loader
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' }
]
}
*/
]
}
}
Although it is possible to put Babel related configuration directly in webpack.config.js
(see comments in the example webpack.config.js
file above) many developers prefer to store Babel specific configuration in a separate file. The file should be placed at the root level and should be named .babelrc
. At this point we will configure Babel to use our two installed babel presets when loading and processing JS files (@babel/preset-env
and @babel/preset-react
).
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
The package.json
doesn't currently contain any scripts. We will add two scripts:
start
: start the Webpack development server with "hot" reloadsbuild
: create a production build in/dist
We'll add these new scripts in the scripts
object. Refer to the package.json
below for reference:
{
"name": "react-webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack serve --mode development --open --hot --port 3000",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@babel/core": "^7.17.8",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"babel-loader": "^8.2.4",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"sass": "^1.49.11",
"sass-loader": "^12.6.0",
"style-loader": "^3.3.1",
"webpack": "^5.71.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4"
}
}
At this point you'll create the following files:
src/index.html
: The main HTML page for your application. The bundled JS and styles will be automatically injected here.src/index.js
: Entry point for the application. It bootstraps React and binds the ReactApp
component to a specific DOM element.src/App.js
: Main React component.
Here is a minimal boilerplate main HTML page. Note that Webpack will automatically inject bundled JS and style code into the HTML file (via the html-webpack-plugin
plugin).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
</head>
<body>
<!-- React will bind to this DOM element -->
<div id="app"></div>
</body>
</html>
Here is a minimal boilerplate main JS file. It bootstraps React and binds the React App
component to a specific DOM element.
Here is an example using React 17 which uses ReactDOM.render()
:
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './App';
// bind the React 'App' compontent to the DOM element with id="app"
const container = document.getElementById('app');
ReactDOM.render(<App />, container);
Here is an example using React 18, which no longer uses ReactDOM.render()
. Instead you'll use createRoot()
and root.render()
:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './App';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App />);
Here is a minimal boilerplate main React compontent for your application. This lambda function returns JSX code.
import React from 'react';
import './styles/App.scss';
export const App = () => {
const dateTime = new Date().toString();
return (
<div>
<h1>React Webpack Tutorial</h1>
<p>Page loaded at: <code>{dateTime}</code></p>
</div>
);
}
Start up your application via the Webpack development server:
~/Projects/react-webpack-tutorial> npm run start
At this point you should see something like:
If you right click on the page and select View Page Source
, you'll see the following:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
<script defer src="main.js"></script></head>
<body>
<!-- React will bind to this DOM element -->
<div id="app"></div>
</body>
</html>
Notice that the <div id="app">
is completely empty! This might seem strange to you until you consider what's actually happening behind the scenes. Our server (in this case it's the Webpack development server) is serving up an initial HTML file which includes a reference to the bundled main.js
file (injected by Webpack). This JS file executes on the client side (within the browser) and manipulates the DOM, adding the content which displays the current date and time. In fact if you use your browser development tools to inspect the page, you'll see the additional content in the DOM:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
<script defer="" src="main.js"></script>
</head>
<body>
<!-- React will bind to this DOM element -->
<div id="app">
<div>
<h1>React Webpack Tutorial</h1>
<p>Page loaded at: Thu Oct 06 2022 17:15:58 GMT-0600 (Mountain Daylight Time)</p>
</div>
</div>
</body>
</html>
Now we'll add some simple styling code to illustrate the way Webpack will bundle and inject styling into your application. You'll create the following files:
src/styles/index.scss
: Global styles for your web application.src/styles/App.scss
: Styles for your main React component.
Note: you should be able to keep the Webpack development server running and it will automatically refresh the browser as you apply your changes.
This file will provide global styling for our web application (it is shamelessly ripped from the index.css
that comes with create-react-app
):
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
Now update our main JS file to reference our global styles:
import React from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './App';
import './styles/index.scss';
const container = document.getElementById('app');
const root = createRoot(container);
root.render(<App />);
This file will provide styling for our main React component:
.App {
display: flex;
flex-flow: column nowrap;
align-items: center;
&-header {
color: indigo;
}
}
Now update our main React component to reference the new style code. We'll also add some className
declarations in our JSX code to reference specific CSS classes.
import React from 'react';
import './styles/App.scss';
export const App = () => {
const dateTime = new Date().toString();
return (
<div className="App">
<h1 className="App-header">React Webpack Tutorial</h1>
<p>Page loaded at: <code>{dateTime}</code></p>
</div>
);
}
At this point your application should look something like:
Inspecting the page using your brower's development tools we see:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
<script defer="" src="main.js"></script>
<style>
.App {
display: flex;
flex-flow: column nowrap;
align-items: center;
}
.App-header {
color: indigo;
}
</style>
<style>
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
}
</style>
</head>
<body>
<!-- React will bind to this DOM element -->
<div id="app">
<div class="App">
<h1 class="App-header">React Webpack Tutorial</h1>
<p>Page loaded at: <code>Thu Oct 06 2022 17:31:33 GMT-0600 (Mountain Daylight Time)</code></p>
</div>
</div>
</body>
</html>
Notice that Webpack automatically injected a <script>
element in <head>
that points to the bundled JS. The bundled JS then executes and injects multiple <style>
elements into the DOM based on the styles that are required for the page.
Note: it's important to remember that when the page is intially loaded, the <style>
elements are not present. These elements are added to the DOM via JavaScript after the initial page load.
We'll be making changes to the webpack configuration in the next section of this tutorial, so for now terminate the webpack development server using CTRL+C
.
Currently JavaScript is injecting the neccessary styles as <style>
elements within the <head>
element of the DOM. Because this technically happens after the browser has already rendered the raw HTML, there is a potential for the page to be loaded and then briefly presented to the user before the styles have been added to the DOM. This can create a "flash" of content that is unstyled to the user.
To eliminate this, you can use the mini-css-extract-plugin
. This will plugin will automatically pregenerate a separate main.css
file that is referenced via a <link>
element with the HTML. The disadvantage of using this plugin is that you might potentially be serving styles to the browser that might not be required for a specific component.
To begin with install the mini-css-extract-plugin
as a dev dependency:
~/Projects/react-webpack-tutorial> npm install --save-dev mini-css-extract-plugin
Now you'll need to update your webpack.config.js
to leverage the new plugin. There are three changes you need to make:
- Require the
mini-css-extract-plugin
. - Instantiate a new instance of the plugin within the
plugins
array. - Replace all instances of the
style-loader
loader with themini-css-extract-plugin
loader.
Below is an updated webpack.config.js
with the changes (marked via *NEW*
in the comments):
// webpack.config.js is run via node.js therefore you might be limited
// on the JS language features and syntax you use (e.g. require vs. import)
// use built in node path module
const path = require('path');
// use HTML Webpack plugin
const HTMLWebpackPlugin = require('html-webpack-plugin');
// *NEW* use Mini CSS Extract plugin
const MiniCSSExtractPlugin = require('mini-css-extract-plugin');
// define default exported object (webpack configuration)
module.exports = {
// entry point of the app (used to create a dependency graph)
entry: './src/index.js',
// bundled .js file will be created as ./dist/main.js
output: {
path: path.join(__dirname, '/dist'),
filename: 'main.js'
},
// inject bundled files into HTML file
plugins: [
new HTMLWebpackPlugin({
template: './src/index.html'
}),
// *NEW* for mini-css-extract-plugin
new MiniCSSExtractPlugin()
],
// define how to process different file types
module: {
rules: [
// JS and JSX files
{
test: /.(js|jsx)$/,
// exclude any .js and .jsx files in node_modules
exclude: /node_modules/,
// process using babel-loader
use: {
loader: 'babel-loader'
}
},
// SCSS files
{
test: /\.scss$/,
// exclude any .scss files in node_modules
exclude: /node_modules/,
// process using: (note reverse order)
// 1. sass-loader
// 2. css-loader
// 3. MiniCSSExtractPlugin
use: [
// *NEW* replace style-loader with mini-css-extract plugin loader
{ loader: MiniCSSExtractPlugin.loader },
{ loader: 'css-loader' },
{ loader: 'sass-loader' }
]
}
]
}
}
Startup your web application using npm run start
. The application should look identical to before, but now if you view the page source, you'll notice that webpack is including a <link>
element that points to a generated main.css
file. This <link>
element is even present in the initial HTML that's served up to the browser, elimating any FOUC that might occur otherwise.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
<script defer src="main.js"></script>
<link href="main.css" rel="stylesheet">
</head>
<body>
<!-- React will bind to this DOM element -->
<div id="app"></div>
</body>
</html>
For now, terminate the webpack development server using CTRL+C
.
Up until now we've been running everything via the Webpack development server. This is the preferred way to develop, but it's worthwhile to understand how you would create a production build for your application. This could be served up by an application server like Nginx if you felt inclined. For the purposes of this tutorial we won't actually setup a separate application server, we'll just show you how webpack creates the optimized bundled files that should be deployed to a production environment.
Previously we setup an npm script called build
:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack serve --mode development --open --hot --port 3000",
"build": "webpack --mode production"
},
The build
script simply runs Webpack in production mode, which by default will:
- Creates the main HTML file which bootstraps the JS web application.
- Bundles and minifies the JS (our
webpack.config.js
defines that our bundled JS file will be created as/dist/main.js
) - Because we're using
mini-css-extract-plugin
, Webpack will bundle and minify the CSS (our bundled CSS is created as/dist/main.css
)
Go ahead and run the following command to create a production build of your web application:
~/Projects/react-webpack-tutorial> npm run build
You should now see the following files created in your /dist
folder:
~/Projects/react-webpack-tutorial
│
└── dist -- location for production builds
├── index.html -- webpack generated HTML file (production)
├── main.css -- webpack generated CSS file (production when using mini-css-extract-plugin)
└── main.js -- webpack bundled JS file (production)
If you open the main.js
and main.css
you'll notice optimized production ready code.
By default Babel will transpile JS written in modern syntax to JS using older syntax that more browsers can understand. The default Babel configuration today is actually quite optimized and has already dropped support for "dead" browsers like Internet Explorer. Even so, it might be useful to learn how to tune the browsers you wish to support using browserlist
configuration (normally defined in package.json
). This configuration defines the browsers you want Babel to target when it transpiles JS code.
If you use create-react-app
you'll notice the following default browserlist configuration in package.json
:
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
This is actually a quite tuned browserlist configuration. For production builds this targets:
- All browsers that have >0.2% market share
- All browsers that are not "dead"
- NOT Opera Mini
To get an idea of browser coverage you can visit: https://browsersl.ist
Here you can put in browserlist queries and see exactly what your coverage will be as well as exactly what browsers are supported.
Here you can see we have almost 92% browser coverage, which is quite tuned overall. Compared to the defaults
browerlist configuration there isn't much difference:
Note: defaults
is a shortcut for: > 0.5%, last 2 versions, Firefox ESR, not dead
This has slightly less coverage, mostly because it removes support for a whole bunch of older Safari on iOS versions.
At this point we're going to demonstrate how using different browserlist configurations can have an effect on your code size and optimization.
Note: because we have a relatively small amount of JS code for our tutorial, the differences in file size won't be as noticable. For larger JS applications, this file size and optimization can be substantial!
To begin with, we will update our package.json
with an explicit browserlist configuration that targets older browsers (e.g. Internet Explorer). The rule for production builds is:
- Greater than 0.2% marketshare
- Last IE version (e.g. IE 11)
Your package.json
file should now look like:
{
"name": "react-webpack-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exsyntaxit 1",
"start": "webpack serve --mode development --open --hot --port 3000",
"build": "webpack --mode production"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.19.3",
"@babel/preset-react": "^7.18.6",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.6.1",
"sass": "^1.55.0",
"sass-loader": "^13.0.2",
"style-loader": "^3.3.1",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.1"
},
"browserslist": {
"production": [
"> 0.2%",
"last 1 ie version"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
This is much more conservative and supports IE 11 which is currently at 0.48% marketshare. Putting this query into https://browsersl.ist we see the following coverage:
Run npm run build
and note the filesize of /dist/main.js
. On my machine it was 140,078 bytes.
Now tweak the browserlist configuration so that the value is defaults and supports es6
. This only targets browers that are included in the default set, that also support ECMAScript 6 (also referred to as ECMAScript 2015) language features. Almost all modern browsers support ES6 and above language features.
Now go ahead and run npm run build
again. Note the filesize of the generated /dist/main.js
file. It should be a little bit smaller (140,039 bytes in my case). The difference here is negiblie, but this is mostly because of the relatively small amount of JS code in our application, and the fact that we're not using advanced ECMAScript language features that would need to be polyfilled / transpiled for older browsers.
In general most developers can target defaults
, but it's good to be aware of how the browserlist configuration works and how it affects the transpiled code.