Skip to content

Commit

Permalink
[Frontend] Migrate to create-react-app (#3156)
Browse files Browse the repository at this point in the history
* Updated create-react-app dependencies

* Fix some type errors

* Fix type errors

* Fix linting and typing

* Fix more things

* Fix typestyle mock

* Fix some unit tests

* Update snapshots

* Frontend server should use its own configuration

* Clean up server tsconfig.json and tslint.json

* Fix mock-backend

* Frontend image cloudbuild config
  • Loading branch information
Bobgy authored Feb 25, 2020
1 parent 25260de commit 968e583
Show file tree
Hide file tree
Showing 58 changed files with 24,844 additions and 12,355 deletions.
10 changes: 10 additions & 0 deletions frontend/.eslintrc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
extends: react-app
ignorePatterns:
- node_modules/
- src/apis # these are generated api clients
- '*.test.ts'
- '*.test.tsx'

rules:
react/jsx-no-target-blank: ['error', { "allowReferrer": true }]

17 changes: 8 additions & 9 deletions frontend/analyze_bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,16 @@
* limitations under the License.
*/

process.env.NODE_ENV = "production"
var BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin
process.env.NODE_ENV = 'production';
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

const webpackConfigProd = require("react-scripts-ts/config/webpack.config.prod")
const webpackConfigProd = require('react-scripts/config/webpack.config.prod');

webpackConfigProd.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: "static",
reportFilename: "report.html",
})
)
analyzerMode: 'static',
reportFilename: 'report.html',
}),
);

require("react-scripts-ts/scripts/build")
require('react-scripts/scripts/build');
2 changes: 1 addition & 1 deletion frontend/mock-backend/mock-api-middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import * as express from 'express';
import * as fs from 'fs';
import RunUtils from '../src/lib/RunUtils';
import helloWorldRuntime from './integration-test-runtime';
import proxyMiddleware from '../server/proxy-middleware';
import proxyMiddleware from './proxy-middleware';
import { ApiFilter, PredicateOp } from '../src/apis/filter';
import { ApiListExperimentsResponse, ApiExperiment } from '../src/apis/experiment';
import { ApiListJobsResponse, ApiJob } from '../src/apis/job';
Expand Down
4 changes: 2 additions & 2 deletions frontend/mock-backend/mock-api-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import * as express from 'express';
import express from 'express';
import mockApiMiddleware from './mock-api-middleware';

const app = express();
Expand All @@ -21,7 +21,7 @@ const port = process.argv[2] || 3001;
// Uncomment the following line to get 1000ms delay to all requests
// app.use((req, res, next) => { setTimeout(next, 1000); });

app.use((_, res, next) => {
app.use((_: any, res: any, next: any) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, content-type');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
Expand Down
85 changes: 85 additions & 0 deletions frontend/mock-backend/proxy-middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import * as express from 'express';
import proxy from 'http-proxy-middleware';
import { URL, URLSearchParams } from 'url';

export function _extractUrlFromReferer(proxyPrefix: string, referer = ''): string {
const index = referer.indexOf(proxyPrefix);
return index > -1 ? referer.substr(index + proxyPrefix.length) : '';
}

export function _trimProxyPrefix(proxyPrefix: string, path: string): string {
return path.indexOf(proxyPrefix) === 0 ? (path = path.substr(proxyPrefix.length)) : path;
}

export function _routePathWithReferer(proxyPrefix: string, path: string, referer = ''): string {
// If a referer header is included, extract the referer URL, otherwise
// just trim out the /_proxy/ prefix. Use the origin of the resulting URL.
const proxiedUrlInReferer = _extractUrlFromReferer(proxyPrefix, referer);
let decodedPath = decodeURIComponent(proxiedUrlInReferer || _trimProxyPrefix(proxyPrefix, path));
if (!decodedPath.startsWith('http://') && !decodedPath.startsWith('https://')) {
decodedPath = 'http://' + decodedPath;
}
return new URL(decodedPath).origin;
}

export function _rewritePath(proxyPrefix: string, path: string, query: string): string {
// Trim the proxy prefix if exists. It won't exist for any requests made
// to absolute paths by the proxied resource.
const querystring = new URLSearchParams(query).toString();
const decodedPath = decodeURIComponent(path);
return _trimProxyPrefix(proxyPrefix, decodedPath) + (querystring && '?' + querystring);
}

export default (app: express.Application, apisPrefix: string) => {
const proxyPrefix = apisPrefix + '/_proxy/';

app.use((req, _, next) => {
// For any request that has a proxy referer header but no proxy prefix,
// prepend the proxy prefix to it and redirect.
if (req.headers.referer) {
const refererUrl = _extractUrlFromReferer(proxyPrefix, req.headers.referer as string);
if (refererUrl && req.url.indexOf(proxyPrefix) !== 0) {
let proxiedUrl = decodeURIComponent(
_extractUrlFromReferer(proxyPrefix, req.headers.referer as string),
);
if (!proxiedUrl.startsWith('http://') && !proxiedUrl.startsWith('https://')) {
proxiedUrl = 'http://' + proxiedUrl;
}
const proxiedOrigin = new URL(proxiedUrl).origin;
req.url = proxyPrefix + encodeURIComponent(proxiedOrigin + req.url);
}
}
next();
});

app.all(
proxyPrefix + '*',
proxy({
changeOrigin: true,
logLevel: 'debug',
target: 'http://127.0.0.1',

router: (req: any) => {
return _routePathWithReferer(proxyPrefix, req.path, req.headers.referer as string);
},

pathRewrite: (_: any, req: any) => {
return _rewritePath(proxyPrefix, req.path, req.query);
},
}),
);
};
24 changes: 24 additions & 0 deletions frontend/mock-backend/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"outDir": "build/dist",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom", "es2019"],
"sourceMap": true,
"allowJs": true,
"resolveJsonModule": true,
"jsx": "react",
"moduleResolution": "node",
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictBindCallApply": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"skipLibCheck": true,
"esModuleInterop": true
},
"exclude": ["dist", "coverage"]
}
Loading

0 comments on commit 968e583

Please sign in to comment.