#
Configure for build
To configure webpack for a production environment, execute the following steps.
#
Install the packages
Open a terminal at the root of the project and install the following packages:
pnpm add -D @workleap/webpack-configs webpack webpack-cli @swc/core @swc/helpers browserslist postcss
yarn add -D @workleap/webpack-configs webpack webpack-cli @swc/core @swc/helpers browserslist postcss
npm install -D @workleap/webpack-configs webpack webpack-cli @swc/core @swc/helpers browserslist postcss
#
Configure webpack
#
HTML template
First, create a public
folder with an index.html
file at the root of the project:
web-project
├── public
├──── index.html
├── src
├──── ...
├── package.json
├── webpack.build.js
Then, open the newly created index.html
file and copy/paste the following content:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="root"></div>
</body>
</html>
The content of the public/index.html
file is the default template that will be used by HtmlWebpackPlugin.
#
Reference local assets
To reference local assets such as a favicon.png
in the default HTML template, it is recommended to preprend the relative path of every asset with the publicPath
of the webpack config.
First, add the asset to the public
folder at the root of the project:
web-project
├── public
├──── index.html
├──── favicon.png
├── src
├──── ...
├── package.json
Then, add the assets to the index.html
file:
<!DOCTYPE html>
<html>
<head>
<link href="<%=webpackConfig.output.publicPath%>favicon.png" rel="icon">
</head>
<body>
<div id="root"></div>
</body>
</html>
If output.publicPath
is set to auto
, use href="favicon.png"
instead.
#
defineBuildConfig
Next, create a configuration file named webpack.build.js
at the root of the project:
web-project
├── src
├──── ...
├── package.json
├── webpack.build.js
Then, open the newly created file and export
the webpack configuration by using the defineBuildConfig(swcConfig, options)
function:
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig);
#
swcConfig
In the previous code sample, the defineBuildConfig(swcConfig, options)
function receive an SWC configuration object through the swcConfig
parameter.
Although the swc-loader defaults to loading the closest .swcrc
configuration file when no configuration object is provided, it lacks support for distinct configuration files by environment like webpack does.
Therefore, @workleap/webpack-configs
choosed to delegate the loading of the SWC configuration to the consumer by making the swcConfig
option required.
#
Use predefined options
The defineBuildConfig(swcConfig, options)
function can be used as shown in the previous example, however, if you wish to customize the default configuration, the function also accept a few predefined options to help with that 👇
#
entry
- Type:
string
- Default:
./src/index.tsx
Set webpack entry option.
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig, {
entry: "./src/another-entry.tsx"
});
#
outputPath
- Type:
string
- Default:
dist
Set webpack output path.
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
import path from "path";
export default defineBuildConfig(swcConfig, {
outputPath: path.resolve("./a-custom-folder")
});
#
publicPath
- Type:
string
- Default:
http://localhost:8080/
Set webpack public path.
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig, {
// The ending "/" is very important.
publicPath: "https://my-app.netlify.app/"
});
Or for an automatic public path:
// @ts-check
import { defineBuildConfig, defineBuildHtmlWebpackPluginConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig, {
publicPath: "auto",
// If you are using the html webpack plugin, make sure to also set the plugin
// public path option to "/".
htmlWebpackPlugin: defineBuildHtmlWebpackPluginConfig({
publicPath: "/"
})
});
#
moduleRules
- Type: An array of webpack moduleRule objects
- Default:
[]
Append the provided webpack module rules to the configuration.
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig, {
moduleRules: [
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader"]
}
]
});
#
plugins
- Type: An array of webpack plugin instances
- Default:
[]
Append the provided webpack plugins to the configuration.
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
import CircularDependencyPlugin from "circular-dependency-plugin";
export default defineBuildConfig(swcConfig, {
plugins: [
new CircularDependencyPlugin({
exclude: /node_modules/,
include: /src/
});
]
});
#
htmlWebpackPlugin
- Type:
boolean
or an object literal accepting anyhtml-webpack-plugin
option - Default:
{ template: "./public/index.html" }
To remove the default instance of html-webpack-plugin, set the property to false
.
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.dev.js";
export default defineBuildConfig(swcConfig, {
htmlWebpackPlugin: false
});
To extend/replace the default html-webpack-plugin
configuration, use the defineBuildHtmlWebpackPluginConfig(options)
function.
// @ts-check
import { defineBuildConfig, defineBuildHtmlWebpackPluginConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
import path from "path";
export default defineBuildConfig(swcConfig, {
htmlWebpackPlugin: defineBuildHtmlWebpackPluginConfig({
template: path.resolve("./my-custom-index.html"),
minify: true
})
});
#
miniCssExtractPluginOptions
- Type: An object literal accepting any
mini-css-extract-plugin
option - Default:
{ filename: "[name].[fullhash].css" }
Forward the provided object literal to the mini-css-extract-plugin.
// @ts-check
import { defineBuildConfig, defineMiniCssExtractPluginConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
import path from "path";
export default defineBuildConfig(swcConfig, {
htmlWebpackPluginOptions: defineMiniCssExtractPluginConfig({
ignoreOrder: true
})
});
#
optimize
- Type:
boolean
|"readable"
- Default:
true
Whether or not to enable webpack production optimizations like code minification and tree shaking. This option can be quite useful when debugging an issue with webpack bundling.
When false
is provided, most of the optimizations, including minification and tree shaking will be turned off:
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig, {
optimize: false
});
When readable
is provided, most of the optimizations will still be applied but the resulting code bundles will be easier to read:
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig, {
optimize: "readable"
});
#
cssModules
- Type:
boolean
- Default:
false
Enable css-loader
modules feature.
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig, {
cssModules: true
});
#
svgr
- Type:
boolean
or an object literal accepting any@svgr/webpack
option - Default:
true
Whether or not to handle .svg
files with @svgr/webpack
. If @svgr/webpack
is desactived, the .svg
files will are handled by the asset/resource
rule.
// @ts-check
import { defineDevConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.dev.js";
export default defineDevConfig(swcConfig, {
svgr: false
});
To extends the @svgr/webpack
rule configuration, provide an object literal instead.
// @ts-check
import { defineDevConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.dev.js";
export default defineDevConfig(swcConfig, {
svgr: {
ref: true
}
});
#
verbose
- Type:
boolean
- Default:
false
Start the webpack process with verbose logging turned on.
// @ts-check
import { defineDevConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.dev.js";
export default defineDevConfig(swcConfig, {
verbose: true
});
#
Configuration transformers
We do not guarantee that your configuration transformers won't break after an update. It's your responsibility to keep them up to date with new releases.
The @workleap/webpack-configs
, but only covers a subset of a webpack configuration. If you need full control over the configuration, you can provide configuration transformer functions through the transformers
option of the defineBuildConfig
function. Remember, no locked in ❤️✌️.
To view the default build configuration of @workleap/webpack-configs
, have a look at the build.ts configuration file on GitHub.
#
transformers
- Type:
((config: WebpackConfig, context: WebpackConfigTransformerContext) => WebpackConfig)[]
- Default:
[]
transformer(config: WebpackConfig, context: WebpackConfigTransformerContext) => WebpackConfig
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
/**
* @type {import("@workleap/webpack-configs").WebpackConfigTransformer}
*/
function useContentHashOutputFilename(config) {
config.output.filename = "[name].[contenthash].bundle.js";
return config;
};
export default defineBuildConfig(swcConfig, {
transformers: [useContentHashOutputFilename]
});
#
Execution context
Generic transformers can use the context
parameter to gather additional information about their execution context, like the environment
they are operating in:
// @ts-check
/**
* @type {import("@workleap/webpack-configs").WebpackConfigTransformer}
*/
export function transformer(config, context) {
if (context.environment === "build") {
config.output.filename = "[name].[contenthash].bundle.js";
}
return config;
};
environment
:"dev" | "build"
verbose
:boolean
#
Utilities
Modifying a webpack configuration object can be an arduous task, to help with that, @workleap/webpack-configs
offer utility functions for modules rules and plugins.
#
Add a CLI script
To create the bundle files for production, add the following script to your project package.json
file:
{
"build": "webpack --config webpack.build.js"
}
#
Use environment variables
To deal with environment variables, the webpack documentation suggests using the --env option from its CLI. While that would work, by using webpack --env
CLI option, the environment variables would only be made available to the webpack configuration files (.e.g. webpack.build.js
) rather than any Node.js files. Therefore we do not recommend using webpack --env
CLI option.
#
cross-env
We recommend instead to define environment variables using cross-env. With cross-env
, the environment variables will be made available to any Node.js files that are executed by the script process (dev
in the example below 👇):
{
"build": "cross-env DEBUG=true webpack --config webpack.build.js"
}
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
if (process.env.DEBUG) {
console.log("Configuring webpack in debug mode!");
}
export default defineBuildConfig(swcConfig);
However, there's a catch. When using cross-env
, the variables will not be available in the application files because cross-env
only makes them available to files that are executed by the process at build time while the application files are executed at runtime by a browser.
To make them accessible to the application files, webpack must be aware of those environment variables and render them into the compiled application files. This is the purpose of the environmentVariables
option.
#
environmentVariables
- Type:
Record<string, unknown>
- Default:
{}
First, define the variables with environmentVariables
:
// @ts-check
import { defineBuildConfig } from "@workleap/webpack-configs";
import { swcConfig } from "./swc.build.js";
export default defineBuildConfig(swcConfig, {
environmentVariables: {
"DEBUG": process.env.DEBUG === "true"
}
});
Then, use the variables in any application files:
export function App() {
if (process.env.DEBUG) {
console.log("The application has been bootstrapped in debug!");
}
return null;
}
The === "true"
part of "DEBUG": process.env.DEBUG === "true"
is very important, otherwise the environment variable value would be "true"
instead of true
.
#
Try it 🚀
To test your new webpack configuration, open a terminal at the root of the project and execute the /dist
folder (or any other outputPath
you configured).