Compiled

Stylesheet Extraction

Stylesheet extraction is highly recommended for all component libraries and applications, so that generated class names can be combined and de-duplicated into one external stylesheet. This allows you to enjoy the decreased stylesheet size that comes with atomic styling.

There are two types of stylesheet extraction:

Which type should I use?

If your package is a component library, use our platform stylesheet extraction. This includes Atlassian Design System packages like @atlaskit/button or any other package that is treated as a platform offering or used across products or repositories.

If your package exists in the same codebase as, and is directly consumed by, a Webpack or Parcel app, use Parcel stylesheet extraction or Webpack stylesheet extraction depending on what bundler your app uses.

Note that Parcel and Webpack are the only bundlers we support.

Platform stylesheet extraction

Platform stylesheet extraction only works if you use Babel to build your component library. Note that we do not recommend nor support using bundlers (e.g. Webpack or Parcel) to build your component library, because bundlers are appropriate for web apps (e.g. Jira) and not for component libraries.

Warning
Ensure that any apps that import your component library also have the Compiled Webpack or Parcel plugins installed (@compiled/webpack-loader or @compiled/parcel-config), otherwise the order in which the styles are applied will become unpredictable. This can be an issue if you have styles that overlap, e.g. if you mix padding and paddingTop in the same component, or have @media queries that potentially overlap.

If the apps that import your component library use other bundlers like Vite or Next.js, or if your apps cannot install the Compiled Webpack or Parcel plugins, stylesheet extraction will still work! However, you must make sure that within each component, you should never mix any CSS properties or styles that overlap.

Add @compiled/babel-plugin-strip-runtime to your Babel configuration, with extractStylesToDirectory set as an option. Set source to the folder your component library's source code is defined in, and dest to the folder your component library's build output is generated to.

For example:

// babel.config.js
module.exports = {
  plugins: [
    // This will handle all `token()` calls outside of
    // Compiled usages
    '@atlaskit/tokens/babel-plugin',

    // ↓↓ Compiled should run last ↓↓
    [
      '@compiled/babel-plugin',
      {
        transformerBabelPlugins: ['@atlaskit/tokens/babel-plugin'],
      },
    ],
    [
      '@compiled/babel-plugin-strip-runtime',
      {
        extractStylesToDirectory: {
          source: 'src',
          dest: 'dist',
        },
      },
    ],
  ],
};

Your dest may vary depending on how you generate your dist/ folder in your component library. For example, if you have mutliple cjs and esm distributions, those will each need a separate dest through Babel's environment-specific configuration.

In each component library's package.json file, you will also need to add "sideEffects": ["**/*.compiled.css"], to ensure that the Compiled stylesheets that are generated are exempt from Webpack's and Parcel's tree-shaking (which would delete the stylesheets!):

{
  "name": "@example/my-component-library",
  // …
  "dependencies": {
    // Replace "version" with the latest version
    "@compiled/react": "^version"
  },
  // …
  "sideEffects": ["**/*.compiled.css"]
  // …
}

To test whether you've set up stylesheet extraction correctly, use your component library's usual build command (e.g. yarn build). Inside the dist folder, you should see some .compiled.css stylesheets generated, one for each .tsx file that uses @compiled/react.

For example, if you have a file with the path packages/design-system/button/dist/cjs/button.js that uses Compiled, you can expect there to be a corresponding packages/design-system/button/dist/cjs/button.compiled.css.

Parcel stylesheet extraction

If you are using a web app that uses Parcel, first install the Parcel loader.

Then configure the extract plugin to true in your Compiled configuration. For example:

// .compiledcssrc
{
  "extract": true, // <-- add this
  "transformerBabelPlugins": [["@atlaskit/tokens/babel-plugin"]]
}

Note that stylesheet extraction feature is disabled on local development due to a known issue.

See the @compiled/parcel-config documentation for information about other configuration options.

Webpack stylesheet extraction

If your web app uses Webpack, first install the webpack loader.

