webpack4+vue2.x 如何让.vue文件的style切割且以link标签引入

尝试了一下webpack+vue的方式搭建框架,发现样式(.vue中<style>内)均被以style标签的样式引入了如下:
image.png
不是说ie对style标签数量有限制吗,所以想以link的方式引入。~~~~


因为mini-css-extract-plugin能做到,但是使用它,.vue文件的style就不起作用了,所以在使用vue-style-loader的情况下如何做到切割css且以link方式引入。

百度、google无果,有没有兄弟给个解决的方向?
已解决 悬赏分:60 - 解决时间 2021-11-26 23:01
反对 0举报 0 收藏 0

回答3

最佳
  • @

    是可以的啊。

    参考CSS提取 | Vue Loader

    我的实验:

    package.json:

    {
      "name": "test",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "cross-env NODE_ENV=production webpack",
        "dev": "cross-env NODE_ENV=development webpack-dev-server"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "@babel/core": "^7.5.5",
        "@babel/preset-env": "^7.5.5",
        "babel-loader": "^8.0.6",
        "babel-plugin-transform-runtime": "^6.23.0",
        "clean-webpack-plugin": "^3.0.0",
        "cross-env": "^6.0.3",
        "css-loader": "^3.2.0",
        "html-webpack-plugin": "^3.2.0",
        "mini-css-extract-plugin": "^0.8.0",
        "vue-loader": "^15.7.1",
        "vue-style-loader": "^4.1.2",
        "vue-template-compiler": "^2.6.10",
        "webpack": "^4.39.1",
        "webpack-cli": "^3.3.6",
        "webpack-dev-server": "^3.8.0"
      },
      "dependencies": {
        "vue": "^2.6.10"
      }
    }
    

    webpack.config.js:

    const path = require('path');
    const VueLoaderPlugin = require('vue-loader/lib/plugin')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    const {CleanWebpackPlugin} = require('clean-webpack-plugin')
    
    module.exports = {
        mode: 'production',
        entry: './src/index.js',
        output: {
            filename: 'main.js',
            path: path.resolve(__dirname, 'dist')
        },
        module: {
            rules: [
                // ... 其它规则
                {
                    test: /\.vue$/,
                    loader: 'vue-loader'
                },
                // 它会应用到普通的 `.css` 文件
                // 以及 `.vue` 文件中的 `<style>` 块
                {
                    test: /\.css$/,
                    use: [
                      process.env.NODE_ENV !== 'production'
                        ? 'vue-style-loader'
                        : MiniCssExtractPlugin.loader,
                      'css-loader'
                    ]
                },
                {
                    test: /\.js$/,
                    loader: 'babel-loader'
                }
            ]
        },
        plugins: [
            new CleanWebpackPlugin(),
            // 请确保引入这个插件!
            new VueLoaderPlugin(),
            new MiniCssExtractPlugin({
                filename: 'style.css'
            }),
            new HtmlWebpackPlugin({
                filename: 'index.html',
                template: 'index.html',
                inject: true
            })
        ],
        resolve:{
            extensions:['.vue','.js'],
            alias:{
                'vue$': 'vue/dist/vue.esm.js'
            }
        },
        devServer:{
            open: true,
            host: 'localhost',
            port: 8081,
            inline: true
        }
    }

    结果

    clipboard.png

    clipboard.png

    支持 0 反对 0 举报
    2021-11-26 06:10
  • @

    请查阅vue-loader文档

    css提取

    注意vue-loader14/15差异比较大,请确定你使用的版本.

    你也可以手动提供loader给vue-loader处理vue里面的块.

    clipboard.png

    支持 0 反对 0 举报
    2021-11-26 06:27
  • @

    首先感谢你的回答

    你运行的build产生了你的结果吗,当你build时,根据你提供的代码,是没使用vue-style-loader,而是使用了三目的后者mini...,你的.vue文件的style样式是否得到了正确显示

    我的依然不行,我是yarn serve即开发模式下观察的他的引入方式,build(其他部分均做了相应改变)我也尝试过,皆无果,部分关键配置如下

    const miniLoader  = function(mode){
      const isDev = mode === 'development'
      const loader =  isDev? 'vue-style-loader' : {
        loader: miniCssExtractPlugin.loader,
        options: {
          hmr: isDev,
        }
      }
      return loader;
    }
    

    module.rules:

        {
          test: /\.s?css$/,
          //   include: path.resolve(__dirname, '../src'),
          use: [
            miniLoader(options.mode), // 'vue-style-loader',
            {
              loader: 'css-loader',
              // 注释部分1:
              // options: {
              //   modules: true,// 开启css module css文件单独打包
              //   importLoaders: 3 // 作用域@import的资源之前有多少loader
              // }
            },
            {
              loader: 'postcss-loader',
              options: {
                ident: 'postcss', // 当使用到require/function时,此(唯一)标识符被需要,任意命名
                plugins: loader => [
                  require('postcss-import')({ root: loader.resourcePath }),
                  require('autoprefixer')()
                ]
              }
            },
            'sass-loader'
          ]
        },
        ...
    

    关于vue-loder(官网) webpack4的配置我也有个疑问:难道生产环境(production)就不用vue-style-loader了吗?


    更新回答
    之前一直拘泥于在使用vue-style-loader的情况下怎么能做到样式link引入,因为之前使用miniCssExtractPlugin.loader时可以做到但.vue文件的style无效。但是就在10分钟前,这个问题莫名其妙的自己好了(build/dev),自然样式就以link标签引入了。
    ` 在结合两位答主答案和通读了vue-loader指南后,有过一些新的收获:

    • .vue文件的<style>,以及<script>内容是可以rules里面被解析的,并且还可以根据style里的lang属性做对应解析(lang="less"就使用test: /.less$/对应的loader)

    image.png

    • vue-style-loader并不是必须的,即使你是vue项目,更多`

    结合答主2说是自定义配置块可能解决,我试过(下面代码部分注释部分2),无论注释与否,vue的样式依然有效,甚至我用styel-loader取代miniCssExtractPlugin.loader(只是以style引入样式,无情!)

    下面贴我最后莫名其妙成功的代码,哈哈:

    `const miniLoader  = function(mode){
      const isDev = mode === 'development'
      const loader =  isDev ?{
        loader: miniCssExtractPlugin.loader,
        options: {
          hmr: isDev,
        }
      } : 'style-loader' 
      return loader;
    }`

    module.rules

    {
              test: /\.s?css$/,
              include: path.resolve(__dirname, '../src'),
              use: [
                miniLoader(options.mode), 
                // 'vue-style-loader',
                {
                  loader: 'css-loader',
                  // 注释部分1:
                  // options: {
                  //   modules: true,// 开启css module
                  //   importLoaders: 3, // 作用域@import的资源之前有多少loader
                  //   localIdentName: '[local]_[hash:base64:5]' // 自定义生成的类名
                  // }
                },
                {
                  loader: 'postcss-loader',//post-css在vue-loader v15x不再是默认配置
                  options: {
                    ident: 'postcss', // 当使用到require/function时,此(唯一)标识符被需要,任意命名
                    plugins: loader => [
                      require('postcss-import')({ root: loader.resourcePath }),
                      require('autoprefixer')()
                    ]
                  }
                },
                'sass-loader'
              ]
            },
    {
              test: /\.vue$/,
              loader: 'vue-loader',
              // 注释部分2
              // options: {
              //   hotReloade: false, //关闭vue文件的热重载
              //   loaders: {
              //     css: [
              //       isDev ? miniCssExtractPlugin.loader: 'style-loader',
              //       'css-loader'
              //     ],
              //     scss: [
              //       isDev ? miniCssExtractPlugin : 'style-loader',
              //       'css-loader', 'post-css-loader', 'scss-loader'
              //     ]
              //   }
              // }
            }

    至此,问题结束,谢谢参与问题的小伙伴!

    支持 0 反对 0 举报
    2021-11-26 08:02