angular - ReferenceError:未定义 HTMLVideoElement
问题描述
尝试为 SSR 构建 Angular 9 Universal 项目时出现此错误:
/Users/my-project/dist/server.js:28676
Object(tslib__WEBPACK_IMPORTED_MODULE_0__["__metadata"])("design:type", HTMLVideoElement)
ReferenceError: HTMLVideoElement is not defined
我在我的项目中使用mat-video播放器,我怀疑这是导致错误的原因,但我不确定如何解决这个问题。有任何想法吗?
我的tsconfig.json:
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"baseUrl": "src",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2017",
"dom"
],
"module": "esnext",
"resolveJsonModule": true,
}
}
解决方案
我终于让它工作了!1周后!
我有同样的问题:
HTMLVideoElement 未定义
尽管环境与 OP 提供的环境不同,但解决方案是相同的,以避免执行 HTMLVideoElement 代码。
我将 pixi.js 与 Angular Universal 一起用于服务器端渲染 (SSR)。
ng add @nguniversal/express-engine
我按照https://angular.io/guide/universal上的文档运行,在我的 Angular 应用程序中设置 SSR
我通过避免导致问题的 pixi.js 代码解决了这个问题。即:
PIXI.Texture.from('assets/image.png');
此调用在此处的函数签名中引用 HTMLVideoElement ... https://pixijs.download/dev/docs/PIXI.Texture.html#from
我改用 PIXI.Loader() 来加载纹理:
this.loader = new PIXI.Loader()
this.texturesArray.forEach((texture: string) => this.loader.add(texture))
this.loader.onComplete.add(this.onTexturesLoaded)
this.loader.load()
问题消失了,现在我的服务器启动正常。
我还必须通过添加属性来更改 tsconfig.server.json 中的“compilerOptions”:
"module": "commonjs"
这是我为任何感兴趣的人提供的最终工作 server.ts 代码:
import 'zone.js/dist/zone-node'
import { ngExpressEngine } from '@nguniversal/express-engine'
import express from 'express'
import { join } from 'path'
import { APP_BASE_HREF } from '@angular/common'
import { existsSync } from 'fs'
import { cloneDeep } from 'lodash-es'
import { mockCanvas } from './mock-canvas'
const fs = require('fs')
const path = require('path')
const filename = path.join(__dirname, '../browser', 'index.html')
const template = fs.readFileSync(filename).toString()
const domino = require('domino')
const win = domino.createWindow(template)
win.HTMLCanvasElement.prototype = cloneDeep(win.HTMLCanvasElement.prototype)
mockCanvas(win)
global['window'] = win
global['document'] = win.document
import { AppServerModule } from './src/main.server'
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express()
const distFolder = join(process.cwd(), 'dist/gematriangle/browser')
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index'
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule
}))
server.set('view engine', 'html')
server.set('views', distFolder)
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}))
// All regular routes use the Universal engine
server.get('*', (req: any, res: any) => {
res.render(indexHtml, {req, providers: [{provide: APP_BASE_HREF, useValue: req.baseUrl}]})
})
return server
}
function run(): void {
const port = process.env.PORT || 4000
// Start up the Node server
const server = app()
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`)
})
}
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire
const mainModule = __non_webpack_require__.main
const moduleFilename = mainModule && mainModule.filename || ''
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run()
}
export * from './src/main.server'
和 PIXI 也需要的 mockCanvas 看起来像这样:
export function mockCanvas(window: any) {
window.HTMLCanvasElement.prototype.getContext = function() {
return {
fillRect: function() {},
clearRect: function() {},
getImageData: function(x: any, y: any, w: any, h: any) {
return {
data: new Array(w * h * 4)
}
},
putImageData: function() {},
createImageData: function(): any { return []},
setTransform: function() {},
drawImage: function() {},
save: function() {},
fillText: function() {},
restore: function() {},
beginPath: function() {},
moveTo: function() {},
lineTo: function() {},
closePath: function() {},
stroke: function() {},
translate: function() {},
scale: function() {},
rotate: function() {},
arc: function() {},
fill: function() {},
measureText: function() {
return {width: 0}
},
transform: function() {},
rect: function() {},
clip: function() {}
}
}
window.HTMLCanvasElement.prototype.toDataURL = function() {
return ''
}
}
推荐阅读
- reactjs - 无法安装反应加载骨架
- sql - 从开始和结束 unixtimestamps 创建一个日期列并链接到其他数据
- python - 不通过 pyodbc 中的 sp_detach_db 分离数据库
- python - 将输出解析为数据框
- c# - 如何将连接字符串存储在微服务的中心位置
- ssh - 可以在不使用 SSH 的情况下重新启动 SSH 吗?
- ffmpeg - Pro ffmpeg 加入我
- django - Django部署加载资源失败:服务器响应状态为404(未找到)
- reactjs - 为什么它一直告诉我有一个循环错误?
- java - Replacing same type of value for different keys in json