Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

39 Moving the Front end application from Go to Next.js #236

Merged
merged 30 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3e873e2
39 adding the next.js frontend app to the code base
xoscar Jul 22, 2022
290c7b8
39 adding the next.js frontend app to the code base
xoscar Jul 26, 2022
7213709
39 adding the next.js frontend app to the code base
xoscar Jul 26, 2022
e71da1a
39 adding the next.js frontend app to the code base
xoscar Jul 26, 2022
439f795
39 adding the next.js frontend app to the code base
xoscar Jul 26, 2022
e63d9fb
Merge branch 'main' into 39-web-application
xoscar Jul 26, 2022
96bbd2c
Merge branch 'main' into 39-web-application
xoscar Jul 27, 2022
3a7b71f
39 removing the deployment details
xoscar Jul 27, 2022
e610494
39 PR updates
xoscar Aug 1, 2022
e403697
Merge branch 'main' into 39-web-application
xoscar Aug 4, 2022
15a0dc6
39 removing the protos folder
xoscar Aug 4, 2022
40135ab
39 fixing multiple minor issues
xoscar Aug 4, 2022
1780b53
39 updating frontend README
xoscar Aug 8, 2022
510d47b
Merge branch 'main' into 39-web-application
xoscar Aug 8, 2022
9d1fede
39 removing unnecessary images
xoscar Aug 8, 2022
19c9cc1
39 fixing ssr bug
xoscar Aug 8, 2022
feaa207
39 fixing ssr bug
xoscar Aug 8, 2022
afb9b75
39 fixing readme lint issues
xoscar Aug 8, 2022
deb5cc8
39 fixing readme lint issues
xoscar Aug 8, 2022
54444cf
39 updating the changelog
xoscar Aug 8, 2022
333a819
39 fixing readme lint issues
xoscar Aug 8, 2022
2ee1a43
39 fixing readme lint issues
xoscar Aug 8, 2022
970d4de
39 fixing multiple minor issues
xoscar Aug 8, 2022
19ea78d
39 fixing multiple minor issues
xoscar Aug 8, 2022
b1ff6c5
39 fixing product price
xoscar Aug 8, 2022
202d656
39 updatig the frontend port to 8080
xoscar Aug 9, 2022
9cdba1c
39 updating the changelog entry
xoscar Aug 9, 2022
9d79048
39 updated PR comments
xoscar Aug 9, 2022
673479a
39 cleaning up PR details
xoscar Aug 9, 2022
69e4e07
Merge branch 'main' into 39-web-application
xoscar Aug 9, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_TRACES_ENDPOINT}
USERS=10

# Frontend
FRONTEND_PORT=8080
FRONTEND_ADDR=frontend:${FRONTEND_PORT}
FRONTEND_PORT=8081
puckpuck marked this conversation as resolved.
Show resolved Hide resolved

# Redis
REDIS_PORT=6379
Expand All @@ -30,7 +29,7 @@ CART_SERVICE_ADDR=cartservice:${CART_SERVICE_PORT}
CHECKOUT_SERVICE_PORT=5050
CHECKOUT_SERVICE_ADDR=checkoutservice:${CHECKOUT_SERVICE_PORT}

CURRENCY_SERVICE_PORT=7000
xoscar marked this conversation as resolved.
Show resolved Hide resolved
CURRENCY_SERVICE_PORT=7001
CURRENCY_SERVICE_ADDR=currencyservice:${CURRENCY_SERVICE_PORT}

