Explain Codes LogoExplain Codes Logo

How to copy static files to build directory with Webpack?

javascript
webpack
file-loader
url-loader
Alex KataevbyAlex Kataev·Oct 16, 2024
TLDR

To move static assets to your build folder, you should utilize the CopyWebpackPlugin. You can easily add it to your webpack.config.js:

const CopyWebpackPlugin = require('copy-webpack-plugin'); // Just like a car, don't forget to "require" your plugins before you "drive" them! module.exports = { // ... plugins: [ new CopyWebpackPlugin({ patterns: [{ from: 'public', to: 'build' }] }) ] };

After this, every file from the public folder is magically transported to the build directory every time you fire up the webpack.

Diving into loaders: Using file-loader and url-loader

Wholly reliant on plugins all the time? Hold your webpack horses, it's time to dive into file-loader or url-loader, when your scenario needs you to require assets within your JavaScript modules.

module: { rules: [ { test: /\.(png|jpe?g|gif)$/i, // collection of file extensions used by designers when they're feeling artsy loader: 'file-loader', options: { name: '[path][name].[ext]', }, }, ], }

Both file-loader and url-loader are at your service to resolve your import/require() on a file into a url and emit the file to the output directory. Remember 'Avatar: The Last Airbender'? These loaders are your Webpack Benders!

Webpack 5's Toolbelt: Asset modules

With the debut of Webpack 5, the need to utilize file-loader is alleviated thanks to Asset Modules. You now get to employ asset files in the raw, no strings attached.

module.exports = { // ... output: { assetModuleFilename: 'images/[hash][ext][query]' }, module: { rules: [ { test: /\.(png|svg|jpg|jpeg|gif)$/i, // photographic memory? This is your test type: 'asset/resource', }, ], }, };

Asset Modules got your back with five asset types in its arsenal: asset/resource, asset/inline, asset/source, asset, and a rule so smart, asset/size-limit, it can choose between asset/resource and asset/inline based on file dimensions.

Configurations and tips for pro-users

By using CopyWebpackPlugin, you can preserve your original directory structure. This is like keeping your cereal crunchy in milk:

new CopyWebpackPlugin({ patterns: [ { from: 'source', to: 'build/[path][name].[ext]' }, // Yes, you can keep things in folders, it's not 1985 anymore ], }),

Taking control over cache busting

Engage in effective cache management by using Webpack’s [hash] or [contenthash] in your filenames. This is basically the plastic cover for your comic book:

output: { filename: 'scripts/[name].[contenthash].js', assetModuleFilename: 'assets/[hash][ext][query]' }

Bulk copying using require.context

For those shiny moments when you have several files to bulk require, require.context() will be your virtual photocopier. This is how you'd invoke it:

const images = require.context('./images', false, /\.png$/); // Michelin Star for file management images.keys().forEach(images); // It's like Google Photos. But for Webpack. And no competition from Apple.

This might get seen as overkill, but hey—desperate times call for desperate require.context().

Error handling and debugging

In case your files aren't copying according to your wishes, make sure to verify plugin version compatibility with your webpack. Always follow the console messages—these breadcrumbs will guide you to your issue.

Often, syntax like require or ES6 import can cause mismatch errors. Remember: debugging is like being a detective. Enjoy the thrill.