Skip to content

Commit

Permalink
Fix ./run gui watch (#6212)
Browse files Browse the repository at this point in the history
- Fixes #6168
- Removes `enso-copy-plugin` in favor of an inline plugin
- It was only used in one place anyway
- It is probably necessary since I've "fixed" it by adding all files as entrypoints (I'm not quite sure why it wasn't working with the fix with `enso-copy-plugin`...)
- Adds live reload (back) to `content/`

# Important Notes
To QA:
Mandatory:
- `./run gui watch --skip-version-check --skip-wasm-opt`

Recommended:
- `npm run watch-dashboard`
- `./run ide watch --skip-version-check --skip-wasm-opt --backend-source release --backend-release latest`
- and with `--ide-option -authentication`
- `./run ide build --skip-version-check --skip-wasm-opt --backend-source release --backend-release latest`
- `Enso` and `Enso -authentication`
  • Loading branch information
somebody1234 authored and MichaelMauderer committed Apr 12, 2023
1 parent 71b07d7 commit 9ee8e97
Show file tree
Hide file tree
Showing 18 changed files with 760 additions and 296 deletions.
2 changes: 0 additions & 2 deletions app/ide-desktop/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,6 @@ export default [
BUNDLED_ENGINE_VERSION: true,
PROJECT_MANAGER_IN_BUNDLE_PATH: true,
BUILD_INFO: true,
// Used in `lib/copy-plugin/src/index.mjs`.
AsyncGenerator: true,
},
},
rules: {
Expand Down
9 changes: 4 additions & 5 deletions app/ide-desktop/lib/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,16 @@
"electron-builder": "^22.14.13",
"electron-notarize": "1.2.2",
"enso-common": "^1.0.0",
"enso-copy-plugin": "^1.0.0",
"esbuild": "^0.17.0",
"esbuild": "^0.17.15",
"fast-glob": "^3.2.12",
"portfinder": "^1.0.32",
"tsx": "^3.12.6"
},
"optionalDependencies": {
"dmg-license": "^1.0.11",
"@esbuild/darwin-x64": "^0.17.0",
"@esbuild/linux-x64": "^0.17.0",
"@esbuild/windows-x64": "^0.17.0"
"@esbuild/darwin-x64": "^0.17.15",
"@esbuild/linux-x64": "^0.17.15",
"@esbuild/windows-x64": "^0.17.15"
},
"scripts": {
"typecheck": "tsc --noEmit",
Expand Down
86 changes: 47 additions & 39 deletions app/ide-desktop/lib/content/esbuild-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,22 @@

import * as childProcess from 'node:child_process'
import * as fs from 'node:fs/promises'
import * as path from 'node:path'
import * as fsSync from 'node:fs'
import * as pathModule from 'node:path'
import * as url from 'node:url'

import * as esbuild from 'esbuild'
import * as esbuildPluginCopy from 'enso-copy-plugin'
import * as esbuildPluginNodeGlobals from '@esbuild-plugins/node-globals-polyfill'
import * as esbuildPluginNodeModules from '@esbuild-plugins/node-modules-polyfill'
import esbuildPluginAlias from 'esbuild-plugin-alias'
import esbuildPluginCopyDirectories from 'esbuild-plugin-copy-directories'
import esbuildPluginTime from 'esbuild-plugin-time'
import esbuildPluginYaml from 'esbuild-plugin-yaml'

import * as utils from '../../utils.js'
import * as utils from '../../utils'
import BUILD_INFO from '../../build.json' assert { type: 'json' }

export const THIS_PATH = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)))
export const THIS_PATH = pathModule.resolve(pathModule.dirname(url.fileURLToPath(import.meta.url)))

// =============================
// === Environment variables ===
Expand All @@ -40,6 +41,8 @@ export interface Arguments {
outputPath: string
/** The main JS bundle to load WASM and JS wasm-pack bundles. */
ensoglAppPath: string
/** `true` if in development mode (live-reload), `false` if in production mode. */
devMode: boolean
}

