zhangyuang / ssr

A most advanced ssr framework support React17/React18/Vue2/Vue3 on Earth that implemented serverless-side render specification.
http://doc.ssr-fc.com/
MIT License
2.61k stars 284 forks source link

vue 开启css module 的问题 #97

Closed lljj-x closed 3 years ago

lljj-x commented 3 years ago

详细描述你的问题

vue 项目开启css module后,server 端的 $style 后会加上 default ,导致在server端的渲染页面 class 挂不上去。

如下代码,在页面直出后,div 没有对应的css

<div :class="$style.box">
  <h1>index page</h1>
</div>

<style module>
  .box {
    background: red;
  }
</style>

image


在 组件created 中打印 $style 的值可以发现server 端多了一级default

/ / created 中输出 
console.log(222, JSON.stringify(this.$style))

server 端执行结果

222 {"default":{"box":"render__box___2pT2Y"}}

client 端执行结果 符合预期

222 "{\"box\":\"render__box___2pT2Y\"}"

期望的结果

server 和 client 都是不带default

当前使用的版本

5.6.4

复现仓库地址

https://github.com/lljj-x/ykssr-vue-css-module

npm install

npm run start

如下文件 /web/pages/index/render.vue,style 加了 module

你本人对问题可能的原因判断(如果你能大概判断的话)

vue loader会做一些default的操作,可能是哪里的webpack配置有关系,尝试配置 libraryTarget commonjs2 也没解决

zhangyuang commented 3 years ago

出现 default本质上是 cjs/esm 混用导致的问题。参考这篇文章 https://zhuanlan.zhihu.com/p/40733281

另外我不建议你在 vue 场景下用 css modules, style scoped 的功能已足够丰富。css modules 跟 vue 的契合度没有scoped那么优秀

如果你一定要用,我可以看看怎么配置

lljj-x commented 3 years ago

感谢回复

我们是旧项目迁移过来,所以一定会有 css modules。

webpack配置做了一些调整没解决,希望大佬帮忙看看

zhangyuang commented 3 years ago

你可以用

import style from './index.less'
created () {
this.style = style
}
<div :class="style.box">
    <h1>index page</h1>
  </div>
zhangyuang commented 3 years ago

看了一下这块 vue的源码,需要使用vue-style-loader来解决。本框架并没有使用该loader。

建议你改成标准的 import style from 'xxx' 的语法。

lljj-x commented 3 years ago

现在想法如果不通过 style-loader 处理,保持现在的 dev 也是用 minicss提取,然后 fork下 vue-loader 组件,调整为在 isServer 的时候优先取 default ,这样做有啥建议呢 ?

https://github.com/vuejs/vue-loader/blob/master/lib/codegen/styleInjection.js#L46

类似这样 isServer

styleInjectionCode += `this[${name}] = ${locals}.default || ${locals}\n`
zhangyuang commented 3 years ago

自己写loader肯定可以啊,都不用fork vue-loader 自己写一个后续的loader处理都行如果你有这个能力的话。我最近是没精力处理这种极端情况。按照标准的css modules写发来就行了

发自我的iPhone

------------------ 原始邮件 ------------------ 发件人: Liu @.> 发送时间: 2021年8月19日 10:34 收件人: ykfe/ssr @.> 抄送: yuuang @.>, Comment @.> 主题: 回复:[ykfe/ssr] vue 开启css module 的问题 (#97)

现在想法如果不通过 style-loader 处理,保持现在的 dev 也是用 minicss提取,然后 fork下 vue-loader 组件,调整为在 isServer 的时候优先取 default ,这样做有啥建议呢 ?

https://github.com/vuejs/vue-loader/blob/master/lib/codegen/styleInjection.js#L46

类似这样 isServer styleInjectionCode += this[${name}] = ${locals}.default || ${locals}\n

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

zhangyuang commented 3 years ago

fork vue-loader 改起来最快,不过会带来后续维护成本的问题emmmm

lljj-x commented 3 years ago

是的,临时先改下vue loader 设置$style 的时候处理。

然后在看加一个中间loader来做这个转换,再次感谢及时回复

baxtergu commented 3 years ago

运行时加个判断: $style?.default?.xxx || $style.xxx,改动范围大的话也可以 created() 后把 $style.default 复制一份到 VueComponent 实例上去,template 用拷贝后的这个 $style 来取值。可能会失去一些响应性,但是大部分情况都能覆盖

lljj-x commented 3 years ago

@baxtergu 考虑过运行时全局mixin统一处理。

但实际情况是代码里面有挺多 module=xxx,不知道代码可能会使用的变量哪些