remove squirrelly, compile a single bundle.css for each page, svelte and hbs server rendering

This commit is contained in:
Martin McKeaveney 2020-11-12 10:25:25 +00:00
parent 6d135fa965
commit 9b914e0395
12 changed files with 137 additions and 195 deletions

View File

@ -77,7 +77,6 @@
"pouchdb-all-dbs": "^1.0.2", "pouchdb-all-dbs": "^1.0.2",
"pouchdb-replication-stream": "^1.2.9", "pouchdb-replication-stream": "^1.2.9",
"sanitize-s3-objectkey": "^0.0.1", "sanitize-s3-objectkey": "^0.0.1",
"squirrelly": "^7.5.0",
"svelte": "^3.29.4", "svelte": "^3.29.4",
"tar-fs": "^2.1.0", "tar-fs": "^2.1.0",
"to-json-schema": "^0.2.5", "to-json-schema": "^0.2.5",

View File

@ -1,27 +1,29 @@
require("svelte/register") require("svelte/register")
const send = require("koa-send") const send = require("koa-send")
const { resolve, join } = require("../../utilities/centralPath") const { resolve, join } = require("../../../utilities/centralPath")
const fetch = require("node-fetch") const fetch = require("node-fetch")
const fs = require("fs-extra") const fs = require("fs-extra")
const uuid = require("uuid") const uuid = require("uuid")
const AWS = require("aws-sdk") const AWS = require("aws-sdk")
const { prepareUploadForS3 } = require("./deploy/aws") const { prepareUploadForS3 } = require("../deploy/aws")
const handlebars = require("handlebars")
const { const {
budibaseAppsDir, budibaseAppsDir,
budibaseTempDir, budibaseTempDir,
} = require("../../utilities/budibaseDir") } = require("../../../utilities/budibaseDir")
const CouchDB = require("../../db") const { getPageParams } = require("../../../db/utils")
const setBuilderToken = require("../../utilities/builder/setBuilderToken") const CouchDB = require("../../../db")
const fileProcessor = require("../../utilities/fileProcessor") const setBuilderToken = require("../../../utilities/builder/setBuilderToken")
const { AuthTypes } = require("../../constants") const fileProcessor = require("../../../utilities/fileProcessor")
const env = require("../../environment") const { AuthTypes } = require("../../../constants")
const env = require("../../../environment")
// this was the version before we started versioning the component library // this was the version before we started versioning the component library
const COMP_LIB_BASE_APP_VERSION = "0.2.5" const COMP_LIB_BASE_APP_VERSION = "0.2.5"
exports.serveBuilder = async function(ctx) { exports.serveBuilder = async function(ctx) {
let builderPath = resolve(__dirname, "../../../builder") let builderPath = resolve(__dirname, "../../../../builder")
if (ctx.file === "index.html") { if (ctx.file === "index.html") {
await setBuilderToken(ctx) await setBuilderToken(ctx)
} }
@ -141,37 +143,31 @@ exports.performLocalFileProcessing = async function(ctx) {
exports.serveAppNew = async function(ctx) { exports.serveAppNew = async function(ctx) {
const App = require("./templates/BudibaseApp.svelte").default const App = require("./templates/BudibaseApp.svelte").default
// Need to get app information here
const { html } = App.render({ const db = new CouchDB(ctx.params.appId)
name: "Budibase",
authenticated: const appInfo = await db.get(ctx.params.appId)
console.log("INFO", appInfo)
const { head, html, css } = App.render({
title: appInfo.name,
pageName:
ctx.auth.authenticated === AuthTypes.APP ? "main" : "unauthenticated", ctx.auth.authenticated === AuthTypes.APP ? "main" : "unauthenticated",
production: env.CLOUD, production: env.CLOUD,
appId: ctx.params.appId,
}) })
// // default to homedir const template = handlebars.compile(
// const appPath = resolve( fs.readFileSync(`${__dirname}/templates/app.hbs`, "utf8")
// budibaseAppsDir(), )
// ctx.params.appId,
// "public",
// mainOrAuth
// )
ctx.body = html ctx.body = template({
head,
// const appId = ctx.user.appId body: html,
style: css.code,
// if (env.CLOUD) { })
// const S3_URL = `https://${appId}.app.budi.live/assets/${appId}/${mainOrAuth}/${ctx.file ||
// "index.production.html"}`
// const response = await fetch(S3_URL)
// const body = await response.text()
// ctx.body = body
// return
// }
// await send(ctx, ctx.file || "index.html", { root: ctx.devPath || appPath })
} }
exports.serveApp = async function(ctx) { exports.serveApp = async function(ctx) {

View File

@ -0,0 +1,62 @@
<script>
export let title = ""
export let favicon = ""
export let appId
export let pageName = ""
export let production
export const PRODUCTION_ASSETS_URL = `https://${appId}.app.budi.live`
function publicPath(path) {
if (production) {
return `${PRODUCTION_ASSETS_URL}/assets/${appId}/${pageName}/${path}`
}
return `/assets/${path}`
}
</script>
<svelte:head>
<meta charset="utf8" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
<link rel="icon" type="image/png" href={favicon} />
<link rel="stylesheet" href={publicPath("bundle.css")} />
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Roboto+Mono" />
<style>
html,
body {
font-family: Inter;
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
*,
*:before,
*:after {
box-sizing: border-box;
}
</style>
</svelte:head>
<body id="app">
<script src={publicPath('clientFrontendDefinition.js')}>
</script>
<script src={publicPath('budibase-client.js')}>
</script>
<script>
loadBudibase()
</script>
</body>

View File

@ -0,0 +1,10 @@
<!doctype html>
<html>
<head>
{{{head}}}
</head>
{{{body}}}
</html>

View File

@ -1,63 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset='utf8'>
<meta name='viewport' content='width=device-width'>
<title>{{ title }}</title>
<link rel='icon' type='image/png' href='{{ favicon }}'>
<style>
html,
body {
font-family: Inter;
height: 100%;
width: 100%;
margin: 0px;
padding: 0px;
}
*, *:before, *:after {
box-sizing: border-box;
}
</style>
{{ each(options.stylesheets) }}
<link rel='stylesheet' href='{{ @this }}'>
{{ /each }}
{{ each(options.screenStyles) }}
{{ if(options.production) }}
<link rel='stylesheet' href='/assets/{{ appId }}/{{ pageName }}{{ @this }}'>
{{#else}}
<link rel='stylesheet' href='/assets{{ @this }}'>
{{ /if }}
{{ /each }}
{{ if(options.pageStyle) }}
{{ if(options.production) }}
<link rel='stylesheet' href='/assets/{{ appId }}/{{ pageName }}{{ pageStyle }}'>
{{#else}}
<link rel='stylesheet' href='/assets{{ pageStyle }}'>
{{ /if }}
{{ /if }}
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto+Mono">
{{ if(options.production) }}
<script src='/assets/{{ appId }}/{{ pageName }}/clientFrontendDefinition.js'></script>
<script src='/assets/{{ appId }}/{{ pageName }}/budibase-client.js'></script>
{{#else}}
<script src='/assets/clientFrontendDefinition.js'></script>
<script src='/assets/budibase-client.js'></script>
{{ /if }}
</head>
<body id="app">
<script>
loadBudibase();
</script>
</body>
</html>

View File

@ -33,6 +33,6 @@ router
.get("/componentlibrary", controller.serveComponentLibrary) .get("/componentlibrary", controller.serveComponentLibrary)
.get("/assets/:file*", controller.serveAppAsset) .get("/assets/:file*", controller.serveAppAsset)
.get("/attachments/:file*", controller.serveAttachment) .get("/attachments/:file*", controller.serveAttachment)
.get("/:appId/:path*", controller.serveApp) .get("/:appId/:path*", controller.serveAppNew)
module.exports = router module.exports = router

View File

@ -38,6 +38,6 @@ function replicateLocal() {
}) })
} }
//replicateLocal() replicateLocal()
module.exports = Pouch module.exports = Pouch

View File

@ -1,27 +1,25 @@
const { constants, copyFile, writeFile, readFile } = require("fs-extra") const { ensureDir, constants, copyFile, writeFile } = require("fs-extra")
const { join, resolve } = require("../centralPath") const { join } = require("../centralPath")
const sqrl = require("squirrelly") const { convertCssToBundle } = require("./convertCssToFiles")
const { convertCssToFiles } = require("./convertCssToFiles")
const publicPath = require("./publicPath")
const { budibaseAppsDir } = require("../budibaseDir") const { budibaseAppsDir } = require("../budibaseDir")
module.exports = async (appId, pageName, pkg) => { module.exports = async (appId, pageName, pkg) => {
const appPath = join(budibaseAppsDir(), appId) const pagePath = join(budibaseAppsDir(), appId, "public", pageName)
pkg.screens = pkg.screens || [] pkg.screens = pkg.screens || []
await convertCssToFiles(publicPath(appPath, pageName), pkg) await ensureDir(pagePath)
await buildIndexHtml(appId, pageName, appPath, pkg) await convertCssToBundle(pagePath, pkg)
await buildFrontendAppDefinition(appId, pageName, pkg, appPath) await buildFrontendAppDefinition(pagePath, pkg)
await copyClientLib(appPath, pageName) await copyClientLib(pagePath)
} }
const copyClientLib = async (appPath, pageName) => { const copyClientLib = async pagePath => {
const sourcepath = require.resolve("@budibase/client") const sourcepath = require.resolve("@budibase/client")
const destPath = join(publicPath(appPath, pageName), "budibase-client.js") const destPath = join(pagePath, "budibase-client.js")
await copyFile(sourcepath, destPath, constants.COPYFILE_FICLONE) await copyFile(sourcepath, destPath, constants.COPYFILE_FICLONE)
@ -32,44 +30,8 @@ const copyClientLib = async (appPath, pageName) => {
) )
} }
const buildIndexHtml = async (appId, pageName, appPath, pkg) => { const buildFrontendAppDefinition = async (pagePath, pkg) => {
const appPublicPath = publicPath(appPath, pageName) const filename = join(pagePath, "clientFrontendDefinition.js")
const stylesheetUrl = s => (s.startsWith("http") ? s : `/${appId}/${s}`)
const templateObj = {
title: pkg.page.title || "Budibase App",
favicon: `${pkg.page.favicon || "/_shared/favicon.png"}`,
stylesheets: (pkg.page.stylesheets || []).map(stylesheetUrl),
screenStyles: pkg.screens.filter(s => s._css).map(s => s._css),
pageStyle: pkg.page._css,
appId,
pageName,
}
const indexHtmlTemplate = await readFile(
resolve(__dirname, "index.template.html"),
"utf8"
)
const indexHtmlPath = join(appPublicPath, "index.html")
const deployableHtmlPath = join(appPublicPath, "index.production.html")
const indexHtml = sqrl.Render(indexHtmlTemplate, templateObj)
const deployableHtml = sqrl.Render(indexHtmlTemplate, {
...templateObj,
production: true,
})
await writeFile(indexHtmlPath, indexHtml, { flag: "w+" })
await writeFile(deployableHtmlPath, deployableHtml, { flag: "w+" })
}
const buildFrontendAppDefinition = async (appId, pageName, pkg) => {
const appPath = join(budibaseAppsDir(), appId)
const appPublicPath = publicPath(appPath, pageName)
const filename = join(appPublicPath, "clientFrontendDefinition.js")
delete pkg.page._css delete pkg.page._css

View File

@ -1,11 +1,15 @@
const crypto = require("crypto") const { writeFile } = require("fs-extra")
const { ensureDir, emptyDir, writeFile } = require("fs-extra")
const { join } = require("../centralPath") const { join } = require("../centralPath")
module.exports.convertCssToFiles = async (publicPagePath, pkg) => { /**
const cssDir = join(publicPagePath, "css") * Reads the _css property of all pages and screens in the budibase application, and creates a singlular CSS
await ensureDir(cssDir) * bundle for the app at <appId>/public/bundle.css.
await emptyDir(cssDir) * @param {*} publicPagePath - path to the public assets directory of the budibase application
* @param {*} pkg - app package information
* @param {*} pageName - the pagename of the page we are compiling CSS for.
*/
module.exports.convertCssToBundle = async (publicPagePath, pkg) => {
let cssString = ""
for (let screen of pkg.screens || []) { for (let screen of pkg.screens || []) {
if (!screen._css) continue if (!screen._css) continue
@ -13,31 +17,10 @@ module.exports.convertCssToFiles = async (publicPagePath, pkg) => {
delete screen._css delete screen._css
continue continue
} }
screen._css = await createCssFile(cssDir, screen._css) cssString += screen._css
} }
if (pkg.page._css) { if (pkg.page._css) cssString += pkg.page._css
pkg.page._css = await createCssFile(cssDir, pkg.page._css)
} writeFile(join(publicPagePath, "bundle.css"), cssString)
}
module.exports.getHashedCssPaths = (cssDir, _css) => {
const fileName =
crypto
.createHash("md5")
.update(_css)
.digest("hex") + ".css"
const filePath = join(cssDir, fileName)
const url = `/css/${fileName}`
return { filePath, url }
}
const createCssFile = async (cssDir, _css) => {
const { filePath, url } = module.exports.getHashedCssPaths(cssDir, _css)
await writeFile(filePath, _css)
return url
} }

View File

@ -1,3 +0,0 @@
const { join } = require("../centralPath")
module.exports = (appPath, pageName) => join(appPath, "public", pageName)

View File

@ -1,6 +1,6 @@
const { existsSync, readFile, writeFile, ensureDir } = require("fs-extra") const { existsSync, readFile, writeFile, ensureDir } = require("fs-extra")
const { join, resolve } = require("./centralPath") const { join, resolve } = require("./centralPath")
const Sqrl = require("squirrelly") const handlebars = require("handlebars")
const uuid = require("uuid") const uuid = require("uuid")
module.exports = async opts => { module.exports = async opts => {
@ -31,7 +31,8 @@ const createDevEnvFile = async opts => {
} }
) )
opts.cookieKey1 = opts.cookieKey1 || uuid.v4() opts.cookieKey1 = opts.cookieKey1 || uuid.v4()
const config = Sqrl.Render(template, opts) const hbTemplate = handlebars.compile(template)
const config = hbTemplate.render(opts)
await writeFile(destConfigFile, config, { flag: "w+" }) await writeFile(destConfigFile, config, { flag: "w+" })
} }
} }

View File

@ -200,10 +200,10 @@
lodash "^4.17.19" lodash "^4.17.19"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@budibase/client@^0.3.4": "@budibase/client@^0.3.6":
version "0.3.4" version "0.3.7"
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.3.4.tgz#aca2d13170dae870d069a56f53519d9fbb4bdc00" resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.3.7.tgz#8ed2d40d91ba3788a69ee5db5078f757adb4187f"
integrity sha512-zs9Jnr1CzvgZY4NrliatqDUm0gVhlcQkpdsMblO+3zRcwBzRXAeFyzwMtGpcbiQm29zHjPBOivmQQUMxgi3lUg== integrity sha512-EgpHfw/WOUYeCG4cILDbaN2WFBDSPS698Z+So7FP5l+4E1fvmqtpXVKJYsviwYEx8AKKYyU3nuDi0l6xzb5Flg==
dependencies: dependencies:
deep-equal "^2.0.1" deep-equal "^2.0.1"
mustache "^4.0.1" mustache "^4.0.1"
@ -7146,11 +7146,6 @@ sprintf-js@~1.0.2:
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
squirrelly@^7.5.0:
version "7.9.2"
resolved "https://registry.yarnpkg.com/squirrelly/-/squirrelly-7.9.2.tgz#f8b0a08201b73653351afe9f7f24878237d2751a"
integrity sha512-QsLQ43p7/p5LfhqMsUM1PP0DU/YuirA/pZ1RQKU8/qZjWHD8uTblpfPoCVkD9VLrS1jCJ+2gqECv3amlPgrLCA==
sshpk@^1.7.0: sshpk@^1.7.0:
version "1.16.1" version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"