webpack-4-配置-ssr-环境遇到document-is-not-defined

3次阅读

共计 2876 个字符,预计需要花费 8 分钟才能阅读完成。

最近使用 webpack 4 配置 ssr 环境,发现的问题:

ReferenceError: document is not defined

本次 package.json 使用版本信息:

{
    "vue-loader": "^15.4.2",
    "mini-css-extract-plugin": "^0.4.3",
    "webpack": "^4.20.2",
    "webpack-cli": "^3.1.2"
    ...
}

相关代码

问题原因:

在服务端渲染打包的配置中使用了 mini-css-extract-plugin 是的 server bundle 中会使用到 documentnode 环境中不存在 window 对象,所以报错。

解决办法:

  • webpack.base.config.js 中不配置样式相关的loader
# 基本配置
const path = require('path')
const webpack = require('webpack')
const {VueLoaderPlugin} = require('vue-loader')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

const resolve = dir => path.join(__dirname, '../', dir)
const isProd = process.env.NODE_ENV === 'production'

const base = {
  mode: isProd ? 'production' : 'development',
  devtool: isProd ? false : 'cheap-eval-source-map',
  output: {path: path.resolve(__dirname, '../dist'),
    publicPath: '/dist/',
    filename: '[name].[chunkhash].js'
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      'public': path.resolve(__dirname, '../public')
    }
  },
  module: {
    noParse: /es6-promise\.js$/, // avoid webpack shimming process
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        include: resolve("src")
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: file => (/node_modules/.test(file) && !/\.vue\.js/.test(file)
        )
      },
      {test: /\.(png|jpg|gif|svg)$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  plugins: setPlugin()}

function setPlugin() {const base = [new VueLoaderPlugin()]
  const dev = [new FriendlyErrorsPlugin()]
  const prod = []
  return base.concat(isProd ? prod : dev)
}

module.exports = base;
  • webpack.client.config.js 中使用mini-css-extract-plugin
# 只展示先关配置
const webpack = require('webpack')
const merge = require('webpack-merge')
const base = require('./webpack.base.config')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')

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

const config = merge(base, {
  module: {
    rules: [
      {test: /\.styl(us)?$/,
        use: [
          isProd ? MiniCssExtractPlugin.loader : 'vue-style-loader',
          {loader: 'css-loader'},
          'stylus-loader'
        ],
      },
      {test: /\.(le|c)ss$/,
        use: [
          isProd ? MiniCssExtractPlugin.loader : 'vue-style-loader',
          {loader: 'css-loader'},
          'less-loader',
        ],
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({filename: isProd ? '[name].[chunkhash].css' : '[name].css',
      chunkFilename: isProd ?  '[id].[chunkhash].css': '[id].css',
    }),
    new VueSSRClientPlugin()]
})

module.exports = config
  • webpack.server.config.js 中不使用mini-css-extract-plugin
# 只展示先关配置
const webpack = require('webpack')
const merge = require('webpack-merge')
const base = require('./webpack.base.config')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')

module.exports = merge(base, {
  target: 'node',
  module: {
    rules: [
      {test: /\.styl(us)?$/,
        use: [
          'vue-style-loader',
          {loader: 'css-loader'},
          'stylus-loader'
        ],
      },
      {test: /\.(le|c)ss$/,
        use: [
          'vue-style-loader',
          {loader: 'css-loader'},
          'less-loader',
        ],
      }
    ]
  },
  plugins: [new VueSSRServerPlugin()
  ]
})
参考 Demo:

tiodot/vnews

相关 issues:

vue-loader@15.0.0-rc.1 in a server bundle
webpack-contrib/mini-css-extract-plugin

结语:

由于本次 webpack4 版本比较新,周边的插件没能及时做出相应更新;

相信经过社区的不断努力,整个生态会更加健壮。

正文完
 0