dcloudio / uni-app

A cross-platform framework using Vue.js
https://uniapp.dcloud.io
Apache License 2.0
40.17k stars 3.64k forks source link

TypeError: Cannot read properties of null (reading 'insertBefore') #3226

Closed MackJac closed 2 years ago

MackJac commented 2 years ago

问题描述 使用uniapp vue3 vite项目构建build:h5:ssr后,npm run serve调试可运行,但是跳转页面报错TypeError: Cannot read properties of null (reading 'insertBefore')

// serve.js
const fs = require('fs')
const path = require('path')
const express = require('express')

const isTest = process.env.NODE_ENV === 'test' || !!process.env.VITE_TEST_BUILD

async function createServer(
  root = process.cwd(),
  isProd = process.env.NODE_ENV === 'production'
) {
  const resolve = (p) => path.resolve(__dirname, p)

  const indexProd = isProd
    ? fs.readFileSync(resolve('dist/build/h5/client/index.html'), 'utf-8')
    : ''

  const manifest = isProd
    ? // @ts-ignore
    require('./dist/build/h5/client/ssr-manifest.json')
    : {}
  console.log(root, isProd)
  const app = express()

  /**
   * @type {import('vite').ViteDevServer}
   */
  let vite
  if (!isProd) {
    vite = await require('vite').createServer({
      root,
      logLevel: isTest ? 'error' : 'info',
      server: {
        middlewareMode: 'ssr',
        watch: {
          // During tests we edit the files too fast and sometimes chokidar
          // misses change events, so enforce polling for consistency
          usePolling: true,
          interval: 100
        }
      }
    })
    // use vite's connect instance as middleware
    app.use(vite.middlewares)
  } else {
    app.use(require('compression')())
    app.use(
      require('serve-static')(resolve('dist/build/h5/client'), {
        index: false
      })
    )
  }

  app.use('*', async (req, res) => {
    try {
      const url = req.originalUrl
      console.log(url)
      let template, render
      if (!isProd) {
        // always read fresh template in dev
        template = fs.readFileSync(resolve('index.html'), 'utf-8')
        template = await vite.transformIndexHtml(url, template)
        render = (await vite.ssrLoadModule('/src/entry-server.js')).render
      } else {
        template = indexProd
        render = require('./dist/build/h5/server/entry-server.js').render
      }
      // const [appHtml, preloadLinks] = await render(url, manifest)
      const { appHtml, preloadLinks, appContext, headMeta } = await render(url)
      const html = template
        .replace(`<!--preload-links-->`, preloadLinks)
        .replace(`<!--app-html-->`, appHtml)
        .replace(`<!--app-context-->`, appContext)
        .replace('<!--head-meta-->', headMeta)

      // const html = template
      //   .replace(`<!--preload-links-->`, preloadLinks)
      //   .replace(`<!--app-html-->`, appHtml)

      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
    } catch (e) {
      vite && vite.ssrFixStacktrace(e)
      console.log(e.stack)
      res.status(500).end(e.stack)
    }
  })

  return { app, vite }
}

if (!isTest) {
  createServer().then(({ app }) =>
    app.listen(5000, () => {
      console.log('http://localhost:5000')
    })
  )
}

