Dev tools and errors
Log levels, readable messages and the signy-dev tools.
Log ids
Signy logs and throws with short ids instead of sentences, so the framework stays small. A warning looks like this in the console:
[signy][WARN] view:unsafe-attribute { name: 'href' }
The id names the part of Signy and the problem. The object after it holds the details, here the attribute that was left out.
Turn warnings on
The default log level is error, so warnings and info do
not show. Raise it while you develop:
import { globalConfig } from 'signy';
globalConfig.configure({ logLevel: 'warn' });
The levels, from quiet to loud, are 'error',
'warn', 'info', 'debug' and
'trace'. With the global build it is
Signy.globalConfig.configure(...).
Some warnings, such as view:unsafe-attribute and
view:lazy-outside-suspense, only exist in dev builds.
Production builds still leave the unsafe attribute out, they just do
not say so. The npm build is a production build when your bundler sets
process.env.NODE_ENV to 'production', and the
.min.js global builds are production builds.
Common ids
| Id | What happened |
|---|---|
view:unsafe-attribute | An on attribute got a string, or a URL attribute got a javascript: URL. It was left out. See Security. |
view:lazy-outside-suspense | A lazy() component rendered outside Suspense, so nothing shows while it loads. |
reactivity:cleanup-unowned | onCleanup() ran outside a component, effect or root. The cleanup never runs. |
reactivity:cleanup-error | A cleanup function threw. The other cleanups still ran. |
router:redirect-loop | Redirects and guards kept redirecting past 10 steps. push() rejects with it. |
router:loader-failed | A route loader threw. The page shows without data. |
app:invalid-state | An app was mounted twice. Create a new one. |
installable:already-installed | The same plugin was passed to use() twice. |
component:app-required | A component was mounted by hand. Mount the root with application(App).mount(). |
signy-dev
signy-dev is not on npm yet. It will be installed with
npm install signy-dev --save-dev.
Importing signy-dev registers a sentence for each of the
44 log ids. Logs and errors then carry it after the id, and
getLogMessage(id) returns it.
import 'signy-dev';
import { getLogMessage } from 'signy';
getLogMessage('view:lazy-outside-suspense');
// 'Lazy component rendered outside Suspense boundary. ...'
enableDevTools() also installs a profiler, an inspector and
an event logger, and creates the global hook
window.__SIGNY_DEVTOOLS_HOOK__ that browser extensions
connect to.
import { enableDevTools } from 'signy-dev';
const devTools = enableDevTools({
profiler: true, // component renders, signal writes, effect runs
inspector: true, // mounted components and apps, signals, effects
eventLogger: false, // a log of every reactive event
globalHook: true,
});
console.log(devTools.profiler?.report());
console.log(devTools.inspector?.getComponents());
devTools.cleanup();
Load it only in development, so production bundles leave it out:
if (import.meta.env.DEV) {
import('signy-dev').then(({ enableDevTools }) => enableDevTools());
}
The tools hold signals and effects weakly, so tracking never keeps one
alive. A second enableDevTools() call replaces the first,
so hot reload can run the setup again.
Names
Give names to what you want to find in the tools:
new Signal(0, { name: 'count' }),
computed(fn, { name: 'total' }),
store(value, { name: 'cart' }), and
static displayName = 'Cart' on a component, which keeps its
name through a minifier.