pwa icon indicating copy to clipboard operation
pwa copied to clipboard

SASS loader (for scss extensions) and dependency on resources in 'node_modules'

Open jan-johansson-mr opened this issue 7 years ago • 4 comments
trafficstars

Hi,

The current PWA (and I think webpack) template doesn't find references in the 'node_module' folder when using SASS in Vue. E.g. the statement (in a Vue file) @import "@material/theme/mdc-theme" fails (file not found).

The file 'utils.js', found in the 'build' folder generates needed loaders for the solution. The search path to 'node_module' can be added to the loader for 'scss', so the referenced file can be found. I don't know if this is the correct way of going about it, but I'll include the 'fix' and then you can decide whether it's good or not (and if not, what to do instead).

Here is the code before the change (begins at the 'generateLoaders' function):

  // generate loader string to be used with extract text plugin
  function generateLoaders (loader, loaderOptions) {
    const loaders = [cssLoader]
    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }

And here is the code after the change:

  // generate loader string to be used with extract text plugin
  function generateLoaders (loader, loaderOptions) {
    const loaders = [cssLoader]
    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass', { includePaths: [path.resolve(__dirname,'../node_modules')]}),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }

The change is introduced by the "scss:" tag, where I put the 'includePaths'.

Thanks

jan-johansson-mr avatar Jan 01 '18 13:01 jan-johansson-mr

https://github.com/webpack-contrib/sass-loader#imports

You have to use a tilde to make sass-loader interpret the path as a node module:

@import "~@material/theme/mdc-theme"

then you don't need any includePaths.

LinusBorg avatar Jan 01 '18 19:01 LinusBorg

Hi,

Thanks for the response, I tried to put the tilde, but it didn't work :-(

Here is part of my test app ('App.Vue'):

<style lang="scss">
$mdc-theme-primary: #ce93d8; // Purple 200
$mdc-theme-primary-light: #ce93d8; // Purple 200
$mdc-theme-primary-dark: #6a1b9a; // Purple 800
$mdc-theme-secondary-light: #ffd180; // Orange A100
$mdc-theme-secondary-dark: #ff6d00; // Orange A700
@import "@material/toolbar/mdc-toolbar";
</style>

When I added tilde, it became:

<style lang="scss">
$mdc-theme-primary: #ce93d8; // Purple 200
$mdc-theme-primary-light: #ce93d8; // Purple 200
$mdc-theme-primary-dark: #6a1b9a; // Purple 800
$mdc-theme-secondary-light: #ffd180; // Orange A100
$mdc-theme-secondary-dark: #ff6d00; // Orange A700
@import "~@material/toolbar/mdc-toolbar";
</style>

I removed my 'fix', and tried both npm run build, and npm run dev. Both commands failed.

So I added my 'includePaths' again.

I've found this, maybe it's something related tilde path suddenly stopped working.

jan-johansson-mr avatar Jan 02 '18 17:01 jan-johansson-mr

@LinusBorg

You have to use a tilde to make sass-loader interpret the path as a node module

This won't work with the material-components-web library because their sass files assumes node-modules in the import path. more and more sass libraries seems to be packaged this way, may be will be worth to add an option to have node-modules in the import path in the future ?

but for now I do not think this is an issue with the pwa template. this is more a material-components-web library config dependency: you need to have node-modules in your sass-loader import path.

stasson avatar Jan 03 '18 10:01 stasson

Alright, thanks for the info.

LinusBorg avatar Jan 03 '18 11:01 LinusBorg