Why a Webpack config for GrapesJS
GrapesJS ships a JavaScript bundle plus a stylesheet. The only thing Webpack needs to know is how to handle that CSS import; the JavaScript works with no special loader. This guide sets up the loaders, an entry that initialises the editor, and production CSS extraction.
1. Install
npm install grapesjs
npm install -D webpack webpack-cli css-loader style-loader
2. webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js' },
module: {
rules: [
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
],
},
};
3. Initialise the editor
// src/index.js
import grapesjs from 'grapesjs';
import 'grapesjs/dist/css/grapes.min.css';
grapesjs.init({
container: '#gjs',
height: '100vh',
fromElement: true,
storageManager: false,
});
The CSS import is handled by the .css rule above.
4. Extract CSS in production
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// ...entry/output
module: {
rules: [
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] },
],
},
plugins: [new MiniCssExtractPlugin()],
};
This emits a cacheable .css file instead of injecting styles at
runtime — better for first paint.
Production tips
Tune the production build for caching and weight. Use MiniCssExtractPlugin instead of style-loader so the editor CSS ships as a cacheable file, and add content-hash filenames ([contenthash]) so browsers cache aggressively but pick up new builds. GrapesJS is sizeable — if only part of your app uses it, load it through a dynamic import('grapesjs') so Webpack splits it into its own chunk and the rest of the app stays light. Turn source maps off (or to source-map external) in production, and let mode: 'production' handle minification and tree-shaking.
Prerequisites
You'll need Node.js 18+ and Webpack 5. The only thing Webpack must know is how to handle the GrapesJS stylesheet import; the JavaScript works with no special loader. Familiarity with entry/output, rules, and plugins is enough.
Add custom blocks to the editor
Register draggable blocks with the Block Manager after grapesjs.init:
editor.BlockManager.add('hero', {
label: 'Hero section',
category: 'Sections',
content: '<section class="hero"><h1>Headline</h1><p>Copy</p></section>',
});
Pull ready-made block libraries and presets from GJS.Market for a richer set.
Code-split GrapesJS into its own chunk
GrapesJS is sizeable. If only part of your app uses it, load it through a dynamic import so Webpack splits it out and the rest of the app stays light:
async function openEditor(container) {
const { default: grapesjs } = await import('grapesjs');
await import('grapesjs/dist/css/grapes.min.css');
return grapesjs.init({ container, height: '100vh' });
}
Performance tips
Use MiniCssExtractPlugin in production to emit a cacheable CSS file
instead of injecting styles at runtime, and add [contenthash] filenames
so browsers cache aggressively but pick up new builds. Turn source maps off (or to an
external map) in production, and let mode: 'production' handle
minification and tree-shaking.
Troubleshooting common errors
“You may need an appropriate loader” on the CSS import means
css-loader/style-loader (or MiniCssExtractPlugin) isn't
configured for .css. An unstyled canvas means the
stylesheet import didn't resolve. A huge bundle means GrapesJS isn't
code-split — load it with a dynamic import.
Webpack vs Vite for GrapesJS
Both bundle GrapesJS cleanly. Webpack is the right home when your project already standardises on it and you want explicit control over loaders and chunks; Vite is lower-config and faster in dev. The GrapesJS-specific setup is equally small on either.
Next steps
Prefer a zero-config bundler? See the GrapesJS + Vite setup. Also see GrapesJS + React, browse the GrapesJS marketplace, or start from the GJS.Market home page.
FAQ
Which loaders does GrapesJS need?
style-loader and css-loader (or
MiniCssExtractPlugin in production) so the editor CSS import
resolves. The JS needs no special loader.
How do I import the stylesheet?
Import 'grapesjs/dist/css/grapes.min.css' in your entry; the CSS rule
routes it through the loaders.
Should I extract CSS in production?
Yes — use MiniCssExtractPlugin to emit a cacheable
.css file instead of injecting styles.