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


Posted in Javascript onOctober 24, 2019

最近使用 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版本比较新,周边的插件没能及时做出相应更新;

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

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

Javascript 相关文章推荐
jquery简单体验
Jan 10 Javascript
Array, Array Constructor, for in loop, typeof, instanceOf
Sep 13 Javascript
javascript 正则表达式相关应介绍
Nov 27 Javascript
JavaScript获取当前网页标题(title)的方法
Apr 03 Javascript
详解Bootstrap的aria-label和aria-labelledby应用
Jan 04 Javascript
基于JS实现textarea中获取动态剩余字数的方法
May 25 Javascript
jQuery checkbox选中问题之prop与attr注意点分析
Nov 15 Javascript
JavaScript函数节流的两种写法
Apr 07 Javascript
yarn的使用与升级Node.js的方法详解
Jun 04 Javascript
js+html5实现手机九宫格密码解锁功能
Jul 30 Javascript
Vue 中对图片地址进行拼接的方法
Sep 03 Javascript
如何获取vue单文件自身源码路径
May 06 Javascript
vue项目使用.env文件配置全局环境变量的方法
Oct 24 #Javascript
微信小程序上传图片并等比列压缩到指定大小的实例代码
Oct 24 #Javascript
nest.js 使用express需要提供多个静态目录的操作方法
Oct 24 #Javascript
Vue 3.0双向绑定原理的实现方法
Oct 23 #Javascript
JavaScript判断数组类型的方法
Oct 23 #Javascript
Vue 2.0双向绑定原理的实现方法
Oct 23 #Javascript
p5.js绘制旋转的正方形
Oct 23 #Javascript
You might like
PHP实现通过CURL上传文件功能示例
2018/05/30 PHP
写自已的js类库需要的核心代码
2012/07/16 Javascript
javascript继承之为什么要继承
2012/11/10 Javascript
javascript中window.event事件用法详解
2012/12/11 Javascript
js实现图片轮换效果代码
2013/04/16 Javascript
一款jquery特效编写的大度宽屏焦点图切换特效的实例代码
2013/08/05 Javascript
JS实现字体选色板实例代码
2013/11/20 Javascript
javascript 用函数语句和表达式定义函数的区别详解
2014/01/06 Javascript
移动Web中图片自适应的两种JavaScript解决方法
2015/06/18 Javascript
JS+CSS实现滑动切换tab菜单效果
2015/08/25 Javascript
简单封装js的dom查询实例代码
2016/07/08 Javascript
微信公众平台开发教程(四) 实例入门:机器人回复(附源码)
2016/12/02 Javascript
利用yarn代替npm管理前端项目模块依赖的方法详解
2017/09/04 Javascript
基于js中this和event 的区别(详解)
2017/10/24 Javascript
JavaScript实现的文本框placeholder提示文字功能示例
2018/07/25 Javascript
js之切换全屏和退出全屏实现代码实例
2019/09/09 Javascript
vuejs中父子组件之间通信方法实例详解
2020/01/17 Javascript
微信小程序实现底部弹出框
2020/11/18 Javascript
[02:03]DOTA2亚洲邀请赛 HGT战队出场宣传片
2015/02/07 DOTA
[57:53]Secret vs Pain 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
Python分支语句与循环语句应用实例分析
2019/05/07 Python
Flask框架单例模式实现方法详解
2019/07/31 Python
python实现京东订单推送到测试环境,提供便利操作示例
2019/08/09 Python
基于pycharm实现批量修改变量名
2020/06/02 Python
python实现PDF中表格转化为Excel的方法
2020/06/16 Python
Django如何批量创建Model
2020/09/01 Python
Emporio Armani腕表天猫官方旗舰店:乔治·阿玛尼为年轻人设计的副线品牌
2017/07/02 全球购物
Marc Jacobs官方网站:美国奢侈品牌
2017/08/29 全球购物
LightInTheBox法国站:中国跨境电商
2020/03/05 全球购物
信用社主任竞聘演讲稿
2014/05/23 职场文书
酒店宣传语大全
2015/07/13 职场文书
公司车队管理制度
2015/08/04 职场文书
教师听课学习心得体会
2016/01/15 职场文书
高三化学教学反思
2016/02/22 职场文书
《弟子规》读后感:知廉耻、明是非、懂荣辱、辨善恶
2019/12/03 职场文书
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA