vuejs / vue-cli

šŸ› ļø webpack-based tooling for Vue.js Development
https://cli.vuejs.org/
MIT License
29.75k stars 6.33k forks source link

includePaths not working with dart-sass and @vue/cli-plugin-unit-mocha #6427

Open lambertkevin opened 3 years ago

lambertkevin commented 3 years ago

Version

4.5.12

Reproduction link

https://github.com/lambertkevin/vue-cli-mocha-bug

Environment info

Environment Info:

  System:
    OS: macOS 11.2.3
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  Binaries:
    Node: 12.18.4 - /usr/local/bin/node
    Yarn: 1.22.10 - /usr/local/bin/yarn
    npm: 6.14.6 - /usr/local/bin/npm
  Browsers:
    Chrome: 89.0.4389.128
    Edge: Not Found
    Firefox: 87.0
    Safari: 14.0.3
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.2.1
    @vue/babel-helper-vue-transform-on:  1.0.2
    @vue/babel-plugin-jsx:  1.0.5
    @vue/babel-plugin-transform-vue-jsx:  1.2.1
    @vue/babel-preset-app:  4.5.12
    @vue/babel-preset-jsx:  1.2.4
    @vue/babel-sugar-composition-api-inject-h:  1.2.1
    @vue/babel-sugar-composition-api-render-instance:  1.2.4
    @vue/babel-sugar-functional-vue:  1.2.2
    @vue/babel-sugar-inject-h:  1.2.2
    @vue/babel-sugar-v-model:  1.2.3
    @vue/babel-sugar-v-on:  1.2.3
    @vue/cli-overlay:  4.5.12
    @vue/cli-plugin-babel: ~4.5.0 => 4.5.12
    @vue/cli-plugin-e2e-cypress: ~4.5.0 => 4.5.12
    @vue/cli-plugin-eslint: ~4.5.0 => 4.5.12
    @vue/cli-plugin-router: ~4.5.0 => 4.5.12
    @vue/cli-plugin-unit-mocha: ~4.5.0 => 4.5.12
    @vue/cli-plugin-vuex: ~4.5.0 => 4.5.12
    @vue/cli-service: ~4.5.0 => 4.5.12
    @vue/cli-shared-utils:  4.5.12
    @vue/compiler-core:  3.0.11
    @vue/compiler-dom:  3.0.11
    @vue/compiler-sfc: ^3.0.0 => 3.0.11
    @vue/compiler-ssr:  3.0.11
    @vue/component-compiler-utils:  3.2.0
    @vue/eslint-config-prettier: ^6.0.0 => 6.0.0
    @vue/preload-webpack-plugin:  1.1.2
    @vue/reactivity:  3.0.11
    @vue/runtime-core:  3.0.11
    @vue/runtime-dom:  3.0.11
    @vue/shared:  3.0.11
    @vue/test-utils: ^2.0.0-0 => 2.0.0-rc.6
    @vue/web-component-wrapper:  1.3.0
    eslint-plugin-vue: ^7.0.0 => 7.9.0
    vue: ^3.0.0 => 3.0.11
    vue-eslint-parser:  7.6.0
    vue-hot-reload-api:  2.3.4
    vue-loader:  15.9.6 (16.2.0)
    vue-router: ^4.0.0-0 => 4.0.6
    vue-style-loader:  4.1.3
    vue-template-es2015-compiler:  1.9.1
    vuex: ^4.0.0-0 => 4.0.0
  npmGlobalPackages:
    @vue/cli: 4.5.12

Steps to reproduce

1- Add an includePaths in the sassOptions of a vue.config.js file.

2- In your style, @import/@use a file that should be accessible through the includePaths option in any file that will be tested with mocha (i.e. HelloWorld.vue in the vue boilerplate).

3- npm run test:unit

What is expected?

It should be able to @import/@use any sass/scss file from the includePaths options.

What is actually happening?

Tests won't pass because of importing issues.

Syntax Error: SassError: Can't find stylesheet to import.
fangbinwei commented 3 years ago

After a period of debugging, I found that dart-sass assume that we are running in a browser(Since we set global.window by jsdom-global), and can't resolve files correctly(on *nix system)

sass.dart.js

var dartNodePreambleSelf = typeof global !== "undefined" ? global : window;
// if we're running in a browser, Dart supports most of this out of box
// make sure we only run these in Node.js environment

var dartNodeIsActuallyNode = !dartNodePreambleSelf.window

when running npm run test:unit, dart-sass set includePaths like below finally, http://localhost/ come from window.location.href set by jsdom-global

image

when running npm run serve, includePaths is

image

The difference in includePath is not the key to this bug, but it illustrates the difference in window.location.href between node and browser, check code


what happened

dart-sass tries to load a stylesheet (not serious)

  1. by sass-loader webpackImporter
  2. working directory
  3. includePaths

working directory determined by window.location.href, in our issue, it's http://localhost/

when loading a stylesheet from includePaths on *nix, e.g. /Users/fangbinwei/issues/vue-cli-mocha-bug/src/assets/test-location/bug. dart-sass assume it's a relative path to http://localhost/, loading stylesheet from 'http://localhost/Users/fangbinwei/issues/vue-cli-mocha-bug/src/assets/test-location/bug'

https://github.com/sass/dart-sass/blob/295a11696240eca4f76f542fdb277b4b01bb7db6/lib/src/importer/node/implementation.dart#L145-L162

To verify, I modified the code in @vue/cli-plugin-unit-mocha/setup.js, and test passed, it also can solve #4053

- require('jsdom-global')(undefined, { pretendToBeVisual: true, url: 'http://localhost' })
+ const url = require('url')
+ require('jsdom-global')(undefined, { pretendToBeVisual: true, url: url.pathToFileURL(process.cwd()).href + "/" })

// https://github.com/vuejs/vue-test-utils/issues/936
window.Date = Date
// https://github.com/vuejs/vue-next/pull/2943
global.ShadowRoot = window.ShadowRoot

+global.SVGElement = window.SVGElement

I'm not sure if it's the solution of this issue, and whether this solution will cause other problems. (may affect vue-router)

but according to the code used by dart-sass, I think a better but ugly hackish workaround maybe like this

require('jsdom-global')(undefined, { pretendToBeVisual: true, url: 'http://localhost' })

process.versions.electron = ''

https://github.com/sass/dart-sass/issues/1270 https://github.com/sass/dart-sass/issues/710 https://github.com/mbullington/node_preamble.dart/issues/26 https://github.com/sass/dart-sass/issues/1294 https://github.com/dart-lang/sdk/issues/27979#issuecomment-704462646

lambertkevin commented 3 years ago

Thanks for your answer and investigation @fangbinwei ! I edited the issue to reflect more precisely on what's happening for google users šŸ‘

lambertkevin commented 3 years ago

Also I can confirm that with your changes, my "mock" project and my real project are both working and passing their tests. šŸ‘