diff --git a/.gitignore b/.gitignore index 2381ff83b1..53701a44d2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,7 @@ node_modules/ yarn-error.log coverage/ tmp/ -static/build/client/ +static/build/** binaries/client/ binaries/server/ locales/**/**.js diff --git a/package.json b/package.json index 0a9afc60d1..6f395eea3c 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "productName": "Lens", "description": "Lens - The Kubernetes IDE", "version": "3.6.0-dev", - "main": "out/main.js", + "main": "static/build/main.js", "copyright": "© 2020, Lakend Labs, Inc.", "license": "MIT", "author": { @@ -12,7 +12,7 @@ }, "scripts": { "dev": "concurrently -k \"yarn dev-run -C\" \"yarn dev:main\" \"yarn dev:renderer\"", - "dev-run": "nodemon --watch out/main.* --exec \"electron --inspect .\" $@", + "dev-run": "nodemon --watch static/build/main.js --exec \"electron --inspect .\" $@", "dev:main": "env DEBUG=true yarn compile:main --watch $@", "dev:renderer": "env DEBUG=true yarn compile:renderer --watch $@", "compile": "env NODE_ENV=production concurrently yarn:compile:*", @@ -87,7 +87,7 @@ { "from": "static/", "to": "static/", - "filter": "**/*" + "filter": "!**/main.js" }, "LICENSE" ], diff --git a/src/common/vars.ts b/src/common/vars.ts index d7e18e3467..8dc9831898 100644 --- a/src/common/vars.ts +++ b/src/common/vars.ts @@ -10,16 +10,27 @@ export const isDevelopment = isDebugging || !isProduction; export const isTestEnv = !!process.env.JEST_WORKER_ID; export const appName = `${packageInfo.productName}${isDevelopment ? "Dev" : ""}` +export const publicPath = "/build/" -// System paths +// Webpack build paths export const contextDir = process.cwd(); -export const staticDir = path.join(contextDir, "static"); -export const outDir = path.join(contextDir, "out"); +export const buildDir = path.join(contextDir, "static", publicPath); export const mainDir = path.join(contextDir, "src/main"); export const rendererDir = path.join(contextDir, "src/renderer"); export const htmlTemplate = path.resolve(rendererDir, "template.html"); export const sassCommonVars = path.resolve(rendererDir, "components/vars.scss"); +// Special runtime paths +const globScope = typeof global !== "undefined" ? global : window; +Object.defineProperty(globScope, "__static", { + get() { + if (isDevelopment) { + return path.resolve(contextDir, "static"); + } + return path.resolve(process.resourcesPath, "static") + } +}) + // Apis export const apiPrefix = "/api" // local router apis export const apiKubePrefix = "/api-kube" // k8s cluster apis diff --git a/src/main/index.ts b/src/main/index.ts index 0c5558ec33..12fbb2bc76 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -3,7 +3,7 @@ import "../common/system-ca" import "../common/prometheus-providers" import { app, dialog } from "electron" -import { appName, staticDir } from "../common/vars"; +import { appName } from "../common/vars"; import path from "path" import { LensProxy } from "./lens-proxy" import { WindowManager } from "./window-manager"; @@ -19,6 +19,10 @@ import { workspaceStore } from "../common/workspace-store"; import { tracker } from "../common/tracker"; import logger from "./logger" +const workingDir = path.join(app.getPath("appData"), appName); +app.setName(appName); +app.setPath("userData", workingDir); + let windowManager: WindowManager; let clusterManager: ClusterManager; let proxyServer: LensProxy; @@ -30,17 +34,13 @@ if (app.commandLine.getSwitchValue("proxy-server") !== "") { async function main() { await shellSync(); - - const workingDir = path.join(app.getPath("appData"), appName); - app.setName(appName); - app.setPath("userData", workingDir); logger.info(`🚀 Starting Lens from "${workingDir}"`) tracker.event("app", "start"); const updater = new AppUpdater() updater.start(); - registerFileProtocol("static", staticDir); + registerFileProtocol("static", __static); // find free port let proxyPort: number diff --git a/src/main/router.ts b/src/main/router.ts index 1b50ec2c2e..976d7cac9c 100644 --- a/src/main/router.ts +++ b/src/main/router.ts @@ -4,7 +4,7 @@ import http from "http" import path from "path" import { readFile } from "fs-extra" import { Cluster } from "./cluster" -import { apiPrefix, appName, outDir } from "../common/vars"; +import { apiPrefix, appName, publicPath } from "../common/vars"; import { helmRoute, kubeconfigRoute, metricsRoute, portForwardRoute, resourceApplierRoute, watchRoute } from "./routes"; export interface RouterRequestOpts { @@ -95,14 +95,14 @@ export class Router { } async handleStaticFile(filePath: string, res: http.ServerResponse) { - const asset = path.join(outDir, filePath); + const asset = path.join(__static, filePath); try { const data = await readFile(asset); res.setHeader("Content-Type", this.getMimeType(asset)); res.write(data) res.end() } catch (err) { - this.handleStaticFile(`${appName}.html`, res); + this.handleStaticFile(`${publicPath}/${appName}.html`, res); } } diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index af1437c38d..7051db1055 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -1,5 +1,5 @@ import type { ClusterId } from "../common/cluster-store"; -import { BrowserWindow, ipcMain, shell, WebContents, webContents } from "electron" +import { BrowserWindow, dialog, ipcMain, shell, WebContents, webContents } from "electron" import windowStateKeeper from "electron-window-state" import { observable } from "mobx"; import { initMenu } from "./menu"; @@ -69,10 +69,14 @@ export class WindowManager { } async showMain() { - await this.showSplash(); - await this.mainView.loadURL(`http://localhost:${this.proxyPort}`) - this.mainView.show(); - this.splashWindow.hide(); + try { + await this.showSplash(); + await this.mainView.loadURL(`http://localhost:${this.proxyPort}`) + this.mainView.show(); + this.splashWindow.hide(); + } catch (err) { + dialog.showErrorBox("ERROR!", err.toString()) + } } async showSplash() { diff --git a/src/renderer/components/+whats-new/whats-new.tsx b/src/renderer/components/+whats-new/whats-new.tsx index 9bde7da141..c63e8f25d1 100644 --- a/src/renderer/components/+whats-new/whats-new.tsx +++ b/src/renderer/components/+whats-new/whats-new.tsx @@ -7,12 +7,11 @@ import { userStore } from "../../../common/user-store" import { navigate } from "../../navigation"; import { Button } from "../button"; import { Trans } from "@lingui/macro"; -import { staticDir } from "../../../common/vars"; import marked from "marked" @observer export class WhatsNew extends React.Component { - releaseNotes = fs.readFileSync(path.join(staticDir, "RELEASE_NOTES.md")).toString(); + releaseNotes = fs.readFileSync(path.join(__static, "RELEASE_NOTES.md")).toString(); ok = () => { navigate("/"); diff --git a/types/mocks.d.ts b/types/mocks.d.ts index 4f88781e0b..7ddd25267b 100644 --- a/types/mocks.d.ts +++ b/types/mocks.d.ts @@ -4,6 +4,9 @@ declare module "win-ca" declare module "@hapi/call" declare module "@hapi/subtext" +// Global path to static assets +declare const __static: string; + // Support import for custom module extensions // https://www.typescriptlang.org/docs/handbook/modules.html#wildcard-module-declarations declare module "*.scss" { diff --git a/webpack.dll.ts b/webpack.dll.ts index cf13919e0c..000ba0af21 100755 --- a/webpack.dll.ts +++ b/webpack.dll.ts @@ -1,10 +1,10 @@ import path from "path"; import webpack, { LibraryTarget } from "webpack"; -import { isDevelopment, outDir } from "./src/common/vars"; +import { isDevelopment, buildDir } from "./src/common/vars"; export const library = "dll" export const libraryTarget: LibraryTarget = "commonjs2" -export const manifestPath = path.resolve(outDir, `${library}.manifest.json`); +export const manifestPath = path.resolve(buildDir, `${library}.manifest.json`); export const packages = [ "react", "react-dom", diff --git a/webpack.main.ts b/webpack.main.ts index bb486d47af..06c52f47dd 100755 --- a/webpack.main.ts +++ b/webpack.main.ts @@ -1,11 +1,11 @@ import path from "path"; import webpack from "webpack"; import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin" -import { isDevelopment, isProduction, mainDir, outDir } from "./src/common/vars"; +import { isDevelopment, isProduction, mainDir, buildDir } from "./src/common/vars"; import nodeExternals from "webpack-node-externals"; export default function (): webpack.Configuration { - console.info('WEBPACK:main', require("./src/common/vars"), process.env) + console.info('WEBPACK:main', require("./src/common/vars")) return { context: __dirname, target: "electron-main", @@ -16,7 +16,7 @@ export default function (): webpack.Configuration { main: path.resolve(mainDir, "index.ts"), }, output: { - path: outDir, + path: buildDir, }, resolve: { extensions: ['.json', '.js', '.ts'] diff --git a/webpack.renderer.ts b/webpack.renderer.ts index de95fbe09a..bda40a47c8 100755 --- a/webpack.renderer.ts +++ b/webpack.renderer.ts @@ -1,4 +1,4 @@ -import { appName, htmlTemplate, isDevelopment, isProduction, outDir, rendererDir, sassCommonVars } from "./src/common/vars"; +import { appName, htmlTemplate, isDevelopment, isProduction, buildDir, rendererDir, sassCommonVars, publicPath } from "./src/common/vars"; import path from "path"; import webpack from "webpack"; import HtmlWebpackPlugin from "html-webpack-plugin"; @@ -7,7 +7,7 @@ import TerserPlugin from "terser-webpack-plugin"; import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin" export default function (): webpack.Configuration { - console.info('WEBPACK:renderer', require("./src/common/vars"), process.env) + console.info('WEBPACK:renderer', require("./src/common/vars")) return { context: __dirname, target: "electron-renderer", @@ -18,8 +18,8 @@ export default function (): webpack.Configuration { [appName]: path.resolve(rendererDir, "bootstrap.tsx"), }, output: { - publicPath: "/", - path: outDir, + publicPath: publicPath, + path: buildDir, filename: '[name].js', chunkFilename: 'chunks/[name].js', },