/**
Expand All @@ -48,9 +51,9 @@ export interface Arguments {
export function argumentsFromEnv(): Arguments {
const wasmArtifacts = utils.requireEnv('ENSO_BUILD_GUI_WASM_ARTIFACTS')
const assetsPath = utils.requireEnv('ENSO_BUILD_GUI_ASSETS')
const outputPath = path.resolve(utils.requireEnv('ENSO_BUILD_GUI'), 'assets')
const outputPath = pathModule.resolve(utils.requireEnv('ENSO_BUILD_GUI'), 'assets')
const ensoglAppPath = utils.requireEnv('ENSO_BUILD_GUI_ENSOGL_APP')
return { wasmArtifacts, assetsPath, outputPath, ensoglAppPath }
return { wasmArtifacts, assetsPath, outputPath, ensoglAppPath, devMode: false }
}

// ===================
Expand All @@ -68,36 +71,6 @@ function git(command: string): string {
return childProcess.execSync(`git ${command}`, { encoding: 'utf8' }).trim()
}

// ==============================
// === Files to manually copy ===
// ==============================

/**
* Static set of files that are always copied to the output directory.
*/
export function alwaysCopiedFiles(wasmArtifacts: string) {
return [
path.resolve(THIS_PATH, 'src', 'index.html'),
path.resolve(THIS_PATH, 'src', 'run.js'),
path.resolve(THIS_PATH, 'src', 'style.css'),
path.resolve(THIS_PATH, 'src', 'docsStyle.css'),
...wasmArtifacts.split(path.delimiter),
]
}

/**
* Generator that yields all files that should be copied to the output directory.
* @yields {string} The file path of the next file to be copied.
*/
export async function* filesToCopyProvider(wasmArtifacts: string, assetsPath: string) {
console.log('Preparing a new generator for files to copy.')
yield* alwaysCopiedFiles(wasmArtifacts)
for (const file of await fs.readdir(assetsPath)) {
yield path.resolve(assetsPath, file)
}
console.log('Generator for files to copy finished.')
}

