webpack4 配置 ssr 环境遇到“document is not defined”

最近使用 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中会使用到document,node环境中不存在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版本比较新,周边的插件没能及时做出相应更新;

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容