Create build step for the web server (#289)

* Create build step for the web server

* Update bskyweb routes and 404 behavior
zio/stable
Paul Frazee 2023-03-14 17:30:15 -05:00 committed by GitHub
parent 8629e167cd
commit 8d2e649b4d
9 changed files with 169 additions and 27 deletions

View File

@ -7,7 +7,7 @@
"icon": "./assets/icon.png", "icon": "./assets/icon.png",
"userInterfaceStyle": "light", "userInterfaceStyle": "light",
"splash": { "splash": {
"image": "./assets/splash.png", "image": "./assets/cloud-splash.png",
"resizeMode": "contain", "resizeMode": "contain",
"backgroundColor": "#ffffff" "backgroundColor": "#ffffff"
}, },

View File

@ -20,8 +20,7 @@ like:
Then build and copy over the big 'ol `bundle.web.js` file: Then build and copy over the big 'ol `bundle.web.js` file:
# in the top level of this repo # in the top level of this repo
yarn webpack build --config ./web/webpack.config.js -d inline-source-map --color yarn build-web
cp dist/bundle.web.js bskyweb/static/
### Golang Daemon ### Golang Daemon

View File

@ -94,20 +94,23 @@ func serve(cctx *cli.Context) error {
// configure routes // configure routes
e.File("/robots.txt", "static/robots.txt") e.File("/robots.txt", "static/robots.txt")
e.Static("/static", "static") e.Static("/static", "static")
e.Static("/static/js", "../web-build/static/js")
e.GET("/", server.WebHome) e.GET("/", server.WebHome)
// generic routes // generic routes
e.GET("/contacts", server.WebGeneric)
e.GET("/search", server.WebGeneric) e.GET("/search", server.WebGeneric)
e.GET("/notifications", server.WebGeneric) e.GET("/notifications", server.WebGeneric)
e.GET("/settings", server.WebGeneric) e.GET("/settings", server.WebGeneric)
e.GET("/settings", server.WebGeneric) e.GET("/sys/debug", server.WebGeneric)
e.GET("/sys/log", server.WebGeneric)
e.GET("/support", server.WebGeneric)
e.GET("/support/privacy", server.WebGeneric)
// profile endpoints; only first populates info // profile endpoints; only first populates info
e.GET("/profile/:handle", server.WebProfile) e.GET("/profile/:handle", server.WebProfile)
e.GET("/profile/:handle/follows", server.WebGeneric) e.GET("/profile/:handle/follows", server.WebGeneric)
e.GET("/profile/:handle/following", server.WebGeneric) e.GET("/profile/:handle/followers", server.WebGeneric)
// post endpoints; only first populates info // post endpoints; only first populates info
e.GET("/profile/:handle/post/:rkey", server.WebPost) e.GET("/profile/:handle/post/:rkey", server.WebPost)

View File

@ -2,21 +2,120 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover">
<meta name="referrer" content="origin-when-cross-origin"> <meta name="referrer" content="origin-when-cross-origin">
<title>{%- block head_title -%}Bluesky{%- endblock -%}</title> <title>{%- block head_title -%}Bluesky{%- endblock -%}</title>
<!-- Hello Humans! API docs at https://atproto.com --> <!-- Hello Humans! API docs at https://atproto.com -->
<style> <style>
/* These styles make the body full-height */ /**
html, body { height: 100%; } * Extend the react-native-web reset:
/* These styles disable body scrolling if you are using <ScrollView> */ * https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/StyleSheet/initialRules.js
body { overflow: hidden; } */
/* These styles make the root element full-height */ html,
#app-root { display:flex; height:100%; } body,
#root {
width: 100%;
/* To smooth any scrolling behavior */
-webkit-overflow-scrolling: touch;
margin: 0px;
padding: 0px;
/* Allows content to fill the viewport and go beyond the bottom */
min-height: 100%;
}
#root {
flex-shrink: 0;
flex-basis: auto;
flex-grow: 1;
display: flex;
flex: 1;
}
html {
scroll-behavior: smooth;
/* Prevent text size change on orientation change https://gist.github.com/tfausak/2222823#file-ios-8-web-app-html-L138 */
-webkit-text-size-adjust: 100%;
height: calc(100% + env(safe-area-inset-top));
}
body {
display: flex;
/* Allows you to scroll below the viewport; default value is visible */
overflow-y: auto;
overscroll-behavior-y: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-ms-overflow-style: scrollbar;
}
/* Enable for apps that support dark-theme */
/*@media (prefers-color-scheme: dark) {
body {
background-color: black;
}
}*/
/* Remove focus state on inputs */ /* Remove focus state on inputs */
*:focus { outline: 0; } *:focus {
outline: 0;
}
/* Remove default link styling */
a {
color: inherit;
}
a[role="link"]:hover {
text-decoration: underline;
}
/* ProseMirror */
.ProseMirror {
font: 18px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
min-height: 140px;
}
.ProseMirror p {
margin: 0;
}
.ProseMirror p.is-editor-empty:first-child::before {
color: #8d8e96;
content: attr(data-placeholder);
float: left;
height: 0;
pointer-events: none;
}
.ProseMirror .mention {
color: #0085ff;
}
.ProseMirror a {
color: #0085ff;
cursor: pointer;
}
.tippy-content .items {
border-radius: 6px;
background: #F3F3F8;
border: 1px solid #e0d9d9;
padding: 3px 3px;
}
.tippy-content .items .item {
display: block;
background: transparent;
color: #8a8c9a;
border: 0;
font: 17px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
padding: 7px 10px 8px;
width: 100%;
text-align: left;
box-sizing: border-box;
letter-spacing: 0.2px;
}
.tippy-content .items .item.is-selected {
background: #fff;
border-radius: 4px;
color: #333;
}
</style> </style>
{% block head_bundle -%}<script defer src="/static/bundle.web.js"></script>{%- endblock %} {% include "scripts.html" %}
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png"/> <link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png"/>
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png"/> <link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png"/>
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png"/> <link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png"/>
@ -38,14 +137,13 @@
</head> </head>
<body> <body>
{%- block body_all %} {%- block body_all %}
<div id="app-root"> <div id="root"></div>
<noscript> <noscript>
{%- block noscript_extra %}{% endblock -%} {%- block noscript_extra %}{% endblock -%}
<h1>Javascript Required</h1> <h1>Javascript Required</h1>
<p>This is a heavily interactive web application, and Javascript is required. Simple HTML interfaces are possible, but that is not what this is. <p>This is a heavily interactive web application, and Javascript is required. Simple HTML interfaces are possible, but that is not what this is.
<p>Learn more about Bluesky at <a href="https://blueskyweb.xyz">blueskyweb.xyz</a> and <a href="https://atproto.com">atproto.com</a>. <p>Learn more about Bluesky at <a href="https://blueskyweb.xyz">blueskyweb.xyz</a> and <a href="https://atproto.com">atproto.com</a>.
</noscript> </noscript>
</div>
{% endblock -%} {% endblock -%}
</body> </body>
</html> </html>

