使用 ExtractTextPlugin 时 Vue 中的范围 CSS 丢失范围

Scoped CSS in Vue losing scope when using ExtractTextPlugin

示例 Vue 代码(正在开发中):

<template lang="pug">
  .wrapper
</template>

<style lang="stylus" scoped>
  .wrapper
    min-height: 100vh
    display: flex
    justify-content: center
    align-items: center
    flex-wrap: wrap
    text-align: center
</style>

在开发中这完全符合预期;由于 data-v-XXX 属性,此特定模板中只有 .wrapper 应用了样式。

在使用提取文本插件的生产环境中,生成的样式是无范围的。它完全没有关键的 data-v-XXX 属性。

我的webpack.production.config.js:

'use strict'

const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const autoprefixer = require('autoprefixer')
const rupture = require('rupture')

if (!process.env.NODE_ENV) process.env.NODE_ENV === 'production'

module.exports = {
  context: __dirname,
  entry: './app/src/client.js',
  output: {
    path: __dirname + '/app/static/dist',
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['.js', '.vue', '.pug', '.styl']
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.DefinePlugin({
      DEVMODE: process.env.NODE_ENV === 'development'
    }),
    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin(),
    new webpack.optimize.AggressiveMergingPlugin(),
    new ExtractTextPlugin('style.css'),
    // This is until these loaders are updated for the new config system
    new webpack.LoaderOptionsPlugin({
      options: {
        // Enables this workaround setup to work
        context: __dirname,
        // Actual options
        postcss: () => [
          autoprefixer({
            browsers: ['last 3 versions', 'ie >= 9']
          })
        ],
        stylus: {
          use: [rupture()]
        }
      }
    })
  ],
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      },
      {
        test: /\.vue$/,
        loader: 'vue',
        options: {
          loaders: {
            css: ExtractTextPlugin.extract({
              loader: 'css',
              fallbackLoader: 'vue-style'
            }),
            stylus: ExtractTextPlugin.extract({
              loader: [
                'css?-autoprefixer', // Disable css-loader's internal autoprefixer
                'csso',
                'postcss',
                'stylus'
              ],
              fallbackLoader: 'vue-style'
            })
          }
        }
      },
      {
        test: /\.pug$/,
        loader: 'pug'
      },
      {
        test: /\.styl$/,
        loader: ExtractTextPlugin.extract({
          loader: [
            'css?-autoprefixer', // Disable css-loader's internal autoprefixer
            'csso',
            'postcss',
            'stylus'
          ],
          fallbackLoader: 'style'
        })
      }
    ]
  }
}

我的开发配置与提取文本插件几乎相同。

非常感谢任何帮助,谢谢!

事实证明,在由 vue-router 加载的 routes.js 中具有动态要求是一个很大的禁忌。

改变了这个:

const view = fileName => require(`./components/pages/${fileName}`)

export default [
  {
    path: '/',
    redirect: {
      name: 'intro'
    }
  },
  {
    path: '/intro',
    name: 'intro',
    component: view('Intro')
  },
  {
    path: '/form',
    name: 'form',
    component: view('Form')
  },
  // Backup catch-all route 404
  {
    path: '*',
    component: view('404')
  }
]

为此:

export default [
  {
    path: '/',
    redirect: {
      name: 'intro'
    }
  },
  {
    path: '/intro',
    name: 'intro',
    component: require('./components/pages/Intro')
  },
  {
    path: '/form',
    name: 'form',
    component: require('./components/pages/Form')
  },
  // Backup catch-all route 404
  {
    path: '*',
    component: require('./components/pages/404')
  }
]

我想这是有道理的,因为我相信 Webpack 会静态分析上下文的需求。