Skip to content
On this page

SFC的style块实现

虚拟模块

现在我们来处理样式部分。在vite中,可以通过导入扩展名为css的文件来加载样式。

js
import 'app.css'

我们将使用Vite的虚拟模块功能,从SFC创建虚拟CSS文件,并将其添加到输出的JS文件的import语句中。
虚拟模块听起来可能有些复杂,但你可以理解为"在内存中保存实际上不存在的文件,使其看起来像是存在的"。
在Vite中,可以使用loadresolveId选项来实现虚拟模块。

ts
export default function myPlugin() {
  const virtualModuleId = 'virtual:my-module'

  return {
    name: 'my-plugin', // 必需的,会在警告和错误中显示
    resolveId(id) {
      if (id === virtualModuleId) {
        return virtualModuleId
      }
    },
    load(id) {
      if (id === virtualModuleId) {
        return `export const msg = "from virtual module"`
      }
    },
  }
}

通过在resolveId中设置要解析的模块id,并在load中处理该id,可以加载模块。
在上面的例子中,文件virtual:my-module实际上并不存在,但是当你写:

ts
import { msg } from 'virtual:my-module'

时,会加载export const msg = "from virtual module"

参考

我们使用这个机制来加载SFC的style块作为虚拟的css文件。
正如最开始说的,在vite中只需要导入扩展名为css的文件,所以我们考虑创建一个名为${SFC文件名}.css的虚拟模块。

使用SFC样式块内容实现虚拟模块

在这个例子中,当有一个"App.vue"文件时,我们考虑将其style部分实现为一个名为"App.vue.css"的虚拟模块。
实现方法很简单,当加载**.vue.css名称的文件时,我们从去掉.css后的文件路径(即正常的Vue文件)使用fs.readFileSync获取SFC,
解析它并获取style标签的内容,然后将其作为code返回。

ts
export default function vitePluginChibivue(): Plugin {
  //  ,
  //  ,
  //  ,
  return {
    //  ,
    //  ,
    //  ,
    resolveId(id) {
      // 这个id实际上不存在,但我们在load中虚拟处理它,所以返回id(表示它可以被加载)
      if (id.match(/\.vue\.css$/)) return id

      // 对于这里没有返回的id,如果该文件实际存在,则该文件会被解析;如果不存在,则会报不存在的错误
    },
    load(id) {
      // 处理.vue.css被加载(import被声明并加载)的情况
      if (id.match(/\.vue\.css$/)) {
        const filename = id.replace(/\.css$/, '')
        const content = fs.readFileSync(filename, 'utf-8') // 正常获取SFC文件
        const { descriptor } = parse(content, { filename }) // 解析SFC

        // 将content合并为结果
        const styles = descriptor.styles.map(it => it.content).join('\n')
        return { code: styles }
      }
    },

    transform(code, id) {
      if (!filter(id)) return

      const outputs = []
      outputs.push("import * as ChibiVue from 'chibivue'")
      outputs.push(`import '${id}.css'`) // 声明${id}.css的import语句
      //  ,
      //  ,
      //  ,
    },
  }
}

现在,让我们在浏览器中检查一下。

load_virtual_css_module

看起来样式已经正确应用了。

在浏览器中,你可以看到css被导入,并且.vue.css文件被虚拟生成了。
load_virtual_css_module2
load_virtual_css_module3

现在我们可以使用SFC了!

到目前为止的源代码:
chibivue (GitHub)

Released under the MIT License. Source is chibivue-land/chibivue