Basic configuration of Webpack, Rollup, and Parcel
How the three bundlers are different
There is always an emerging technology. The new tools come with it.
I am going to list the basic configuration of modern JavaScript bundlers of:
to bundle each of the following JavaScript codes:
- ES Modules
- TypeScript
- React
- React+TypeScript
Each type of source file has extension of .js, .ts, .jsx or .tsx.
Along with the config files, I will show you the yarn commands to install the necessary packages.
The source code can be found at GitHub repo. Please follow the instruction written in the README.md to perform bundling on your machine.
Presumption
The configurations shown below are just to perform simple bundling. They do not adapt to:
- Watching changes
- Hot module replacement
- Code splitting
Common config files
Whatever bundler you use, the configurations of TypeScript and Babel are shared. Please keep in mind that the configurations of the following two files are bare minimum, not to meet the need of various development.
Tyescript
tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true,
"moduleResolution": "node"
},
}
Babel
babel.config.js
{
"presets": ["@babel/preset-react"]
}
Babel has an amazing page on how to install and setup itself based on the build system. See Using Babel.
Webpack
Please add build command to package.json:
package.json
{
…
"scripts": {
"build": "webpack"
},
…
}
The default Webpack config file is webpack.config.js.
ES Module
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
};
yarn add -D webpack webpack-cli
TypeScript
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.ts',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
};
yarn add -D ts-loader typescript webpack webpack-cli
React
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.jsx',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ['@babel/preset-react']
}
}
}
]
},
};
yarn add react react-dom
yarn add -D @babel/core @babel/preset-react babel-loader webpack webpack-cli
React+TypeScript
const path = require('path');
module.exports = {
mode: 'production',
entry: './src/index.tsx',
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
};
yarn add react react-dom
yarn add -D @babel/core @babel/preset-react @types/react @types/react-dom ts-loader typescript webpack webpack-cli
Rollup
Please add build command to package.json:
package.json
{
…
"scripts": {
"build": "rollup --bundleConfigAsCjs"
},
…
}
The --bundleConfigAsCjs option allows you to use import/export in rollup.config.js without setting "type": "module" in package.json.
The default Rollup config file is rollup.config.js.
ES Module
export default {
input: 'src/index.js',
output: {
file: 'dist/index.js',
format: 'iife'
},
};
yarn add -D rollup
TypeScript
import typescript from '@rollup/plugin-typescript';
export default {
input: 'src/index.ts',
output: {
file: 'dist/index.js',
format: 'iife'
},
plugins: [typescript()]
};
yarn add -D @rollup/plugin-typescript rollup tslib typescript
React
import replace from '@rollup/plugin-replace';
import babel from '@rollup/plugin-babel';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'src/index.jsx',
output: {
file: 'dist/index.js',
format: 'iife',
},
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
preventAssignment: true,
}),
babel({babelHelpers: 'bundled'}),
resolve(),
commonjs(),
],
};
yarn add react react-dom
yarn add -D @babel/core @babel/preset-react @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-replace rollup
React+TypeScript
import replace from '@rollup/plugin-replace';
import typescript from '@rollup/plugin-typescript';
import babel from '@rollup/plugin-babel';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
export default {
input: 'src/index.tsx',
output: {
file: 'dist/index.js',
format: 'iife',
},
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
preventAssignment: true,
}),
typescript(),
babel({babelHelpers: 'bundled'}),
resolve(),
commonjs(),
],
};
yarn add react react-dom
yarn add -D @babel/core @babel/preset-react @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-replace @rollup/plugin-typescript @types/react @types/react-dom rollup tslib typescript
Parcel
Please add build command to package.json:
package.json
{
…
"scripts": {
"build": "parcel build"
},
…
}
Parcel doesn’t have dedicated config file. You add config properties to package.json.
ES Modules
{
…
"source": "src/index.js",
"main": "dist/index.js",
…
}
yarn add -D parcel
TypeScript
{
…
"source": "src/index.ts",
"main": "dist/index.js",
…
}
yarn add -D parcel typescript
React
{
…
"source": "src/index.jsx",
"main": "dist/index.js",
…
}
yarn add react react-dom
yarn add -D parcel
React+TypeScript
{
…
"source": "src/index.tsx",
"main": "dist/index.js",
…
}
yarn add react react-dom
yarn add -D @types/react @types/react-dom parcel typescript
What’s best
Here is my opinion.
Webpack still has the advantage of its longevity, despite its hustling configuration. Very extendable, rich documents, plenty of resources are available on the Internet.
Rollup is the alternative to Webpack. When you run yarn add -D rollup, the file size of node_modules was 2.7MB, while that of Webpack is 19.2MB. The project was suspended but when I developed CI build system for serverless app on Amazon Web Service, I chose to use Rollup. The simple compilation was enough. Webpack was a overkill.
Rollup is great for package development, not so for application development.
Parcel is not an option. Its non-configuration philosophy makes the project rigid, leaving programmers skeptical to use them in the nature and dynamism of software development.