ReferenceError:在使用服务器端渲染的angular4中未定义navigator

时间:2017-04-11 03:32:53

标签: angular codemirror serverside-rendering angular-universal simplemde

我正在使用simpleMDE编辑器和我的角度4服务器端渲染应用程序并使用

获取textarea的引用
@ViewChild('simpleMDE') textarea : ElementRef;

并在ngAfterViewInit()

中初始化它
   this.simplemde = new SimpleMDE(
      {
          element: this.textarea.nativeElement.value,
      })
在模板中的

使用像这样的textarea

<textarea id="simpleMDE" #simpleMDE></textarea> 

启动服务器时抛出错误

projectpath\node_modules\codemirror\lib\codemirror.js:11
        typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
                                                                                 ^
ReferenceError: navigator is not defined
    at projectpath\node_modules\codemirror\lib\codemirror.js:18:17

请提出建议,我坚持到这里。  GitHub Repo

4 个答案:

答案 0 :(得分:2)

如Angular Universal Documentation中所述

窗口,文档,导航器和其他浏览器类型 - 在服务器上不存在 - 因此使用它们或任何使用它们的库(例如jQuery)都不起作用

如果您需要使用它们,请考虑将它们仅限于您的客户并将其包装在一起。您可以使用PLATFORM_ID标记注入的Object来检查当前平台是浏览器还是服务器。

 import { PLATFORM_ID } from '@angular/core';
 import { isPlatformBrowser, isPlatformServer } from '@angular/common';

 constructor(@Inject(PLATFORM_ID) private platformId: Object) { ... }

 ngOnInit() {
   if (isPlatformBrowser(this.platformId)) {
      // Client only code.
      ...
   }
   if (isPlatformServer(this.platformId)) {
     // Server only code.
     ...
   }
 }

需要操纵库:(

编辑: 在以下行中,错误来自codemirror.js

var userAgent = navigator.userAgent;
var platform = navigator.platform;

尝试操纵该代码

if(navigator){
  var userAgent = navigator.userAgent;
  var platform = navigator.platform;
}else{
 var userAgent="server";
 var platform="server";
}
P.S:不确定会产生什么影响:D。

答案 1 :(得分:1)

猜猜你的js / ts文件中有这样的代码。

import CodeMirror from 'codemirror';

正如@Parth Ghiya所回答,navigator仅在浏览器中支持,这将导致错误。

在尝试支持服务器呈现时,您可以通过以下方式对代码进行一些更改(延迟要求):

// just before places where are using codemirror
const CodeMirror = require('codemirror');   
require('codemirror/addon/hint/show-hint');

CodeMirror(...)

答案 2 :(得分:0)

以下是我处理这种问题的方法。 对我来说,服务器渲染仅用于SEO目的。像codemirror这样的东西并没有真正对SEO做任何事情。因此,我的方法是不在服务器端呈现它#34;。

enter image description here ref

基本结构如上图所示。

你有2个启动文件,一个用于服务器渲染,另一个用于客户端渲染。

因此,您实际上可以为每个启动文件使用不同的应用程序模块。

在服务器渲染的应用程序模块中,您可以使用模拟组件替换使用浏览器对象的组件,并将真实组件用于客户端。

这样您就不必担心服务器渲染上有问题的组件了。

另一种解决方案是使用webpack来处理这些浏览器对象。

像这样ref

module: {
  rules: [
    { 
      test: /@angular(\\|\/)material/, use: "imports-loader?window=>global,CSS=>null,navigator=>{get userAgent(){return Zone.current.get('req')['headers']['user-agent'];}}"
    }
  ]
}

就个人而言,我更喜欢第一种解决方案。第二个对我来说有点hacky并且在服务器端渲染与SEO无关的组件并没有给我们带来任何好处。

答案 3 :(得分:0)

为简单起见,只需输入

TextInput

在server.ts文件的顶部。这样,它将忽略该错误。