exports.createServer = createServer
// package.json
{
  "name": "yiling-web-app",
  "version": "0.0.1",
  "scripts": {
    "dev": "npm run dev:h5",
    "build": "npm run build:h5",
    "serve": "cross-env NODE_ENV=production node serve",
    "dev:app": "uni -p app --mode development",
    "dev:custom": "uni -p --mode development",
    "dev:h5": "uni --mode development",
    "dev:h5:ssr": "uni --ssr --mode development",
    "dev:mp-alipay": "uni -p mp-alipay --mode development",
    "dev:mp-baidu": "uni -p mp-baidu --mode development",
    "dev:mp-kuaishou": "uni -p mp-kuaishou --mode development",
    "dev:mp-lark": "uni -p mp-lark --mode development",
    "dev:mp-qq": "uni -p mp-qq --mode development",
    "dev:mp-toutiao": "uni -p mp-toutiao --mode development",
    "dev:mp-weixin": "uni -p mp-weixin --mode development",
    "dev:quickapp-webview": "uni -p quickapp-webview --mode development",
    "dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei --mode development",
    "dev:quickapp-webview-union": "uni -p quickapp-webview-union --mode development",
    "build:app": "uni build -p app --mode production",
    "build:custom": "uni build -p --mode production",
    "build:h5": "node compileRoute.js h5 && uni build --mode production",
    "build:h5:ssr": "node compileRoute.js h5 && uni build --ssr --mode production",
    "build:mp-alipay": "node compileRoute.js h5 && uni build -p mp-alipay --mode production",
    "build:mp-baidu": "node compileRoute.js mp-alipay && uni build -p mp-baidu --mode production",
    "build:mp-kuaishou": "node compileRoute.js mp-kuaishou && uni build -p mp-kuaishou --mode production",
    "build:mp-lark": "node compileRoute.js mp-lark && uni build -p mp-lark --mode production",
    "build:mp-qq": "node compileRoute.js mp-qq && uni build -p mp-qq --mode production",
    "build:mp-toutiao": "node compileRoute.js mp-toutiao && uni build -p mp-toutiao --mode production",
    "build:mp-weixin": "node compileRoute.js mp-weixin && uni build -p mp-weixin --mode production",
    "build:quickapp-webview": "node compileRoute.js quickapp-webview && uni build -p quickapp-webview --mode production",
    "build:quickapp-webview-huawei": "node compileRoute.js quickapp-webview-huawei && uni build -p quickapp-webview-huawei --mode production",
    "build:quickapp-webview-union": "node compileRoute.js quickapp-webview-union && uni build -p quickapp-webview-union --mode production",
    "route-watch": "nodemon --watch src/router compileRoute.js"
  },
  "dependencies": {
    "@dcloudio/uni-app": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-app-plus": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-components": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-h5": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-mp-alipay": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-mp-baidu": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-mp-kuaishou": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-mp-lark": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-mp-qq": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-mp-toutiao": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-mp-weixin": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-quickapp-webview": "3.0.0-alpha-3030820220114004",
    "vue": "^3.2.27",
    "vue-i18n": "9.1.9",
    "vuex": "^4.0.2"
  },
  "devDependencies": {
    "@dcloudio/types": "^2.5.15",
    "@dcloudio/uni-automator": "3.0.0-alpha-3030820220114004",
    "@dcloudio/uni-cli-shared": "3.0.0-alpha-3030820220114004",
    "@dcloudio/vite-plugin-uni": "3.0.0-alpha-3030820220114004",
    "@xianzhengquan/postcss-px-2-vw": "0.0.1",
    "autoprefixer": "^10.4.0",
    "compression": "^1.7.4",
    "cross-env": "^7.0.3",
    "node-sass": "^7.0.1",
    "nodemon": "^2.0.15",
    "sass": "^1.48.0",
    "sass-loader": "^12.4.0",
    "serve-static": "^1.14.1",
    "vite": "^2.7.7"
  },
  "browserslist": [
    "Android >= 4.4",
    "ios >= 9"
  ]
}

复现步骤 [复现问题的步骤]

  1. npm run build:h5:ssr
  2. npm run serve
  3. 跳转页面报错

实际结果 TypeError: Cannot read properties of null (reading 'insertBefore')

补充信息 查看@dcloudio/uni-h5有以下代码,不知道是否因为这个 insertBefore(blot, ref2) { if (blot instanceof ListItem) { super.insertBefore(blot, ref2); } else { const index2 = ref2 == null ? this.length() : ref2.offset(this); const after = this.split(index2); after.parent.insertBefore(blot, after); } }

fxy060608 commented 2 years ago

发测试工程

MackJac commented 2 years ago

发测试工程

https://gitee.com/mymjc/uniapp-vue3-demo.git

fxy060608 commented 2 years ago
  1. serve.js 顶部补充 require('module-alias/register')
  2. package.json 中增加 module-alias 依赖以及
    "_moduleAliases": {
        "vue": "node_modules/@dcloudio/uni-h5-vue",
        "vue/server-renderer": "node_modules/@vue/server-renderer"
    },