Vue-cli: SASS files from NPM modules referencing relative imports won't build

Created on 24 May 2019  Â·  21Comments  Â·  Source: vuejs/vue-cli

Version

3.7.0

Reproduction link

https://github.com/christophehenry/mrt

Environment info

Environment Info:

  System:
    OS: Linux 5.0 Fedora 28 (Twenty Eight) 28 (Twenty Eight)
    CPU: (8) x64 Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
  Binaries:
    Node: 8.11.3 - ~/.nvm/versions/node/v8.11.3/bin/node
    Yarn: 1.7.0 - /usr/bin/yarn
    npm: 6.9.0 - ~/.nvm/versions/node/v8.11.3/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: 66.0.4
  npmGlobalPackages:
    @vue/cli: 3.7.0

Steps to reproduce

git clone https://github.com/christophehenry/mrt.git && cd mrt
npm i
npm run test:unit

What is expected?

Test run correctly

What is actually happening?

sass-loader will crash with error stating relative imports of NPM module can't be found.


Full stacktrace:

WEBPACK  Failed to compile with 1 error(s)

Error in ./src/components/HelloWorld.vue?vue&type=style&index=0&id=469af010&scoped=true&lang=scss&

  Module build failed (from ./node_modules/sass-loader/lib/loader.js):
  Can't find stylesheet to import.
    â•·
  8 │ @import "functions";
    │         ^^^^^^^^^^^
    ╵
    ./mrt/node_modules/bootstrap/scss/bootstrap.scss 8:9  @import
    stdin 1:9                                                           root stylesheet
        in http:/localhost/$HOME/mrt/node_modules/bootstrap/scss/bootstrap.scss (line 8, column 9)

 ERROR  mocha-webpack exited with code 1.
unit-mocha

Most helpful comment

Just occurred to me that this change can be made using webpack chaining.
https://cli.vuejs.org/guide/webpack.html#chaining-advanced

// vue.config.js
module.exports = {
  chainWebpack: (config) => {
    if (process.env.NODE_ENV === 'test') {
      const scssRule = config.module.rule('scss');
      scssRule.uses.clear();
      scssRule
        .use('null-loader')
        .loader('null-loader');
    }
  },
};

Not perfect but than the previous attempt

All 21 comments

I think I've got the same issue. Styles load normal for build/serve, however they cannot resolve for unit testing with mocha.

Reproduction with a fresh vue cli project:

  1. vue create hello-world
  2. Choose mocha unit tests and sass (dart-sass).
  3. Add a file "src\style\main.scss"
  4. Import it from "src\components\HelloWorld.vue": @import '../style/main';
  5. run npm run test:unit. You'll get the error.

Does anyone have any idea why? I've been debugging for a few hours, no clue why it's not working.

Confirming seeing the same issue using the ~@ shortcut...

@import "~@/scss/color";
@import "~@/scss/mixins";

