Webpack Example: Difference between revisions
Line 112: | Line 112: | ||
=Environment Variables= | =Environment Variables= | ||
We can define environment variables with the define built-in plugin. | We can define environment variables with the define built-in plugin. | ||
<syntaxhighlight lang=js"> | <syntaxhighlight lang="js"> | ||
new webpack.DefinePlugin({ | new webpack.DefinePlugin({ | ||
'process.env.NODE_ENV': JSON.stringify(env), | 'process.env.NODE_ENV': JSON.stringify(env), | ||
Line 118: | Line 118: | ||
}), | }), | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=React Specific= | =React Specific= | ||
Had a bit of trouble with this. So thought I would note it down. For React there is a public directory generated. We need to copy the contents of this to the root directory. Make sure you delete the manifest.json from public if you are using it. Also I found you needed to also delete the %PUBLIC_URL% from the index.html | Had a bit of trouble with this. So thought I would note it down. For React there is a public directory generated. We need to copy the contents of this to the root directory. Make sure you delete the manifest.json from public if you are using it. Also I found you needed to also delete the %PUBLIC_URL% from the index.html |
Latest revision as of 23:47, 12 December 2024
Introduction
This page is about webpack which I guess is quite old. I wanted to capture what I learned when I used it.
Structure of the Code
For me I divided this up in the following way
webpack.config.js
This essentially handles the merge of the other files. I added to parameters for, which environment and whether to show the BundleAnalyzer report.
import { merge } from 'webpack-merge'
import { commonConfig } from './webpack.config.common.js'
import { devConfig } from './webpack.config.dev.js'
import { prodConfig } from './webpack.config.prod.js'
export default ({ env, withReport }) => {
console.log(`Building for ${env} environment...`)
switch (env) {
case 'development':
return merge(commonConfig(env, withReport), devConfig(process.env.SSL_KEY_FILE, process.env.SSL_CRT_FILE))
case 'production':
return merge(commonConfig(env, withReport), prodConfig)
default:
throw new Error('No matching configuration was found!')
}
}
Running the build
So to do the build we launch this from npm. all pretty obvious
"start": "webpack serve --config configs/webpack/webpack.config.js --env env=development",
"dev": "webpack --config configs/webpack/webpack.config.js --env env=development",
"build": "webpack --config configs/webpack/webpack.config.js --env env=production",
"report": "webpack --config configs/webpack/webpack.config.js --env env=production --env=withReport",
The report option runs the BundleAnalyzerPlugin which shows the breakdown of the bundle. This tells you what each bundle comprises of. More on that below
When the build is run, webpack will output the necessary you need to load in the html.
This was a mistake I made when using webpack. These bundles must but in the index.html for it to work.
<!doctype html>
<html lang="en">
<head>
...
<script defer async src="runtime.js"></script>
<script defer async src="vendor_react.js"></script>
<script defer async src="common_app.js"></script>
<script defer async src="app.js"></script>
</head>
..
Code Splitting
For production we split the code to allow faster loading of the app. Using the output from the bundle analyzer we can see where we might want to make the splits. For this case we use exceljs which is rater big. For the webpack configure we use splitChunks
optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single',
splitChunks: {
minSize: 17000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
automaticNameDelimiter: '_',
enforceSizeThreshold: 30000,
cacheGroups: {
common: {
test: /[\\/]node_modules[\\/]/,
priority: -5,
reuseExistingChunk: true,
chunks: 'initial',
name: 'common_app',
minSize: 0,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
// we are opting out of defaultVendors, so rest of the node modules will be part of default cacheGroup
defaultVendors: false,
reactPackage: {
test: /[\\/]node_modules[\\/](react|react-dom|react-router|react-router-dom)[\\/]/,
name: 'vendor_react',
chunks: 'all',
priority: 10,
},
exceljsPackage: {
test: /[\\/]node_modules[\\/](exceljs)[\\/]/,
name: 'vendor_exceljs',
chunks: 'all',
priority: 9,
},
},
},
In react, we use Lazy loading, we can name to the bundles with secret code.
const HomePage = lazy(() =>
import(
/*
webpackChunkName: "home-page",
webpackPrefetch: true
*/
'./pages/homePage/index'
).then(module => ({
default: module.HomePage,
}))
)
Environment Variables
We can define environment variables with the define built-in plugin.
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(env),
'process.env.REACT_APP_TEST_ENV_VAR': JSON.stringify(process.env.REACT_APP_TEST_ENV_VAR),
}),
React Specific
Had a bit of trouble with this. So thought I would note it down. For React there is a public directory generated. We need to copy the contents of this to the root directory. Make sure you delete the manifest.json from public if you are using it. Also I found you needed to also delete the %PUBLIC_URL% from the index.html
new CopyWebpackPlugin({
patterns: [{ from: 'public', to: outputPath }],
}),