Skip to main contentSkip to docs navigation

Bundle Chassis CSS and JavaScript with Webpack — loaders, the import order, and CSS extraction for production.

Webpack is a JavaScript module bundler that compiles modules and their dependencies into static assets. This guide walks through a fresh project; if you already have Webpack set up, jump to Import Chassis.

Installation covers the moving parts — the only Webpack-specific work here is configuring loaders to process Sass.

Setup

This guide assumes Node.js is installed and you're comfortable in a terminal.

  1. Create a project folder and initialize npm.

    Shell
    mkdir my-project && cd my-project
    pnpm init
  2. Install Webpack and its plugins. webpack is the bundler core, webpack-cli enables the webpack command in the terminal, webpack-dev-server runs a local development server, and html-webpack-plugin keeps index.html in src/ instead of dist/. The --save-dev flag (or -D in pnpm) marks these as build-time dependencies.

    Shell
    pnpm add -D webpack webpack-cli webpack-dev-server html-webpack-plugin
  3. Install Chassis CSS and its tokens. Add the optional peer dependencies for the components that need them, or omit both and use chassis.bundle.* which includes them.

    Shell
    pnpm add @chassis-ui/css @chassis-ui/tokens
    pnpm add @floating-ui/dom vanilla-calendar-pro   # optional
  4. Install Sass tooling. Webpack needs loaders to handle Sass and to add vendor prefixes via PostCSS.

    Shell
    pnpm add -D autoprefixer css-loader postcss-loader sass sass-loader style-loader

Project structure

Create the source folders and starter files:

Shell
mkdir -p src/js src/scss
touch src/index.html src/js/main.js src/scss/styles.scss webpack.config.js

The result:

TEXT
my-project/
├── src/
│   ├── js/
│   │   └── main.js
│   ├── scss/
│   │   └── styles.scss
│   └── index.html
├── package.json
├── pnpm-lock.yaml
└── webpack.config.js

Configure Webpack

Open webpack.config.js and add the bare-bones config below. It tells Webpack where to find the entry point, where to emit the bundle, and how the dev server should serve it.

JavaScript
'use strict'

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'development',
  entry: './src/js/main.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist')
  },
  devServer: {
    static: path.resolve(__dirname, 'dist'),
    port: 8080,
    hot: true
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' })
  ]
}

Fill in src/index.html so Webpack has something to render:

HTML
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Chassis CSS w/ Webpack</title>
  </head>
  <body>
    <div class="container py-large px-medium mx-auto">
      <h1>Hello, Chassis CSS and Webpack!</h1>
      <button class="button primary">Primary button</button>
    </div>
  </body>
</html>

Add start and build scripts to package.json:

JSON
{
  "scripts": {
    "start": "webpack serve",
    "build": "webpack build --mode=production"
  }
}

You can now run pnpm start to launch the dev server, but the page won't be styled yet — Webpack isn't configured to handle Sass.

Import Chassis

Webpack needs the Sass loaders from the previous step and a Sass entry point. The sass-loader requires a loadPaths entry pointing to the project's Sass directory so token overrides can be resolved.

  1. Add the loader rules to webpack.config.js. Replace the existing module.exports with the version below — the new piece is the module.rules block.

    JavaScript
    'use strict'
    
    const path = require('path')
    const autoprefixer = require('autoprefixer')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
      mode: 'development',
      entry: './src/js/main.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      },
      devServer: {
        static: path.resolve(__dirname, 'dist'),
        port: 8080,
        hot: true
      },
      plugins: [
        new HtmlWebpackPlugin({ template: './src/index.html' })
      ],
      module: {
        rules: [
          {
            test: /\.scss$/,
            use: [
              'style-loader',     // Injects CSS into a <style> tag
              'css-loader',       // Resolves @import and url()
              {
                loader: 'postcss-loader',
                options: { postcssOptions: { plugins: [autoprefixer] } }
              },
              {
                loader: 'sass-loader',
                options: {
                  sassOptions: {
                    loadPaths: [
                      path.resolve(__dirname, 'src/scss')  // project token override
                    ]
                  }
                }
              }
            ]
          }
        ]
      }
    }
  2. Fill in src/scss/styles.scss. The token source resolves through _vendor.scss before the rest of Chassis processes its variables, so a single @use directive is all that's needed.

    SCSS
    // 1. Chassis CSS — token source resolves via the loadPaths entry in webpack.config.js
    @use "@chassis-ui/css/scss/chassis";
    
    // 2. Optional: settings overrides use the `with (...)` syntax
    // @use "@chassis-ui/css/scss/chassis" with (
    //   $enable-fluid-font-sizes: false,
    //   $enable-component-shadows: true,
    // );

    The default token build (chassis/docs) is resolved via the loadPaths entry above. To switch to a custom token set, place a _chassis-tokens.scss on an earlier loadPaths entry — see Customize → Sass for details.

  3. Import the JavaScript and load the stylesheet from src/js/main.js.

    JavaScript
    import '../scss/styles.scss'
    import * as chassis from '@chassis-ui/css'

    For smaller bundles, import only the required plugins:

    JavaScript
    import { Modal, Tooltip } from '@chassis-ui/css'
  4. Run the dev server.

    Shell
    pnpm start

    The page should now render with Chassis styling — the heading uses the Chassis type scale, the button is filled with the primary palette, and the container is constrained.

Build optimizations

The style-loader setup above injects CSS via a <style> tag in the head. That's fine in development but suboptimal for production: it ships unstyled HTML to the browser before the JS evaluates. For production builds, extract the CSS to a separate file.

Extract CSS

The mini-css-extract-plugin replaces style-loader to write the compiled CSS to a separate file, enabling the browser to download the stylesheet in parallel with the JavaScript bundle. Install it:

Shell
pnpm add -D mini-css-extract-plugin

Wire it into the config in place of style-loader:

DIFF
 const path = require('path')
 const autoprefixer = require('autoprefixer')
 const HtmlWebpackPlugin = require('html-webpack-plugin')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')

 module.exports = {

   plugins: [
-    new HtmlWebpackPlugin({ template: './src/index.html' })
+    new HtmlWebpackPlugin({ template: './src/index.html' }),
+    new MiniCssExtractPlugin()
   ],
   module: {
     rules: [
       {
         test: /\.scss$/,
         use: [
-          'style-loader',
+          MiniCssExtractPlugin.loader,
           'css-loader',

         ]
       }
     ]
   }
 }

After pnpm build, the bundle contains a separate dist/main.css ready to link from any HTML page.

Next steps

These docs cover JavaScript integration, Sass customization, and bundle optimization for a Webpack-based Chassis project.