kristerkari / react-native-postcss-transformer

Use PostCSS to style your React Native apps.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Find a way to clean up user's configuration for the transformer

kristerkari opened this issue · comments

It would be nice to only require the user to setup this:

rn-cli.config.js:

module.exports = {
  getTransformModulePath() {
    return require.resolve("react-native-postcss-transformer");
  },
  getSourceExts() {
    return ["css"];
  }
};

But the main problem is that with PostCSS the user is not forced to use any specific file extension. So, the extension could be .css, .sss, .js or something else.

One way to solve that would be to specify possible file extensions inside the transformer, and then check if the user given values in getSourceExts() match. That is however not currently possible as metro bundler does not give any access the values of getSourceExts().

That is why there is a need for an extra wrapper file to call the transformer:

postcss-transformer.js:

var upstreamTransformer = require("metro/src/transformer");
var postcssTransformer = require("react-native-postcss-transformer");
var postCSSExtensions = ["css"]; // <-- Add other extensions if needed.

module.exports.transform = function({ src, filename, options }) {
  if (postCSSExtensions.some(ext => filename.endsWith("." + ext))) {
    return postcssTransformer.transform({ src, filename, options });
  } else {
    return upstreamTransformer.transform({ src, filename, options });
  }
};

Hey @kristerkari could we use the postcss.config.js file to do that? Something like:

// postcss.config.js
module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
  reactNativePostCssTransformer: {
    extensions: ['css']
  }
};

And then we can maybe read this file inside metro.config.js and also inside the transfomer:

// metro.config.js
const { getDefaultConfig } = require("metro-config");
const postCssConfig = require('./postcss.config.js');

module.exports = (async () => {
  const {
    resolver: { sourceExts },
  } = await getDefaultConfig();

  return {
    transformer: {
      babelTransformerPath: require.resolve("./postcss-transformer.js"),
    },
    resolver: {
      sourceExts: [...sourceExts, ...postCssConfig.reactNativePostCssTransformer.extensions],
    },
  };
})();

And then we would do the same thing inside the transformer.
We could use the same strategy that the webpack loader does to find the config file: https://github.com/webpack-contrib/postcss-loader/blob/master/src/utils.js#L37

The con of this approach is that we would be adding a property to postcss.config.js that isn't "native" but that seems pretty minor in my opinion.

@marlonmarcello Thanks for the suggestion!

The only problem that I see with that approach is that we would be adding custom fields to the PostCSS config, which might then not be supported by some PostCSS tooling, and possibly cause errors.

I would like to find some kind of solution that would be "future proof" and not affect other tools/libraries.