This command pulls the UI-related dependencies (notably, the NodeJS binary) and installs the node_modules
in ui/node_modules
:
tools/install-build-deps --ui
# Will build into ./out/ui by default. Can be changed with --out path/ # The final bundle will be available at ./ui/out/dist/. # The build script creates a symlink from ./ui/out to $OUT_PATH/ui/. ui/build
The devserver has a live reload functionality: once you make a change in TypeScript files, the resulting code will be recompiled and the page is going to reload automatically. By default, this logic uses a timeout in order to prevent successive reloads on rapid changes. This logic can be disabled via development-only “Rapid live reload” flag in the UI. Disabling it will reload the page earlier, at the cost of sometimes making multiple reloads in a row.
# This will automatically build the UI. There is no need to manually run # ui/build before running ui/run-dev-server. ui/run-dev-server
Navigate to http://localhost:10000/ to see the changes.
NOTE: If you made changes to Trace Processor you need to restart the server.
UI unit tests are located next to the functionality being tested, and have _unittest.ts
or _jsdomtest.ts
suffixes. The following command runs all unit tests:
ui/run-unittests
This command will perform the build first; which is not necessary if you already have a development server running. In this case, to avoid interference with the rebuild done by development server and to get the results faster, you can use
ui/run-unittests --no-build
to skip the build steps.
Script ui/run-unittests
also supports --watch
parameter, which would restart the testing when the underlying source files are changed. This can be used in conjunction with --no-build
, and on its own as well.
If you're looking for an IDE to write the TypeScript code, Visual Studio Code works well out of the box. WebStorm or IntelliJ Idea Ultimate (Community does not have JavaScript/TypeScript support) also work really well. The code is located in the ui
folder.
For VSCode users, we recommend using the eslint & prettier extensions to handle this entirely from within the IDE. See the Useful Extensions section on how to set this up.
We use eslint
to lint TypeScript and JavaScript, and prettier
to format TypeScript, JavaScript, and SCSS.
To auto-format all source files, run ui/format-sources, which takes care of running both prettier and eslint on the changed files:
# By default it formats only files that changed from the upstream Git branch # (typicaly origin/main). # Pass --all for formatting all files under ui/src ui/format-sources
Presubmit checks require no formatting or linting issues, so fix all issues using the commands above before submitting a patch.
Perfetto UI uses the Mithril library for rendering the interface. The majority of the components in the codebase use class components. When Mithril is imported via m
alias (as it is usually done in the codebase), the class component should extend m.ClassComponent
, which has an optional generic parameter allowing the component to take inputs. The entry point of class components is a view
method, returning a tree of virtual DOM elements to be rendered when the component is present on the page.
Local state of components can reside in class members and accessed directly in methods via accessing this
. State that is shared across different components is stored in the State
class definition, and should be modified via implementing a new action in src/common/actions.ts
. A new field added to State
should be initialized in src/common/empty_state.ts
.
There are restrictions on whan can be used in the global state: plain JS objects are OK, but class instances are not (this limitation is due to state serialization: the state should be a valid JSON object). If storing class instances (like Map
and Set
data structures) is necessary, these can be stored in the NonSerializableState
portion of the state, that is omitted from saving into JSON objects.