我正在创建具有Google登录功能的通用React应用程序。不幸的是,Google没有可在客户端和服务器上使用的通用Google API(gapi)库。

我在这里真正想做的是运行服务器代码,让Babel在进行更改时自动重新编译我的代码,并让它自动重新启动服务器(就像nodemon一样,但是有一个编译步骤)。我找到了一个名为babel-watch的npm软件包,可以执行此操作,但是它并未与webpack集成。

在我的模板index.html文件中,HTML <head>中包含以下代码:

index.html

<script type="text/javascript">
  window.gapiPromise = new Promise(resolve => window.gapiLoadedCallback = () => resolve(gapi))
</script>
<script src="https://apis.google.com/js/platform:auth2.js?onload=gapiLoadedCallback" async defer></script>


上面创建了一个新的Promise,当加载gapi时,将使用platform.js的值进行解析。但是,由于仅在客户端上加载,因此gapigapiPromise在服务器上不存在。

我也有一个Google Sign In React组件,当准备使用gapiPromise时,该组件使用全局gapi变量进行按钮呈现:

GoogleSignIn.jsx

import React from 'react'

// should only run on client
if (gapiPromise !== false) {
  gapiPromise.then(gapi => {
    gapi.auth2.init({
      client_id: '[removed]'
    })
  })
}

class GoogleSignIn extends React.Component {
  constructor(props) {
    super(props)
  }
  componentDidMount() {
    // should only run on client
    if (gapiPromise !== false) {
     gapiPromise.then(gapi => gapi.signin2.render('g-signin2', {
        'scope': 'email',
        'width': 160,
        'height': 50,
        'theme': 'light',
        'onsuccess': this.props.onSuccess,
        'onfailure': this.props.onFailure
      }))
    }
  }
  render() {
    return (
      <div className="google-sign-in">
        <div id="g-signin2"></div>
      </div>
    )
  }
}

export default GoogleSignIn


这在客户端上可以正常工作,但是当我尝试在服务器上呈现它时,Node抱怨说:

/Users/jreznik/Sites/my-app/dist/server.js:3568
  if (gapiPromise !== false) {
      ^

ReferenceError: gapiPromise is not defined
    at Object.defineProperty.value (/Users/jreznik/Sites/my-app/dist/server.js:3568:6)
    at __webpack_require__ (/Users/jreznik/Sites/my-app/dist/server.js:20:30)
    at Object.defineProperty.value (/Users/jreznik/Sites/my-app/dist/server.js:3408:22)
    at __webpack_require__ (/Users/jreznik/Sites/my-app/dist/server.js:20:30)
    at Object.defineProperty.value (/Users/jreznik/Sites/my-app/dist/server.js:3354:24)
    at __webpack_require__ (/Users/jreznik/Sites/my-app/dist/server.js:20:30)
    at Object.defineProperty.value (/Users/jreznik/Sites/my-app/dist/server.js:194:21)
    at __webpack_require__ (/Users/jreznik/Sites/my-app/dist/server.js:20:30)
    at Object.<anonymous> (/Users/jreznik/Sites/my-app/dist/server.js:59:16)
    at Object.<anonymous> (/Users/jreznik/Sites/my-app/dist/server.js:131:31)


我尝试在此文件中的gapiPromise前面加上global.(即global.gapiPromise),然后在服务器的入口文件(global.gapiPromise = false)中定义server.js,但是Node抱怨:

/Users/jreznik/Sites/my-app/dist/server.js:3569
      global.gapiPromise.then(function (gapi) {
                        ^

TypeError: Cannot read property 'then' of undefined


最后,我能够使用webpack的DefinePlugin使其工作:

webpack.server.config.js

...

plugins: [
  new webpack.DefinePlugin({
    'window': {},
    'gapiPromise': false
  })
]

...


但是,如果执行此操作,则无法使用babel-watch npm软件包自动重新编译并重新启动服务器。

如何让Node停止抱怨这些未定义的全局变量?

最佳答案

它是一个客户端库,这意味着它仅与浏览器中的DOM一起使用。它实际上等效于window.gapiPromisewindow对象表示浏览器中打开的窗口。

09-25 18:40