css-modules / css-modules-require-hook

A require hook to compile CSS Modules in runtime
MIT License
484 stars 44 forks source link

relative references not resolved correctly any more with 4.2.2 #104

Closed joscha closed 6 years ago

joscha commented 7 years ago

Coming from 4.1.0, I can see a regression in 4.2.2, where relative imports can't be found any more, e.g.:

Can't resolve module path from `src/a` to `pages/x/y/z/foo.css`

where src/a.css would have:

@value a as b from "pages/x/y/z/foo.css";

I suspect it is coming from the new postcss-modules-resolve-imports "^1.3.0" dependency, but that is just a hunch.

joscha commented 7 years ago

I suppose I could make it work with the resolve.modules option of https://github.com/css-modules/postcss-modules-resolve-imports#options - is there any way to pass that config through? EDIT: not currently: https://github.com/css-modules/css-modules-require-hook/blob/c89b4fb66e9b47088e38e5e530e9244ce5903aa7/src/index.js#L70

craigglennie commented 7 years ago

I think I'm having the same problem. The resolver is being setup with only an extension argument. The cleanest way I can see to fix it is to have css-modules-require-hook also take an 'alias' object and pass it into ResolveImports when it's created. This would let users specify other locations for the resolver to look.

So, assuming that your CSS lives in ./src/styles/colors.css and you have an import statement like @value blue01 from 'styles/colors.css'; you could create an alias that can map styles to an absolute path:

const hook = require('css-modules-require-hook');
hook({
  //... other config
  resolveAlias: {styles: '/absolute/prefix/for/relative/path/styles'}
})

And that gets added to the resolve object that's passed in when ResolveImports is instantiated. Or, let the user fully specify the resolve object, which would give them full control over the resolver.

One way it can be addressed now (other than pinning an older version) is to use the use option and fully specify your plugins, which lets you configure the resolver. It's annoying, because it's more convenient to use prepend and append than specify the full set (which you can get from src/index.js) but it does work. For example:

hook({
  use: [
    // ... other plugins
    new ResolveImports({
      resolve: {
        alias: {
          styles: `${process.cwd()}/src/styles`
        },
        extensions: ['.css']
      }
    })
  ]
});
hoschi commented 7 years ago

Version 4.2.2 is also broken for me, 4.2.1 works fine. Here is my setup to mimic webpacks resolve logic for tests:

let basePath = path.resolve(__dirname, '../../');
let hook = require('css-modules-require-hook');

// setup CSS modules for SCSS files
hook({
    //devMode:true,
    extensions: '.scss',
    // generate easy assertable names, which be still distinguishable enough between modules
    generateScopedName: '[name]_[local]',
    rootDir: basePath,
    preprocessCss: function (css) {
        // basepath above doesn't work, replace file names, so they are findable by hook
        var modified = css.replace(/from 'assets/g, `from '${basePath}/assets`);
        return modified;
    },
});

Would be great to do it with resolve.modules from the postcss plugin you arleady using, instead of rewriting the paths.

joscha commented 7 years ago

is there any news on this?

joscha commented 6 years ago

@sullenor any chance to get a hint on where I should fix this?

mightyaleksey commented 6 years ago

Yeah, I changed the module resolution algorithm with adding postcss-modules-resolve-imports. So instead of path.resolve(fromDir, destFile) it became more stricter and closer to the core nodejs resolution algorithm. So it tries to resolve pages/x/y/z/foo.css via node_modules folder.

I published 4.2.3 version with resolve option, so you may add custom folders to check with resolve.modules option (similar to node_modules, but please, provide an absolute path) and omit an extension in @value and composes decls:

const path = require('path');

hook({
  resolve: {
    modules: [path.resolve('pages')],
  }
});

Excuse me for inconvenience.

joscha commented 6 years ago

@sullenor works a charm, thank you!