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无果,有没有兄弟给个解决的方向?
阅读 4.3k
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

请查阅vue-loader文档

css提取

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

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

clipboard.png

首先感谢你的回答

你运行的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'
          //     ]
          //   }
          // }
        }

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

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题