wemake-services/wemake-vue-template

Discussion: Support typed css-modules with Typescript

Aperta

#1386 aperta il 23 ott 2019

 (10 commenti) (0 reazioni) (0 assegnatari)TypeScript (69 fork)auto 404
featurehelp wantedquestion

Metriche repository

Star
 (728 stelle)
Metriche merge PR
 (Nessuna PR mergiata in 30 g)

Descrizione

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 😄

Guida contributor