我正在创建具有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
的值进行解析。但是,由于仅在客户端上加载,因此gapi
和gapiPromise
在服务器上不存在。我也有一个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.gapiPromise
。 window
对象表示浏览器中打开的窗口。