View File

@ -2,14 +2,26 @@
{% block head_title %}Error {{ statusCode }} - Bluesky{% endblock %} {% block head_title %}Error {{ statusCode }} - Bluesky{% endblock %}
{# don't include the bundle on error pages #} {% block noscript_extra %}
{% block head_bundle %}{% endblock %} {%- if statusCode == 404 %}
{% block body_all %}
{% if statusCode == 404 %}
<h1>404: Not Found</h1> <h1>404: Not Found</h1>
{% endif %}
{% endblock %}
{# don't include the bundle on non-404 error pages #}
{% block head_bundle %}
{% if statusCode == 404 %}
{{ super() }}
{% else %}
{% endif %}
{% endblock %}
{%- block body_all %}
{% if statusCode == 404 %}
{{ super() }}
{% else %} {% else %}
<h1>{{ statusCode }}: Server Error</h1> <h1>{{ statusCode }}: Server Error</h1>
<p>Sorry about that! Our <a href="https://bluesky.statuspage.io/">Status Page</a> might have more context. <p>Sorry about that! Our <a href="https://bluesky.statuspage.io/">Status Page</a> might have more context.
{% endif %} {% endif %}
{% endblock %} {% endblock -%}

View File

@ -0,0 +1,2 @@
<script defer="defer" src="/static/js/412.e47ad7b9.js"></script>
<script defer="defer" src="/static/js/main.f526ceaa.js"></script>

View File

@ -6,6 +6,7 @@
"android": "expo run:android", "android": "expo run:android",
"ios": "expo run:ios", "ios": "expo run:ios",
"web": "expo start --web", "web": "expo start --web",
"build-web": "expo export:web && node ./scripts/post-web-build.js",
"start": "expo start --dev-client", "start": "expo start --dev-client",
"clean-cache": "rm -rf node_modules/.cache/babel-loader/*", "clean-cache": "rm -rf node_modules/.cache/babel-loader/*",
"test": "jest --forceExit --testTimeout=20000 --bail", "test": "jest --forceExit --testTimeout=20000 --bail",

View File

@ -0,0 +1,27 @@
const path = require('path')
const fs = require('fs')
const projectRoot = path.join(__dirname, '..')
const webBuildJs = path.join(projectRoot, 'web-build', 'static', 'js')
const templateFile = path.join(
projectRoot,
'bskyweb',
'templates',
'scripts.html',
)
const jsFiles = fs.readdirSync(webBuildJs).filter(name => name.endsWith('.js'))
jsFiles.sort((a, b) => {
// make sure main is written last
if (a.startsWith('main')) return 1
if (b.startsWith('main')) return -1
return a.localeCompare(b)
})
console.log(`Found ${jsFiles.length} js files in web-build`)
console.log(`Writing ${templateFile}`)
const outputFile = jsFiles
.map(name => `<script defer="defer" src="/static/js/${name}"></script>`)
.join('\n')
fs.writeFileSync(templateFile, outputFile)

View File

@ -238,7 +238,7 @@ const styles = StyleSheet.create({
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
width: 136, width: 138,
borderRadius: 24, borderRadius: 24,
paddingVertical: 10, paddingVertical: 10,
paddingHorizontal: 16, paddingHorizontal: 16,