.auth {
  display: flex;
  flex-direction: column;
  flex: 0 0 100%;
  justify-content: flex-start;
  align-content: center;
  width: 100%;
  z-index: 5;
...

package.json

"devDependencies": {
    "@types/chai": "^4.1.0",
    "@types/mocha": "^5.2.4",
    "@vue/cli-plugin-babel": "^3.8.0",
    "@vue/cli-plugin-e2e-cypress": "^3.8.0",
    "@vue/cli-plugin-typescript": "^3.8.0",
    "@vue/cli-plugin-unit-mocha": "^3.8.0",
    "@vue/cli-service": "^3.8.0",
    "@vue/test-utils": "1.0.0-beta.29",
    "chai": "^4.1.2",
    "lint-staged": "^8.1.5",
    "sass": "^1.18.0",
    "sass-loader": "^7.1.0",
    "typescript": "^3.4.3",
    "vue-svg-loader": "^0.12.0",
    "vue-template-compiler": "^2.6.10"
  },

the same issue

the same issue

Fix: just remove special characters and spaces from project path ("C#" name of folder for example renamed to CSharp).

Same problem, and I've been looking for a couple of hours and no success. My path doesn't contain any special characters, as @grandsilence suggested.

same issue

same issue

same issue, I do not have special characters in my path, either (using debian/linux). Any solution or workaround?

I also encountered the same problem, but there is no problem with node-sass.

I'm having the same issue in new project. Created structure using vue-cli/sass/mocha. Have global design-tokens.scss which connected in vue.config.js:

module.exports = {
    css: {
        loaderOptions: {
            sass: {
                data: `@import "~@/styles/design-tokens.scss";`
            }
        }
    }
}

It's working just fine when using serve/build, but unit-tests (yarn test:unit) throwing an error:

 Can't find stylesheet to import.
 │ @import "~@/styles/design-tokens.scss";

Anyone has solved the issue? It seems strange that in such large well-known project unit-tests with scss just not working and an issue is open for a few month.

The only valid workaround I know of is using node-sass instead of dart-sass (with the disadvantages it comes with).

I think the issue relates to how mocha-webpack handles webpack CSS Preprocessors. https://github.com/zinserjan/mocha-webpack/blob/master/docs/installation/webpack-configuration.md

The document suggests replacing all CSS modules with a null-loader. A bit of tracing showed that the vue-cli basically executes the following command when running a unit test:

npx mocha-webpack \
--recursive \
--require node_modules/@vue/cli-plugin-unit-mocha/setup.js \
--webpack-config node_modules/@vue/cli-service/webpack.config.js \
'tests/unit/**/*.spec.js'

The file node_modules/@vue/cli-service/webpack.config.js generates the webpack config and passes it into mocha. To intercept and replace CSS Preprocessor modules with the null-loader I created a wrapper.

/* fix-webpack.config.js */
// eslint-disable-next-line import/no-extraneous-dependencies
const vueCliWebpack = require('@vue/cli-service/webpack.config');

vueCliWebpack.module.rules = vueCliWebpack.module.rules.map((rule) => {
  const regExpStr = rule.test.toString();
  if (regExpStr === '/\\.sass$/' || regExpStr === '/\\.scss$/') {
    return {
      test: rule.test,
      loader: 'null-loader',
    };
  }
  return rule;
});
module.exports = vueCliWebpack;

(note: you need to install the null-loader and possibly edit the rule tests to requirements)
I couldn't find a way of forcing vue-cli-service test:unit to use my version of the generator but the following command works.

npx mocha-webpack \
--recursive \
--require node_modules/@vue/cli-plugin-unit-mocha/setup.js \
--webpack-config fix-webpack.config.js \
'tests/unit/**/*.spec.js'

I'm using this as a temporary workaround. The good part is that its is much quicker to run tests without having to run CSS Preprocessors. However I still don't understand the root cause of the failure and this workaround does not run in the context of the vue-cli.

Just occurred to me that this change can be made using webpack chaining.
https://cli.vuejs.org/guide/webpack.html#chaining-advanced

// vue.config.js
module.exports = {
  chainWebpack: (config) => {
    if (process.env.NODE_ENV === 'test') {
      const scssRule = config.module.rule('scss');
      scssRule.uses.clear();
      scssRule
        .use('null-loader')
        .loader('null-loader');
    }
  },
};

Not perfect but than the previous attempt

The only valid workaround I know of is using node-sass instead of dart-sass (with the disadvantages it comes with).

You are right,The solution can also be @import "../~styles/_varibles.scss";

i don’t want to use any framework integration or wrapper!
How to use material-components-web?

I'm having this problem using laravel-mix. Anyone here been able to fix it?

https://material.io/develop/web/docs/getting-started/
look at appendix at the bottom of document
Appendix: Configuring a Sass Importer for Nested node_modules

Came across this today, this bug still exists. Used @robbishop's solution and it seems to work.

  • @vue/cli-plugin-unit-mocha: 4.1.2
  • @vue/cli-service: 4.1.2
  • Node: 13.7.0
  • Npm: 6.13.6

same issue, solved by

removing

  css: {
    extract: {
      filename: "[name].css",
      chunkFilename: "[name].css"
    }
  },

from vue.config.js

I'm having this problem using laravel-mix. Anyone here been able to fix it?

@JoshPJackson

Here's what worked for me based on robbishop's solution:

if (process.env.NODE_ENV !== "testing") {
    mix.version();
}

if (process.env.NODE_ENV === "testing") {
    const nodeExternals = require("webpack-node-externals");

    mix.webpackConfig((webpack) => {
        return {
            devtool: "inline-cheap-module-source-map",
            externals: [nodeExternals()],
            module: {
                rules: [
                    {
                        test: /\.scss/,
                        use: "null-loader",
                    },
                ],
            },
        };
    });
}

This assumes that your test script in package.json sets env to testing as in:
"test": "cross-env NODE_ENV=testing mochapack --webpack-config node_modules/laravel-mix/setup/webpack.config.js --require test/setup.js test/**/*.spec.js",

the same issue

Was this page helpful?
0 / 5 - 0 ratings

Related issues

evelynhathaway picture evelynhathaway  Â·  35Comments

mayefeng picture mayefeng  Â·  44Comments

joeirimpan picture joeirimpan  Â·  35Comments

italomaia picture italomaia  Â·  88Comments

yyx990803 picture yyx990803  Â·  34Comments