EMAIL_SERVICE_PORT=8080
Expand All @@ -45,7 +44,7 @@ PRODUCT_CATALOG_SERVICE_ADDR=productcatalogservice:${PRODUCT_CATALOG_SERVICE_POR
RECOMMENDATION_SERVICE_PORT=9001
RECOMMENDATION_SERVICE_ADDR=recommendationservice:${RECOMMENDATION_SERVICE_PORT}

SHIPPING_SERVICE_PORT=50051
SHIPPING_SERVICE_PORT=50053
SHIPPING_SERVICE_ADDR=shippingservice:${SHIPPING_SERVICE_PORT}

FEATURE_FLAG_SERVICE_PORT=50052
Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ obj/
.idea/
build/
node_modules/
src/shippingservice/target/
src/shippingservice/target/

coverage
.next/
out/
build
src/frontend/protos
5 changes: 3 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ services:
ports:
- "${FRONTEND_PORT}:${FRONTEND_PORT}"
environment:
- PORT=${FRONTEND_PORT}
xoscar marked this conversation as resolved.
Show resolved Hide resolved
- FRONTEND_ADDR
- AD_SERVICE_ADDR
- CART_SERVICE_ADDR
Expand Down Expand Up @@ -176,7 +177,7 @@ services:
context: ./
dockerfile: ./src/paymentservice/Dockerfile
ports:
- "${PAYMENT_SERVICE_PORT}:${PAYMENT_SERVICE_PORT}"
- "${PAYMENT_SERVICE_PORT}"
xoscar marked this conversation as resolved.
Show resolved Hide resolved
environment:
- PAYMENT_SERVICE_PORT
- OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
Expand Down Expand Up @@ -208,7 +209,7 @@ services:
context: ./
dockerfile: ./src/recommendationservice/Dockerfile
ports:
- "${RECOMMENDATION_SERVICE_PORT}:${RECOMMENDATION_SERVICE_PORT}"
- "${RECOMMENDATION_SERVICE_PORT}"
depends_on:
- productcatalogservice
- otelcol
Expand Down
26 changes: 26 additions & 0 deletions src/frontend/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
xoscar marked this conversation as resolved.
Show resolved Hide resolved
"extends": ["plugin:react/recommended", "plugin:@typescript-eslint/recommended", "next/core-web-vitals"],
"plugins": ["@typescript-eslint"],
"root": true,
"globals": {},
"rules": {
"@typescript-eslint/no-non-null-assertion": "off",
"react-hooks/exhaustive-deps": "warn",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"max-len": [
"error",
{
"code": 150,
"ignoreComments": true,
"ignoreTrailingComments": true,
"ignoreUrls": true,
"ignoreStrings": true,
"ignoreTemplateLiterals": true
}
]
},
"parser": "@typescript-eslint/parser",
"env": {},
"overrides": []
}
6 changes: 6 additions & 0 deletions src/frontend/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.idea
.git
build
dist
.husky
node_modules
15 changes: 15 additions & 0 deletions src/frontend/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"importOrderSeparation": true,
"importOrderSortSpecifiers": true,
"singleQuote": true,
"arrowParens": "avoid",
"bracketSpacing": true,
"semi": true,
"trailingComma": "es5",
"printWidth": 120,
"jsxBracketSameLine": false,
"proseWrap": "always",
"quoteProps": "as-needed",
"tabWidth": 2,
"useTabs": false
}
85 changes: 41 additions & 44 deletions src/frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
# Copyright 2020 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.

FROM golang:1.17.7-alpine AS builder

RUN apk add build-base protoc

WORKDIR /usr/src/app/

# Restore dependencies
COPY ./src/frontend/ ./
COPY ./pb/ ./proto/
RUN go mod download
RUN go get google.golang.org/protobuf/cmd/protoc-gen-go
RUN go get google.golang.org/grpc/cmd/protoc-gen-go-grpc

# Build executable
RUN protoc -I ./proto/ ./proto/demo.proto --go_out=./ --go-grpc_out=./
RUN go build -o /go/bin/frontend/ ./

# -----------------------------------------------------------------------------

FROM alpine

RUN apk add busybox-extras net-tools bind-tools
WORKDIR /usr/src/app/

COPY --from=builder /go/bin/frontend/ ./
COPY ./src/frontend/templates/ ./templates/
COPY ./src/frontend/static/ ./static/

EXPOSE ${FRONTEND_PORT}
ENTRYPOINT [ "./frontend" ]
FROM node:16-alpine AS deps
RUN apk add --no-cache libc6-compat

WORKDIR /app

COPY ./src/frontend/package*.json ./
RUN npm ci

FROM node:16-alpine AS builder
RUN apk add --no-cache libc6-compat protoc
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY ./pb ./pb
COPY ./src/frontend .

RUN mkdir protos
RUN npm run grpc:generate
xoscar marked this conversation as resolved.
Show resolved Hide resolved
RUN npm run build

FROM node:16-alpine AS runner
WORKDIR /app
RUN apk add --no-cache protoc

ENV NODE_ENV=production

RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json

COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

ENV PORT 8080
EXPOSE ${PORT}
xoscar marked this conversation as resolved.
Show resolved Hide resolved

CMD ["node", "server.js"]
135 changes: 19 additions & 116 deletions src/frontend/README.md
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,131 +1,34 @@
# Frontend service
xoscar marked this conversation as resolved.
Show resolved Hide resolved
xoscar marked this conversation as resolved.
Show resolved Hide resolved
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

The **frontend** service is responsible for rendering the UI for the store's website.
It serves as the main entry point for the application routing requests to their
appropriate backend services.
The application uses Server Side Rendering (SSR) to generate HTML consumed by
the clients, which could be web browsers, web crawlers, mobile clients or something
else.
## Getting Started

## OpenTelemetry instrumentation
First, run the development server:

### Initialization

The OpenTelemetry SDK is initialized in `main` using the `InitTraceProvider` function.

```go
func InitTracerProvider() *sdktrace.TracerProvider {
ctx := context.Background()

exporter, err := otlptracegrpc.New(ctx)
if err != nil {
log.Fatal(err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithBatcher(exporter),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
return tp
}
```

Services should call `TraceProvider.Shutdown()` when the service is shutdown to
ensure all spans are exported.
This service makes that call as part of a deferred function in `main`.

```go
// Initialize OpenTelemetry Tracing
tp := InitTracerProvider()
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Printf("Error shutting down tracer provider: %v", err)
}
}()
```bash
npm run dev
# or
yarn dev
```

### HTTP instrumentation
Open [http://localhost:8081](http://localhost:8081) with your browser to see the result.
xoscar marked this conversation as resolved.
Show resolved Hide resolved

This service receives HTTP requests, controlled by the gorilla/mux Router.
The following routes are defined by the frontend:
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.

| Path | Method | Use |
|-------------------|--------|-----------------------------------|
| `/` | GET | Main index page |
| `/cart` | GET | View Cart |
| `/cart` | POST | Add to Cart |
| `/cart/checkout` | POST | Place Order |
| `/cart/empty` | POST | Empty Cart |
| `/logout` | GET | Logout |
| `/product/{id}` | GET | View Product |
| `/setCurrency` | POST | Set Currency |
| `/static/` | * | Static resources |
| `/robots.txt` | * | Search engine response (disallow) |
| `/_healthz` | * | Health check (ok) |
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
xoscar marked this conversation as resolved.
Show resolved Hide resolved

These requests are instrumented in the main function as part of the router's definition.
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

```go
// Add OpenTelemetry instrumentation to incoming HTTP requests controlled by the gorilla/mux Router.
r.Use(otelmux.Middleware("server"))
```
## Learn More

### gRPC instrumentation
To learn more about Next.js, take a look at the following resources:

This service will issue several outgoing gRPC calls, which have instrumentation
hooks added in the `mustConnGRPC` function.
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

```go
func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr string) {
// Add OpenTelemetry instrumentation to outgoing gRPC requests
var err error
ctx, cancel := context.WithTimeout(ctx, time.Second*3)
defer cancel()
*conn, err = grpc.DialContext(ctx, addr,
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),
grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor()),
)
if err != nil {
panic(errors.Wrapf(err, "grpc: failed to connect %s", addr))
}
}
```
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

### Service specific instrumentation attributes
## Deploy on Vercel

All requests incoming to the frontend service will receive the following attributes:
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
xoscar marked this conversation as resolved.
Show resolved Hide resolved

- `app.session.id`
- `app.request.id`
- `app.currency`
- `app.user.id` (when the user is present)

These attributes are added in the `instrumentHandler` function (defined in the
middleware.go file) which wraps all HTTP routes specified within the
gorilla/mux router.
Additional attributes are added within each handler's function as appropriate
(ie: `app.cart.size`, `app.cart.total.price`).

Adding attributes to existing auto-instrumented spans can be accomplished by
getting the current span from context, then adding attributes to it.

```go
span := trace.SpanFromContext(r.Context())
span.SetAttributes(
attribute.Int(instr.AppPrefix+"cart.size", cartSize(cart)),
attribute.Int(instr.AppPrefix+"cart.items.count", len(items)),
attribute.Float64(instr.AppPrefix+"cart.shipping.cost", shippingCostFloat),
attribute.Float64(instr.AppPrefix+"cart.total.price", totalPriceFloat),
)
```

When an error is encountered, the current span's status code and error message
are set.

```go
// set span status on error
span := trace.SpanFromContext(r.Context())
span.SetStatus(codes.Error, errMsg)
```
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
20 changes: 20 additions & 0 deletions src/frontend/components/Ad/Ad.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import styled from 'styled-components';
import RouterLink from 'next/link';

export const Ad = styled.section`
position: relative;
background-color: ${({ theme }) => theme.colors.otelYellow};
font-size: ${({ theme }) => theme.sizes.dMedium};
text-align: center;
padding: 48px;

* {
color: ${({ theme }) => theme.colors.white};
margin: 0;
cursor: pointer;
}
`;

export const Link = styled(RouterLink)`
color: black;
`;
18 changes: 18 additions & 0 deletions src/frontend/components/Ad/Ad.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useAd } from '../../providers/Ad.provider';
import * as S from './Ad.styled';

const Ad = () => {
const {
adList: [{ text, redirectUrl } = { text: '', redirectUrl: '' }],
} = useAd();

return (
<S.Ad>
<S.Link href={redirectUrl}>
<p>{text}</p>
</S.Link>
</S.Ad>
);
};

export default Ad;
1 change: 1 addition & 0 deletions src/frontend/components/Ad/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Ad';
Loading