component-compiler-utils
component-compiler-utils copied to clipboard
Fail to locate @import file "~@pkg/style.styl" in node_modules
Expected behavior
Expect to locate the .styl file from node_modules with ~ (which works well when bundled with Webpack)
<style lang="stylus" scoped>
@import '~@my-pkg/style.styl'
</style>
Actual behavior
Get the error:
failed to locate @import file ~@my-pkg/style.styl
at Evaluator.visitImport (C:\Users\dev\node_modules\stylus\lib\visitor\evaluator.js:915:21)
...
...
...
However, when I import the .styl file with relative path:
<style lang="stylus">
@import '../node_modules/@my-pkg/style.styl'
</style>
It works fine.
Steps to reproduce the behavior
My rollup config:
import vue from 'rollup-plugin-vue'
import typescript from 'rollup-plugin-typescript2'
import nodeResolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import json from 'rollup-plugin-json'
export default {
input: 'src/index.vue',
output: {
format: 'esm',
file: 'dist/bundle.esm.js'
},
plugins: [
nodeResolve({
jsnext: true,
main: true
}),
commonjs(),
json(),
typescript({
rollupCommonJSResolveHack: true,
useTsconfigDeclarationDir: true
}),
vue()
]
}
this is the most problematic in rollup-plugin-vue for me, have you find a way for this issue ?
it looks like rollup-plugin-vue does not support alias resolution in style blocks... how come this is not solved yet ?
@KarlBao @r4fx after few hours of debugging, i found a fix which works.
In your rollup config, add :
-
Import the stylus node evaluator with
import { Evaluator } from 'stylus' -
Pass it along the
vueoptions with
vue({
style: {
preprocessOptions: {
stylus: { Evaluator }
}
}
}),
- Now, we can patch
Evaluatorto support alias resolution :
const visitImport = Evaluator.prototype.visitImport
Evaluator.prototype.visitImport = function(imported) {
const path = imported.path.first
if (path.string.startsWith('~'))
path.string = path.string.replace('~', '').replace('@', '/whatever-absolute-path-we-want/src')
return visitImport.call(this, imported)
}
This dirty solution works as a workaround and should definitely be addressed in other way. Although, it works cleanly enough not to relay on any dirty patch located in node_modules.
All in one place explanation :
import alias from 'rollup-plugin-alias'
import vue from 'rollup-plugin-vue'
import { Evaluator } from 'stylus'
const aliases = {
'@' : `${__dirname}/src`
}
const visitImport = Evaluator.prototype.visitImport
Evaluator.prototype.visitImport = function(imported) {
const path = imported.path.first
if (path.string.startsWith('~')) {
const alias = Object.keys(aliases).find(entry => path.string.startsWith(`~${entry}`))
if (alias)
path.string = path.string.substr(1).replace(alias, aliases[alias])
}
return visitImport.call(this, imported)
}
const plugins = [
alias(aliases),
vue({
style: {
preprocessOptions: {
stylus: { Evaluator }
}
}
}),
]
🚀
@y-nk You rock, man! It works well!