一文让你彻底弄懂 “vue-style-loader” 跟 “style-loader” 区别

简介

用过 vue-cli 脚手架搭建 vue 项目都知道,vue-cli 中内置了 vue-style-loader 去加载样式模块,最后通过

很简单,就是一个简单的 vue 文件。

然后在 main.js 中引入 app.vue 文件:

import Vue from 'vue';
import App from './app.vue';
new Vue({
     
    el: '#app',
    render: (h) => h(App),
});

ok!一切准备完毕后,我们直接在工程目录运行 npm run dev 命令:

npm run dev

运行完毕后浏览器打开:
一文让你彻底弄懂 “vue-style-loader” 跟 “style-loader” 区别_第1张图片

跟不上的童鞋可以直接下载源码:https://gitee.com/vv_bug/style-loader-demo

vue-style-loader

官网地址:https://github.com/vuejs/vue-style-loader

This is a fork based on style-loader. Similar to style-loader, you can chain it after css-loader to dynamically inject CSS into the document as style tags. However, since this is included as a dependency and used by default in vue-loader, in most cases you don’t need to configure this loader yourself.

意思大概是:“基于 style-loader fork 过来的,跟 style-loader 类似。”

官网解释的还是比较敷衍的,我们结合 Demo 继续往下看。

看一下现在的设置,我们找到 webpack.config.js

const path = require('path');
const config = new (require('webpack-chain'))();
config
    .context(path.resolve(__dirname, '.')) // webpack 上下文目录为项目根目录
    .entry('app') // 入口文件名称为 app
        .add('./src/main.js') // 入口文件为 ./src/main.ts
        .end()
    .output
        .path(path.join(__dirname, './dist')) // webpack 输出的目录为根目录的 dist 目录
        .filename('[name].[hash:8].js') // 打包出来的 bundle 名称为 "[name].[hash:8].js"
        .publicPath('/') // publicpath 配置为 "/"
        .end()
    .resolve
        .extensions
            .add('.js')
            .add('.vue') // 配置以 .js 等结尾的文件当模块使用的时候都可以省略后缀
            .end()
        .end()
    .module
        .rule('vue') // vue-loader 相关配置
            .test(/\.vue$/) // 匹配 .vue 文件
            .use('vue-loader')
                .loader('vue-loader')
                .end()
            .end()
        .rule('css') // css-loader 相关配置
            .test(/\.css$/)
            .use('vue-style-loader')
                .loader('vue-style-loader')
                .end()
            .use('css-loader')
                .loader('css-loader')
                .options({
     
                    esModule: false
                })
                .end()
            .end()
        .end()
    .plugin('vue-loader-plugin') // vue-loader 必须要添加 vue-loader-plugin
        .use(require('vue-loader').VueLoaderPlugin, [])
        .end()
    .plugin('html') // 添加 html-webpack-plugin 插件
        .use(require('html-webpack-plugin'), [
            {
     
                template: path.resolve(__dirname, './public/index.html'), // 指定模版文件
                chunks: ['app'], // 指定需要加载的 chunk
                inject: 'body', // 指定 script 脚本注入的位置为 body
            },
        ])
        .end()
    .devServer
        .host('0.0.0.0') // 服务器外部可访问
        .disableHostCheck(true) // 关闭白名单校验
        .contentBase(path.resolve(__dirname, './public')) // 设置一个 express 静态目录
        .historyApiFallback({
     
            disableDotRule: true, // 禁止在链接中使用 "." 符号
            rewrites: [
                {
      from: /^\/$/, to: '/index.html' }, // 将所有的 404 响应重定向到 index.html 页面
            ],
        })
        .port(8080) // 当前端口号
        .hot(true) // 打开页面热载功能
        .sockPort('location') // 设置成平台自己的端口
        .open(true);
module.exports = config.toConfig();

再看一下现在的样式,我们找到 src/app.vue 文件:


上面的样式到底是怎样起作用的呢?

首先经过 vue-loader 处理一遍变成了这样:

.app[data-v-5ef48958] {
     
    color: red;
}

可以看到,我们样式经过 vue-loader 处理后加上了一个 “data-v-5ef48958”,这是为什么呢?因为我们在 style 标签上加了 scoped 标记:


上面的样式到底是怎样起作用的呢?

首先经过 vue-loader 处理一遍变成了这样:

.app[data-v-5ef48958] {
     
    color: red;
}

可以看到,我们样式经过 vue-loader 处理后加上了一个 “data-v-5ef48958”,这是为什么呢?因为我们在 style 标签上加了 scoped 标记: