diff options
author | Kristóf Marussy <kristof@marussy.com> | 2021-12-30 21:47:46 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2021-12-30 21:47:46 +0100 |
commit | 1383dde6aa0d25b5fa23d7a7b64ba7de21ec5b99 (patch) | |
tree | 94739ff48121a1d69358acf5f2c60124d1b1cdec /scripts/watch.js | |
parent | build: Only use vite typings in renderer (diff) | |
download | sophie-1383dde6aa0d25b5fa23d7a7b64ba7de21ec5b99.tar.gz sophie-1383dde6aa0d25b5fa23d7a7b64ba7de21ec5b99.tar.zst sophie-1383dde6aa0d25b5fa23d7a7b64ba7de21ec5b99.zip |
build: Fully switch over to ESM
Now we can run with ESM at build and test time and transpile into
commonjs for electron. This greatly simplifies testing, since we treat
everything as ESM during build with esbuild anyways. Now the test
environment and the build scripts match the apparent (but not the actual
for the main, preload, and inject modules) runtime environment.
Caveats:
- We may use top-level async expressions in tests and script, but not in
code that gets transpiled into commonjs or scripts that get imported
by vite. The limitation w.r.t. commonjs seems fundamental.
- Jest only experimentally supports ESM and there are some limitations
with mocking. Most limitations (except the lack of automatic mocks)
can be worked around by async importing code that uses mocks.
- There are packages marked as modules (so that node reads any scripts
in them as ESM) that nevertheless get transpiled into commonjs
modules. However, these should be clearly marked by using a .cjs
extension as their bundle. The worst offender is the root package,
which has a .cjs as its main entry point that gets read by electron,
but is in fact marked as a module. This doesn't seem to bother electron
at all. The service-inject package is an IIFE with a .js extension,
but it outputs a fully self-contained bundle, so the choice of module
format should be irrelevant.
Diffstat (limited to 'scripts/watch.js')
-rw-r--r-- | scripts/watch.js | 44 |
1 files changed, 27 insertions, 17 deletions
diff --git a/scripts/watch.js b/scripts/watch.js index d4229e9..82a8feb 100644 --- a/scripts/watch.js +++ b/scripts/watch.js | |||
@@ -1,20 +1,20 @@ | |||
1 | // @ts-check | 1 | import { build as esbuildBuild } from 'esbuild'; |
2 | import { spawn } from 'child_process'; | ||
3 | import { watch } from 'chokidar'; | ||
4 | import electronPath from 'electron'; | ||
5 | import { join } from 'path'; | ||
6 | import { createServer } from 'vite'; | ||
2 | 7 | ||
3 | const esbuild = require('esbuild'); | 8 | import { fileURLToDirname } from '../config/build-common.js'; |
4 | const { spawn } = require('child_process'); | ||
5 | const chokidar = require('chokidar'); | ||
6 | const electronPath = require('electron'); | ||
7 | const { join } = require('path'); | ||
8 | const { createServer } = require('vite'); | ||
9 | 9 | ||
10 | process.env.MODE = 'development'; | 10 | /** @type {string} */ |
11 | process.env.NODE_ENV = 'development'; | 11 | const thisDir = fileURLToDirname(import.meta.url); |
12 | 12 | ||
13 | /** @type {string} */ | 13 | /** @type {string} */ |
14 | const sharedModule = join(__dirname, '../packages/shared/dist/index.mjs'); | 14 | const sharedModule = join(thisDir, '../packages/shared/dist/index.mjs'); |
15 | 15 | ||
16 | /** @type {string} */ | 16 | /** @type {string} */ |
17 | const serviceSharedModule = join(__dirname, '../packages/service-shared/dist/index.mjs'); | 17 | const serviceSharedModule = join(thisDir, '../packages/service-shared/dist/index.mjs'); |
18 | 18 | ||
19 | /** @type {RegExp[]} */ | 19 | /** @type {RegExp[]} */ |
20 | const stderrIgnorePatterns = [ | 20 | const stderrIgnorePatterns = [ |
@@ -34,15 +34,17 @@ const stderrIgnorePatterns = [ | |||
34 | * @return {Promise<void>} | 34 | * @return {Promise<void>} |
35 | */ | 35 | */ |
36 | async function setupEsbuildWatcher(packageName, extraPaths, callback) { | 36 | async function setupEsbuildWatcher(packageName, extraPaths, callback) { |
37 | const config = require(`../packages/${packageName}/esbuild.config.js`); | 37 | /** @type {{ default: import('esbuild').BuildOptions }} */ |
38 | const { default: config } = await import(`../packages/${packageName}/esbuild.config.js`); | ||
38 | config.logLevel = 'info'; | 39 | config.logLevel = 'info'; |
39 | config.incremental = true; | 40 | config.incremental = true; |
40 | const incrementalBuild = await esbuild.build(config); | 41 | |
42 | const incrementalBuild = await esbuildBuild(config); | ||
41 | const paths = [ | 43 | const paths = [ |
42 | join(__dirname, `../packages/${packageName}/src`), | 44 | join(thisDir, `../packages/${packageName}/src`), |
43 | ...(extraPaths || []), | 45 | ...(extraPaths || []), |
44 | ]; | 46 | ]; |
45 | const watcher = chokidar.watch(paths, { | 47 | const watcher = watch(paths, { |
46 | ignored: /(^|[\/\\])\.|__(tests|mocks)__|\.(spec|test)\.[jt]sx?$/, | 48 | ignored: /(^|[\/\\])\.|__(tests|mocks)__|\.(spec|test)\.[jt]sx?$/, |
47 | ignoreInitial: true, | 49 | ignoreInitial: true, |
48 | persistent: true, | 50 | persistent: true, |
@@ -51,7 +53,7 @@ async function setupEsbuildWatcher(packageName, extraPaths, callback) { | |||
51 | callback(); | 53 | callback(); |
52 | } | 54 | } |
53 | watcher.on('change', () => { | 55 | watcher.on('change', () => { |
54 | incrementalBuild.rebuild().then(() => { | 56 | incrementalBuild.rebuild?.().then(() => { |
55 | if (callback) { | 57 | if (callback) { |
56 | console.log(`\u26a1 Reloading package ${packageName}`); | 58 | console.log(`\u26a1 Reloading package ${packageName}`); |
57 | callback(); | 59 | callback(); |
@@ -81,7 +83,7 @@ async function setupDevServer(packageName) { | |||
81 | clearScreen: false, | 83 | clearScreen: false, |
82 | }, | 84 | }, |
83 | }, | 85 | }, |
84 | configFile: join(__dirname, `../packages/${packageName}/vite.config.js`), | 86 | configFile: join(thisDir, `../packages/${packageName}/vite.config.js`), |
85 | }); | 87 | }); |
86 | await viteDevServer.listen(); | 88 | await viteDevServer.listen(); |
87 | return viteDevServer; | 89 | return viteDevServer; |
@@ -158,6 +160,9 @@ function setupMainPackageWatcher(viteDevServer) { | |||
158 | * @returns {Promise<void>} | 160 | * @returns {Promise<void>} |
159 | */ | 161 | */ |
160 | async function setupDevEnvironment() { | 162 | async function setupDevEnvironment() { |
163 | process.env.MODE = 'development'; | ||
164 | process.env.NODE_ENV = 'development'; | ||
165 | |||
161 | /** @type {import('vite').ViteDevServer | null} */ | 166 | /** @type {import('vite').ViteDevServer | null} */ |
162 | let viteDevServer = null; | 167 | let viteDevServer = null; |
163 | /** @type {(event: import('vite').HMRPayload) => void} */ | 168 | /** @type {(event: import('vite').HMRPayload) => void} */ |
@@ -182,6 +187,11 @@ async function setupDevEnvironment() { | |||
182 | ])), | 187 | ])), |
183 | ]); | 188 | ]); |
184 | 189 | ||
190 | if (viteDevServer === null) { | ||
191 | console.error('Failed to create vite dev server'); | ||
192 | return; | ||
193 | } | ||
194 | |||
185 | console.log('\ud83c\udf80 Sophie is starting up') | 195 | console.log('\ud83c\udf80 Sophie is starting up') |
186 | return setupMainPackageWatcher(viteDevServer); | 196 | return setupMainPackageWatcher(viteDevServer); |
187 | } | 197 | } |