Non-JS file types
Files that only HTML, Vue, Svelte, Astro, MDX, GraphQL, or CSS reference still count as used. Fallow reads these file types and React Native platform files with no plugin or config.
A file that only an HTML page, a Vue template, or a stylesheet references is not unused. Fallow analyzes more than .js and .ts files: it reads imports and exports from non-JavaScript file types, based on the file extension. You do not need a plugin or config.
Fallow finds .html files and reads the <script src> and <link> tags as module graph edges. This covers projects with HTML entry points, such as Parcel or setups with no framework.
Fallow reads:
<script src="./main.js">script references<link rel="stylesheet" href="./styles.css">stylesheet references<link rel="modulepreload" href="./vendor.js">module preload references- Root-relative paths (for example
<script src="/src/main.tsx">). Fallow resolves them against the directory of the HTML file first, then against the project root, then againstpublic/in the project root.htmltagged templates in JS and TS files use the same order, without thepublic/step (see the SSR layouts tab).
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="./styles/main.css" />
<link rel="modulepreload" href="./vendor/lodash.js" />
</head>
<body>
<div id="app"></div>
<script src="./src/main.ts"></script>
</body>
</html>Fallow reads references to ./styles/main.css, ./vendor/lodash.js, and ./src/main.ts from this file.
The Parcel plugin adds index.html as an entry pattern, so fallow finds HTML entry files with no extra config.
Angular template complexity. fallow health reports the complexity of Angular templates as synthetic <template> findings. This covers standalone .html files that templateUrl references and inline @Component({ template: \...` })` literals. Fallow counts these template constructs:
- control-flow blocks (
@if,@for,@switch,@case,@defer (when ...),@let) - legacy structural directives (
*ngIf,*ngFor) - bound attributes (
[x],(x),bind-x,on-x) \{\{ \}\}interpolations
Fallow reports an inline-template finding on the @Component decorator line. To suppress it, put // fallow-ignore-next-line complexity directly above the decorator. To suppress an external-template finding, put <!-- fallow-ignore-file complexity --> at the top of the .html file.
Fallow reads the <script> block of Vue and Svelte single-file components and analyzes it like a JS or TS module. It also reads the <template> section for component references, directives, and expressions. An import that only the template uses therefore counts as used.
Script extraction:
<script>and<script setup>blockslang="ts"andlang="tsx"attributes<script src="./external.ts">external script references (Vue only. In Svelte, a<script src>tag is runtime HTML and does not add an import.)- HTML comments (
<!-- ... -->), which fallow removes before parsing
Vue template tracking:
- Component tags:
<MyComponent>resolves to importedMyComponent - Custom directives:
v-focus-trapresolves to importedvFocusTrap v-onandv-bindobject syntax (for examplev-on="handlers")- Template expressions:
\{\{ formatDate() \}\}marksformatDateas used - Namespace member access:
utils.formatDatein a template marks the member as used
Svelte template tracking:
- Component tags:
<Button>resolves to importedButton - Directives:
use:tooltip,transition:fade,animate:flip,in:fly,out:fade - Attribute expressions:
{expression}and shorthand attributes{variable} $storesubscriptions:$myStoremarksmyStoreas used
<script setup lang="ts">
import { ref } from 'vue'
import { formatDate } from '@/utils/date'
import FocusTrap from '@/components/FocusTrap.vue'
const count = ref(0)
</script>
<template>
<FocusTrap>
<div>{{ formatDate(new Date()) }}</div>
</FocusTrap>
</template>Fallow reads imports of ref from vue, formatDate from @/utils/date, and FocusTrap from @/components/FocusTrap.vue. The template uses <FocusTrap> and formatDate, so fallow does not report them as unused, although the script block does not use them.
Svelte components export props implicitly. Fallow cannot tell props from utility exports, so it can miss unused exports in .svelte files. For details, see Limitations.
SSR frameworks such as Hono can render HTML from a tagged template literal (html`...`). Fallow reads <script src="..."> and <link rel="stylesheet|modulepreload" href="..."> in these templates as it does in plain HTML. Each one is an asset reference that keeps the target file reachable.
Fallow reads:
<script src="./app.js">insidehtml`...`tagged templates<link rel="stylesheet" href="./global.css">insidehtml`...`tagged templates<link rel="modulepreload" href="./vendor.js">insidehtml`...`tagged templates- Root-relative paths (
<link href="/static/style.css">). Fallow resolves them against the parent directory of the source file first, then against the project root
import { html } from 'hono/html'
export const Layout = ({ title, body }: { title: string; body: string }) => html`
<!doctype html>
<html>
<head>
<title>${title}</title>
<link rel="stylesheet" href="/static/style.css" />
<script defer src="/static/app.js"></script>
</head>
<body>${body}</body>
</html>
`Fallow reads references to /static/style.css and /static/app.js from this file and marks those files in static/ as reachable.
Fallow does not read <script src> and <link href> in JSX or TSX layouts. In JSX, these attributes are runtime HTML, not module imports, so they do not add a graph edge. If a JSX layout is the only reference to an asset, add the asset to entry or ignorePatterns.
In tagged templates, fallow matches only the bare identifier tag html. It ignores other tags, such as css, sql, and gql. It skips an asset reference that an interpolation splits (html`<script src="${base}/app.js">`), so it does not produce a broken specifier.
Plain JavaScript files can reference TypeScript types through JSDoc import() expressions. Fallow reads these references and marks the types as used, so untyped JS files do not cause false unused-export reports.
/**
* @param cfg {import('./types.ts').Config}
* @returns {import('./types.ts').Result}
*/
function boot(cfg) {
return { ok: true };
}Fallow marks the Config and Result types from ./types.ts as used, although no import statement binds them. This works in all JSDoc tags (@param, @returns, @type, @typedef, @callback). Fallow also supports:
- union annotations with more than one
import()expression ({import('./a').A | import('./b').B}) - nested member access
- bare package specifiers
- parent-relative paths
Fallow reads only /** */ JSDoc blocks. It ignores single-star /* */ comments, because they are not JSDoc. The TypeScript compiler does the same.
Astro components start with a frontmatter block between two --- lines. Fallow analyzes the content of this block as TypeScript.
Fallow also follows the client scripts in the template body: <script src="..."> references and ESM import statements in inline <script> blocks. Astro bundles both into the page at build time, so their targets stay reachable.
---
import Header from '../components/Header.astro'
import Footer from '../components/Footer.astro'
import type { Props } from './types'
---
<html>
<body>
<Header />
<slot />
<Footer />
<script src="../scripts/analytics.ts"></script>
<script>
import '../scripts/hydrate'
</script>
</body>
</html>Fallow reads imports of Header, Footer, and the Props type from this file. It also reads ../scripts/analytics.ts (external) and ../scripts/hydrate (inline ESM).
MDX files can contain JavaScript import and export statements next to Markdown content. Fallow adds these statements to the module graph.
import { CodeBlock } from '../components/CodeBlock'
import { Callout } from '../components/Callout'
export const meta = { title: 'Getting Started' }
# Getting Started
<CodeBlock language="bash">
npm install fallow
</CodeBlock>Fallow tracks the imports of CodeBlock and Callout, and the named export meta.
GraphQL documents can import fragments from other .graphql and .gql files with #import comments. Fallow reads these relative links and keeps the imported fragment files reachable.
Fallow reads:
#import "./fragment.graphql"relative imports# import '../shared/fields.gql'with optional whitespace after#- Relative imports with no extension, such as
#import "./fragment". Fallow tries.graphqland.gql
#import "./fragments/user-fields"
query CurrentUser {
currentUser {
...UserFields
}
}fragment UserFields on User {
id
name
}Fallow reads the reference to ./fragments/user-fields from query.graphql. Because the reference has no extension, fallow tries .graphql and .gql. It then marks fragments/user-fields.graphql as reachable.
Fallow reads only relative #import specifiers that start with ./ or ../. It ignores package specifiers and schema-loader syntax on purpose, because they do not point to a local document in the module graph.
Fallow treats the class names in CSS and SCSS module files (.module.css and .module.scss) as named exports. When a component imports styles from a CSS module, fallow knows which classes exist.
.root {
display: flex;
}
.primary {
background: blue;
}
.disabled {
opacity: 0.5;
}This file exports root, primary, and disabled as named exports.
CSS features fallow tracks:
| Feature | Description |
|---|---|
@import | Adds an edge to the module graph |
@use | Fallow resolves Sass @use rules as module imports |
@forward | Fallow treats Sass @forward rules as re-exports |
@apply / @tailwind | Counts as a use of the Tailwind CSS dependency |
@plugin | Fallow reads Tailwind v4 plugin sources as default imports (package or relative) |
When Tailwind is in your package.json, @apply and @tailwind directives mark the tailwindcss dependency as used. This prevents a false "unused dependency" report. A Tailwind v4 @plugin "pkg" directive marks its package or local plugin file as used.
React Native projects use a file extension per platform for each platform implementation. Fallow treats these files as variants of the same module.
Supported platform extensions:
| Extension | Platform |
|---|---|
.web.ts / .web.tsx | Web (react-native-web) |
.ios.ts / .ios.tsx | iOS |
.android.ts / .android.tsx | Android |
.native.ts / .native.tsx | Native (iOS + Android) |
src/
Button.tsx # Default implementation
Button.web.tsx # Web override
Button.native.tsx # Native overrideWhen another file imports ./Button, fallow resolves the import to all platform variants and marks each one as reachable.