我试图通过一些第三方库在angular 9项目上设置SSR,但没有成功。
错误下方
ReferenceError: window is not defined
at ./node_modules/intl-tel-input/build/js/intlTelInput.js (main.js:295050:32)
at Object../node_modules/intl-tel-input/build/js/intlTelInput.js (main.js:295052:3)
at __webpack_require__ (main.js:20:30)
at Object../node_modules/intl-tel-input/index.js (main.js:296381:18)
at __webpack_require__ (main.js:20:30)
at Module../node_modules/intl-tel-input-ng/__ivy_ngcc__/fesm2015/intl-tel-input-ng.js (main.js:294832:72)
at __webpack_require__ (main.js:20:30)
at Object.. main.js:463107:29)
at __webpack_require__ (main.js:20:30)
at Object.. main.js:462977:33)
A server error has occurred.
node exited with 1 code.
connect ECONNREFUSED 127.0.0.1:50362
我无法访问服务器端的窗口对象,这很正常,因此为避免此错误,我正在检查平台并在需要intl-tel-input lib的组件中使用条件逻辑...没有成功。
如何在SSR期间修复窗口,导航器,文档错误?
package.json文件下方
{
"name": "dz",
"version": "0.0.0",
"scripts": {
"compile:server_bak": "webpack --mode production --config webpack.server.config.js --progress --colors",
"build:ssr_bak": "npm run build:client-and-server-bundles && npm run compile:server",
"serve:ssr_bak": "node dist/server",
"build:client-and-server-bundles_bak": "npm run build-prod && ng run dz:server:production",
"dev:ssr": "ng run dz:serve-ssr",
"serve:ssr": "node dist/server/main.js",
"build:ssr": "ng build --prod && ng run dz:server:production",
"prerender": "ng run dz:prerender"
},
"private": true,
"dependencies": {
"@angular/animations": "^9.0.0",
"@angular/cdk": "^9.0.0",
"@angular/common": "^9.0.0",
"@angular/compiler": "^9.0.0",
"@angular/core": "^9.0.0",
"@angular/forms": "^9.0.0",
"@angular/google-maps": "^9.0.0-rc.0",
"@angular/localize": "^9.0.0-next.5",
"@angular/material": "^9.0.0",
"@angular/platform-browser": "^9.0.0",
"@angular/platform-browser-dynamic": "^9.0.0",
"@angular/platform-server": "^9.0.0",
"@angular/pwa": "^0.803.23",
"@angular/router": "^9.0.0",
"@angular/service-worker": "^9.0.0",
"@kolkov/angular-editor": "^1.0.3",
"@ng-bootstrap/ng-bootstrap": "^5.2.1",
"@ng-toolkit/universal": "^8.0.3",
"@nguniversal/common": "~9.0.0",
"@nguniversal/express-engine": "^9.0.0",
"@ngx-translate/core": "^11.0.1",
"@ngx-translate/http-loader": "^4.0.0",
"@nicky-lenaers/ngx-scroll-to": "^3.0.1",
"@sentry/browser": "^5.11.1",
"@smip/ngx-materialize": "^0.3.0",
"@swimlane/ngx-charts": "^13.0.2",
"@trilon/ng-universal": "^2.1.0",
"@types/express": "^4.17.1",
"@types/lodash": "^4.14.141",
"acorn": "^7.1.0",
"angular-calendar": "0.27.9",
"angular-in-memory-web-api": "~0.9.0",
"angular-resizable-element": "^3.3.0",
"angular2-image-upload": "1.0.0-rc.2",
"body-parser": "^1.19.0",
"bootstrap": "^4.4.1",
"calendar-utils": "0.7.0",
"cookie-parser": "^1.4.4",
"cookieconsent": "^3.1.1",
"core-js": "^3.6.4",
"cors": "~2.8.5",
"date-fns": "^1.30.1",
"domino": "^2.1.4",
"express": "^4.17.1",
"express-http-proxy": "^1.6.0",
"font-awesome": "^4.7.0",
"google-libphonenumber": "^3.2.6",
"gzip-all": "^1.0.0",
"imagesloaded": "^4.1.4",
"intersection-observer": "^0.7.0",
"intl-tel-input": "16.0.10",
"intl-tel-input-ng": "0.1.0",
"materialize-css": "^1.0.0",
"mock-browser": "^0.92.14",
"moment": "^2.24.0",
"ng2-sticky-kit": "^6.1.0",
"ngx-cookieconsent": "^2.2.3",
"ngx-google-places-autocomplete": "^2.0.4",
"ngx-lightbox": "^2.1.0",
"ngx-moment": "^3.5.0",
"ngx-pagination": "5.0.0",
"ngx-progressbar": "^6.0.1",
"ngx-quicklink": "^0.2.0",
"ngx-scrollspy": "^1.2.1",
"path": "^0.12.7",
"popper.js": "^1.16.1",
"positioning": "1.4.0",
"preboot": "^7.0.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^6.5.4",
"rxjs-compat": "^6.5.4",
"sweetalert2": "^9.7.0",
"ts-helpers": "^1.1.2",
"tslib": "^1.10.0",
"typings": "^2.1.1",
"webpack": "^4.41.5",
"workbox-sw": "^4.3.1",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/architect": "^0.900.1",
"@angular-devkit/build-angular": "^0.900.1",
"@angular/cli": "^9.0.1",
"@angular/compiler-cli": "^9.0.0",
"@angular/language-service": "^9.0.0",
"@types/jasminewd2": "~2.0.6",
"@types/jquery": "^3.2.12",
"firebase-tools": "^6.10.0",
"fuzzy": "^0.1.3",
"http-server": "^0.11.1",
"inquirer": "^6.2.2",
"inquirer-autocomplete-prompt": "^1.0.1",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~4.2.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.5.1",
"protractor": "~6.0.0",
"ts-loader": "^5.4.5",
"@nguniversal/builders": "^9.0.0",
"@types/express": "^4.17.0",
"@types/node": "^12.11.1",
"@types/jasmine": "~3.5.0",
"codelyzer": "^5.1.2",
"karma": "~4.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~2.1.0",
"ts-node": "~8.3.0",
"tslint": "~5.17.0",
"typescript": "~3.7.5",
"webpack-cli": "^3.3.10",
"webpack-node-externals": "^1.7.2"
},
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
答案 0 :(得分:1)
尝试以这种方式使用窗口对象
.ts文件中的文件导入
glue::glue()
然后在构造函数中注入
import { WINDOW } from '@ng-toolkit/universal';
并在下面的任何函数中使用它
constructor(@Inject(WINDOW) public window: Window) {
}
答案 1 :(得分:1)
如果有多个组件,则需要使用窗口。还有一种方法可以解决此错误,无需导入或安装任何第三方程序包。
此错误的原因是,在节点服务器上执行或解析代码时,未定义窗口。因此,为避免这种情况,我们可以放置if (isPlatformBrowser(this.platformId))
这样的条件,仅在脚本在浏览器级别运行时才会执行
import { isPlatformBrowser } from '@angular/common';
@Component({
selector: 'space-app',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(
@Inject(PLATFORM_ID) private platformId: any
) { }
ngOnInit() {}
onActivate() {
if (isPlatformBrowser(this.platformId)) {
window.scrollTo(0, 0);
}
}
}
这是您将直接使用window
的地方。但是,如果有任何第三方角度软件包正在使用您不知道的window
呢?为了防止这些情况下的错误。我们需要在server.ts中添加一段代码
const path = require('path');
const domino = require('domino');
const templateA = fs.readFileSync(path.join('dist/browser', 'index.html')).toString();
const win = domino.createWindow(templateA);
global['window'] = win;
global['document'] = win.document;
// Express server
export const app = express();
但是请确保export const app = express()
的位置正确
答案 2 :(得分:0)
我在server.ts
文件的顶部声明了这一点,并且有效了
(global as {window: unknown}).window = global;
答案 3 :(得分:0)
我有 2 个具有相同配置的 Angular SSR 项目,但其中一个遇到问题,因为 node_modules 使用 window
但未验证。
解决办法:
在 main.js
中找到哪个 lib 出错,然后搜索如何传递它。
对我来说,我只是将 Nodejs 版本从 10.x 升级到 14.x,问题就解决了。