wemake-services/wemake-vue-template

Discussion: Support typed css-modules with Typescript

Open

#1,386 opened on Oct 23, 2019

 (10 comments) (0 reactions) (0 assignees)TypeScript (69 forks)auto 404
featurehelp wantedquestion

Repository metrics

Stars
 (728 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

Hi, I am working on typed Vue css-modules in Typescript support for Nuxt.js. I saw the issue: https://github.com/nuxt/typescript/issues/35, actually I found this template thanks to this (I am very grateful for this template by the way, this is what I needed but not deserved):]

Yesterday I have had some successes with a custom fork of a css-modules-typescript-loader package:

  1. I extended webpack configuration in nuxt.config.ts build.extend method:
function enableCssModulesPlugin (config): void {
  if (!(config.module && config.module.rules)) { return; }
  for (const rule of config.module.rules) {
    if (!rule.oneOf) { continue; }
    const useLoaders = rule.oneOf.map(e => e.use);
    for (const loaders of useLoaders) {
      const loadersCopy = loaders.map(e => ({ ...e }));
      loadersCopy.map(({ loader }, index) => {
        if (loader === 'css-loader') {
          loaders.splice(index, 0, '@alza54/css-modules-typescript-loader');
        }
        return {};
      });
    }
  }
}
// ...
// enableCssModulesPlugin(config);
  1. I modified Vue.$style augmentation by changing type Readonly<Record<string, string>> to any
  2. In all components I have imported definition file (which exports generated interface of class names)
  3. In all components I have created style computed getter like this:
get style (): cssModules {
  return this.$style;
}

and it kinda worked.

But...

It doesn't make a sense, because types are available after building Webpack modules. Useless.

What will happen when I rename .reload or .actions classes? What if I have a typo there?

Considering that, I suggest trying new approach: extending Typescript configuration instead. I found that typescript-plugin-css-modules seems to work remarkably good for me:

// test.module.scss
// camelCase for simplicity
$mistyrose: #ffe4e1;

.mistyrose {
  &Background {
    background: $mistyrose;
  }
  &Color {
    color: $mistyrose;
  }
  &Border {
    border: 1px solid $mistyrose;
  }
}

$counts: 'One', 'Two', 'Three';
@each $count in $counts {
  .element#{$count} {
    background: $mistyrose;
  }
}

B9TW3gHlCg

This plugin transforms Sass/SCSS to CSS using sass.renderSync method; I assume that .vue files support could be achieved with a customRenderer function extracting CSS from Vue single file components.

I am just not assured of how to assign exported classes to the $style property yet, though.

I believe this is a proper way of implementing typed Vue CSS modules, unlike extending webpack configuration. I would love to hear your opinion about this @sobolevn 😄

Contributor guide