Skip to content
No description, website, or topics provided.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Webpack loader for ReasonML fans who want to use CSS Modules in their projects.

It's a drop-in replacement for css-loader. In other words, when you replace 'css-loader' in your webpack.config.js to 'reason-css-modules-loader'. It'll work without any problem.


Install via npm npm install --save-dev reason-css-modules-loader



Just change 'css-loader' with 'reason-css-modules-loader'.


// webpack.config.js
module.exports = {
  module: {
    rules: [
        test: /\.css$/,
        use: [
            loader: 'reason-css-modules-loader',
            query: {
              sourceMap: !isProduction,
              importLoaders: 1,
              localIdentName: isProduction ? '[hash:base64:5]' : '[local]__[hash:base64:5]'

Then, style definition files will be created under ./src/styles directory. (You can change this with destDir option.)


To include a CSS Module file to a Reason code, write code like below on the top of your ReasonML code:

let styles = [%raw {| require("./Component.css") |}]

Change the Component above with your component name. If you're new to [$raw] syntax. Click here.

Then, you can call CSS-Module-ized styles in your ReasonReact codes:

<div className=styles##isRead>

However, this code isn't type-safe. You can just use any class names that don't exist. So, let's add the type definition.

let styles: ComponentStyles.definition = [%raw {| require("./Component.css") |}]

NOTE: You cannot add the type definition in the beginning. Because * file doesn't exist becaust it is created by the reason-css-modules-loader.


  1. Write type-unsafe code first and save it to generate the .bs.js file.
  2. Then, the loader will generate * file.
  3. Add type definition next to the styles.

Like original CSS Modules, you can use re-classnames.

<div className=Cn.make([styles##isRead, styles##blue])>

Some of you are wondering why ## is used instead of . or #. It's because the compiled type is Js.t(object). Check this doc to learn more about this syntax.


You can just set options like any other loaders.

css-loader options

If it is an option that css-loader supports, you can use it.

NOTE: Unlike the default css-loader settings, modules and camelCase are forced to true. And you cannot change them to false.

It's not a bad decision because you don't need to use this loader if you don't want to use CSS Modules. And camel case is the naming convention of ReasonML.

destDir option

By default, CSS Modules type definition files are created under ./src/styles folder to prevent clutter.

However, for some reason, you might want to change this location. Then, you can change it with destDir option.

Example 1: Change it to ./src/css folder.

  loader: 'reason-css-modules-loader',
  query: {
    destDir: './src/css',

You can even create * files side-by-side to their relevant componants.

Example 2: Add file right next to .css file.

  loader: 'reason-css-modules-loader',
  query: {
    destDir: 'current',

NOTE: As ReasonML creates a compiled JavaScript version of each .re file, I personally don't recommend creating files next to .css. File tree becomes too cluttered.

Don't you think it's too much?


If there wasn't typings-for-css-modules-loader, I couldn't make reason-css-modules-loader.

This module inspired and guided me.

You can’t perform that action at this time.