Then configure the extract option to true in the webpack loader and turn on the extract plugin.

// webpack.config.js
+const { CompiledExtractPlugin } = require('@compiled/webpack-loader');

module.exports = {
    module: {
        rules: [
            {
                test: /\.(js|ts|tsx)$/,
                exclude: /node_modules/,
                use: [
                    { loader: 'babel-loader' },
                    {
                        loader: '@compiled/webpack-loader',
+                       options: {
+                           extract: true,
+                       },
                    },
                ],
            },
        ],
    },
+   plugins: [
+       new CompiledExtractPlugin(),
+   ],
};

For more configuration options see the loader package docs.

CSS configuration

Add loaders to handle and extract found styles. We support and recommend mini-css-extract-plugin; we don't currently support other CSS loaders. Note: mini-css-extract-plugin dropped support for Webpack v4 in 2.0.0, Webpack v4 users will need to use mini-css-extract-plugin@1.6.2.

npm i css-loader mini-css-extract-plugin --save-dev

If you don't already handle .css files in your webpack.config.js, you can update it like this:

// webpack.config.js
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    module: {
        rules: [
            {
                test: /\.(js|ts|tsx)$/,
                exclude: /node_modules/,
                use: [
                    { loader: 'babel-loader' },
                    {
                        loader: '@compiled/webpack-loader',
                        options: {
                            extract: true,
                        },
                    },
                ],
            },
+           {
+               test: /\.css$/i,
+               use: [MiniCssExtractPlugin.loader, 'css-loader'],
+           },
        ],
    },
    plugins: [
+       new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),
        new CompiledExtractPlugin(),
    ],
};

Note that we don't currently support style-loader for loading css files from Compiled. If you are using style-loader, or you're using a different loader for your css files already, you can use regular expressions to ensure that both Compiled's css files and your other css files are loaded correctly:

// webpack.config.js
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
    module: {
        rules: [
            {
                test: /\.(js|ts|tsx)$/,
                exclude: /node_modules/,
                use: [
                    { loader: 'babel-loader' },
                    {
                        loader: '@compiled/webpack-loader',
                        options: {
                            extract: true,
                        },
                    },
                ],
            },
+           {
+               test: /compiled-css\.css$/i,
+               use: [MiniCssExtractPlugin.loader, 'css-loader'],
+           },
            // The following loader will be used for css files that are not from Compiled.
            {
-               test: /\.css$/i,
+               test: /(?<!compiled-css)(?<!\.compiled)\.css$/,
                // Put your existing css loader configuration here
                use: ['style-loader', 'css-loader'],
            },
        ],
    },
    plugins: [
+       new MiniCssExtractPlugin(),
        new CompiledExtractPlugin(),
    ],
};

All extracted styles will be placed in a file called compiled-css.css.

Production optimization

Filename

Some production environments may require you to include a hash in the filename to allow the stylesheet to be cached correctly.

To do this, pass the filename option to the extract plugin, including [contenthash] in the name.

// webpack.config.js
-new MiniCssExtractPlugin()
+new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' })

See the mini-css-extract-plugin docs for more information on the available options.

CSS minification

Turn on the minimizer plugin.

npm i css-minimizer-webpack-plugin --save-dev
// webpack.config.js
+const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = {
+   mode: 'production',
    module: {
        rules: [
            {
                test: /\.(js|ts|tsx)$/,
                exclude: /node_modules/,
                use: [
                    { loader: 'babel-loader' },
                    {
                        loader: '@compiled/webpack-loader',
                        options: {
                            extract: true,
                        },
                    },
                ],
            },
            {
                test: /\.css$/i,
                use: [MiniCssExtractPlugin.loader, 'css-loader'],
            },
        ],
    },
    plugins: [
        new MiniCssExtractPlugin({ filename: '[contenthash].[name].css' })
        new CompiledExtractPlugin(),
    ],
+   optimization: {
+       minimizer: [
+           '...',
+           new CssMinimizerPlugin(),
+       ],
+   },
};

Suggest changes to this page ➚