// ================
// === Bundling ===
// ================
Expand All @@ -106,27 +79,62 @@ export async function* filesToCopyProvider(wasmArtifacts: string, assetsPath: st
* Generate the builder options.
*/
export function bundlerOptions(args: Arguments) {
const { outputPath, ensoglAppPath, wasmArtifacts, assetsPath } = args
const { outputPath, ensoglAppPath, wasmArtifacts, assetsPath, devMode } = args
const buildOptions = {
// Disabling naming convention because these are third-party options.
/* eslint-disable @typescript-eslint/naming-convention */
absWorkingDir: THIS_PATH,
bundle: true,
entryPoints: [path.resolve(THIS_PATH, 'src', 'index.ts')],
loader: {
'.html': 'copy',
'.css': 'copy',
'.wasm': 'copy',
'.svg': 'copy',
'.png': 'copy',
'.ttf': 'copy',
},
entryPoints: [
pathModule.resolve(THIS_PATH, 'src', 'index.ts'),
pathModule.resolve(THIS_PATH, 'src', 'index.html'),
pathModule.resolve(THIS_PATH, 'src', 'run.js'),
pathModule.resolve(THIS_PATH, 'src', 'style.css'),
pathModule.resolve(THIS_PATH, 'src', 'docsStyle.css'),
...wasmArtifacts.split(pathModule.delimiter),
...fsSync
.readdirSync(assetsPath)
.map(fileName => pathModule.resolve(assetsPath, fileName)),
].map(path => ({ in: path, out: pathModule.basename(path, pathModule.extname(path)) })),
outdir: outputPath,
outbase: 'src',
plugins: [
{
// This is a workaround that is needed
// because esbuild panics when using `loader: { '.js': 'copy' }`.
// See https://github.com/evanw/esbuild/issues/3041.
// Setting `loader: 'copy'` prevents this file from being converted to ESM
// because of the `"type": "module"` in the `package.json`.
// This file MUST be in CommonJS format because it is loaded using `Function()`
// in `ensogl/pack/js/src/runner/index.ts`
name: 'pkg-js-is-cjs',
setup: build => {
build.onLoad({ filter: /\/pkg.js$/ }, async ({ path }) => ({
contents: await fs.readFile(path),
loader: 'copy',
}))
},
},
esbuildPluginCopyDirectories(),
esbuildPluginYaml.yamlPlugin({}),
esbuildPluginNodeModules.NodeModulesPolyfillPlugin(),
esbuildPluginNodeGlobals.NodeGlobalsPolyfillPlugin({ buffer: true, process: true }),
esbuildPluginAlias({ ensogl_app: ensoglAppPath }),
esbuildPluginTime(),
esbuildPluginCopy.create(() => filesToCopyProvider(wasmArtifacts, assetsPath)),
],
define: {
GIT_HASH: JSON.stringify(git('rev-parse HEAD')),
GIT_STATUS: JSON.stringify(git('status --short --porcelain')),
BUILD_INFO: JSON.stringify(BUILD_INFO),
IS_DEV_MODE: JSON.stringify(devMode),
},
sourcemap: true,
minify: true,
Expand Down
10 changes: 5 additions & 5 deletions app/ide-desktop/lib/content/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"enso-authentication": "^1.0.0",
"enso-copy-plugin": "^1.0.0",
"esbuild": "^0.17.0",
"esbuild": "^0.17.15",
"esbuild-plugin-alias": "^0.2.1",
"esbuild-plugin-copy-directories": "^1.0.0",
"esbuild-plugin-time": "^1.0.0",
"esbuild-plugin-yaml": "^0.0.1",
"eslint": "^8.36.0",
Expand All @@ -51,8 +51,8 @@
"typescript": "^4.9.3"
},
"optionalDependencies": {
"@esbuild/darwin-x64": "^0.17.0",
"@esbuild/linux-x64": "^0.17.0",
"@esbuild/windows-x64": "^0.17.0"
"@esbuild/darwin-x64": "^0.17.15",
"@esbuild/linux-x64": "^0.17.15",
"@esbuild/windows-x64": "^0.17.15"
}
}
18 changes: 18 additions & 0 deletions app/ide-desktop/lib/content/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,29 @@ import GLOBAL_CONFIG from '../../../../gui/config.yaml' assert { type: 'yaml' }

const logger = app.log.logger

// =================
// === Constants ===
// =================

/** Path to the SSE endpoint over which esbuild sends events. */
const ESBUILD_PATH = '/esbuild'
/** SSE event indicating a build has finished. */
const ESBUILD_EVENT_NAME = 'change'
/** One second in milliseconds. */
const SECOND = 1000
/** Time in seconds after which a `fetchTimeout` ends. */
const FETCH_TIMEOUT = 300

// ===================
// === Live reload ===
// ===================

if (IS_DEV_MODE) {
new EventSource(ESBUILD_PATH).addEventListener(ESBUILD_EVENT_NAME, () => {
location.reload()
})
}

// =============
// === Fetch ===
// =============
Expand Down
10 changes: 8 additions & 2 deletions app/ide-desktop/lib/content/watch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @file File watch and compile service. */
import * as esbuild from 'esbuild'
import * as portfinder from 'portfinder'
import chalk from 'chalk'

import * as bundler from './esbuild-config'
import * as dashboardBundler from '../dashboard/esbuild-config'
Expand All @@ -24,15 +25,20 @@ async function watch() {
// This MUST be called before `builder.watch()` as `tailwind.css` must be generated
// before the copy plugin runs.
await dashboardBuilder.watch()
const opts = bundler.bundleOptions()
const opts = bundler.bundlerOptions({
...bundler.argumentsFromEnv(),
devMode: true,
})
const builder = await esbuild.context(opts)
await builder.watch()
await builder.serve({
port: await portfinder.getPortPromise({ port: PORT }),
servedir: opts.outdir,
onRequest(args) {
if (args.status !== HTTP_STATUS_OK) {
console.error(`HTTP error ${args.status} when serving path '${args.path}'.`)
console.error(
chalk.red(`HTTP error ${args.status} when serving path '${args.path}'.`)
)
}
},
})
Expand Down
12 changes: 0 additions & 12 deletions app/ide-desktop/lib/copy-plugin/package.json

This file was deleted.

110 changes: 0 additions & 110 deletions app/ide-desktop/lib/copy-plugin/src/index.mjs

This file was deleted.

0 comments on commit 9ee8e97

Please sign in to comment.