Mini-css-extract-plugin: 做 vue 服务端渲染,生产环境运行 报错 document is not defined

Created on 11 Oct 2018  ·  3Comments  ·  Source: webpack-contrib/mini-css-extract-plugin


执行 yarn run build 后运行打开网页报如下错误,
但是开发环境是正常的。

$ yarn run start
yarn run v1.9.4
$ cross-env NODE_ENV=production node server
11111 true
11111 production
[HPM] Proxy created: /buyer  ->  http://docker.guangeryi.com
[HPM] Proxy created: /file  ->  http://docker.guangeryi.com
[HPM] Proxy created: /captcha  ->  http://docker.guangeryi.com
[HPM] Proxy created: /wechatLogin  ->  http://docker.guangeryi.com
[HPM] Proxy created: /checkWechatLogin  ->  http://docker.guangeryi.com
[HPM] Proxy created: /login  ->  http://docker.guangeryi.com
server started at localhost:8087
ReferenceError: document is not defined
    at i.push.r.(anonymous function).Promise.then.r.(anonymous function) (server             -bundle.js:1:437)
    at new Promise (<anonymous>)
    at Function.t [as e] (server-bundle.js:1:375)
    at e (server-bundle.js:1:14882)
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1776:17
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1803:66
    at Array.map (<anonymous>)
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1803:38
    at Array.map (<anonymous>)
    at flatMapComponents (E:\workspace\geywrite_buyer\node_modules\vue-router\di             st\vue-router.common.js:1802:26)
error during render : /
ReferenceError: document is not defined
    at i.push.r.(anonymous function).Promise.then.r.(anonymous function) (server             -bundle.js:1:437)
    at new Promise (<anonymous>)
    at Function.t [as e] (server-bundle.js:1:375)
    at e (server-bundle.js:1:14882)
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1776:17
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1803:66
    at Array.map (<anonymous>)
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1803:38
    at Array.map (<anonymous>)
    at flatMapComponents (E:\workspace\geywrite_buyer\node_modules\vue-router\di             st\vue-router.common.js:1802:26)
ReferenceError: document is not defined
    at i.push.r.(anonymous function).Promise.then.r.(anonymous function) (server             -bundle.js:1:437)
    at new Promise (<anonymous>)
    at Function.t [as e] (server-bundle.js:1:375)
    at e (server-bundle.js:1:14882)
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1776:17
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1803:66
    at Array.map (<anonymous>)
    at E:\workspace\geywrite_buyer\node_modules\vue-router\dist\vue-router.commo             n.js:1803:38
    at Array.map (<anonymous>)
    at flatMapComponents (E:\workspace\geywrite_buyer\node_modules\vue-router\di             st\vue-router.common.js:1802:26)

下面是我的配置文件
webpack.base.config.js

var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')

const isProd = process.env.NODE_ENV === 'production'

console.log('33333333333333: ', MiniCssExtractPlugin.loader)

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

const createLintingRule = () => ({
  test: /\.(js|vue)$/,
  loader: 'eslint-loader',
  enforce: 'pre',
  include: [resolve('src'), resolve('test')],
  options: {
    formatter: require('eslint-friendly-formatter'),
    emitWarning: !config.dev.showEslintErrorsInOverlay
  }
})

const webpackConfig = {
  output: {
    path: config.build.assetsRoot,
    filename: 'js/[name].js',
    publicPath: isProd
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    modules: [
      resolve('src'),
      resolve('node_modules')
    ],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'assets': resolve('src/assets'),
      'components': resolve('src/components'),
      'router': resolve('src/router'),
      'store': resolve('src/store')
    }
  },
  module: {
    rules: [
      ...(config.dev.useEslint ? [createLintingRule()] : []),
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [
          resolve('src'),
          resolve('test'),
          resolve('node_modules/webpack-dev-server/client')
        ],
        exclude: [resolve('src/assets')]
      },
      {
        test: /\.(sa|sc|c)ss$/,
        use: [
          !isProd ? 'vue-style-loader' :  MiniCssExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'sass-loader'
        ]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        include: [resolve('static'), resolve('src')],
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      'jQuery': 'jquery',
      _: 'lodash'
    }),
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: '[name].css',
      chunkFilename: '[id].css'
    }),
    new VueLoaderPlugin()
  ],
  optimization: {
    minimizer: [
      new UglifyJsPlugin({
        uglifyOptions: {
          compress: false
        }
      })
    ]
  }
}

// if (isProd) {
//   webpackConfig.plugins.push(
//     new webpack.optimize.UglifyJsPlugin({
//       compress: { warnings: false }
//     })
//   )
// }
// if (isProd) {
//   webpackConfig.optimization.minimizer = [
//     new UglifyJsPlugin({
//       uglifyOptions: {
//           compress: false
//       }
//     })
//   ]
// }

module.exports = webpackConfig

以下是 webpack.client.config.js

const webpack = require('webpack')
const merge = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')

const config = merge(baseConfig, {
  entry: {
    app: ['normalize.css/normalize.css', 'babel-polyfill', './src/entry-client.js']
  },
  plugins: [
    // strip dev-only code in Vue source
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
      'process.env.VUE_ENV': '"client"'
    }),
    new VueSSRClientPlugin()
  ],
  optimization: {
    splitChunks: {
      chunks: 'initial',
      cacheGroups: {
        vendor: {
          chunks: 'initial',
          test: /^node_modules\/.*(?<!\.css)$/,
          name: 'vendor',
          enforce: true
        }
      }
    },
    runtimeChunk: {
      name: 'manifest'
    }
  }
})

module.exports = config

看了 https://github.com/webpack-contrib/mini-css-extract-plugin/issues/90 这个issues 但是还是不知道如何解决。

Most helpful comment

I collect a solution solving this problem
https://github.com/vuejs/vue-router/issues/2380#issuecomment-443482640
hope that helps you

All 3 comments

Please use English language

I collect a solution solving this problem
https://github.com/vuejs/vue-router/issues/2380#issuecomment-443482640
hope that helps you

use extract-css-chunks-webpack-plugin instead mini-css-extract-plugin

webpack.base.config.js

const ExtractCssChunksPlugin = require('extract-css-chunks-webpack-plugin')
{
  ...
  {
        test: /\.css$/,
        use: [
          {
            loader: ExtractCssChunksPlugin.loader,
            options: {
              hot: !isProd,
              reloadAll: !isProd
            }
          },
          'postcss-loader',
          'css-loader'
        ]
      },
      {
        test: /\.less$/,
        use: [
          {
            loader: ExtractCssChunksPlugin.loader,
            options: {
              hot: !isProd,
              reloadAll: !isProd
            }
          },
          'css-loader',
          'postcss-loader',
          'less-loader'
        ]
      }
  ...
  plugins: [
   ...
    new ExtractCssChunksPlugin({
      filename: isProd ? 'css/[name].[contenthash:8].css' : '[name].css',
      chunkFilename: isProd ? 'css/[name].[contenthash:8].chunk.css' : '[name].chunk.css'
    })
  ]
}

webpack.server.config.js

{
  ...
  plugins: [
    new webpack.optimize.LimitChunkCountPlugin({
      maxChunks: 1
    })
  ]
}

extract-css-chunks-webpack-plugin

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Legends picture Legends  ·  4Comments

TheHolyWaffle picture TheHolyWaffle  ·  4Comments

stavalfi picture stavalfi  ·  4Comments

silasFFF picture silasFFF  ·  4Comments

YanYuanFE picture YanYuanFE  ·  3Comments