基于Vite开发Vue应用,快别在style标签里导入css文件啦

874 阅读2分钟

前言

我们公司前端内部在开发vue形成了一个开发习惯,大家在写css的时候都会提取成单独的文件,然后再导入到需要使用这个css的文件中,但是css导入到vue文件中大体分为两种方式,一个是在style标签导入,一个是在script标签导入,下面我们就来分析下这两种导入方式的差异。

style标签导入

看一个示例,只是一个为了说明问题的示例

// 父组件 App.vue
<template>
  <div class="parent">
    Parent
    <Child  />
  </div>
</template>

<style>
@import url('@/assets/main.css');
</style>

// 子组件  Child.vue
<template>
  <div class="child">
    Child
  </div>
</template>

<style>
@import url('@/assets/main.css');
</style>

// main.css内容
.parent {
  color: red;
}
.child {
  color: green;
}

乍一看这样导入没什么问题,而且页面样式也都能正常显示。但是通过谷歌的Devtool就能看出一些端倪。

image.png

哎,奇怪怎么class类会出现了两份。

不急 咱们来分析下原因

看下App.vue最终运行被编译的内容

image.png 发现被导入的main.css被处理成了一个虚拟文件,再来看下这个文件实际返回的内容

image.png 这个文件把style标签里面导入的main.css文件处理成了一个字符串变量__vite__css,然后通过内部的__vite__updateStyle方法把这些css通过style标签的方式插入到文档中。

同理Child.vue引入的css也被同样的处理了

image.png

正因为同样的一份css被处理了两次并且都通过内部方法__vite__updateStyle把css通过style标签插入到文档中,才导致一个parent类出现了两次。 开发环境中这个类被处理了两次,最终生产环境这个类也会被处理两次,导致最终打包生成的css资源变大

image.png

说到这不得不提一嘴@vue/compiler-sfc插件在处理vue单文件组件时的基本原理,它会把一个vue文件处理成3个部分templatescriptstyle,然后分别将每个部分交给对应的预处理器处理生成纯净的css或者javascript,以后再交回给@vue/compiler-sfc统一处理

image.png

script标签导入

// 父组件 App.vue
<template>
  <div class="parent">
    Parent
    <Child  />
  </div>
</template>

<script>
import '@/assets/main.css';
</script>

// 子组件  Child.vue
<template>
  <div class="child">
    Child
  </div>
</template>

<script>
import '@/assets/main.css';
</script>

再来看看App.vue加载的css资源有什么变化

image.png

Child.vue加载的css资源

image.png

不难发现这两个文件引入的css文件地址变成了一个,那我们页面引用的css也就只有一份了,相同的类名也不会出现多个

image.png 最终构建后生成的文件也不会包含重复的css样式

image.png

总结

弄清楚这两种导入css文件的区别啦,如果不是提别需要scoped,为了降低最终构建生成的包体积,所以我们优先考虑在script标签里面导入css。