React + React Router + GitHub Pages + Google Analytics踩坑之路

React + React Router + GitHub Pages + Google Analytics踩坑之路

作者:LiuST

我用React制作了一个单页应用(SPA),在后来的发布在GitHub Pages(或Coding Pages、Gitee Pages)上、引入React Router (v4)、使用Google Analytics分析用户浏览量,乃至用Google AdSense发布广告的过程遇到了许多问题(主要与React Router有关),并且很少看到有人讨论这些问题(可能是这个做法很奇葩吧),于是有了这篇文章记录踩坑之路。

这篇文章并不是教程,许多中间的步骤被省略。如果你略懂这些技术,想采用同样的方法建网站,也许会对你有所帮助。

P.S. 我的网站地址为https://lemonjing.com,欢迎访问。

创建React应用

(这部分借鉴了教程serverless stack)

初始化React应用

使用create-react-app脚手架初始化react应用。

npx create-react-app my-app --use-npm

运行react应用。

cd my-app
npm start

在git托管平台(如GitHub)上,新建一个repo,得到repo url,如https://github.com/username/my-app.git。

将本地的react应用与远程仓库连接。

git init
git add .
git commit -m "First commit"
git remote add origin https://github.com/username/my-app.git
git remote -v
git push -u origin master

处理路由

我的网站里有不同的页面,如App1、App2。进入网站后是有一个主页,提供到App1、App2的链接。所以需要用到路由React Router。

安装React Router v4。

npm install [email protected] --save

修改src/index.js

import { BrowserRouter as Router } from 'react-router-dom';

// ...

ReactDOM.render(
  
    
  ,
  document.getElementById('root')
);

新建src/Routes.js

import React from "react";
import { Route, Switch } from "react-router-dom";
// Home.js的内容在后文
import Home from "./containers/Home";
// 假设我有App1、App2在 src/containers/ 文件夹中
import App1 from "./containers/App1";
import App2 from "./containers/App2";

export default function Routes() {
  return (
    
      
      
      f
      { /* 路径不存在,则回到主页。 */ }
      
    
  );
}

src/App.js中使用Routes

// ...

function App(props) {
  return (
      

我的应用

); }

主页有链接指向App1和App2。src/containers/Home.js可以是下面这个样子:

import React from "react";
import { Link } from "react-router-dom";

export default function Home() {
  return (
    

主页

应用1 应用1
); }

发布在GitHub Pages

安装gh-pages

npm install gh-pages --save-dev

修改package.json

// ...
  "homepage": "https://username.github.io/reponame",

// ...
  "scripts": {
      // ...
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build"
  }

部署到github pages。

npm run deploy

实际上运行这行命令发生的就是:

  1. 运行predeploy,也就是npm run build
  2. gh-pages(命令)将指定路径(在这里也就是build文件夹)下的内容复制到git分支gh-pages(分支的名字),并push。gh-pages分支是GitHub Pages的默认发布源。

使用自己的域名

package.json里的homepage改为自己的域名。

新建一个文件public/CNAME,在里面输入自己的域名,如mydomain.com

使用其他Pages

根据需要更改package.json的scripts - deploy对应的命令。

例如,我要部署在Coding Pages上,使用的命令如下:

gh-pages -d build -b master -o coding -r https://e.coding.net/xxx.git

-d表示路径,默认为'.'

-b表示分支名,默认为gh-pages

-o表示remote 名,默认为origin

-r表示repo url,默认为url for the origin remote of the current dir。

详见npm_gh-pages

问题来了:无法通过路径直接访问页面

通过mydomain.com进入页面,点击主页中的链接后可以进入mydomain.com/app1。

但是如果此时刷新,结果会是404;或者直接访问mydomain.com/app1,结果同样是404。因为React Router是前端的路由,由JavaScript处理的,GitHub Pages并不知道mydomain.com/app1有一个页面。

解决方法1:使用HashRouter而不是BrowserRouter

index.js中的router改为:

import { HashRouter as Router } from 'react-router-dom';

这样链接就变为mydomain.com/#/app1,可以直接访问。原因是#号后面的内容会被忽略。

优点

  1. 简单,原生。

缺点

  1. URL不好看
  2. 搜索引擎和Google Analytics等不会记录,他们会认为 mydomain.com/#/app1 和 mydomain.com/ 是同一个页面

解决方法2:使用404.html

当GitHub Pages无法找到页面的时候,如果你的repo里有一个404.html,GitHub Pages会返回你的404.html。

你可以直接将index.html复制一份, 改名为404.html,问题就解决了。

还有一个同样原理但是复杂一些的做法:spa-github-pages

优点

  1. URL好看

缺点

  1. 当你直接访问mydomain.com/app1时,返回的状态码是404。不利于SEO。Google Analytics和Google AdSense也会误解。

解决方法3:为每个路径创建一个文件夹

这个方法是从LoeiFy的一个issue看到的。

例如我有/app1,/app2两个路径,我就在build之后在build文件夹里新建app1,app2两个文件夹,并将index.html拷贝进去。

这样一来当我访问mydomain.com/app1的时候,GitHub Pages就会去/app1文件夹下找index.html,返回回来。

每次都复制一遍未免有些复杂,我们可以自动化这个过程。

在项目根目录新建deploy.js

// deploy.js

// 根据你的路径修改routes
const routes = [
    'app1',
    'app2',
]

// 给每个route都新建一个文件夹,把index.html拷贝进去
const fs = require('fs-extra')
const path = require('path')
routes.forEach((route) => {
    fs.copySync(path.join('build', 'index.html'), path.join('build', route, 'index.html'))
})

然后修改package.json

//...
  "scripts": {
     //每次build的时候自动执行deploy.js
    "build": "react-scripts build && node deploy.js",
     //...
  }

这样每次build的时候就会自动执行deploy.js

使用Google Analytics

注册谷歌账号,到Google Analytics按提示操作即可。

但是这样有一个问题,就是在从主页点击链接进入子页面(如mydomain.com/app1)的时候,analytics并不知道,因为这只是用JavaScript控制的页面变化。

关于这个问题,react-ga的一个issue里有很多讨论,其中一个解决方式起作用了,我写在了这篇博客里。

使用Google AdSense

AdSense的审核不容易通过,我在我的网站只有一页的时候(尽管浏览量很高)申请了几次都没有通过,后来有了多个页面的内容时才通过。然后两天后就因为非法流量被限制了广告投放,两个星期后还没有恢复。

index.html中添加(如果有的话不需要重复):

<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js">script>

在你需要放广告的组件中,根据你的client和slot:

export default class AdComponent extends React.Component {
  componentDidMount () {
    (window.adsbygoogle = window.adsbygoogle || []).push({});
  }

render () {
    return (
        
{ /* ... */ } { /* ... */ }
); } }

你可能感兴趣的:(react,网站)