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
 (PR metrics pending)

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