Skip to content

Make babel-plugin-react-css-modules work with commonjs require #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sashako opened this issue Jan 8, 2017 · 6 comments
Open

Make babel-plugin-react-css-modules work with commonjs require #38

sashako opened this issue Jan 8, 2017 · 6 comments

Comments

@sashako
Copy link

sashako commented Jan 8, 2017

Hello,

when requiring scss files using require() syntax I get Cannot use styleName attribute without importing at least one stylesheet.. However if I switch to using import it works (minus an eslint parsing error).

I'm trying to introduce css-modules into an old code base. I have the es6 babel preset running (that's why imports work), but code is linted without modules support and I would love to keep it that way for the time being. Is there anyway to make this plugin work with require?

@gajus gajus changed the title Plugin doesn't recognize css files loaded with require, only import Make babel-plugin-react-css-modules work with commonjs require Jan 15, 2017
@gajus
Copy link
Owner

gajus commented Jan 15, 2017

I'm trying to introduce css-modules into an old code base. I have the es6 babel preset running (that's why imports work), but code is linted without modules support and I would love to keep it that way for the time being. Is there anyway to make this plugin work with require?

It is possible. However, there hasn't been any demand for it.

Provided that babel-plugin-react-css-modules itself is somewhat bleeding-edge solution, I cannot see many people use it in combination with commonjs.

I can leave this issue open to see if more people thumbs up the feature.

@aikar
Copy link

aikar commented Jan 29, 2017

@gajus per my note on #1 about my issues with 'styles' scope, would it be possible if this plugin instead of looking for that specific import and referencing it, looked for any variable 'in scope' at render() named 'styles' or 'this.styles'? Then the plugin shouldn't care how styles was created.

@hakatashi
Copy link

Note that ES2015 modules are not yet standard (in spite of its name) and possibly breaking by future spec changes. That's why I hesitate using import in my brand new codes.

@WesleyKapow
Copy link

@gajus Could you point me in the direction of how to get this working? I'm afraid switching away from commonjs may be more work.

@martpie
Copy link

martpie commented Dec 29, 2018

This problem is quite important with TypeScript setups where TypeScript transpiles imports to requires (Named imports are undefined)

Sure I could. try to make a quite complex full-babel setup (and drop ts-loader) with the plugins in correct order, but then I can't use presets as they are loaded before plugins, and it gets reallyyy complicated.

I'd be happy to try to help solving this particular issue, but I would need a maintainer or a contributor to tell me where I could start looking at. (cc @gajus)

@yume-chan
Copy link
Contributor

@martpie It's not hard:

  1. Here is the code processing the import statements:

ImportDeclaration (path: *, stats: *): void {
if (notForPlugin(path, stats)) {
return;
}
const filename = stats.file.opts.filename;
const targetResourcePath = getTargetResourcePath(path, stats);
let styleImportName: string;
if (path.node.specifiers.length === 0) {
// use imported file path as import name
styleImportName = path.node.source.value;
} else if (path.node.specifiers.length === 1) {
styleImportName = path.node.specifiers[0].local.name;
} else {
// eslint-disable-next-line no-console
console.warn('Please report your use case. https://github.com/gajus/babel-plugin-react-css-modules/issues/new?title=Unexpected+use+case.');
throw new Error('Unexpected use case.');
}
filenameMap[filename].styleModuleImportMap[styleImportName] = requireCssModule(targetResourcePath, {
context: stats.opts.context,
filetypes: stats.opts.filetypes || {},
generateScopedName: stats.opts.generateScopedName
});
if (stats.opts.webpackHotModuleReloading) {
addWebpackHotModuleAccept(path);
}
if (stats.opts.removeImport) {
path.remove();
}
},

The function name ImportDeclaration tells babel what statements you are interested.

  1. Obviously you need to create a similar function to process require calls. For that, you need to know what statement types you want.

Here you can use https://astexplorer.net/ , type in code with require calls, it will display how babel parses the code (maybe you need to choose babel-eslint9 as parser for best result).

image

So maybe you can try CallExpression, and test its callee.type === 'Identifier' && callee.name === 'require'

  1. Copy the logic, tweak anything not work, write tests, done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants