Skip to content

Commit

Permalink
Rewrite frontend using Vite and vanilla JavaScript
Browse files Browse the repository at this point in the history
This commit rewrites the frontend using Vite and vanilla JavaScript. We were
using an old version of Parcel that had more than 50 associated vulns, but
moved to Vite instead since that's our standard build tool these days.

- Use Goa client converted to es6 with amdtoes6.
- Use Vite instead of Parcel to build the frontend.
- Use NPM instead of Yarn to manage dependencies.
- Rewrite the frontend using vanilla JavaScript instead of jQuery.
- Embed assets from web/dist directly (root public dir is removed).
  • Loading branch information
sevein committed Oct 2, 2023
1 parent c64df5a commit 8e2a827
Show file tree
Hide file tree
Showing 23 changed files with 1,236 additions and 6,648 deletions.
5 changes: 0 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
/dist
/public/web
/web/.cache
/web/.parcel-cache
/web/node_modules

*.swp
*.log
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
FROM node:18 as frontend
WORKDIR /src
COPY web /src/web
RUN yarn --cwd /src/web install --frozen-lockfile
RUN yarn --cwd /src/web build
RUN npm --cwd /src/web ci
RUN npm --cwd /src/web run build

FROM golang:1.21.1-alpine AS build
RUN apk add --no-cache ca-certificates git make
WORKDIR /src
COPY --from=frontend /src/public/web ./public/web
COPY --from=frontend /src/web/dist ./web/dist
COPY . .
RUN make build

Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ deps: tools
.PHONY: goagen
goagen:
@goagen app -d github.com/artefactual-labs/amflow/design -o internal/api
@goagen js -d github.com/artefactual-labs/amflow/design -o web/js/client --noexample
@goagen js -d github.com/artefactual-labs/amflow/design -o web/ --noexample
@mv web/js/client.js web/client.amd.js
@rm -rf web/js
@cd web && npm run amdtoes6

.PHONY: clean
clean:
Expand Down
2 changes: 1 addition & 1 deletion design/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ var _ = Resource("web", func() {
Origin("*", func() {
Methods("GET, OPTIONS")
})
Files("/*filepath", "web/")
Files("/*filepath", "dist")
})
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ require (
github.com/zach-klippenstein/goregen v0.0.0-20160303162051-795b5e3961ea // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/tools v0.7.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
Expand Down
5 changes: 3 additions & 2 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"io/fs"
"net/http"
"path/filepath"
"time"

"github.com/goadesign/goa"
Expand All @@ -13,7 +14,7 @@ import (
"github.com/artefactual-labs/amflow/internal/api/app"
"github.com/artefactual-labs/amflow/internal/api/controllers"
"github.com/artefactual-labs/amflow/internal/graph"
"github.com/artefactual-labs/amflow/public"
"github.com/artefactual-labs/amflow/web"
)

func Create(graph *graph.Workflow, logger *logrus.Entry) *goa.Service {
Expand All @@ -34,7 +35,7 @@ func Create(graph *graph.Workflow, logger *logrus.Entry) *goa.Service {
// Web controller.
webCtrl := controllers.NewSwaggerController(service)
webCtrl.FileSystem = func(dir string) http.FileSystem {
assetsDir, _ := fs.Sub(public.Assets, "web")
assetsDir, _ := fs.Sub(web.Assets, filepath.Clean(dir))
return http.FS(assetsDir)
}
app.MountWebController(service, webCtrl)
Expand Down
8 changes: 4 additions & 4 deletions internal/api/app/controllers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions web/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist/.keep
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
4 changes: 2 additions & 2 deletions public/assets.go → web/assets.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package public
package web

import (
"embed"
)

//go:embed web/*
//go:embed dist/*
var Assets embed.FS
File renamed without changes.
96 changes: 96 additions & 0 deletions web/client.es6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// This module exports functions that give access to the amflow API hosted at localhost.
// It uses the axios javascript library for making the actual HTTP requests.
import axios from 'axios';
function merge(obj1, obj2) {
var obj3 = {};
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
return obj3;
}

export default function (scheme, host, timeout) {
scheme = scheme || 'http';
host = host || 'localhost';
timeout = timeout || 20000;

// Client is the object returned by this module.
var client = axios;

// URL prefix for all API requests.
var urlPrefix = scheme + '://' + host;

// Add link
// path is the request path, the format is "/workflow/:workflowID/links"
// config is an optional object to be merged into the config built by the function prior to making the request.
// The content of the config object is described here: https://github.com/mzabriskie/axios#request-api
// This function returns a promise which raises an error if the HTTP response is a 4xx or 5xx.
client.addLinkWorkflow = function (path, config) {
var cfg = {
timeout: timeout,
url: urlPrefix + path,
method: 'patch',
responseType: 'json'
};
if (config) {
cfg = merge(cfg, config);
}
return client(cfg);
}

// Delete link
// path is the request path, the format is "/workflow/:workflowID/links/:linkID"
// config is an optional object to be merged into the config built by the function prior to making the request.
// The content of the config object is described here: https://github.com/mzabriskie/axios#request-api
// This function returns a promise which raises an error if the HTTP response is a 4xx or 5xx.
client.deleteLinkWorkflow = function (path, config) {
var cfg = {
timeout: timeout,
url: urlPrefix + path,
method: 'delete',
responseType: 'json'
};
if (config) {
cfg = merge(cfg, config);
}
return client(cfg);
}

// Move link
// path is the request path, the format is "/workflow/:workflowID/links/:linkID"
// config is an optional object to be merged into the config built by the function prior to making the request.
// The content of the config object is described here: https://github.com/mzabriskie/axios#request-api
// This function returns a promise which raises an error if the HTTP response is a 4xx or 5xx.
client.moveLinkWorkflow = function (path, config) {
var cfg = {
timeout: timeout,
url: urlPrefix + path,
method: 'patch',
responseType: 'json'
};
if (config) {
cfg = merge(cfg, config);
}
return client(cfg);
}

// Read workflow
// path is the request path, the format is "/workflow/:workflowID"
// config is an optional object to be merged into the config built by the function prior to making the request.
// The content of the config object is described here: https://github.com/mzabriskie/axios#request-api
// This function returns a promise which raises an error if the HTTP response is a 4xx or 5xx.
client.showWorkflow = function (path, config) {
var cfg = {
timeout: timeout,
url: urlPrefix + path,
method: 'get',
responseType: 'json'
};
if (config) {
cfg = merge(cfg, config);
}
return client(cfg);
}
return client;
};


71 changes: 0 additions & 71 deletions web/css/style.css

This file was deleted.

30 changes: 11 additions & 19 deletions web/index.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test</title>
<base href="/">
<script src="./js/app.js"></script>
<link rel="stylesheet" type="text/css" href="./css/style.css">
</head>
<body>
<div class="wrapper">
<div class="box sidebar">
<button class="reload-btn">Reload</button>
</div>
<div class="box content">
<div class="viewport"></div>
</div>
</div>
</body>
</html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>amflow</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.js"></script>
</body>
</html>
34 changes: 0 additions & 34 deletions web/js/app.js

This file was deleted.

16 changes: 0 additions & 16 deletions web/js/client.js

This file was deleted.

0 comments on commit 8e2a827

Please sign in to comment.