lukeed / pwa

(WIP) Universal PWA Builder

Home Page:https://pwa.cafe

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Custom postcss webpack style rules missing with pwa.config.js

malikbenkirane opened this issue · comments

TLDR; missing access to preprocessors options with pwa.config.js

I'm wondering how I could add custom postcss style rules to the webpack configuration.

Although, I didn't figured out where lives the code for pwa.config.js yet, I actually found there was no clean way to add custom postcss plugins use rules

let obj = {
css: [],
less: fn('less'),
sass: fn('sass', { indentedSyntax: true }),
scss: fn('sass'),
stylus: fn('stylus'),
styl: fn('stylus')
};

One way to work around this limitation as suggested by

rules.push({ test, include:[src], use:user.concat(obj[ext]) });
rules.push({ test, exclude:[src], use:vendor.concat(obj[ext]) });

and
function generate(isProd, name, options = {}) {
options.sourceMap = isProd;
return (name += '-loader') && { loader:name, options };
}

would be searching for weback's rules where use.length > 0 and use[use.length-1].loader === ext + '-loader' in pwm.config.js and in order to update the options within the last item of the use object.

Thus, I wonder if it wouldn't be possible to pass options from mutation of an object similarly to postcss array for instance as there is only one preprocessor used in general.

As I didn't figured out how pwa.config.js is interpreted under the hood I don't know yet how to pass options to webpack/style.js. Though I hope it is feasible.

Sorry, I'm not 100% sure what you're asking quite yet.

Are you trying to modify the PostCSS config? If so, you can do that through a postcss key within your pwa.config.js file. Here's an example:

// pwa.config.js
exports.postcss = function (config) {
  config.plugins.push(require('postcss-flexbugs-fixes'));
};

Hi @lukeed, I'm actually trying to update sass-loader include path and that is what I've managed to do right now. Here is the pwa.config.js prototype I've been testing with :

exports.webpack = function(config, env) {
  let { production, webpack } = env;
  let index = 0;
  for (let rule of config.module.rules) {
    let use = rule.use;
    if (use && use.length > 0 && use[use.length-1].loader === 'sass-loader') {
      let opts = config.module.rules[index].use[use.length-1].options;
      if (opts && opts.sassOptions && opts.sassOptions.includePaths) {
        opts.sassOptions.includePaths.push('theme');
      } else if (opts && opts.sassOptions) {
        opts.sassOptions.includPaths = ['theme'];
      } else if (opts) {
        opts.sassOptions = {
          includePaths: ['theme'],
        };
      } else {
        config.module.rules[index].use[use.length-1].options = {
          sassOptions: {
            includePaths: ['theme'],
          },
        };
      }
      console.log('sass-loader sassOptions configuration updated!');
      console.log(JSON.stringify(config.module.rules[index],null,2));
      break
    }
    index++
  }
}

This is quite a lot of code for such a simple configuration update and I can't see how PostCSS could be used to do so.

I hope that this example added some clarity to what I'm trying to propose.

Ah, I see. Thanks!

In a future release, I'll make this such that you can add an exports.sass key to your config file.

You're right – that's too much for such a simple thing, and not having it exposed is contradictory to the rest of the system/ethos.

I should be able to release a patch-fix for this this weekend.

@lukeed Looking forward for the patch. I can help too 😉 I just need some insights though. For instance the files I should be looking etc...

Thanks for your patience on this.

This is now achievable in the next release (happening in a few minutes):

// pwa.config.js

exports.sass = {
  // your options here
  // passed directly to sass-loader
}

That config object will be used for .scss and .sass extensions – PWA will enforce indentedSyntax: true for the .sass extension though, since that's required.

Please note that includePaths seems to be broken/doesn't work as advertised.
I spent some time debugging this to make sure your use-case was supported. Turns out that includePaths can't live inside the sassOptions object. You have to do this instead:

exports.sass {
  includePaths: ['path/to/theme']
}

// OR, if you want to use function-type:

const { join } = require('path');

exports.sass = function (config, env) {
  config.includePaths = [
    join(env.src, 'theme')
  ];
}

Hope that cleans up your config file now :)

Ok, as of v0.5.4 we're now using the updated version of sass-loader 😅

This means you can disregard my comment about about includePaths not working inside sassOptions... this is the correct variant now:

// you can also use function config if you want
exports.sass = {
  sassOptions: {
    includePaths: ['path/to/theme']
  }
}

Amazing! Thank you @lukeed

No problem, thanks for the heads up :)