diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c82a1c13c0..efdfad31d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,10 +37,12 @@ To get started clone the repo and get the web application started. 1. Run `git clone git@github.com:firefox-devtools/profiler.git` 2. Run `cd profiler` 3. Run `yarn install`, this will install all of the dependencies. -4. Run `yarn start`, this will start up the development server. +4. Run `yarn start` to serve a production build with live rebuilds and no service worker. 5. Point your browser to [http://localhost:4242](http://localhost:4242). 6. If port `4242` is taken, then you can run the web app on a different port: `FX_PROFILER_PORT=1234 yarn start` +Use `yarn start-dev` for an unminified development build with React diagnostics on port `4241`. Use `yarn start-prod` to build and serve the deployable version, including its service worker, on port `4243`. + This project uses [TypeScript](https://www.typescriptlang.org/). ## Using GitHub Codespaces diff --git a/package.json b/package.json index 96d95bbd57..c56d8bf82e 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "preinstall": "node bin/pre-install.js", "publish": "rimraf public_html && cp -r dist public_html", "serve-static": "ws -d dist/ -s index.html -p 4243", - "start": "cross-env NODE_ENV=development node scripts/run-dev-server.mjs", + "start": "cross-env NODE_ENV=production ENABLE_SERVICE_WORKER=false node scripts/run-dev-server.mjs", + "start-dev": "cross-env NODE_ENV=development node scripts/run-dev-server.mjs", "start-prod": "yarn build-prod && yarn serve-static", "start-l10n": "cross-env NODE_ENV=development L10N=1 node scripts/run-dev-server.mjs", "start-l10n-prod": "yarn build-l10n-prod && yarn serve-static", diff --git a/scripts/build.mjs b/scripts/build.mjs index 01ebca600d..b6650d147a 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -15,7 +15,11 @@ async function build() { // Build the worker first so we can read its output path from the metafile // and inject it into the main bundle via SOURCE_MAP_WORKER_PATH. - const workerResult = await esbuild.build(sourceMapWorkerConfig); + const workerResult = await esbuild.build({ + ...sourceMapWorkerConfig, + entryNames: + process.env.NODE_ENV === 'production' ? '[name]-[hash]' : '[name]', + }); const buildResult = await esbuild.build({ ...mainBundleConfig, diff --git a/scripts/lib/esbuild-configs.mjs b/scripts/lib/esbuild-configs.mjs index 9da953801b..227a4e3aad 100644 --- a/scripts/lib/esbuild-configs.mjs +++ b/scripts/lib/esbuild-configs.mjs @@ -84,6 +84,9 @@ export const mainBundleConfig = { // In dev, the worker is not hashed so the path is predictable. // In production, build.mjs overrides this after building the worker first. SOURCE_MAP_WORKER_PATH: JSON.stringify('/source-map.worker.js'), + 'process.env.ENABLE_SERVICE_WORKER': JSON.stringify( + process.env.ENABLE_SERVICE_WORKER || 'true' + ), }, external: ['zlib'], plugins: [ @@ -118,10 +121,10 @@ export const mainBundleConfig = { // Source map worker bundle configuration. // Built as a standalone IIFE so that npm dependencies (lezer, source-map) are // bundled into a single file that can be loaded as a Web Worker without needing -// ES module support. In production the output filename includes a content hash -// (e.g. source-map-ABCD1234.worker.js). The path is then injected into the main -// bundle via the SOURCE_MAP_WORKER_PATH define. In dev there is no hash since the -// dev server always serves fresh content and the define can't be updated mid-watch. +// ES module support. Watched builds use a stable filename because the main +// bundle's SOURCE_MAP_WORKER_PATH define can't be updated when only the worker +// changes. The one-off production build overrides this with a content hash and +// injects the resulting path into the main bundle. export const sourceMapWorkerConfig = { ...baseConfig, entryPoints: ['src/profile-logic/source-maps/source-map.worker.ts'], @@ -131,7 +134,7 @@ export const sourceMapWorkerConfig = { target: browserslistToEsbuild(), sourcemap: true, splitting: false, - entryNames: isProduction ? '[name]-[hash]' : '[name]', + entryNames: '[name]', metafile: true, plugins: [wasmLoader()], }; diff --git a/scripts/run-dev-server.mjs b/scripts/run-dev-server.mjs index 71d87fef02..2aaa4052cd 100644 --- a/scripts/run-dev-server.mjs +++ b/scripts/run-dev-server.mjs @@ -11,7 +11,9 @@ import { serveAndOpenProfile } from './lib/profile-server.mjs'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; -const port = parseInt(process.env.FX_PROFILER_PORT) || 4242; +const isProduction = process.env.NODE_ENV === 'production'; +const defaultPort = isProduction ? 4242 : 4241; +const port = parseInt(process.env.FX_PROFILER_PORT) || defaultPort; const host = process.env.FX_PROFILER_HOST || 'localhost'; const argv = yargs(hideBin(process.argv)) @@ -33,13 +35,15 @@ startDevServer(mainBundleConfig, { console.log(barAscii); console.log(`> Firefox Profiler is listening at: ${profilerUrl}\n`); - if (port === 4242) { + if (port === defaultPort) { console.log( '> You can change this default port with the environment variable FX_PROFILER_PORT.\n' ); } - console.log('> esbuild development server enabled'); + console.log( + `> esbuild ${isProduction ? 'production' : 'development'} build with live rebuilds enabled` + ); console.log(barAscii); if (argv.profile) { diff --git a/src/components/app/ServiceWorkerManager.tsx b/src/components/app/ServiceWorkerManager.tsx index db4d87ec73..bca9c6ff27 100644 --- a/src/components/app/ServiceWorkerManager.tsx +++ b/src/components/app/ServiceWorkerManager.tsx @@ -244,6 +244,7 @@ class ServiceWorkerManagerImpl extends PureComponent { override componentDidMount() { if ( process.env.NODE_ENV === 'production' && + process.env.ENABLE_SERVICE_WORKER !== 'false' && // Do not install the service worker for l10n branch so localizers can see // the changes easily with a single refresh. This variable is added by // esbuild's define option. diff --git a/src/test/components/ServiceWorkerManager.test.tsx b/src/test/components/ServiceWorkerManager.test.tsx index 138dc974bd..f11daad2f4 100644 --- a/src/test/components/ServiceWorkerManager.test.tsx +++ b/src/test/components/ServiceWorkerManager.test.tsx @@ -61,6 +61,7 @@ describe('app/ServiceWorkerManager', () => { afterEach(() => { process.env.NODE_ENV = 'development'; + delete process.env.ENABLE_SERVICE_WORKER; Object.defineProperty(window, 'location', nativeLocation); nativeLocation = null; @@ -171,6 +172,14 @@ describe('app/ServiceWorkerManager', () => { expect(Workbox).not.toHaveBeenCalled(); }); + it('does not register a service worker in a local production build', () => { + process.env.NODE_ENV = 'production'; + process.env.ENABLE_SERVICE_WORKER = 'false'; + + setup(); + expect(Workbox).not.toHaveBeenCalled(); + }); + describe('in the home, with the `none` datasource', () => { it('shows a notice when the SW is updated, and the user can close it', () => { process.env.NODE_ENV = 'production';