likes
comments
collection
share

link和@import加载CSS文件的区别

作者站长头像
站长
· 阅读数 7

CSS @import

  • @import 用于从其他样式表导入样式规则
  • @import 必须在CSS文档的头部,但可以在@charset规则后面
  • @import 不是一个嵌套语句,不能在条件组的规则中使用
  • @import 支持媒介查询

link和@import的区别

  • 差别1:老祖宗的差别。link属于XHTML标签,而@import完全是CSS提供的一种方式。

link标签除了可以加载CSS外,还可以做很多其它的事情,比如定义RSS,定义rel连接属性等,@import就只能加载CSS了。

  • 差别2:加载顺序的差别。

当在外联css文件A中使用@import引用另一个css文件B时,只有等css文件 A下载完解析时,浏览器才知道还有css文件B需要下载,此时css文件A和css文件B是串行加载的。 如果css文件A和css文件B都是通过link加载,则是并行的。

  • 差别3:兼容性的差别。

由于@import是CSS2.1提出的所以老的浏览器不支持,@import只有在IE5以上的才能识别,而link标签无此问题。

  • 差别4:使用dom控制样式时的差别。

我们可以通过js创建一个link标签,然后加载一个css文件。从而改变某一个dom的样式。而js是无法控制@import的。

        let link = document.createElement('link')
        link.href = './link.css'
        link.rel = 'stylesheet'
        document.body.append(link)

不建议使用@import

之所以要把这个删除掉:因为现在大多数项目都会经过webpack、vite这些工具进行打包。打包后@import可能也就被替换掉了,也就不存在下面那些问题了。

webpack通过css-loader对@import的默认处理

webpack + css-loader 测试:

  1. 安装css-loader、style-loader
  2. 配置webpack.config.js文件
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    module: {
      rules: [
        {
          test: /\.css$/i,
          use: ['style-loader', 'css-loader'],
        },
      ],
    },
    optimization: {
      runtimeChunk: 'single',   
    },
 };
  
  1. 在根目录下创建src文件夹
  2. src文件夹下新建index.js文件,在该文件中引用css文件
import css from './link.css';

  1. 在src文件夹下新建link.css文件
@import url(@import.css);
        .box {
            width: 400px;
            height: 400px;
            background-color: aqua;
        }
  1. 在src文件夹下新建@import.css文件
.box {
    width: 100px;
    height: 100px;
    background-color: green;
}
  1. 执行webpack,打包后的结果文件内容如下

webpack 将@import 转化为自定义的__webpack_require__方法导入

"use strict";
(self["webpackChunkcss_loader"] = self["webpackChunkcss_loader"] || []).push([[792],{

/***/ 943:
/***/ ((module, __webpack_exports__, __webpack_require__) => {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(236);
/* harmony import */ var WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(517);
/* harmony import */ var WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(WEBPACK_IMPORTED_MODULE_1__);
// Imports


var ___CSS_LOADER_EXPORT___ = WEBPACK_IMPORTED_MODULE_1___default()((WEBPACK_IMPORTED_MODULE_0___default()));
// Module
___CSS_LOADER_EXPORT___.push([module.id, `.box {
    width: 100px;
    height: 100px;
    background-color: green;
}`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);


/***/ }),

/***/ 638:
/***/ ((module, __webpack_exports__, __webpack_require__) => {

/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   A: () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(236);
/* harmony import */ var WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(517);
/* harmony import */ var WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(943); 
//link.css文件通过@import引用@import.css文件转化为了webpack自定义的导入方法__webpack_require__
// Imports



var ___CSS_LOADER_EXPORT___ = _node_modules_pnpm_css_loader_7_1_1_webpack_5_91_0_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_pnpm_css_loader_7_1_1_webpack_5_91_0_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));
___CSS_LOADER_EXPORT___.i(_node_modules_pnpm_css_loader_7_1_1_webpack_5_91_0_node_modules_css_loader_dist_cjs_js_import_css__WEBPACK_IMPORTED_MODULE_2__/* ["default"] */ .A);
// Module
___CSS_LOADER_EXPORT___.push([module.id, `.box {
            width: 400px;
            height: 400px;
            background-color: aqua;
        }`, ""]);
// Exports
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);


/***/ }),

webpack还可以通过插件mini-css-extract-plugin将css提取到单独文件中

webpack + css-loader + mini-css-extract-plugin测试

  1. webpack配置文件如下:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");


module.exports = {
    module: {
      rules: [
        {
          test: /\.css$/i,
          use: [MiniCssExtractPlugin.loader, 'css-loader'],
        },
      ],
    },
    plugins: [
      new HtmlWebpackPlugin(),
      new MiniCssExtractPlugin()
    ],
    optimization: {
      runtimeChunk: 'single',   
      minimize: false
    },

  };
  
  1. webpack打包后结果文件内容如下:

link和@import加载CSS文件的区别

在vite中会默认通过posscss-import对@import进行处理:

link和@import加载CSS文件的区别

postcss-import测试:

待转换的css文件:

@import url(@import.css);
        .box {
            width: 400px;
            height: 400px;
            background-color: aqua;
        }

postcss-import官方例子

// dependencies
const fs = require("fs")
const postcss = require("postcss")
const atImport = require("postcss-import")

// css to be processed
const css = fs.readFileSync("./link.css", "utf8")

// process css
postcss()
  .use(atImport())
  .process(css, {
    // `from` option is needed here
    from: "link.css"
  })
  .then((result) => {
    const output = result.css

    console.log(output)
  })

执行后的输出结果:

link和@import加载CSS文件的区别

Vite+Vue3项目的一个例子:

  • 在某一个Vue3+Vite项目的子组件中编写如下css代码:

HelloWorld.vue

<style scoped>
@import url(./HelloWorld.css);
.box {
  line-height: 100px;
  color: #fff;
}
</style>

HelloWorld.css

.box {
    width: auto;
    height: 200px;
    background-color: red;
}
  • 默认情况下vite的处理结果为:

link和@import加载CSS文件的区别

  • 原因一:使用@import引入的CSS会影响浏览器的并行下载

使用@import引用的CSS文件只有在引入它的那个CSS文件被下载、解析之后,浏览器才会知道还有另外一个CSS需要下载,这时才会去下载,然后下载后开始解析、构建render tree等一系列操作。这就导致了浏览器无法并行下载所需的样式文件。

案例A:在css文件中@import另一个css文件, 串行加载

link.css

@import url(./@import.css);
.box {
    width: 200px;
    height: 300px;
    background-color: red;
}

@import.css

.box {
    width: 100px;
    height: 100px;
    background-color: green;
}

link和@import加载CSS文件的区别

案例B:2个css文件都使用link加载,并行加载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="./@import.css" rel="stylesheet" />
    <link  href="./link.css" rel="stylesheet" />
</head>
<body>
    <div class="box"></div>
</body>
</html>

link和@import加载CSS文件的区别

  • 原因2: @import 是 CSS2.1 才出现的概念,所以如果浏览器版本较低,无法正确导入外部样式文件。