vue-hackernews-2.0 升级到 webpack4 和 nodejs14 的坑(上)

概述

最近非常想做一个服务端渲染项目,那就打算从尤大的vue-hackernews-2.0开始入手呗。其实我之前试图改造过这个项目,但是因为当时很菜所以失败了。现在我觉得有能力改造好,那就开始呗。把心得记录下来,供以后开发时参考,相信对其他人也有用。

mode

webpack4带来的第一个大变化就是增加了mode字段来区分生产环境还是开发环境,所以我们到webpack.base.config.js里面去增加mode字段:

mode: isProd ? 'production' : 'development',

package.json

老项目的依赖如下:

"dependencies": {
    "compression": "^1.7.1",
    "cross-env": "^5.1.1",
    "es6-promise": "^4.1.1",
    "express": "^4.16.2",
    "extract-text-webpack-plugin": "^3.0.2",
    "firebase": "4.6.2",
    "lru-cache": "^4.1.1",
    "route-cache": "0.4.3",
    "serve-favicon": "^2.4.5",
    "vue": "^2.5.22",
    "vue-router": "^3.0.1",
    "vue-server-renderer": "^2.5.22",
    "vuex": "^3.0.1",
    "vuex-router-sync": "^5.0.0"
},
"devDependencies": {
    "autoprefixer": "^7.1.6",
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-preset-env": "^1.6.1",
    "chokidar": "^1.7.0",
    "css-loader": "^0.28.7",
    "file-loader": "^1.1.5",
    "friendly-errors-webpack-plugin": "^1.6.1",
    "extract-text-webpack-plugin": "^3.0.2",
    "rimraf": "^2.6.2",
    "stylus": "^0.54.5",
    "stylus-loader": "^3.0.1",
    "sw-precache-webpack-plugin": "^0.11.4",
    "url-loader": "^0.6.2",
    "vue-loader": "^15.3.0",
    "vue-template-compiler": "^2.5.22",
    "webpack": "^3.8.1",
    "webpack-dev-middleware": "^1.12.0",
    "webpack-hot-middleware": "^2.20.0",
    "webpack-merge": "^4.2.1",
    "webpack-node-externals": "^1.7.2"
}

我们删除一下插件,用更新的插件来代替他:

// 删除
"babel-core": "^6.26.0",
"extract-text-webpack-plugin": "^3.0.2",

// 添加
"@babel/cli": "^7.11.6",
"@babel/core": "^7.11.6",
"@babel/preset-env": "^7.11.5",
"mini-css-extract-plugin": "^1.0.0",

// webpack4 需要安装 webpack-cli
"webpack-cli": "^3.3.12",

然后重新安装所有其它依赖,让它们达到最新版本。

firebase

尤大的这个项目是使用 firebase 来获取 hackernews 的数据的,我本来想用 axios 取代的,但是我去看了一下hackernews 的 api之后发现,尤大的 firebase 的写法只需要少量代码就能够获取全部数据,如果使用 axios 的话,就需要先去请求一个总接口获取文章 id,然后再用这些 id 去一篇篇获取每篇文章的数据,非常麻烦,所以这里就没有升级到 axios。

另外,我去看了一下最新版本的 firebase 的 api,发现使用方法和尤大那个版本的使用方法是一样的,所以这里只需要升级 firebase 到最新版本即可。

lru-cache

lru-cache 升级到最新版本之后需要使用 new 语法:

// 旧的语法
api.cachedItems = LRU({
    max: 1000,
    maxAge: 1000 * 60 * 15 // 15 min cache
})

// 新的语法
api.cachedItems = new LRU({
    max: 1000,
    maxAge: 1000 * 60 * 15 // 15 min cache
})

babel

老项目使用的 babel-core 现在已经不建议使用了,用@babel/preset-env替代,然后在 babel-loader 的 presets 里面加入@babel/preset-env

{
    test: /.js$/,
    loader: 'babel-loader',
    exclude: /node_modules/,
    options: {
        presets: ['@babel/preset-env']
    }
}

css

webpack4 摈弃了 extract-text-webpack-plugin 而使用新的 mini-css-extract-plugin 插件,我们注释掉上一个插件的代码,然后使用新的 mini-css-extract-plugin 插件。

但是这个插件有一个问题,就是它在 extract css 文件的时候会使用 document 方法,从而导致 ssr 的服务端打包的时候会报document is not defined的错误,具体可以看这里

解决方案推荐使用 null-loader,原理是在服务端打包的时候,不处理 css,这就要求客户端和服务端使用不同的配置,代码如下:

// webpack.client.config.js
module: {
    rules: [
      {
        test: /.styl(us)?$/,
        use: [
          isProd ? {
            loader: MiniCssExtractPlugin.loader,
            options: {
              esModule: false,
            },
          } : 'vue-style-loader',
          {
            loader: 'css-loader',
            options: {
              esModule: false,
            }
          },
          'stylus-loader'
        ],
      },
    ],
}
plugins: [
    new MiniCssExtractPlugin({
      filename: 'common.[chunkhash].css'
    }),
]

// webpack.server.config.js
module: {
    rules: [
      {
        test: /.styl(us)?$/,
        use: 'null-loader'
      }
    ]
},

由于此项目是使用 stylus 的,所以如果使用 scss 等的话可以类似处理。

原文地址:https://www.cnblogs.com/yangzhou33/p/13800189.html